@@ -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
*/
@@ -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>
Add an implementation of the HPET (High Precision Event Timer) ACPI table. Signed-off-by: Simon Glass <sjg at chromium.org> --- arch/x86/lib/acpi_table.c | 54 +++++++++++++++++++++++++++++++++++++++ include/acpi_table.h | 32 ++++++++++++++++------- 2 files changed, 77 insertions(+), 9 deletions(-)