Add a new method to acpi_ops to let drivers fill out ACPI MADT. The code is unused for now until drivers implement the new ops.
TEST: Booted on QEMU sbsa using driver model generated MADT. Signed-off-by: Patrick Rudolph <patrick.rudo...@9elements.com> Cc: Simon Glass <s...@chromium.org> --- Changelog v4: - Drop __weak attribute and make driver model mandatory on Arm --- arch/arm/lib/acpi_table.c | 13 ++++++++++++ drivers/core/acpi.c | 16 +++++++++++++++ include/dm/acpi.h | 26 +++++++++++++++++++++++ lib/acpi/acpi_table.c | 2 +- test/dm/acpi.c | 43 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 1 deletion(-) diff --git a/arch/arm/lib/acpi_table.c b/arch/arm/lib/acpi_table.c index db6e40bdef..b264a31cbb 100644 --- a/arch/arm/lib/acpi_table.c +++ b/arch/arm/lib/acpi_table.c @@ -10,6 +10,8 @@ #include <acpi/acpigen.h> #include <acpi/acpi_device.h> #include <acpi/acpi_table.h> +#include <dm/acpi.h> +#include <dm/uclass.h> #include <string.h> void acpi_write_madt_gicc(struct acpi_madt_gicc *gicc, uint cpu_num, @@ -112,3 +114,14 @@ int acpi_pptt_add_cache(struct acpi_ctx *ctx, const u32 flags, return offset; } + +void *acpi_fill_madt(struct acpi_madt *madt, struct acpi_ctx *ctx) +{ + uclass_probe_all(UCLASS_CPU); + uclass_probe_all(UCLASS_IRQ); + + /* All SoCs must use the driver model */ + acpi_fill_madt_subtbl(ctx); + + return ctx->current; +} diff --git a/drivers/core/acpi.c b/drivers/core/acpi.c index 9f78422892..4763963914 100644 --- a/drivers/core/acpi.c +++ b/drivers/core/acpi.c @@ -48,6 +48,7 @@ enum method_t { METHOD_FILL_SSDT, METHOD_INJECT_DSDT, METHOD_SETUP_NHLT, + METHOD_FILL_MADT, }; /* Prototype for all methods */ @@ -282,6 +283,8 @@ acpi_method acpi_get_method(struct udevice *dev, enum method_t method) switch (method) { case METHOD_WRITE_TABLES: return aops->write_tables; + case METHOD_FILL_MADT: + return aops->fill_madt; case METHOD_FILL_SSDT: return aops->fill_ssdt; case METHOD_INJECT_DSDT: @@ -328,6 +331,19 @@ int acpi_recurse_method(struct acpi_ctx *ctx, struct udevice *parent, return 0; } +int acpi_fill_madt_subtbl(struct acpi_ctx *ctx) +{ + int ret; + + log_debug("Writing MADT table\n"); + ret = acpi_recurse_method(ctx, dm_root(), METHOD_FILL_MADT, TYPE_NONE); + log_debug("Writing MADT finished, err=%d\n", ret); + if (ret) + return log_msg_ret("build", ret); + + return ret; +} + int acpi_fill_ssdt(struct acpi_ctx *ctx) { void *start = ctx->current; diff --git a/include/dm/acpi.h b/include/dm/acpi.h index 3adfe21767..d6bc0c099a 100644 --- a/include/dm/acpi.h +++ b/include/dm/acpi.h @@ -146,6 +146,22 @@ struct acpi_ops { */ int (*write_tables)(const struct udevice *dev, struct acpi_ctx *ctx); + /** + * fill_madt() - Generate MADT sub-tables for a device + * + * This is called to create the MADT table. The method should write out + * whatever sub-table is needed by this device. It will end up in the + * MADT table. + * + * Note that this is called 'fill' because the entire contents of the + * MADT is build by calling this method on all devices. + * + * @dev: Device to write + * @ctx: ACPI context to use + * @return 0 if OK, -ve on error + */ + int (*fill_madt)(const struct udevice *dev, struct acpi_ctx *ctx); + /** * fill_ssdt() - Generate SSDT code for a device * @@ -231,6 +247,16 @@ int acpi_copy_name(char *out_name, const char *name); */ int acpi_write_dev_tables(struct acpi_ctx *ctx); +/** + * acpi_fill_madt_subtbl() - Generate ACPI tables for MADT + * + * This is called to create the MADT sub-tables for all devices. + * + * @ctx: ACPI context to use + * Return: 0 if OK, -ve on error + */ +int acpi_fill_madt_subtbl(struct acpi_ctx *ctx); + /** * acpi_fill_ssdt() - Generate ACPI tables for SSDT * diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c index 639d78125f..5b9b4d2f29 100644 --- a/lib/acpi/acpi_table.c +++ b/lib/acpi/acpi_table.c @@ -257,11 +257,11 @@ int acpi_write_madt(struct acpi_ctx *ctx, const struct acpi_writer *entry) header->revision = ACPI_MADT_REV_ACPI_3_0; acpi_inc(ctx, sizeof(struct acpi_madt)); + /* TODO: Get rid of acpi_fill_madt and use driver model */ current = acpi_fill_madt(madt, ctx); /* (Re)calculate length and checksum */ header->length = (uintptr_t)current - (uintptr_t)madt; - header->checksum = table_compute_checksum((void *)madt, header->length); acpi_add_table(ctx, madt); ctx->current = (void *)madt + madt->header.length; diff --git a/test/dm/acpi.c b/test/dm/acpi.c index 7da381f1a5..69ce4bd46f 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -95,6 +95,21 @@ static int testacpi_get_name(const struct udevice *dev, char *out_name) return acpi_copy_name(out_name, ACPI_TEST_DEV_NAME); } +static int testacpi_fill_madt(const struct udevice *dev, struct acpi_ctx *ctx) +{ + u64 *data = ctx->current; + + /* Only fill madt once */ + if (device_get_uclass_id(dev->parent) != UCLASS_TEST_ACPI) + return 0; + + *data = 0xdeadbeef; + + acpi_inc(ctx, sizeof(u64)); + + return 0; +} + static int testacpi_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx) { const char *data; @@ -124,6 +139,7 @@ static int testacpi_inject_dsdt(const struct udevice *dev, struct acpi_ctx *ctx) struct acpi_ops testacpi_ops = { .get_name = testacpi_get_name, .write_tables = testacpi_write_tables, + .fill_madt = testacpi_fill_madt, .fill_ssdt = testacpi_fill_ssdt, .inject_dsdt = testacpi_inject_dsdt, }; @@ -532,6 +548,33 @@ static int dm_test_acpi_fill_ssdt(struct unit_test_state *uts) } DM_TEST(dm_test_acpi_fill_ssdt, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +/* Test acpi_fill_madt() */ +static int dm_test_acpi_fill_madt(struct unit_test_state *uts) +{ + struct acpi_ctx ctx; + u64 *buf; + + buf = malloc(BUF_SIZE); + ut_assertnonnull(buf); + + acpi_reset_items(); + ctx.current = buf; + buf[1] = 'z'; /* sentinel */ + ut_assertok(acpi_fill_madt_subtbl(&ctx)); + + /* + * These values come from acpi-test2's acpi-ssdt-test-data property. + * This device comes first because of u-boot,acpi-ssdt-order + */ + ut_asserteq(0xdeadbeef, buf[0]); + + ut_asserteq('z', buf[1]); + + return 0; +} + +DM_TEST(dm_test_acpi_fill_madt, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + /* Test acpi_inject_dsdt() */ static int dm_test_acpi_inject_dsdt(struct unit_test_state *uts) { -- 2.46.0