]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
x86: acpi: Support generation of the HPET table
authorSimon Glass <sjg@chromium.org>
Tue, 22 Sep 2020 18:45:09 +0000 (12:45 -0600)
committerBin Meng <bmeng.cn@gmail.com>
Fri, 25 Sep 2020 03:27:17 +0000 (11:27 +0800)
Add an implementation of the HPET (High Precision Event Timer) ACPI
table. Since this is x86-specific, put it in an x86-specific file

Signed-off-by: Simon Glass <sjg@chromium.org>
arch/x86/include/asm/acpi_table.h
arch/x86/lib/acpi_table.c
include/acpi/acpi_table.h

index 733085c178519bc2da090755aa6875c7a87cf1bc..7047ee6c7724ce850767461ecb96ca8c48167683 100644 (file)
@@ -36,6 +36,16 @@ int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base,
 u32 acpi_fill_mcfg(u32 current);
 u32 acpi_fill_csrt(u32 current);
 
+/**
+ * acpi_write_hpet() - Write out a HPET table
+ *
+ * Write out the table for High-Precision Event Timers
+ *
+ * @ctx: Current ACPI context
+ * @return 0 if OK, -ve on error
+ */
+int acpi_write_hpet(struct acpi_ctx *ctx);
+
 /**
  * acpi_create_gnvs() - Create a GNVS (Global Non Volatile Storage) table
  *
index 36ef3e5f0b7f2694bafeaa1cf17f2c6dae766343..0080c96cfe7768b2de2385d5c9a53c644b7bdddf 100644 (file)
@@ -529,3 +529,62 @@ ulong acpi_get_rsdp_addr(void)
 {
        return acpi_rsdp_addr;
 }
+
+/**
+ * acpi_write_hpet() - Write out a HPET table
+ *
+ * Write out the table for High-Precision Event Timers
+ *
+ * @hpet: Place to put HPET table
+ */
+static int acpi_create_hpet(struct acpi_hpet *hpet)
+{
+       struct acpi_table_header *header = &hpet->header;
+       struct acpi_gen_regaddr *addr = &hpet->addr;
+
+       /*
+        * See IA-PC HPET (High Precision Event Timers) Specification v1.0a
+        * https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/software-developers-hpet-spec-1-0a.pdf
+        */
+       memset((void *)hpet, '\0', sizeof(struct acpi_hpet));
+
+       /* Fill out header fields. */
+       acpi_fill_header(header, "HPET");
+
+       header->aslc_revision = ASL_REVISION;
+       header->length = sizeof(struct acpi_hpet);
+       header->revision = acpi_get_table_revision(ACPITAB_HPET);
+
+       /* Fill out HPET address */
+       addr->space_id = 0;  /* Memory */
+       addr->bit_width = 64;
+       addr->bit_offset = 0;
+       addr->addrl = CONFIG_HPET_ADDRESS & 0xffffffff;
+       addr->addrh = ((unsigned long long)CONFIG_HPET_ADDRESS) >> 32;
+
+       hpet->id = *(u32 *)CONFIG_HPET_ADDRESS;
+       hpet->number = 0;
+       hpet->min_tick = 0; /* HPET_MIN_TICKS */
+
+       header->checksum = table_compute_checksum(hpet,
+                                                 sizeof(struct acpi_hpet));
+
+       return 0;
+}
+
+int acpi_write_hpet(struct acpi_ctx *ctx)
+{
+       struct acpi_hpet *hpet;
+       int ret;
+
+       log_debug("ACPI:    * HPET\n");
+
+       hpet = ctx->current;
+       acpi_inc_align(ctx, sizeof(struct acpi_hpet));
+       acpi_create_hpet(hpet);
+       ret = acpi_add_table(ctx, hpet);
+       if (ret)
+               return log_msg_ret("add", ret);
+
+       return 0;
+}
index fe9b29f3f82d5d22bb34e09d580b26b7dd559f91..f8140446a599c4929882c2bae036c45fe7a6a2b5 100644 (file)
@@ -20,6 +20,9 @@
 #define OEM_TABLE_ID           "U-BOOTBL"      /* U-Boot Table */
 #define ASLC_ID                        "INTL"          /* Intel ASL Compiler */
 
+/* TODO(sjg@chromium.org): Figure out how to get compiler revision */
+#define ASL_REVISION   0
+
 #define ACPI_RSDP_REV_ACPI_1_0 0
 #define ACPI_RSDP_REV_ACPI_2_0 2
 
@@ -56,6 +59,15 @@ struct __packed acpi_table_header {
        u32 aslc_revision;      /* ASL compiler revision number */
 };
 
+struct acpi_gen_regaddr {
+       u8 space_id;    /* Address space ID */
+       u8 bit_width;   /* Register size in bits */
+       u8 bit_offset;  /* Register bit offset */
+       u8 access_size; /* Access size */
+       u32 addrl;      /* Register address, low 32 bits */
+       u32 addrh;      /* Register address, high 32 bits */
+};
+
 /* A maximum number of 32 ACPI tables ought to be enough for now */
 #define MAX_ACPI_TABLES                32
 
@@ -71,6 +83,16 @@ struct acpi_xsdt {
        u64 entry[MAX_ACPI_TABLES];
 };
 
+/* HPET timers */
+struct __packed acpi_hpet {
+       struct acpi_table_header header;
+       u32 id;
+       struct acpi_gen_regaddr addr;
+       u8 number;
+       u16 min_tick;
+       u8 attributes;
+};
+
 /* FADT Preferred Power Management Profile */
 enum acpi_pm_profile {
        ACPI_PM_UNSPECIFIED = 0,
@@ -138,15 +160,6 @@ enum acpi_address_space_size {
        ACPI_ACCESS_SIZE_QWORD_ACCESS
 };
 
-struct acpi_gen_regaddr {
-       u8 space_id;    /* Address space ID */
-       u8 bit_width;   /* Register size in bits */
-       u8 bit_offset;  /* Register bit offset */
-       u8 access_size; /* Access size */
-       u32 addrl;      /* Register address, low 32 bits */
-       u32 addrh;      /* Register address, high 32 bits */
-};
-
 /* FADT (Fixed ACPI Description Table) */
 struct __packed acpi_fadt {
        struct acpi_table_header header;