]>
Commit | Line | Data |
---|---|---|
37655163 AS |
1 | /* |
2 | * ARM64 Specific Low-Level ACPI Boot Support | |
3 | * | |
4 | * Copyright (C) 2013-2014, Linaro Ltd. | |
5 | * Author: Al Stone <al.stone@linaro.org> | |
6 | * Author: Graeme Gregory <graeme.gregory@linaro.org> | |
7 | * Author: Hanjun Guo <hanjun.guo@linaro.org> | |
8 | * Author: Tomasz Nowicki <tomasz.nowicki@linaro.org> | |
9 | * Author: Naresh Bhat <naresh.bhat@linaro.org> | |
10 | * | |
11 | * This program is free software; you can redistribute it and/or modify | |
12 | * it under the terms of the GNU General Public License version 2 as | |
13 | * published by the Free Software Foundation. | |
14 | */ | |
15 | ||
16 | #define pr_fmt(fmt) "ACPI: " fmt | |
17 | ||
18 | #include <linux/acpi.h> | |
19 | #include <linux/bootmem.h> | |
20 | #include <linux/cpumask.h> | |
6e7300cf | 21 | #include <linux/efi-bgrt.h> |
37655163 AS |
22 | #include <linux/init.h> |
23 | #include <linux/irq.h> | |
24 | #include <linux/irqdomain.h> | |
25 | #include <linux/memblock.h> | |
b10d79f7 | 26 | #include <linux/of_fdt.h> |
37655163 | 27 | #include <linux/smp.h> |
888125a7 | 28 | #include <linux/serial_core.h> |
37655163 | 29 | |
fccb9a81 HG |
30 | #include <asm/cputype.h> |
31 | #include <asm/cpu_ops.h> | |
32 | #include <asm/smp_plat.h> | |
33 | ||
89e44b51 JZZ |
34 | #ifdef CONFIG_ACPI_APEI |
35 | # include <linux/efi.h> | |
36 | # include <asm/pgtable.h> | |
37 | #endif | |
38 | ||
b10d79f7 AS |
39 | int acpi_noirq = 1; /* skip ACPI IRQ initialization */ |
40 | int acpi_disabled = 1; | |
37655163 AS |
41 | EXPORT_SYMBOL(acpi_disabled); |
42 | ||
b10d79f7 | 43 | int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */ |
37655163 AS |
44 | EXPORT_SYMBOL(acpi_pci_disabled); |
45 | ||
b10d79f7 | 46 | static bool param_acpi_off __initdata; |
6a1f5471 | 47 | static bool param_acpi_on __initdata; |
fb094eb1 | 48 | static bool param_acpi_force __initdata; |
b10d79f7 AS |
49 | |
50 | static int __init parse_acpi(char *arg) | |
51 | { | |
52 | if (!arg) | |
53 | return -EINVAL; | |
54 | ||
55 | /* "acpi=off" disables both ACPI table parsing and interpreter */ | |
56 | if (strcmp(arg, "off") == 0) | |
57 | param_acpi_off = true; | |
6a1f5471 AB |
58 | else if (strcmp(arg, "on") == 0) /* prefer ACPI over DT */ |
59 | param_acpi_on = true; | |
b10d79f7 AS |
60 | else if (strcmp(arg, "force") == 0) /* force ACPI to be enabled */ |
61 | param_acpi_force = true; | |
62 | else | |
63 | return -EINVAL; /* Core will print when we return error */ | |
64 | ||
65 | return 0; | |
66 | } | |
67 | early_param("acpi", parse_acpi); | |
68 | ||
69 | static int __init dt_scan_depth1_nodes(unsigned long node, | |
70 | const char *uname, int depth, | |
71 | void *data) | |
72 | { | |
73 | /* | |
9981293f MR |
74 | * Ignore anything not directly under the root node; we'll |
75 | * catch its parent instead. | |
b10d79f7 | 76 | */ |
9981293f MR |
77 | if (depth != 1) |
78 | return 0; | |
2366c7fd | 79 | |
9981293f MR |
80 | if (strcmp(uname, "chosen") == 0) |
81 | return 0; | |
82 | ||
83 | if (strcmp(uname, "hypervisor") == 0 && | |
84 | of_flat_dt_is_compatible(node, "xen,xen")) | |
85 | return 0; | |
86 | ||
87 | /* | |
88 | * This node at depth 1 is neither a chosen node nor a xen node, | |
89 | * which we do not expect. | |
90 | */ | |
91 | return 1; | |
b10d79f7 AS |
92 | } |
93 | ||
37655163 AS |
94 | /* |
95 | * __acpi_map_table() will be called before page_init(), so early_ioremap() | |
96 | * or early_memremap() should be called here to for ACPI table mapping. | |
97 | */ | |
98 | char *__init __acpi_map_table(unsigned long phys, unsigned long size) | |
99 | { | |
100 | if (!size) | |
101 | return NULL; | |
102 | ||
103 | return early_memremap(phys, size); | |
104 | } | |
105 | ||
106 | void __init __acpi_unmap_table(char *map, unsigned long size) | |
107 | { | |
108 | if (!map || !size) | |
109 | return; | |
110 | ||
111 | early_memunmap(map, size); | |
112 | } | |
113 | ||
c5a13305 MR |
114 | bool __init acpi_psci_present(void) |
115 | { | |
116 | return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_COMPLIANT; | |
117 | } | |
118 | ||
119 | /* Whether HVC must be used instead of SMC as the PSCI conduit */ | |
120 | bool __init acpi_psci_use_hvc(void) | |
121 | { | |
122 | return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_USE_HVC; | |
123 | } | |
124 | ||
54971e43 LP |
125 | /* |
126 | * acpi_fadt_sanity_check() - Check FADT presence and carry out sanity | |
127 | * checks on it | |
128 | * | |
129 | * Return 0 on success, <0 on failure | |
130 | */ | |
131 | static int __init acpi_fadt_sanity_check(void) | |
37655163 | 132 | { |
54971e43 LP |
133 | struct acpi_table_header *table; |
134 | struct acpi_table_fadt *fadt; | |
135 | acpi_status status; | |
54971e43 LP |
136 | int ret = 0; |
137 | ||
138 | /* | |
139 | * FADT is required on arm64; retrieve it to check its presence | |
140 | * and carry out revision and ACPI HW reduced compliancy tests | |
141 | */ | |
6b11d1d6 | 142 | status = acpi_get_table(ACPI_SIG_FADT, 0, &table); |
54971e43 LP |
143 | if (ACPI_FAILURE(status)) { |
144 | const char *msg = acpi_format_exception(status); | |
145 | ||
146 | pr_err("Failed to get FADT table, %s\n", msg); | |
147 | return -ENODEV; | |
148 | } | |
149 | ||
150 | fadt = (struct acpi_table_fadt *)table; | |
37655163 AS |
151 | |
152 | /* | |
153 | * Revision in table header is the FADT Major revision, and there | |
154 | * is a minor revision of FADT which was introduced by ACPI 5.1, | |
155 | * we only deal with ACPI 5.1 or newer revision to get GIC and SMP | |
54971e43 | 156 | * boot protocol configuration data. |
37655163 | 157 | */ |
54971e43 LP |
158 | if (table->revision < 5 || |
159 | (table->revision == 5 && fadt->minor_revision < 1)) { | |
160 | pr_err("Unsupported FADT revision %d.%d, should be 5.1+\n", | |
161 | table->revision, fadt->minor_revision); | |
162 | ret = -EINVAL; | |
163 | goto out; | |
fccb9a81 | 164 | } |
37655163 | 165 | |
54971e43 LP |
166 | if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) { |
167 | pr_err("FADT not ACPI hardware reduced compliant\n"); | |
168 | ret = -EINVAL; | |
169 | } | |
37655163 | 170 | |
54971e43 LP |
171 | out: |
172 | /* | |
6b11d1d6 | 173 | * acpi_get_table() creates FADT table mapping that |
54971e43 LP |
174 | * should be released after parsing and before resuming boot |
175 | */ | |
6b11d1d6 | 176 | acpi_put_table(table); |
54971e43 | 177 | return ret; |
37655163 AS |
178 | } |
179 | ||
180 | /* | |
181 | * acpi_boot_table_init() called from setup_arch(), always. | |
182 | * 1. find RSDP and get its address, and then find XSDT | |
183 | * 2. extract all tables and checksums them all | |
184 | * 3. check ACPI FADT revision | |
54971e43 | 185 | * 4. check ACPI FADT HW reduced flag |
37655163 AS |
186 | * |
187 | * We can parse ACPI boot-time tables such as MADT after | |
188 | * this function is called. | |
54971e43 | 189 | * |
fb094eb1 LP |
190 | * On return ACPI is enabled if either: |
191 | * | |
192 | * - ACPI tables are initialized and sanity checks passed | |
193 | * - acpi=force was passed in the command line and ACPI was not disabled | |
194 | * explicitly through acpi=off command line parameter | |
195 | * | |
196 | * ACPI is disabled on function return otherwise | |
37655163 AS |
197 | */ |
198 | void __init acpi_boot_table_init(void) | |
199 | { | |
b10d79f7 AS |
200 | /* |
201 | * Enable ACPI instead of device tree unless | |
202 | * - ACPI has been disabled explicitly (acpi=off), or | |
2366c7fd SZ |
203 | * - the device tree is not empty (it has more than just a /chosen node, |
204 | * and a /hypervisor node when running on Xen) | |
6a1f5471 | 205 | * and ACPI has not been [force] enabled (acpi=on|force) |
b10d79f7 AS |
206 | */ |
207 | if (param_acpi_off || | |
6a1f5471 AB |
208 | (!param_acpi_on && !param_acpi_force && |
209 | of_scan_flat_dt(dt_scan_depth1_nodes, NULL))) | |
888125a7 | 210 | goto done; |
37655163 | 211 | |
54971e43 LP |
212 | /* |
213 | * ACPI is disabled at this point. Enable it in order to parse | |
214 | * the ACPI tables and carry out sanity checks | |
215 | */ | |
b10d79f7 AS |
216 | enable_acpi(); |
217 | ||
54971e43 LP |
218 | /* |
219 | * If ACPI tables are initialized and FADT sanity checks passed, | |
220 | * leave ACPI enabled and carry on booting; otherwise disable ACPI | |
221 | * on initialization error. | |
fb094eb1 LP |
222 | * If acpi=force was passed on the command line it forces ACPI |
223 | * to be enabled even if its initialization failed. | |
54971e43 LP |
224 | */ |
225 | if (acpi_table_init() || acpi_fadt_sanity_check()) { | |
226 | pr_err("Failed to init ACPI tables\n"); | |
fb094eb1 LP |
227 | if (!param_acpi_force) |
228 | disable_acpi(); | |
37655163 | 229 | } |
888125a7 AM |
230 | |
231 | done: | |
232 | if (acpi_disabled) { | |
233 | if (earlycon_init_is_deferred) | |
234 | early_init_dt_scan_chosen_stdout(); | |
235 | } else { | |
236 | parse_spcr(earlycon_init_is_deferred); | |
6e7300cf BS |
237 | if (IS_ENABLED(CONFIG_ACPI_BGRT)) |
238 | acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt); | |
888125a7 | 239 | } |
37655163 | 240 | } |
d60fc389 | 241 | |
89e44b51 JZZ |
242 | #ifdef CONFIG_ACPI_APEI |
243 | pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr) | |
244 | { | |
245 | /* | |
246 | * According to "Table 8 Map: EFI memory types to AArch64 memory | |
247 | * types" of UEFI 2.5 section 2.3.6.1, each EFI memory type is | |
248 | * mapped to a corresponding MAIR attribute encoding. | |
249 | * The EFI memory attribute advises all possible capabilities | |
250 | * of a memory region. We use the most efficient capability. | |
251 | */ | |
252 | ||
253 | u64 attr; | |
254 | ||
255 | attr = efi_mem_attributes(addr); | |
256 | if (attr & EFI_MEMORY_WB) | |
257 | return PAGE_KERNEL; | |
258 | if (attr & EFI_MEMORY_WT) | |
259 | return __pgprot(PROT_NORMAL_WT); | |
260 | if (attr & EFI_MEMORY_WC) | |
261 | return __pgprot(PROT_NORMAL_NC); | |
262 | return __pgprot(PROT_DEVICE_nGnRnE); | |
263 | } | |
264 | #endif |