Skip to content

Commit 724f4c0

Browse files
vlsunilpalmer-dabbelt
authored andcommitted
RISC-V: Add ACPI initialization in setup_arch()
Initialize the ACPI core for RISC-V during boot. ACPI tables and interpreter are initialized based on the information passed from the firmware and the value of the kernel parameter 'acpi'. With ACPI support added for RISC-V, the kernel parameter 'acpi' is also supported on RISC-V. Hence, update the documentation. Signed-off-by: Sunil V L <[email protected]> Acked-by: Rafael J. Wysocki <[email protected]> Reviewed-by: Andrew Jones <[email protected]> Acked-by: Conor Dooley <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 8b7809e commit 724f4c0

File tree

3 files changed

+135
-4
lines changed

3 files changed

+135
-4
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
acpi= [HW,ACPI,X86,ARM64]
1+
acpi= [HW,ACPI,X86,ARM64,RISCV64]
22
Advanced Configuration and Power Interface
33
Format: { force | on | off | strict | noirq | rsdt |
44
copy_dsdt }
55
force -- enable ACPI if default was off
6-
on -- enable ACPI but allow fallback to DT [arm64]
6+
on -- enable ACPI but allow fallback to DT [arm64,riscv64]
77
off -- disable ACPI if default was on
88
noirq -- do not use ACPI for IRQ routing
99
strict -- Be less tolerant of platforms that are not
1010
strictly ACPI specification compliant.
1111
rsdt -- prefer RSDT over (default) XSDT
1212
copy_dsdt -- copy DSDT to memory
13-
For ARM64, ONLY "acpi=off", "acpi=on" or "acpi=force"
14-
are available
13+
For ARM64 and RISCV64, ONLY "acpi=off", "acpi=on" or
14+
"acpi=force" are available
1515

1616
See also Documentation/power/runtime_pm.rst, pci=noacpi
1717

arch/riscv/kernel/acpi.c

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/acpi.h>
1717
#include <linux/io.h>
1818
#include <linux/pci.h>
19+
#include <linux/efi.h>
1920

2021
int acpi_noirq = 1; /* skip ACPI IRQ initialization */
2122
int acpi_disabled = 1;
@@ -24,6 +25,131 @@ EXPORT_SYMBOL(acpi_disabled);
2425
int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */
2526
EXPORT_SYMBOL(acpi_pci_disabled);
2627

