blob: 9d32158ce36fc7b105f0bdae6440c5e9b82263f7 [file] [log] [blame]
Thomas Gleixnerd94d71c2019-05-29 07:12:40 -07001// SPDX-License-Identifier: GPL-2.0-only
Liu Yu-B132012e1ae9c2012-03-15 10:52:13 +00002/*
3 * ePAPR para-virtualization support.
4 *
Liu Yu-B132012e1ae9c2012-03-15 10:52:13 +00005 * Copyright (C) 2012 Freescale Semiconductor, Inc.
6 */
7
8#include <linux/of.h>
Rob Herring26a20562013-09-26 07:40:04 -05009#include <linux/of_fdt.h>
Liu Yu-B132012e1ae9c2012-03-15 10:52:13 +000010#include <asm/epapr_hcalls.h>
11#include <asm/cacheflush.h>
12#include <asm/code-patching.h>
Liu Yu-B132012f979de2012-07-03 05:48:53 +000013#include <asm/machdep.h>
14
Stuart Yoderf9294e92013-03-22 09:12:13 +000015#if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
Liu Yu-B132012f979de2012-07-03 05:48:53 +000016extern void epapr_ev_idle(void);
17extern u32 epapr_ev_idle_start[];
Stuart Yoderf9294e92013-03-22 09:12:13 +000018#endif
Liu Yu-B132012e1ae9c2012-03-15 10:52:13 +000019
20bool epapr_paravirt_enabled;
Scott Wood8067bd82014-05-15 11:28:26 -050021static bool __maybe_unused epapr_has_idle;
Liu Yu-B132012e1ae9c2012-03-15 10:52:13 +000022
Laurentiu TUDOR4e21b942013-07-03 17:13:15 +030023static int __init early_init_dt_scan_epapr(unsigned long node,
24 const char *uname,
25 int depth, void *data)
Liu Yu-B132012e1ae9c2012-03-15 10:52:13 +000026{
Liu Yu-B132012e1ae9c2012-03-15 10:52:13 +000027 const u32 *insts;
Rob Herring9d0c4df2014-04-01 23:49:03 -050028 int len;
Laurentiu TUDOR4e21b942013-07-03 17:13:15 +030029 int i;
Liu Yu-B132012e1ae9c2012-03-15 10:52:13 +000030
Laurentiu TUDOR4e21b942013-07-03 17:13:15 +030031 insts = of_get_flat_dt_prop(node, "hcall-instructions", &len);
Liu Yu-B132012e1ae9c2012-03-15 10:52:13 +000032 if (!insts)
Laurentiu TUDOR4e21b942013-07-03 17:13:15 +030033 return 0;
Liu Yu-B132012e1ae9c2012-03-15 10:52:13 +000034
35 if (len % 4 || len > (4 * 4))
Laurentiu TUDOR4e21b942013-07-03 17:13:15 +030036 return -1;
Liu Yu-B132012e1ae9c2012-03-15 10:52:13 +000037
Liu Yu-B132012f979de2012-07-03 05:48:53 +000038 for (i = 0; i < (len / 4); i++) {
Alexander Graf235959b2014-05-13 16:44:09 +020039 u32 inst = be32_to_cpu(insts[i]);
40 patch_instruction(epapr_hypercall_start + i, inst);
Stuart Yoderf9294e92013-03-22 09:12:13 +000041#if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
Alexander Graf235959b2014-05-13 16:44:09 +020042 patch_instruction(epapr_ev_idle_start + i, inst);
Stuart Yoderf9294e92013-03-22 09:12:13 +000043#endif
Liu Yu-B132012f979de2012-07-03 05:48:53 +000044 }
45
Stuart Yoderf9294e92013-03-22 09:12:13 +000046#if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
Laurentiu TUDOR4e21b942013-07-03 17:13:15 +030047 if (of_get_flat_dt_prop(node, "has-idle", NULL))
Stuart Yoder83e267d2014-04-30 18:34:23 -050048 epapr_has_idle = true;
Stuart Yoderf9294e92013-03-22 09:12:13 +000049#endif
Liu Yu-B132012e1ae9c2012-03-15 10:52:13 +000050
51 epapr_paravirt_enabled = true;
52
Laurentiu TUDOR4e21b942013-07-03 17:13:15 +030053 return 1;
54}
55
56int __init epapr_paravirt_early_init(void)
57{
58 of_scan_flat_dt(early_init_dt_scan_epapr, NULL);
59
Liu Yu-B132012e1ae9c2012-03-15 10:52:13 +000060 return 0;
61}
62
Stuart Yoder83e267d2014-04-30 18:34:23 -050063static int __init epapr_idle_init(void)
64{
Scott Wood440d74d2014-05-12 10:05:19 -050065#if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
Stuart Yoder83e267d2014-04-30 18:34:23 -050066 if (epapr_has_idle)
67 ppc_md.power_save = epapr_ev_idle;
Scott Wood440d74d2014-05-12 10:05:19 -050068#endif
Stuart Yoder83e267d2014-04-30 18:34:23 -050069
70 return 0;
71}
72
73postcore_initcall(epapr_idle_init);