Message ID | 20200613205459.v3.29.I91d8e58921d27a54f6ecb58ecd5b72d141238f63@changeid |
---|---|
State | Superseded |
Headers | show |
Series | dm: Add programmatic generation of ACPI tables (part B) | expand |
Hi Simon, -----"Simon Glass" <sjg at chromium.org> schrieb: ----- > Betreff: [PATCH v3 29/35] acpi: Support ordering SSDT data by device > > Add a /chosen property to control the order in which the data appears > in the SSDT. This allows matching up U-Boot's output from a dump of the > known-good data obtained from within Linux. > > Signed-off-by: Simon Glass <sjg at chromium.org> > --- > > Changes in v3: > - Make find_item() static and rename to find_acpi_item() > - Rename build_type() and add a comment > > Changes in v1: > - Generalise the ACPI function recursion with acpi_recurse_method() > > arch/sandbox/dts/test.dts | 5 +- > doc/device-tree-bindings/chosen.txt | 9 ++++ > drivers/core/acpi.c | 75 +++++++++++++++++++++++++++++ > test/dm/acpi.c | 15 +++--- > 4 files changed, 96 insertions(+), 8 deletions(-) Reviewed-by: Wolfgang Wallner <wolfgang.wallner at br-automation.com>
Hi Simon, On Sun, Jun 14, 2020 at 10:55 AM Simon Glass <sjg at chromium.org> wrote: > > Add a /chosen property to control the order in which the data appears > in the SSDT. This allows matching up U-Boot's output from a dump of the > known-good data obtained from within Linux. > > Signed-off-by: Simon Glass <sjg at chromium.org> > --- > > Changes in v3: > - Make find_item() static and rename to find_acpi_item() > - Rename build_type() and add a comment > > Changes in v1: > - Generalise the ACPI function recursion with acpi_recurse_method() > > arch/sandbox/dts/test.dts | 5 +- > doc/device-tree-bindings/chosen.txt | 9 ++++ > drivers/core/acpi.c | 75 +++++++++++++++++++++++++++++ > test/dm/acpi.c | 15 +++--- > 4 files changed, 96 insertions(+), 8 deletions(-) > > diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts > index 30394946f8..993082763d 100644 > --- a/arch/sandbox/dts/test.dts > +++ b/arch/sandbox/dts/test.dts > @@ -254,7 +254,7 @@ > compatible = "denx,u-boot-devres-test"; > }; > > - acpi-test { > + acpi_test1: acpi-test { > compatible = "denx,u-boot-acpi-test"; > acpi-ssdt-test-data = "ab"; > child { > @@ -262,7 +262,7 @@ > }; > }; > > - acpi-test2 { > + acpi_test2: acpi-test2 { > compatible = "denx,u-boot-acpi-test"; > acpi-ssdt-test-data = "cd"; > }; > @@ -895,6 +895,7 @@ > setting = "sunrise ohoka"; > other-node = "/some-bus/c-test at 5"; > int-values = <0x1937 72993>; > + u-boot,acpi-ssdt-order = <&acpi_test2 &acpi_test1>; > chosen-test { > compatible = "denx,u-boot-fdt-test"; > reg = <9 1>; > diff --git a/doc/device-tree-bindings/chosen.txt b/doc/device-tree-bindings/chosen.txt > index 395c9501e3..d4dfc05847 100644 > --- a/doc/device-tree-bindings/chosen.txt > +++ b/doc/device-tree-bindings/chosen.txt > @@ -134,3 +134,12 @@ Example > phandlepart = <&mmc 1>; > }; > }; > + > +u-boot,acpi-ssdt-order > +---------------------- > + > +This provides the ordering to use when writing device data to the ACPI SSDT > +(Secondary System Descriptor Table). Each cell is a phandle pointer to a device > +node to add. The ACPI information is written in this order. > + > +If the ordering does not include all nodes, an error is generated. > diff --git a/drivers/core/acpi.c b/drivers/core/acpi.c > index df3d7ba417..4719a5c4e4 100644 > --- a/drivers/core/acpi.c > +++ b/drivers/core/acpi.c > @@ -108,6 +108,76 @@ static int acpi_add_item(struct acpi_ctx *ctx, struct udevice *dev, > return 0; > } > > +static struct acpi_item *find_acpi_item(const char *devname) > +{ > + int i; > + > + for (i = 0; i < item_count; i++) { > + struct acpi_item *item = &acpi_item[i]; > + > + if (!strcmp(devname, item->dev->name)) > + return item; > + } > + > + return NULL; > +} > + > +/** > + * sort_acpi_item_type - Sort the ACPI items into the desired order > + * > + * This looks up the ordering in the device tree and then adds each item one by > + * one into the supplied buffer > + * > + * @ctx: ACPI context > + * @start: Start position to put the sorted items. The items will follow each > + * other in sorted order > + * @type: Type of items to sort > + * @return 0 if OK, -ve on error > + */ > +static int sort_acpi_item_type(struct acpi_ctx *ctx, void *start, > + enum gen_type_t type) > +{ > + const u32 *order; > + int size; > + int count; > + void *ptr; > + void *end = ctx->current; > + > + ptr = start; > + order = ofnode_read_chosen_prop("u-boot,acpi-ssdt-order", &size); > + if (!order) { > + log_warning("Failed to find ordering, leaving as is\n"); > + return 0; > + } > + > + count = size / sizeof(u32); > + while (count--) { > + struct acpi_item *item; > + const char *name; > + ofnode node; > + > + node = ofnode_get_by_phandle(fdt32_to_cpu(*order++)); > + name = ofnode_get_name(node); > + item = find_acpi_item(name); > + if (!item) { > + log_err("Failed to find item '%s'\n", name); > + return log_msg_ret("find", -ENOENT); > + } > + if (item->type == type) { > + log_debug(" - add %s\n", item->dev->name); > + memcpy(ptr, item->buf, item->size); > + ptr += item->size; Should ctx->current be updated? > + } > + } > + > + if (ptr != end) { > + log_warning("*** Missing bytes: ptr=%p, end=%p\n", ptr, end); > + return -ENXIO; > + } > + > + return 0; > +} > + > acpi_method acpi_get_method(struct udevice *dev, enum method_t method) > { > struct acpi_ops *aops; > @@ -163,11 +233,16 @@ int acpi_recurse_method(struct acpi_ctx *ctx, struct udevice *parent, > > int acpi_fill_ssdt(struct acpi_ctx *ctx) > { > + void *start = ctx->current; > int ret; > > log_debug("Writing SSDT tables\n"); > + item_count = 0; > ret = acpi_recurse_method(ctx, dm_root(), METHOD_FILL_SSDT, TYPE_SSDT); > log_debug("Writing SSDT finished, err=%d\n", ret); > + ret = sort_acpi_item_type(ctx, start, TYPE_SSDT); > + if (ret) > + return log_msg_ret("build", ret); > > return ret; > } > diff --git a/test/dm/acpi.c b/test/dm/acpi.c > index d46d1fbe66..4e1d401e0d 100644 > --- a/test/dm/acpi.c > +++ b/test/dm/acpi.c > @@ -425,13 +425,16 @@ static int dm_test_acpi_fill_ssdt(struct unit_test_state *uts) > buf[4] = 'z'; /* sentinel */ > ut_assertok(acpi_fill_ssdt(&ctx)); > > - /* These values come from acpi-test's acpi-ssdt-test-data property */ > - ut_asserteq('a', buf[0]); > - ut_asserteq('b', buf[1]); > + /* > + * 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('c', buf[0]); > + ut_asserteq('d', buf[1]); > > - /* These values come from acpi-test2's acpi-ssdt-test-data property */ > - ut_asserteq('c', buf[2]); > - ut_asserteq('d', buf[3]); > + /* These values come from acpi-test's acpi-ssdt-test-data property */ > + ut_asserteq('a', buf[2]); > + ut_asserteq('b', buf[3]); > > ut_asserteq('z', buf[4]); > Regards, Bin
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 30394946f8..993082763d 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -254,7 +254,7 @@ compatible = "denx,u-boot-devres-test"; }; - acpi-test { + acpi_test1: acpi-test { compatible = "denx,u-boot-acpi-test"; acpi-ssdt-test-data = "ab"; child { @@ -262,7 +262,7 @@ }; }; - acpi-test2 { + acpi_test2: acpi-test2 { compatible = "denx,u-boot-acpi-test"; acpi-ssdt-test-data = "cd"; }; @@ -895,6 +895,7 @@ setting = "sunrise ohoka"; other-node = "/some-bus/c-test at 5"; int-values = <0x1937 72993>; + u-boot,acpi-ssdt-order = <&acpi_test2 &acpi_test1>; chosen-test { compatible = "denx,u-boot-fdt-test"; reg = <9 1>; diff --git a/doc/device-tree-bindings/chosen.txt b/doc/device-tree-bindings/chosen.txt index 395c9501e3..d4dfc05847 100644 --- a/doc/device-tree-bindings/chosen.txt +++ b/doc/device-tree-bindings/chosen.txt @@ -134,3 +134,12 @@ Example phandlepart = <&mmc 1>; }; }; + +u-boot,acpi-ssdt-order +---------------------- + +This provides the ordering to use when writing device data to the ACPI SSDT +(Secondary System Descriptor Table). Each cell is a phandle pointer to a device +node to add. The ACPI information is written in this order. + +If the ordering does not include all nodes, an error is generated. diff --git a/drivers/core/acpi.c b/drivers/core/acpi.c index df3d7ba417..4719a5c4e4 100644 --- a/drivers/core/acpi.c +++ b/drivers/core/acpi.c @@ -108,6 +108,76 @@ static int acpi_add_item(struct acpi_ctx *ctx, struct udevice *dev, return 0; } +static struct acpi_item *find_acpi_item(const char *devname) +{ + int i; + + for (i = 0; i < item_count; i++) { + struct acpi_item *item = &acpi_item[i]; + + if (!strcmp(devname, item->dev->name)) + return item; + } + + return NULL; +} + +/** + * sort_acpi_item_type - Sort the ACPI items into the desired order + * + * This looks up the ordering in the device tree and then adds each item one by + * one into the supplied buffer + * + * @ctx: ACPI context + * @start: Start position to put the sorted items. The items will follow each + * other in sorted order + * @type: Type of items to sort + * @return 0 if OK, -ve on error + */ +static int sort_acpi_item_type(struct acpi_ctx *ctx, void *start, + enum gen_type_t type) +{ + const u32 *order; + int size; + int count; + void *ptr; + void *end = ctx->current; + + ptr = start; + order = ofnode_read_chosen_prop("u-boot,acpi-ssdt-order", &size); + if (!order) { + log_warning("Failed to find ordering, leaving as is\n"); + return 0; + } + + count = size / sizeof(u32); + while (count--) { + struct acpi_item *item; + const char *name; + ofnode node; + + node = ofnode_get_by_phandle(fdt32_to_cpu(*order++)); + name = ofnode_get_name(node); + item = find_acpi_item(name); + if (!item) { + log_err("Failed to find item '%s'\n", name); + return log_msg_ret("find", -ENOENT); + } + if (item->type == type) { + log_debug(" - add %s\n", item->dev->name); + memcpy(ptr, item->buf, item->size); + ptr += item->size; + } + } + + if (ptr != end) { + log_warning("*** Missing bytes: ptr=%p, end=%p\n", ptr, end); + return -ENXIO; + } + + return 0; +} + acpi_method acpi_get_method(struct udevice *dev, enum method_t method) { struct acpi_ops *aops; @@ -163,11 +233,16 @@ int acpi_recurse_method(struct acpi_ctx *ctx, struct udevice *parent, int acpi_fill_ssdt(struct acpi_ctx *ctx) { + void *start = ctx->current; int ret; log_debug("Writing SSDT tables\n"); + item_count = 0; ret = acpi_recurse_method(ctx, dm_root(), METHOD_FILL_SSDT, TYPE_SSDT); log_debug("Writing SSDT finished, err=%d\n", ret); + ret = sort_acpi_item_type(ctx, start, TYPE_SSDT); + if (ret) + return log_msg_ret("build", ret); return ret; } diff --git a/test/dm/acpi.c b/test/dm/acpi.c index d46d1fbe66..4e1d401e0d 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -425,13 +425,16 @@ static int dm_test_acpi_fill_ssdt(struct unit_test_state *uts) buf[4] = 'z'; /* sentinel */ ut_assertok(acpi_fill_ssdt(&ctx)); - /* These values come from acpi-test's acpi-ssdt-test-data property */ - ut_asserteq('a', buf[0]); - ut_asserteq('b', buf[1]); + /* + * 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('c', buf[0]); + ut_asserteq('d', buf[1]); - /* These values come from acpi-test2's acpi-ssdt-test-data property */ - ut_asserteq('c', buf[2]); - ut_asserteq('d', buf[3]); + /* These values come from acpi-test's acpi-ssdt-test-data property */ + ut_asserteq('a', buf[2]); + ut_asserteq('b', buf[3]); ut_asserteq('z', buf[4]);
Add a /chosen property to control the order in which the data appears in the SSDT. This allows matching up U-Boot's output from a dump of the known-good data obtained from within Linux. Signed-off-by: Simon Glass <sjg at chromium.org> --- Changes in v3: - Make find_item() static and rename to find_acpi_item() - Rename build_type() and add a comment Changes in v1: - Generalise the ACPI function recursion with acpi_recurse_method() arch/sandbox/dts/test.dts | 5 +- doc/device-tree-bindings/chosen.txt | 9 ++++ drivers/core/acpi.c | 75 +++++++++++++++++++++++++++++ test/dm/acpi.c | 15 +++--- 4 files changed, 96 insertions(+), 8 deletions(-)