[U-Boot] [PATCH 1/3] x86: acpi: Move APIs unrelated to ACPI tables generation to a separate library

acpi_find_fadt(), acpi_find_wakeup_vector() and enter_acpi_mode() are something unrelated to ACPI tables generation. Move these to a separate library.
This also fixes several style issues reported by checkpatch in the original codes.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
arch/x86/cpu/cpu.c | 1 + arch/x86/include/asm/acpi.h | 41 +++++++++++++++ arch/x86/include/asm/acpi_table.h | 28 ---------- arch/x86/lib/Makefile | 1 + arch/x86/lib/acpi.c | 108 ++++++++++++++++++++++++++++++++++++++ arch/x86/lib/acpi_s3.c | 1 + arch/x86/lib/acpi_table.c | 101 +---------------------------------- 7 files changed, 153 insertions(+), 128 deletions(-) create mode 100644 arch/x86/include/asm/acpi.h create mode 100644 arch/x86/lib/acpi.c
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 6aefa12..f7601b3 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -24,6 +24,7 @@ #include <errno.h> #include <malloc.h> #include <syscon.h> +#include <asm/acpi.h> #include <asm/acpi_s3.h> #include <asm/acpi_table.h> #include <asm/control_regs.h> diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h new file mode 100644 index 0000000..4475d04 --- /dev/null +++ b/arch/x86/include/asm/acpi.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2018, Bin Meng bmeng.cn@gmail.com + */ + +#ifndef __ASM_ACPI_H__ +#define __ASM_ACPI_H__ + +struct acpi_fadt; + +/** + * acpi_find_fadt() - find ACPI FADT table in the system memory + * + * This routine parses the ACPI table to locate the ACPI FADT table. + * + * @return: a pointer to the ACPI FADT table in the system memory + */ +struct acpi_fadt *acpi_find_fadt(void); + +/** + * acpi_find_wakeup_vector() - find OS installed wake up vector address + * + * This routine parses the ACPI table to locate the wake up vector installed + * by the OS previously. + * + * @fadt: a pointer to the ACPI FADT table in the system memory + * @return: wake up vector address installed by the OS + */ +void *acpi_find_wakeup_vector(struct acpi_fadt *fadt); + +/** + * enter_acpi_mode() - enter into ACPI mode + * + * This programs the ACPI-defined PM1_CNT register to enable SCI interrupt + * so that the whole system swiches to ACPI mode. + * + * @pm1_cnt: PM1_CNT register I/O address + */ +void enter_acpi_mode(int pm1_cnt); + +#endif /* __ASM_ACPI_H__ */ diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h index 239bcdc..dd516df 100644 --- a/arch/x86/include/asm/acpi_table.h +++ b/arch/x86/include/asm/acpi_table.h @@ -317,15 +317,6 @@ int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base, u16 seg_nr, u8 start, u8 end); u32 acpi_fill_mcfg(u32 current); void acpi_create_gnvs(struct acpi_global_nvs *gnvs); -/** - * enter_acpi_mode() - enter into ACPI mode - * - * This programs the ACPI-defined PM1_CNT register to enable SCI interrupt - * so that the whole system swiches to ACPI mode. - * - * @pm1_cnt: PM1_CNT register I/O address - */ -void enter_acpi_mode(int pm1_cnt); ulong write_acpi_tables(ulong start);
/** @@ -336,22 +327,3 @@ ulong write_acpi_tables(ulong start); * @return: ACPI RSDP table address */ ulong acpi_get_rsdp_addr(void); - -/** - * acpi_find_fadt() - find ACPI FADT table in the sytem memory - * - * This routine parses the ACPI table to locate the ACPI FADT table. - * - * @return: a pointer to the ACPI FADT table in the system memory - */ -struct acpi_fadt *acpi_find_fadt(void); - -/** - * acpi_find_wakeup_vector() - find OS installed wake up vector address - * - * This routine parses the ACPI table to locate the wake up vector installed - * by the OS previously. - * - * @return: wake up vector address installed by the OS - */ -void *acpi_find_wakeup_vector(struct acpi_fadt *); diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index ba07ac7..1e8efcc 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_INTEL_MID) += scu.o obj-y += sections.o obj-y += sfi.o obj-y += string.o +obj-y += acpi.o obj-$(CONFIG_HAVE_ACPI_RESUME) += acpi_s3.o ifndef CONFIG_QEMU obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi_table.o diff --git a/arch/x86/lib/acpi.c b/arch/x86/lib/acpi.c new file mode 100644 index 0000000..cba9c24 --- /dev/null +++ b/arch/x86/lib/acpi.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018, Bin Meng bmeng.cn@gmail.com + */ + +#include <common.h> +#include <asm/acpi_table.h> +#include <asm/io.h> +#include <asm/tables.h> + +static struct acpi_rsdp *acpi_valid_rsdp(struct acpi_rsdp *rsdp) +{ + if (strncmp((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0) + return NULL; + + debug("Looking on %p for valid checksum\n", rsdp); + + if (table_compute_checksum((void *)rsdp, 20) != 0) + return NULL; + debug("acpi rsdp checksum 1 passed\n"); + + if ((rsdp->revision > 1) && + (table_compute_checksum((void *)rsdp, rsdp->length) != 0)) + return NULL; + debug("acpi rsdp checksum 2 passed\n"); + + return rsdp; +} + +struct acpi_fadt *acpi_find_fadt(void) +{ + char *p, *end; + struct acpi_rsdp *rsdp = NULL; + struct acpi_rsdt *rsdt; + struct acpi_fadt *fadt = NULL; + int i; + + /* Find RSDP */ + for (p = (char *)ROM_TABLE_ADDR; p < (char *)ROM_TABLE_END; p += 16) { + rsdp = acpi_valid_rsdp((struct acpi_rsdp *)p); + if (rsdp) + break; + } + + if (!rsdp) + return NULL; + + debug("RSDP found at %p\n", rsdp); + rsdt = (struct acpi_rsdt *)(uintptr_t)rsdp->rsdt_address; + + end = (char *)rsdt + rsdt->header.length; + debug("RSDT found at %p ends at %p\n", rsdt, end); + + for (i = 0; ((char *)&rsdt->entry[i]) < end; i++) { + fadt = (struct acpi_fadt *)(uintptr_t)rsdt->entry[i]; + if (strncmp((char *)fadt, "FACP", 4) == 0) + break; + fadt = NULL; + } + + if (!fadt) + return NULL; + + debug("FADT found at %p\n", fadt); + return fadt; +} + +void *acpi_find_wakeup_vector(struct acpi_fadt *fadt) +{ + struct acpi_facs *facs; + void *wake_vec; + + debug("Trying to find the wakeup vector...\n"); + + facs = (struct acpi_facs *)(uintptr_t)fadt->firmware_ctrl; + + if (!facs) { + debug("No FACS found, wake up from S3 not possible.\n"); + return NULL; + } + + debug("FACS found at %p\n", facs); + wake_vec = (void *)(uintptr_t)facs->firmware_waking_vector; + debug("OS waking vector is %p\n", wake_vec); + + return wake_vec; +} + +void enter_acpi_mode(int pm1_cnt) +{ + u16 val = inw(pm1_cnt); + + /* + * PM1_CNT register bit0 selects the power management event to be + * either an SCI or SMI interrupt. When this bit is set, then power + * management events will generate an SCI interrupt. When this bit + * is reset power management events will generate an SMI interrupt. + * + * Per ACPI spec, it is the responsibility of the hardware to set + * or reset this bit. OSPM always preserves this bit position. + * + * U-Boot does not support SMI. And we don't have plan to support + * anything running in SMM within U-Boot. To create a legacy-free + * system, and expose ourselves to OSPM as working under ACPI mode + * already, turn this bit on. + */ + outw(val | PM1_CNT_SCI_EN, pm1_cnt); +} diff --git a/arch/x86/lib/acpi_s3.c b/arch/x86/lib/acpi_s3.c index 514b92f..0391718 100644 --- a/arch/x86/lib/acpi_s3.c +++ b/arch/x86/lib/acpi_s3.c @@ -4,6 +4,7 @@ */
#include <common.h> +#include <asm/acpi.h> #include <asm/acpi_s3.h> #include <asm/acpi_table.h> #include <asm/post.h> diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index 7c4321b..e26c54d 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -12,8 +12,8 @@ #include <dm/uclass-internal.h> #include <version.h> #include <asm/acpi/global_nvs.h> +#include <asm/acpi.h> #include <asm/acpi_table.h> -#include <asm/io.h> #include <asm/ioapic.h> #include <asm/lapic.h> #include <asm/mpspec.h> @@ -337,27 +337,6 @@ static void acpi_create_mcfg(struct acpi_mcfg *mcfg) header->checksum = table_compute_checksum((void *)mcfg, header->length); }
-void enter_acpi_mode(int pm1_cnt) -{ - u16 val = inw(pm1_cnt); - - /* - * PM1_CNT register bit0 selects the power management event to be - * either an SCI or SMI interrupt. When this bit is set, then power - * management events will generate an SCI interrupt. When this bit - * is reset power management events will generate an SMI interrupt. - * - * Per ACPI spec, it is the responsibility of the hardware to set - * or reset this bit. OSPM always preserves this bit position. - * - * U-Boot does not support SMI. And we don't have plan to support - * anything running in SMM within U-Boot. To create a legacy-free - * system, and expose ourselves to OSPM as working under ACPI mode - * already, turn this bit on. - */ - outw(val | PM1_CNT_SCI_EN, pm1_cnt); -} - /* * QEMU's version of write_acpi_tables is defined in drivers/misc/qfw.c */ @@ -482,81 +461,3 @@ ulong acpi_get_rsdp_addr(void) { return acpi_rsdp_addr; } - -static struct acpi_rsdp *acpi_valid_rsdp(struct acpi_rsdp *rsdp) -{ - if (strncmp((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0) - return NULL; - - debug("Looking on %p for valid checksum\n", rsdp); - - if (table_compute_checksum((void *)rsdp, 20) != 0) - return NULL; - debug("acpi rsdp checksum 1 passed\n"); - - if ((rsdp->revision > 1) && - (table_compute_checksum((void *)rsdp, rsdp->length) != 0)) - return NULL; - debug("acpi rsdp checksum 2 passed\n"); - - return rsdp; -} - -struct acpi_fadt *acpi_find_fadt(void) -{ - char *p, *end; - struct acpi_rsdp *rsdp = NULL; - struct acpi_rsdt *rsdt; - struct acpi_fadt *fadt = NULL; - int i; - - /* Find RSDP */ - for (p = (char *)ROM_TABLE_ADDR; p < (char *)ROM_TABLE_END; p += 16) { - rsdp = acpi_valid_rsdp((struct acpi_rsdp *)p); - if (rsdp) - break; - } - - if (rsdp == NULL) - return NULL; - - debug("RSDP found at %p\n", rsdp); - rsdt = (struct acpi_rsdt *)rsdp->rsdt_address; - - end = (char *)rsdt + rsdt->header.length; - debug("RSDT found at %p ends at %p\n", rsdt, end); - - for (i = 0; ((char *)&rsdt->entry[i]) < end; i++) { - fadt = (struct acpi_fadt *)rsdt->entry[i]; - if (strncmp((char *)fadt, "FACP", 4) == 0) - break; - fadt = NULL; - } - - if (fadt == NULL) - return NULL; - - debug("FADT found at %p\n", fadt); - return fadt; -} - -void *acpi_find_wakeup_vector(struct acpi_fadt *fadt) -{ - struct acpi_facs *facs; - void *wake_vec; - - debug("Trying to find the wakeup vector...\n"); - - facs = (struct acpi_facs *)fadt->firmware_ctrl; - - if (facs == NULL) { - debug("No FACS found, wake up from S3 not possible.\n"); - return NULL; - } - - debug("FACS found at %p\n", facs); - wake_vec = (void *)facs->firmware_waking_vector; - debug("OS waking vector is %p\n", wake_vec); - - return wake_vec; -}

write_acpi_tables() currently touches ACPI hardware to switch to ACPI mode at the end. Move such operation out of this function, so that it only does what the function name tells us.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
arch/x86/cpu/cpu.c | 20 +++++++++++++++++--- arch/x86/lib/acpi_table.c | 11 ----------- 2 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index f7601b3..3a45677 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -206,16 +206,30 @@ __weak void board_final_cleanup(void) int last_stage_init(void) { board_final_cleanup(); + struct acpi_fadt __maybe_unused *fadt;
-#if CONFIG_HAVE_ACPI_RESUME - struct acpi_fadt *fadt = acpi_find_fadt(); +#ifdef CONFIG_HAVE_ACPI_RESUME + fadt = acpi_find_fadt();
- if (fadt != NULL && gd->arch.prev_sleep_state == ACPI_S3) + if (fadt && gd->arch.prev_sleep_state == ACPI_S3) acpi_resume(fadt); #endif
write_tables();
+#ifdef CONFIG_GENERATE_ACPI_TABLE + fadt = acpi_find_fadt(); + + /* Don't touch ACPI hardware on HW reduced platforms */ + if (fadt && !(fadt->flags & ACPI_FADT_HW_REDUCED_ACPI)) { + /* + * Other than waiting for OSPM to request us to switch to ACPI + * mode, do it by ourselves, since SMI will not be triggered. + */ + enter_acpi_mode(fadt->pm1a_cnt_blk); + } +#endif + return 0; } #endif diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index e26c54d..e48c9b9 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -12,7 +12,6 @@ #include <dm/uclass-internal.h> #include <version.h> #include <asm/acpi/global_nvs.h> -#include <asm/acpi.h> #include <asm/acpi_table.h> #include <asm/ioapic.h> #include <asm/lapic.h> @@ -444,16 +443,6 @@ ulong write_acpi_tables(ulong start) acpi_rsdp_addr = (unsigned long)rsdp; debug("ACPI: done\n");
- /* Don't touch ACPI hardware on HW reduced platforms */ - if (fadt->flags & ACPI_FADT_HW_REDUCED_ACPI) - return current; - - /* - * Other than waiting for OSPM to request us to switch to ACPI mode, - * do it by ourselves, since SMI will not be triggered. - */ - enter_acpi_mode(fadt->pm1a_cnt_blk); - return current; }

On Thu, Jun 28, 2018 at 6:38 AM, Bin Meng bmeng.cn@gmail.com wrote:
write_acpi_tables() currently touches ACPI hardware to switch to ACPI mode at the end. Move such operation out of this function, so that it only does what the function name tells us.
{ board_final_cleanup();
struct acpi_fadt __maybe_unused *fadt;
I guess this would be first line in the function. No? And personally I don't like to see __maybe_unused near to local variables (see also below).
+#ifdef CONFIG_HAVE_ACPI_RESUME
fadt = acpi_find_fadt();
if (fadt != NULL && gd->arch.prev_sleep_state == ACPI_S3)
if (fadt && gd->arch.prev_sleep_state == ACPI_S3) acpi_resume(fadt);
#endif
write_tables();
+#ifdef CONFIG_GENERATE_ACPI_TABLE
fadt = acpi_find_fadt();
This sounds superfluous, we create tables ourselves, why do we need traverse again to find them?
Looks like you would do something such as
struct acpi_fadt *fadt /* maybe save to do as well: = acpi_find_fadt() */;
...
fadt = write_tables(); //or any other way to get the pointer without traversing ...
/* Don't touch ACPI hardware on HW reduced platforms */
if (fadt && !(fadt->flags & ACPI_FADT_HW_REDUCED_ACPI)) {
/*
* Other than waiting for OSPM to request us to switch to ACPI
* mode, do it by ourselves, since SMI will not be triggered.
*/
enter_acpi_mode(fadt->pm1a_cnt_blk);
}

Hi Andy,
On Thu, Jun 28, 2018 at 3:57 PM, Andy Shevchenko andy.shevchenko@gmail.com wrote:
On Thu, Jun 28, 2018 at 6:38 AM, Bin Meng bmeng.cn@gmail.com wrote:
write_acpi_tables() currently touches ACPI hardware to switch to ACPI mode at the end. Move such operation out of this function, so that it only does what the function name tells us.
{ board_final_cleanup();
struct acpi_fadt __maybe_unused *fadt;
I guess this would be first line in the function. No?
Yes, it should be the first line. Will fix.
And personally I don't like to see __maybe_unused near to local variables (see also below).
Without __maybe_unused
+#ifdef CONFIG_HAVE_ACPI_RESUME
fadt = acpi_find_fadt();
if (fadt != NULL && gd->arch.prev_sleep_state == ACPI_S3)
if (fadt && gd->arch.prev_sleep_state == ACPI_S3) acpi_resume(fadt);
#endif
write_tables();
+#ifdef CONFIG_GENERATE_ACPI_TABLE
fadt = acpi_find_fadt();
This sounds superfluous, we create tables ourselves, why do we need traverse again to find them?
Looks like you would do something such as
struct acpi_fadt *fadt /* maybe save to do as well: = acpi_find_fadt() */;
Do the assignment here only works for S3 path.
...
fadt = write_tables(); //or any other way to get the pointer without traversing
Let write_tables() return FADT address is odd. write_tables() is generic API for writing various configuration tables.
...
/* Don't touch ACPI hardware on HW reduced platforms */
if (fadt && !(fadt->flags & ACPI_FADT_HW_REDUCED_ACPI)) {
/*
* Other than waiting for OSPM to request us to switch to ACPI
* mode, do it by ourselves, since SMI will not be triggered.
*/
enter_acpi_mode(fadt->pm1a_cnt_blk);
}
Regards, Bin

The wrapper #ifndef is currently missing in acpi_table.h. Add it to prevent it from being included multiple times.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
arch/x86/include/asm/acpi_table.h | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h index dd516df..95fae03 100644 --- a/arch/x86/include/asm/acpi_table.h +++ b/arch/x86/include/asm/acpi_table.h @@ -6,6 +6,9 @@ * Copyright (C) 2016, Bin Meng bmeng.cn@gmail.com */
+#ifndef __ASM_ACPI_TABLE_H__ +#define __ASM_ACPI_TABLE_H__ + #define RSDP_SIG "RSD PTR " /* RSDP pointer signature */ #define OEM_ID "U-BOOT" /* U-Boot */ #define OEM_TABLE_ID "U-BOOTBL" /* U-Boot Table */ @@ -327,3 +330,5 @@ ulong write_acpi_tables(ulong start); * @return: ACPI RSDP table address */ ulong acpi_get_rsdp_addr(void); + +#endif /* __ASM_ACPI_TABLE_H__ */
participants (2)
-
Andy Shevchenko
-
Bin Meng