Hi Patrick, On Wed, 11 Sept 2024 at 00:25, Patrick Rudolph <[email protected]> wrote: > > 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 <[email protected]> > Cc: Simon Glass <[email protected]> > --- > arch/arm/lib/acpi_table.c | 7 +++++++ > drivers/core/acpi.c | 16 +++++++++++++++ > include/dm/acpi.h | 26 ++++++++++++++++++++++++ > lib/acpi/acpi_table.c | 2 +- > test/dm/acpi.c | 42 +++++++++++++++++++++++++++++++++++++++ > 5 files changed, 92 insertions(+), 1 deletion(-) >
Reviewed-by: Simon Glass <[email protected]> > diff --git a/arch/arm/lib/acpi_table.c b/arch/arm/lib/acpi_table.c > index db6e40bdef..8c17e9eb36 100644 > --- a/arch/arm/lib/acpi_table.c > +++ b/arch/arm/lib/acpi_table.c > @@ -112,3 +112,10 @@ int acpi_pptt_add_cache(struct acpi_ctx *ctx, const u32 > flags, > > return offset; > } > + > +__weak void *acpi_fill_madt(struct acpi_madt *madt, struct acpi_ctx *ctx) > +{ > + /* TODO: Drop __weak once all SoCs are migrated to 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 d7deed2df1..96ca3b05a0 100644 > --- a/lib/acpi/acpi_table.c > +++ b/lib/acpi/acpi_table.c > @@ -261,11 +261,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..cc032a4618 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,32 @@ 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 >

