diff mbox series

[v3,08/57] x86: acpi: Support external GNVS tables

Message ID 20200906154340.v3.8.Ic4e4767888256deed0503035fd4cc5c4d1060a62@changeid
State Superseded
Delegated to: Bin Meng
Headers show
Series dm: Add programatic generation of ACPI tables (part D) | expand

Commit Message

Simon Glass Sept. 6, 2020, 9:43 p.m. UTC
At present U-Boot puts a magic number in the ASL for the GNVS table and
searches for it later.

Add a Kconfig option to use a different approach, where the ASL files
declare the table as an external symbol. U-Boot can then put it wherever
it likes, without any magic numbers or searching.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 arch/x86/Kconfig                       |  7 +++++
 arch/x86/cpu/apollolake/Kconfig        |  1 +
 arch/x86/include/asm/acpi/global_nvs.h |  3 ++
 arch/x86/lib/acpi_table.c              | 42 ++++++++++++++------------
 4 files changed, 33 insertions(+), 20 deletions(-)
diff mbox series

Patch

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 256a1100bd3..680f26f1b8e 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -788,6 +788,13 @@  config GENERATE_ACPI_TABLE
 	  by the operating system. It defines platform-independent interfaces
 	  for configuration and power management monitoring.
 
+config ACPI_GNVS_EXTERNAL
+	bool
+	help
+	  Put the GNVS (Global Non-Volatile Sleeping) table separate from the
+	  DSDT and add a pointer to the table from the DSDT. This allows
+	  U-Boot to better control the address of the GNVS.
+
 endmenu
 
 config HAVE_ACPI_RESUME
diff --git a/arch/x86/cpu/apollolake/Kconfig b/arch/x86/cpu/apollolake/Kconfig
index 37d6289ee41..16ac2b3f504 100644
--- a/arch/x86/cpu/apollolake/Kconfig
+++ b/arch/x86/cpu/apollolake/Kconfig
@@ -17,6 +17,7 @@  config INTEL_APOLLOLAKE
 	select PCH_SUPPORT
 	select P2SB
 	select SMP_AP_WORK
+	select ACPI_GNVS_EXTERNAL
 	imply ENABLE_MRC_CACHE
 	imply AHCI_PCI
 	imply SCSI
diff --git a/arch/x86/include/asm/acpi/global_nvs.h b/arch/x86/include/asm/acpi/global_nvs.h
index d56d35ca533..a552cf6374f 100644
--- a/arch/x86/include/asm/acpi/global_nvs.h
+++ b/arch/x86/include/asm/acpi/global_nvs.h
@@ -11,6 +11,9 @@ 
  * ACPI_GNVS_SIZE. They are to be used in platform's global_nvs.asl file
  * to declare the GNVS OperationRegion, as well as write_acpi_tables()
  * for the GNVS address runtime fix up.
+ *
+ * If using CONFIG_ACPI_GNVS_EXTERNAL, we don't need to locate the GNVS in
+ * DSDT, since it is created by code, so ACPI_GNVS_ADDR is unused.
  */
 #define ACPI_GNVS_ADDR	0xdeadbeef
 #define ACPI_GNVS_SIZE	0x100
diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c
index 3a93fedfc3e..942b2334eab 100644
--- a/arch/x86/lib/acpi_table.c
+++ b/arch/x86/lib/acpi_table.c
@@ -428,17 +428,30 @@  ulong write_acpi_tables(ulong start_addr)
 	       dsdt->length - sizeof(struct acpi_table_header));
 
 	acpi_inc_align(ctx, dsdt->length - sizeof(struct acpi_table_header));
+	dsdt->length = ctx->current - (void *)dsdt;
 
-	/* Pack GNVS into the ACPI table area */
-	for (i = 0; i < dsdt->length; i++) {
-		u32 *gnvs = (u32 *)((u32)dsdt + i);
-		if (*gnvs == ACPI_GNVS_ADDR) {
-			ulong addr = (ulong)map_to_sysmem(ctx->current);
-
-			debug("Fix up global NVS in DSDT to %#08lx\n", addr);
-			*gnvs = addr;
-			break;
+	if (!IS_ENABLED(CONFIG_ACPI_GNVS_EXTERNAL)) {
+		/* Pack GNVS into the ACPI table area */
+		for (i = 0; i < dsdt->length; i++) {
+			u32 *gnvs = (u32 *)((u32)dsdt + i);
+
+			if (*gnvs == ACPI_GNVS_ADDR) {
+				*gnvs = map_to_sysmem(ctx->current);
+				debug("Fix up global NVS in DSDT to %#08x\n",
+				      *gnvs);
+				break;
+			}
 		}
+
+		/*
+		 * Fill in platform-specific global NVS variables. If this fails
+		 * we cannot return the error but this should only happen while
+		 * debugging.
+		 */
+		addr = acpi_create_gnvs(ctx->current);
+		if (IS_ERR_VALUE(addr))
+			printf("Error: Gailed to create GNVS\n");
+		acpi_inc_align(ctx, sizeof(struct acpi_global_nvs));
 	}
 
 	/*
@@ -446,20 +459,9 @@  ulong write_acpi_tables(ulong start_addr)
 	 * the GNVS address. Set the checksum to zero since it is part of the
 	 * region being checksummed.
 	 */
-	dsdt->length = ctx->current - (void *)dsdt;
 	dsdt->checksum = 0;
 	dsdt->checksum = table_compute_checksum((void *)dsdt, dsdt->length);
 
-	/*
-	 * Fill in platform-specific global NVS variables. If this fails we
-	 * cannot return the error but this should only happen while debugging.
-	 */
-	addr = acpi_create_gnvs(ctx->current);
-	if (IS_ERR_VALUE(addr))
-		printf("Error: Failed to create GNVS\n");
-
-	acpi_inc_align(ctx, sizeof(struct acpi_global_nvs));
-
 	debug("ACPI:    * FADT\n");
 	fadt = ctx->current;
 	acpi_inc_align(ctx, sizeof(struct acpi_fadt));