From d2628984b7831b26d8f9ac25c966d6151df7a929 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 22 Sep 2020 12:45:09 -0600 Subject: [PATCH] x86: acpi: Support generation of the HPET table 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 --- 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 733085c178..7047ee6c77 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 36ef3e5f0b..0080c96cfe 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -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; +} diff --git a/include/acpi/acpi_table.h b/include/acpi/acpi_table.h index fe9b29f3f8..f8140446a5 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@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.39.5