x86: acpi: Support external GNVS tables
authorSimon Glass <sjg@chromium.org>
Tue, 22 Sep 2020 18:44:53 +0000 (12:44 -0600)
committerBin Meng <bmeng.cn@gmail.com>
Fri, 25 Sep 2020 03:27:13 +0000 (11:27 +0800)
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>
arch/x86/Kconfig
arch/x86/cpu/apollolake/Kconfig
arch/x86/include/asm/acpi/global_nvs.h
arch/x86/lib/acpi_table.c

index 256a110..680f26f 100644 (file)
@@ -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
index 37d6289..16ac2b3 100644 (file)
@@ -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
index d56d35c..a552cf6 100644 (file)
@@ -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
index c445aa6..36ef3e5 100644 (file)
@@ -430,17 +430,31 @@ ulong write_acpi_tables(ulong start_addr)
               dsdt->length - sizeof(struct acpi_table_header));
 
        acpi_inc(ctx, dsdt->length - sizeof(struct acpi_table_header));
+       dsdt->length = ctx->current - (void *)dsdt;
+       acpi_align(ctx);
 
-       /* 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));
        }
 
        /*
@@ -448,12 +462,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);
 
-       acpi_align(ctx);
-
        /*
         * Fill in platform-specific global NVS variables. If this fails we
         * cannot return the error but this should only happen while debugging.