Add an implementation of the HPET (High Precision Event Timer) ACPI
table.

Signed-off-by: Simon Glass <[email protected]>
---

 arch/x86/lib/acpi_table.c | 54 +++++++++++++++++++++++++++++++++++++++
 include/acpi_table.h      | 32 ++++++++++++++++-------
 2 files changed, 77 insertions(+), 9 deletions(-)

diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c
index 4c35111c48..a810b12cfe 100644
--- a/arch/x86/lib/acpi_table.c
+++ b/arch/x86/lib/acpi_table.c
@@ -32,6 +32,26 @@ extern const unsigned char AmlCode[];
 /* ACPI RSDP address to be used in boot parameters */
 static ulong acpi_rsdp_addr;
 
+int acpi_write_hpet(struct acpi_ctx *ctx, const struct udevice *dev)
+{
+       struct acpi_hpet *hpet;
+       int ret;
+
+       /*
+        * We explicitly add these tables later on:
+        */
+       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;
+}
+
 static void acpi_create_facs(struct acpi_facs *facs)
 {
        memset((void *)facs, 0, sizeof(struct acpi_facs));
@@ -385,6 +405,40 @@ void acpi_create_ssdt(struct acpi_ctx *ctx, struct 
acpi_table_header *ssdt,
        ssdt->checksum = table_compute_checksum((void *)ssdt, ssdt->length);
 }
 
+/* http://www.intel.com/hardwaredesign/hpetspec_1.pdf */
+int acpi_create_hpet(struct acpi_hpet *hpet)
+{
+       struct acpi_table_header *header = &hpet->header;
+       struct acpi_gen_regaddr *addr = &hpet->addr;
+
+       memset((void *)hpet, 0, sizeof(struct acpi_hpet));
+       if (!header)
+               return -EFAULT;
+
+       /* 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 = *(unsigned int *)CONFIG_HPET_ADDRESS;
+       hpet->number = 0;
+       hpet->min_tick = 0; /* HPET_MIN_TICKS */
+
+       header->checksum = table_compute_checksum((void *)hpet,
+                                                 sizeof(struct acpi_hpet));
+
+       return 0;
+}
+
 /*
  * QEMU's version of write_acpi_tables is defined in drivers/misc/qfw.c
  */
diff --git a/include/acpi_table.h b/include/acpi_table.h
index e3dedc2496..1d78665abe 100644
--- a/include/acpi_table.h
+++ b/include/acpi_table.h
@@ -70,6 +70,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
 
@@ -85,6 +94,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,
@@ -152,15 +171,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;
@@ -617,6 +627,10 @@ int acpi_add_table(struct acpi_ctx *ctx, void *table);
  */
 void acpi_setup_base_tables(struct acpi_ctx *ctx, void *start);
 
+int acpi_write_hpet(struct acpi_ctx *ctx, const struct udevice *dev);
+
+int acpi_create_hpet(struct acpi_hpet *hpet);
+
 #endif /* !__ACPI__*/
 
 #include <asm/acpi_table.h>
-- 
2.25.0.341.g760bfbb309-goog

Reply via email to