28+
static bool param_acpi_off __initdata;
29+
static bool param_acpi_on __initdata;
30+
static bool param_acpi_force __initdata;
31+
32+
static int __init parse_acpi(char *arg)
33+
{
34+
if (!arg)
35+
return -EINVAL;
36+
37+
/* "acpi=off" disables both ACPI table parsing and interpreter */
38+
if (strcmp(arg, "off") == 0)
39+
param_acpi_off = true;
40+
else if (strcmp(arg, "on") == 0) /* prefer ACPI over DT */
41+
param_acpi_on = true;
42+
else if (strcmp(arg, "force") == 0) /* force ACPI to be enabled */
43+
param_acpi_force = true;
44+
else
45+
return -EINVAL; /* Core will print when we return error */
46+
47+
return 0;
48+
}
49+
early_param("acpi", parse_acpi);
50+
51+
/*
52+
* acpi_fadt_sanity_check() - Check FADT presence and carry out sanity
53+
* checks on it
54+
*
55+
* Return 0 on success, <0 on failure
56+
*/
57+
static int __init acpi_fadt_sanity_check(void)
58+
{
59+
struct acpi_table_header *table;
60+
struct acpi_table_fadt *fadt;
61+
acpi_status status;
62+
int ret = 0;
63+
64+
/*
65+
* FADT is required on riscv; retrieve it to check its presence
66+
* and carry out revision and ACPI HW reduced compliancy tests
67+
*/
68+
status = acpi_get_table(ACPI_SIG_FADT, 0, &table);
69+
if (ACPI_FAILURE(status)) {
70+
const char *msg = acpi_format_exception(status);
71+
72+
pr_err("Failed to get FADT table, %s\n", msg);
73+
return -ENODEV;
74+
}
75+
76+
fadt = (struct acpi_table_fadt *)table;
77+
78+
/*
79+
* The revision in the table header is the FADT's Major revision. The
80+
* FADT also has a minor revision, which is stored in the FADT itself.
81+
*
82+
* TODO: Currently, we check for 6.5 as the minimum version to check
83+
* for HW_REDUCED flag. However, once RISC-V updates are released in
84+
* the ACPI spec, we need to update this check for exact minor revision
85+
*/
86+
if (table->revision < 6 || (table->revision == 6 && fadt->minor_revision < 5))
87+
pr_err(FW_BUG "Unsupported FADT revision %d.%d, should be 6.5+\n",
88+
table->revision, fadt->minor_revision);
89+
90+
if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) {
91+
pr_err("FADT not ACPI hardware reduced compliant\n");
92+
ret = -EINVAL;
93+
}
94+
95+
/*
96+
* acpi_get_table() creates FADT table mapping that
97+
* should be released after parsing and before resuming boot
98+
*/
99+
acpi_put_table(table);
100+
return ret;
101+
}
102+
103+
/*
104+
* acpi_boot_table_init() called from setup_arch(), always.
105+
* 1. find RSDP and get its address, and then find XSDT
106+
* 2. extract all tables and checksums them all
107+
* 3. check ACPI FADT HW reduced flag
108+
*
109+
* We can parse ACPI boot-time tables such as MADT after
110+
* this function is called.
111+
*
112+
* On return ACPI is enabled if either:
113+
*
114+
* - ACPI tables are initialized and sanity checks passed
115+
* - acpi=force was passed in the command line and ACPI was not disabled
116+
* explicitly through acpi=off command line parameter
117+
*
118+
* ACPI is disabled on function return otherwise
119+
*/
120+
void __init acpi_boot_table_init(void)
121+
{
122+
/*
123+
* Enable ACPI instead of device tree unless
124+
* - ACPI has been disabled explicitly (acpi=off), or
125+
* - firmware has not populated ACPI ptr in EFI system table
126+
* and ACPI has not been [force] enabled (acpi=on|force)
127+
*/
128+
if (param_acpi_off ||
129+
(!param_acpi_on && !param_acpi_force &&
130+
efi.acpi20 == EFI_INVALID_TABLE_ADDR))
131+
return;
132+
133+
/*
134+
* ACPI is disabled at this point. Enable it in order to parse
135+
* the ACPI tables and carry out sanity checks
136+
*/
137+
enable_acpi();
138+
139+
/*
140+
* If ACPI tables are initialized and FADT sanity checks passed,
141+
* leave ACPI enabled and carry on booting; otherwise disable ACPI
142+
* on initialization error.
143+
* If acpi=force was passed on the command line it forces ACPI
144+
* to be enabled even if its initialization failed.
145+
*/
146+
if (acpi_table_init() || acpi_fadt_sanity_check()) {
147+
pr_err("Failed to init ACPI tables\n");
148+
if (!param_acpi_force)
149+
disable_acpi();
150+
}
151+
}
152+
27153
/*
28154
* __acpi_map_table() will be called before paging_init(), so early_ioremap()
29155
* or early_memremap() should be called here to for ACPI table mapping.

arch/riscv/kernel/setup.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* Nick Kossifidis <[email protected]>
99
*/
1010

11+
#include <linux/acpi.h>
1112
#include <linux/cpu.h>
1213
#include <linux/init.h>
1314
#include <linux/mm.h>
@@ -276,6 +277,10 @@ void __init setup_arch(char **cmdline_p)
276277

277278
efi_init();
278279
paging_init();
280+
281+
/* Parse the ACPI tables for possible boot-time configuration */
282+
acpi_boot_table_init();
283+
279284
#if IS_ENABLED(CONFIG_BUILTIN_DTB)
280285
unflatten_and_copy_device_tree();
281286
#else

0 commit comments

Comments
 (0)