blob: 2ed14d4a47f5997b0866f6c2d96533d565b238f4 [file] [log] [blame]
Thomas Gleixnerd94d71c2019-05-29 07:12:40 -07001// SPDX-License-Identifier: GPL-2.0-only
Liu Yu-B132012e1ae9c02012-03-15 10:52:13 +00002/*
3 * ePAPR para-virtualization support.
4 *
Liu Yu-B132012e1ae9c02012-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-B132012e1ae9c02012-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>
Jordan Niethe75346252020-05-06 13:40:26 +100014#include <asm/inst.h>
Liu Yu-B132012f979de2012-07-03 05:48:53 +000015
Stuart Yoderf9294e92013-03-22 09:12:13 +000016#if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
Liu Yu-B132012f979de2012-07-03 05:48:53 +000017extern void epapr_ev_idle(void);
18extern u32 epapr_ev_idle_start[];
Stuart Yoderf9294e92013-03-22 09:12:13 +000019#endif
Liu Yu-B132012e1ae9c02012-03-15 10:52:13 +000020
21bool epapr_paravirt_enabled;
Scott Wood8067bd82014-05-15 11:28:26 -050022static bool __maybe_unused epapr_has_idle;
Liu Yu-B132012e1ae9c02012-03-15 10:52:13 +000023
Laurentiu TUDOR4e21b942013-07-03 17:13:15 +030024static int __init early_init_dt_scan_epapr(unsigned long node,
25 const char *uname,
26 int depth, void *data)
Liu Yu-B132012e1ae9c02012-03-15 10:52:13 +000027{
Liu Yu-B132012e1ae9c02012-03-15 10:52:13 +000028 const u32 *insts;
Rob Herring9d0c4df2014-04-01 23:49:03 -050029 int len;
Laurentiu TUDOR4e21b942013-07-03 17:13:15 +030030 int i;
Liu Yu-B132012e1ae9c02012-03-15 10:52:13 +000031
Laurentiu TUDOR4e21b942013-07-03 17:13:15 +030032 insts = of_get_flat_dt_prop(node, "hcall-instructions", &len);
Liu Yu-B132012e1ae9c02012-03-15 10:52:13 +000033 if (!insts)
Laurentiu TUDOR4e21b942013-07-03 17:13:15 +030034 return 0;
Liu Yu-B132012e1ae9c02012-03-15 10:52:13 +000035
36 if (len % 4 || len > (4 * 4))
Laurentiu TUDOR4e21b942013-07-03 17:13:15 +030037 return -1;
Liu Yu-B132012e1ae9c02012-03-15 10:52:13 +000038
Liu Yu-B132012f979de2012-07-03 05:48:53 +000039 for (i = 0; i < (len / 4); i++) {
Jordan Niethe94afd062020-05-06 13:40:31 +100040 struct ppc_inst inst = ppc_inst(be32_to_cpu(insts[i]));
41 patch_instruction((struct ppc_inst *)(epapr_hypercall_start + i), inst);
Stuart Yoderf9294e92013-03-22 09:12:13 +000042#if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
Jordan Niethe94afd062020-05-06 13:40:31 +100043 patch_instruction((struct ppc_inst *)(epapr_ev_idle_start + i), inst);
Stuart Yoderf9294e92013-03-22 09:12:13 +000044#endif
Liu Yu-B132012f979de2012-07-03 05:48:53 +000045 }
46
Stuart Yoderf9294e92013-03-22 09:12:13 +000047#if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
Laurentiu TUDOR4e21b942013-07-03 17:13:15 +030048 if (of_get_flat_dt_prop(node, "has-idle", NULL))
Stuart Yoder83e267d2014-04-30 18:34:23 -050049 epapr_has_idle = true;
Stuart Yoderf9294e92013-03-22 09:12:13 +000050#endif
Liu Yu-B132012e1ae9c02012-03-15 10:52:13 +000051
52 epapr_paravirt_enabled = true;
53
Laurentiu TUDOR4e21b942013-07-03 17:13:15 +030054 return 1;
55}
56
57int __init epapr_paravirt_early_init(void)
58{
59 of_scan_flat_dt(early_init_dt_scan_epapr, NULL);
60
Liu Yu-B132012e1ae9c02012-03-15 10:52:13 +000061 return 0;
62}
63
Stuart Yoder83e267d2014-04-30 18:34:23 -050064static int __init epapr_idle_init(void)
65{
Scott Wood440d74d2014-05-12 10:05:19 -050066#if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
Stuart Yoder83e267d2014-04-30 18:34:23 -050067 if (epapr_has_idle)
68 ppc_md.power_save = epapr_ev_idle;
Scott Wood440d74d2014-05-12 10:05:19 -050069#endif
Stuart Yoder83e267d2014-04-30 18:34:23 -050070
71 return 0;
72}
73
74postcore_initcall(epapr_idle_init);