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@chromium.org> Reviewed-by: Wolfgang Wallner <wolfgang.wallner@br-automation.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
parent
64ba6f43ef
commit
0f7b111f70
|
@ -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";
|
||||
};
|
||||
|
@ -924,6 +924,7 @@
|
|||
setting = "sunrise ohoka";
|
||||
other-node = "/some-bus/c-test@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>;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -108,6 +108,85 @@ 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* This algorithm rewrites the context buffer without changing its
|
||||
* length. So there is no need to update ctx-current
|
||||
*/
|
||||
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 the sort order is missing an item then the output will be too
|
||||
* small. Report this error since the item needs to be added to the
|
||||
* ordering for the ACPI tables to be complete.
|
||||
*/
|
||||
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 +242,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;
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
|
||||
|
|
Loading…
Reference in New Issue