Commit | Line | Data |
---|---|---|
d94d71cb | 1 | // SPDX-License-Identifier: GPL-2.0-only |
2e1ae9c0 LYB |
2 | /* |
3 | * ePAPR para-virtualization support. | |
4 | * | |
2e1ae9c0 LYB |
5 | * Copyright (C) 2012 Freescale Semiconductor, Inc. |
6 | */ | |
7 | ||
8 | #include <linux/of.h> | |
26a2056e | 9 | #include <linux/of_fdt.h> |
2e1ae9c0 LYB |
10 | #include <asm/epapr_hcalls.h> |
11 | #include <asm/cacheflush.h> | |
12 | #include <asm/code-patching.h> | |
2f979de8 LYB |
13 | #include <asm/machdep.h> |
14 | ||
f9294e98 | 15 | #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64) |
2f979de8 LYB |
16 | extern void epapr_ev_idle(void); |
17 | extern u32 epapr_ev_idle_start[]; | |
f9294e98 | 18 | #endif |
2e1ae9c0 LYB |
19 | |
20 | bool epapr_paravirt_enabled; | |
8067bd8a | 21 | static bool __maybe_unused epapr_has_idle; |
2e1ae9c0 | 22 | |
4e21b94c LT |
23 | static int __init early_init_dt_scan_epapr(unsigned long node, |
24 | const char *uname, | |
25 | int depth, void *data) | |
2e1ae9c0 | 26 | { |
2e1ae9c0 | 27 | const u32 *insts; |
9d0c4dfe | 28 | int len; |
4e21b94c | 29 | int i; |
2e1ae9c0 | 30 | |
4e21b94c | 31 | insts = of_get_flat_dt_prop(node, "hcall-instructions", &len); |
2e1ae9c0 | 32 | if (!insts) |
4e21b94c | 33 | return 0; |
2e1ae9c0 LYB |
34 | |
35 | if (len % 4 || len > (4 * 4)) | |
4e21b94c | 36 | return -1; |
2e1ae9c0 | 37 | |
2f979de8 | 38 | for (i = 0; i < (len / 4); i++) { |
235959be AG |
39 | u32 inst = be32_to_cpu(insts[i]); |
40 | patch_instruction(epapr_hypercall_start + i, inst); | |
f9294e98 | 41 | #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64) |
235959be | 42 | patch_instruction(epapr_ev_idle_start + i, inst); |
f9294e98 | 43 | #endif |
2f979de8 LYB |
44 | } |
45 | ||
f9294e98 | 46 | #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64) |
4e21b94c | 47 | if (of_get_flat_dt_prop(node, "has-idle", NULL)) |
83e267d7 | 48 | epapr_has_idle = true; |
f9294e98 | 49 | #endif |
2e1ae9c0 LYB |
50 | |
51 | epapr_paravirt_enabled = true; | |
52 | ||
4e21b94c LT |
53 | return 1; |
54 | } | |
55 | ||
56 | int __init epapr_paravirt_early_init(void) | |
57 | { | |
58 | of_scan_flat_dt(early_init_dt_scan_epapr, NULL); | |
59 | ||
2e1ae9c0 LYB |
60 | return 0; |
61 | } | |
62 | ||
83e267d7 SY |
63 | static int __init epapr_idle_init(void) |
64 | { | |
440d74d1 | 65 | #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64) |
83e267d7 SY |
66 | if (epapr_has_idle) |
67 | ppc_md.power_save = epapr_ev_idle; | |
440d74d1 | 68 | #endif |
83e267d7 SY |
69 | |
70 | return 0; | |
71 | } | |
72 | ||
73 | postcore_initcall(epapr_idle_init); |