1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * RISC-V Specific Low-Level ACPI Boot Support |
4 | * |
5 | * Copyright (C) 2013-2014, Linaro Ltd. |
6 | * Author: Al Stone <al.stone@linaro.org> |
7 | * Author: Graeme Gregory <graeme.gregory@linaro.org> |
8 | * Author: Hanjun Guo <hanjun.guo@linaro.org> |
9 | * Author: Tomasz Nowicki <tomasz.nowicki@linaro.org> |
10 | * Author: Naresh Bhat <naresh.bhat@linaro.org> |
11 | * |
12 | * Copyright (C) 2021-2023, Ventana Micro Systems Inc. |
13 | * Author: Sunil V L <sunilvl@ventanamicro.com> |
14 | */ |
15 | |
16 | #include <linux/acpi.h> |
17 | #include <linux/efi.h> |
18 | #include <linux/io.h> |
19 | #include <linux/memblock.h> |
20 | #include <linux/pci.h> |
21 | |
22 | int acpi_noirq = 1; /* skip ACPI IRQ initialization */ |
23 | int acpi_disabled = 1; |
24 | EXPORT_SYMBOL(acpi_disabled); |
25 | |
26 | int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */ |
27 | EXPORT_SYMBOL(acpi_pci_disabled); |
28 | |
29 | static bool param_acpi_off __initdata; |
30 | static bool param_acpi_on __initdata; |
31 | static bool param_acpi_force __initdata; |
32 | |
33 | static struct acpi_madt_rintc cpu_madt_rintc[NR_CPUS]; |
34 | |
35 | static int __init parse_acpi(char *arg) |
36 | { |
37 | if (!arg) |
38 | return -EINVAL; |
39 | |
40 | /* "acpi=off" disables both ACPI table parsing and interpreter */ |
41 | if (strcmp(arg, "off" ) == 0) |
42 | param_acpi_off = true; |
43 | else if (strcmp(arg, "on" ) == 0) /* prefer ACPI over DT */ |
44 | param_acpi_on = true; |
45 | else if (strcmp(arg, "force" ) == 0) /* force ACPI to be enabled */ |
46 | param_acpi_force = true; |
47 | else |
48 | return -EINVAL; /* Core will print when we return error */ |
49 | |
50 | return 0; |
51 | } |
52 | early_param("acpi" , parse_acpi); |
53 | |
54 | /* |
55 | * acpi_fadt_sanity_check() - Check FADT presence and carry out sanity |
56 | * checks on it |
57 | * |
58 | * Return 0 on success, <0 on failure |
59 | */ |
60 | static int __init acpi_fadt_sanity_check(void) |
61 | { |
62 | struct acpi_table_header *table; |
63 | struct acpi_table_fadt *fadt; |
64 | acpi_status status; |
65 | int ret = 0; |
66 | |
67 | /* |
68 | * FADT is required on riscv; retrieve it to check its presence |
69 | * and carry out revision and ACPI HW reduced compliancy tests |
70 | */ |
71 | status = acpi_get_table(ACPI_SIG_FADT, instance: 0, out_table: &table); |
72 | if (ACPI_FAILURE(status)) { |
73 | const char *msg = acpi_format_exception(exception: status); |
74 | |
75 | pr_err("Failed to get FADT table, %s\n" , msg); |
76 | return -ENODEV; |
77 | } |
78 | |
79 | fadt = (struct acpi_table_fadt *)table; |
80 | |
81 | /* |
82 | * The revision in the table header is the FADT's Major revision. The |
83 | * FADT also has a minor revision, which is stored in the FADT itself. |
84 | * |
85 | * TODO: Currently, we check for 6.5 as the minimum version to check |
86 | * for HW_REDUCED flag. However, once RISC-V updates are released in |
87 | * the ACPI spec, we need to update this check for exact minor revision |
88 | */ |
89 | if (table->revision < 6 || (table->revision == 6 && fadt->minor_revision < 5)) |
90 | pr_err(FW_BUG "Unsupported FADT revision %d.%d, should be 6.5+\n" , |
91 | table->revision, fadt->minor_revision); |
92 | |
93 | if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) { |
94 | pr_err("FADT not ACPI hardware reduced compliant\n" ); |
95 | ret = -EINVAL; |
96 | } |
97 | |
98 | /* |
99 | * acpi_get_table() creates FADT table mapping that |
100 | * should be released after parsing and before resuming boot |
101 | */ |
102 | acpi_put_table(table); |
103 | return ret; |
104 | } |
105 | |
106 | /* |
107 | * acpi_boot_table_init() called from setup_arch(), always. |
108 | * 1. find RSDP and get its address, and then find XSDT |
109 | * 2. extract all tables and checksums them all |
110 | * 3. check ACPI FADT HW reduced flag |
111 | * |
112 | * We can parse ACPI boot-time tables such as MADT after |
113 | * this function is called. |
114 | * |
115 | * On return ACPI is enabled if either: |
116 | * |
117 | * - ACPI tables are initialized and sanity checks passed |
118 | * - acpi=force was passed in the command line and ACPI was not disabled |
119 | * explicitly through acpi=off command line parameter |
120 | * |
121 | * ACPI is disabled on function return otherwise |
122 | */ |
123 | void __init acpi_boot_table_init(void) |
124 | { |
125 | /* |
126 | * Enable ACPI instead of device tree unless |
127 | * - ACPI has been disabled explicitly (acpi=off), or |
128 | * - firmware has not populated ACPI ptr in EFI system table |
129 | * and ACPI has not been [force] enabled (acpi=on|force) |
130 | */ |
131 | if (param_acpi_off || |
132 | (!param_acpi_on && !param_acpi_force && |
133 | efi.acpi20 == EFI_INVALID_TABLE_ADDR)) |
134 | return; |
135 | |
136 | /* |
137 | * ACPI is disabled at this point. Enable it in order to parse |
138 | * the ACPI tables and carry out sanity checks |
139 | */ |
140 | enable_acpi(); |
141 | |
142 | /* |
143 | * If ACPI tables are initialized and FADT sanity checks passed, |
144 | * leave ACPI enabled and carry on booting; otherwise disable ACPI |
145 | * on initialization error. |
146 | * If acpi=force was passed on the command line it forces ACPI |
147 | * to be enabled even if its initialization failed. |
148 | */ |
149 | if (acpi_table_init() || acpi_fadt_sanity_check()) { |
150 | pr_err("Failed to init ACPI tables\n" ); |
151 | if (!param_acpi_force) |
152 | disable_acpi(); |
153 | } |
154 | } |
155 | |
156 | static int acpi_parse_madt_rintc(union acpi_subtable_headers *, const unsigned long end) |
157 | { |
158 | struct acpi_madt_rintc *rintc = (struct acpi_madt_rintc *)header; |
159 | int cpuid; |
160 | |
161 | if (!(rintc->flags & ACPI_MADT_ENABLED)) |
162 | return 0; |
163 | |
164 | cpuid = riscv_hartid_to_cpuid(rintc->hart_id); |
165 | /* |
166 | * When CONFIG_SMP is disabled, mapping won't be created for |
167 | * all cpus. |
168 | * CPUs more than num_possible_cpus, will be ignored. |
169 | */ |
170 | if (cpuid >= 0 && cpuid < num_possible_cpus()) |
171 | cpu_madt_rintc[cpuid] = *rintc; |
172 | |
173 | return 0; |
174 | } |
175 | |
176 | /* |
177 | * Instead of parsing (and freeing) the ACPI table, cache |
178 | * the RINTC structures since they are frequently used |
179 | * like in cpuinfo. |
180 | */ |
181 | void __init acpi_init_rintc_map(void) |
182 | { |
183 | if (acpi_table_parse_madt(id: ACPI_MADT_TYPE_RINTC, handler: acpi_parse_madt_rintc, max_entries: 0) <= 0) { |
184 | pr_err("No valid RINTC entries exist\n" ); |
185 | BUG(); |
186 | } |
187 | } |
188 | |
189 | struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu) |
190 | { |
191 | return &cpu_madt_rintc[cpu]; |
192 | } |
193 | |
194 | u32 get_acpi_id_for_cpu(int cpu) |
195 | { |
196 | return acpi_cpu_get_madt_rintc(cpu)->uid; |
197 | } |
198 | |
199 | /* |
200 | * __acpi_map_table() will be called before paging_init(), so early_ioremap() |
201 | * or early_memremap() should be called here to for ACPI table mapping. |
202 | */ |
203 | void __init __iomem *__acpi_map_table(unsigned long phys, unsigned long size) |
204 | { |
205 | if (!size) |
206 | return NULL; |
207 | |
208 | return early_ioremap(phys_addr: phys, size); |
209 | } |
210 | |
211 | void __init __acpi_unmap_table(void __iomem *map, unsigned long size) |
212 | { |
213 | if (!map || !size) |
214 | return; |
215 | |
216 | early_iounmap(addr: map, size); |
217 | } |
218 | |
219 | void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) |
220 | { |
221 | efi_memory_desc_t *md, *region = NULL; |
222 | pgprot_t prot; |
223 | |
224 | if (WARN_ON_ONCE(!efi_enabled(EFI_MEMMAP))) |
225 | return NULL; |
226 | |
227 | for_each_efi_memory_desc(md) { |
228 | u64 end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT); |
229 | |
230 | if (phys < md->phys_addr || phys >= end) |
231 | continue; |
232 | |
233 | if (phys + size > end) { |
234 | pr_warn(FW_BUG "requested region covers multiple EFI memory regions\n" ); |
235 | return NULL; |
236 | } |
237 | region = md; |
238 | break; |
239 | } |
240 | |
241 | /* |
242 | * It is fine for AML to remap regions that are not represented in the |
243 | * EFI memory map at all, as it only describes normal memory, and MMIO |
244 | * regions that require a virtual mapping to make them accessible to |
245 | * the EFI runtime services. |
246 | */ |
247 | prot = PAGE_KERNEL_IO; |
248 | if (region) { |
249 | switch (region->type) { |
250 | case EFI_LOADER_CODE: |
251 | case EFI_LOADER_DATA: |
252 | case EFI_BOOT_SERVICES_CODE: |
253 | case EFI_BOOT_SERVICES_DATA: |
254 | case EFI_CONVENTIONAL_MEMORY: |
255 | case EFI_PERSISTENT_MEMORY: |
256 | if (memblock_is_map_memory(addr: phys) || |
257 | !memblock_is_region_memory(base: phys, size)) { |
258 | pr_warn(FW_BUG "requested region covers kernel memory\n" ); |
259 | return NULL; |
260 | } |
261 | |
262 | /* |
263 | * Mapping kernel memory is permitted if the region in |
264 | * question is covered by a single memblock with the |
265 | * NOMAP attribute set: this enables the use of ACPI |
266 | * table overrides passed via initramfs. |
267 | * This particular use case only requires read access. |
268 | */ |
269 | fallthrough; |
270 | |
271 | case EFI_RUNTIME_SERVICES_CODE: |
272 | /* |
273 | * This would be unusual, but not problematic per se, |
274 | * as long as we take care not to create a writable |
275 | * mapping for executable code. |
276 | */ |
277 | prot = PAGE_KERNEL_RO; |
278 | break; |
279 | |
280 | case EFI_ACPI_RECLAIM_MEMORY: |
281 | /* |
282 | * ACPI reclaim memory is used to pass firmware tables |
283 | * and other data that is intended for consumption by |
284 | * the OS only, which may decide it wants to reclaim |
285 | * that memory and use it for something else. We never |
286 | * do that, but we usually add it to the linear map |
287 | * anyway, in which case we should use the existing |
288 | * mapping. |
289 | */ |
290 | if (memblock_is_map_memory(addr: phys)) |
291 | return (void __iomem *)__va(phys); |
292 | fallthrough; |
293 | |
294 | default: |
295 | if (region->attribute & EFI_MEMORY_WB) |
296 | prot = PAGE_KERNEL; |
297 | else if ((region->attribute & EFI_MEMORY_WC) || |
298 | (region->attribute & EFI_MEMORY_WT)) |
299 | prot = pgprot_writecombine(PAGE_KERNEL); |
300 | } |
301 | } |
302 | |
303 | return ioremap_prot(offset: phys, size, pgprot_val(prot)); |
304 | } |
305 | |
306 | #ifdef CONFIG_PCI |
307 | |
308 | /* |
309 | * These interfaces are defined just to enable building ACPI core. |
310 | * TODO: Update it with actual implementation when external interrupt |
311 | * controller support is added in RISC-V ACPI. |
312 | */ |
313 | int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn, |
314 | int reg, int len, u32 *val) |
315 | { |
316 | return PCIBIOS_DEVICE_NOT_FOUND; |
317 | } |
318 | |
319 | int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn, |
320 | int reg, int len, u32 val) |
321 | { |
322 | return PCIBIOS_DEVICE_NOT_FOUND; |
323 | } |
324 | |
325 | int acpi_pci_bus_find_domain_nr(struct pci_bus *bus) |
326 | { |
327 | return -1; |
328 | } |
329 | |
330 | struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) |
331 | { |
332 | return NULL; |
333 | } |
334 | #endif /* CONFIG_PCI */ |
335 | |