[PATCH v3 24/57] x86: acpi: Support generation of the HPET table

Simon Glass
2020-09-06T21:43:32Z

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>
---

(no changes since v1)

Changes in v1:
- Put this code in an x86-specific place and update commit message

arch/x86/include/asm/acpi_table.h | 10 ++++++
arch/x86/lib/acpi_table.c | 59 +++++++++++++++++++++++++++++++
include/acpi/acpi_table.h | 31 +++++++++++-----
3 files changed, 91 insertions(+), 9 deletions(-)

diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h
index 733085c1785..7047ee6c772 100644
--- a/arch/x86/include/asm/acpi_table.h
+++ b/arch/x86/include/asm/acpi_table.h
@@ -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
*
diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c
index 942b2334eab..e1900ffe42f 100644
--- a/arch/x86/lib/acpi_table.c
+++ b/arch/x86/lib/acpi_table.c
@@ -516,3 +516,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;
+}
diff --git a/include/acpi/acpi_table.h b/include/acpi/acpi_table.h
index fe9b29f3f82..f8140446a59 100644
--- a/include/acpi/acpi_table.h
+++ b/include/acpi/acpi_table.h
@@ -20,6 +20,9 @@
#define OEM_TABLE_ID "U-BOOTBL" /* U-Boot Table */
#define ASLC_ID "INTL" /* Intel ASL Compiler */

+/* TODO(sjg at 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;
--
2.28.0.526.ge36021eeef-goog