acpi: Change device properties to work as a tree
There is a second ACPI _DSD document from the UEFI Forum that details how _DSD style tables can be nested, creating a tree of similarly formatted tables. This document is linked from acpi_device.h. In order to support this the device property interface needs to be more flexible and build up a tree of properties to write all entries at once instead of writing each entry as it is generated. In the end this is a more flexible solution that can support drivers that need child tables like the DA7219 codec, while only requiring minor changes to the existing drivers that use the device property interface. This was tested on reef (apollolake) and chell (skylake) boards to ensure that there was no change in the generated SSDT AML. Change-Id: Ia22e3a5fd3982ffa7c324bee1a8d190d49f853dd Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: https://review.coreboot.org/15537 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
parent
9217f9def0
commit
ffc9990ece
|
@ -24,14 +24,31 @@
|
||||||
#include <gpio.h>
|
#include <gpio.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
#define ACPI_DP_UUID "daffd814-6eba-4d8c-8a91-bc9bbf4aa301"
|
||||||
* Pointer to length field in device properties package
|
#define ACPI_DP_CHILD_UUID "dbb8e3e6-5886-4ba6-8795-1319f52a966b"
|
||||||
* Location is set in dp_header() and length filled in by dp_footer()
|
|
||||||
*/
|
|
||||||
static char *dp_count_ptr;
|
|
||||||
|
|
||||||
/* Count of the number of device properties in the current set */
|
enum acpi_dp_type {
|
||||||
static char dp_count;
|
ACPI_DP_TYPE_INTEGER,
|
||||||
|
ACPI_DP_TYPE_STRING,
|
||||||
|
ACPI_DP_TYPE_REFERENCE,
|
||||||
|
ACPI_DP_TYPE_TABLE,
|
||||||
|
ACPI_DP_TYPE_ARRAY,
|
||||||
|
ACPI_DP_TYPE_CHILD,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct acpi_dp {
|
||||||
|
enum acpi_dp_type type;
|
||||||
|
const char *name;
|
||||||
|
struct acpi_dp *next;
|
||||||
|
union {
|
||||||
|
struct acpi_dp *child;
|
||||||
|
struct acpi_dp *array;
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
uint64_t integer;
|
||||||
|
const char *string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/* Write empty word value and return pointer to it */
|
/* Write empty word value and return pointer to it */
|
||||||
static void *acpi_device_write_zero_len(void)
|
static void *acpi_device_write_zero_len(void)
|
||||||
|
@ -473,39 +490,8 @@ void acpi_device_write_spi(const struct acpi_spi *spi)
|
||||||
acpi_device_fill_len(desc_length);
|
acpi_device_fill_len(desc_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write a header for using _DSD to export Device Properties */
|
static void acpi_dp_write_array(const struct acpi_dp *array);
|
||||||
void acpi_dp_write_header(void)
|
static void acpi_dp_write_value(const struct acpi_dp *prop)
|
||||||
{
|
|
||||||
/* Name (_DSD) */
|
|
||||||
acpigen_write_name("_DSD");
|
|
||||||
|
|
||||||
/* Package (2) */
|
|
||||||
acpigen_write_package(2);
|
|
||||||
|
|
||||||
/* ToUUID (ACPI_DP_UUID) */
|
|
||||||
acpigen_write_uuid(ACPI_DP_UUID);
|
|
||||||
|
|
||||||
/* Package (X) */
|
|
||||||
acpigen_emit_byte(0x12);
|
|
||||||
acpigen_write_len_f();
|
|
||||||
dp_count_ptr = acpigen_get_current();
|
|
||||||
acpigen_emit_byte(0); /* Number of elements, filled by dp_footer */
|
|
||||||
|
|
||||||
/* Reset element counter */
|
|
||||||
dp_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fill in length values from writing Device Properties */
|
|
||||||
void acpi_dp_write_footer(void)
|
|
||||||
{
|
|
||||||
/* Patch device property element count */
|
|
||||||
*dp_count_ptr = dp_count;
|
|
||||||
|
|
||||||
acpigen_pop_len(); /* Inner package length */
|
|
||||||
acpigen_pop_len(); /* Outer package length */
|
|
||||||
}
|
|
||||||
|
|
||||||
void acpi_dp_write_value(const struct acpi_dp *prop)
|
|
||||||
{
|
{
|
||||||
switch (prop->type) {
|
switch (prop->type) {
|
||||||
case ACPI_DP_TYPE_INTEGER:
|
case ACPI_DP_TYPE_INTEGER:
|
||||||
|
@ -515,86 +501,266 @@ void acpi_dp_write_value(const struct acpi_dp *prop)
|
||||||
acpigen_write_string(prop->string);
|
acpigen_write_string(prop->string);
|
||||||
break;
|
break;
|
||||||
case ACPI_DP_TYPE_REFERENCE:
|
case ACPI_DP_TYPE_REFERENCE:
|
||||||
|
case ACPI_DP_TYPE_CHILD:
|
||||||
acpigen_emit_namestring(prop->string);
|
acpigen_emit_namestring(prop->string);
|
||||||
break;
|
break;
|
||||||
|
case ACPI_DP_TYPE_ARRAY:
|
||||||
|
acpi_dp_write_array(prop->array);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write Device Property key with value as an integer */
|
/* Package (2) { "prop->name", VALUE } */
|
||||||
void acpi_dp_write_keyval(const char *key, const struct acpi_dp *prop)
|
static void acpi_dp_write_property(const struct acpi_dp *prop)
|
||||||
{
|
{
|
||||||
acpigen_write_package(2);
|
acpigen_write_package(2);
|
||||||
acpigen_write_string(key);
|
acpigen_write_string(prop->name);
|
||||||
acpi_dp_write_value(prop);
|
acpi_dp_write_value(prop);
|
||||||
acpigen_pop_len();
|
acpigen_pop_len();
|
||||||
dp_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write Device Property key with value as an integer */
|
|
||||||
void acpi_dp_write_integer(const char *key, uint64_t value)
|
|
||||||
{
|
|
||||||
const struct acpi_dp prop = ACPI_DP_INTEGER(value);
|
|
||||||
acpi_dp_write_keyval(key, &prop);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write Device Property key with value as a string */
|
|
||||||
void acpi_dp_write_string(const char *key, const char *value)
|
|
||||||
{
|
|
||||||
const struct acpi_dp prop = ACPI_DP_STRING(value);
|
|
||||||
acpi_dp_write_keyval(key, &prop);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write Device Property key with value as a reference */
|
|
||||||
void acpi_dp_write_reference(const char *key, const char *value)
|
|
||||||
{
|
|
||||||
const struct acpi_dp prop = ACPI_DP_REFERENCE(value);
|
|
||||||
acpi_dp_write_keyval(key, &prop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write array of Device Properties */
|
/* Write array of Device Properties */
|
||||||
void acpi_dp_write_array(const char *key, const struct acpi_dp *array, int len)
|
static void acpi_dp_write_array(const struct acpi_dp *array)
|
||||||
{
|
{
|
||||||
int i;
|
const struct acpi_dp *dp;
|
||||||
acpigen_write_package(2);
|
char *pkg_count;
|
||||||
acpigen_write_string(key);
|
|
||||||
acpigen_write_package(len);
|
/* Package element count determined as it is populated */
|
||||||
for (i = 0; i < len; i++)
|
pkg_count = acpigen_write_package(0);
|
||||||
acpi_dp_write_value(&array[i]);
|
|
||||||
|
for (dp = array; dp; dp = dp->next) {
|
||||||
|
acpi_dp_write_value(dp);
|
||||||
|
(*pkg_count)++;
|
||||||
|
}
|
||||||
|
|
||||||
acpigen_pop_len();
|
acpigen_pop_len();
|
||||||
acpigen_pop_len();
|
|
||||||
dp_count++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write array of Device Properties with values as integers */
|
static void acpi_dp_free(struct acpi_dp *dp)
|
||||||
void acpi_dp_write_integer_array(const char *key, uint64_t *array, int len)
|
|
||||||
{
|
{
|
||||||
int i;
|
while (dp) {
|
||||||
acpigen_write_package(2);
|
struct acpi_dp *p = dp->next;
|
||||||
acpigen_write_string(key);
|
|
||||||
acpigen_write_package(len);
|
switch (dp->type) {
|
||||||
for (i = 0; i < len; i++)
|
case ACPI_DP_TYPE_CHILD:
|
||||||
acpigen_write_integer(array[i]);
|
acpi_dp_free(dp->child);
|
||||||
acpigen_pop_len();
|
break;
|
||||||
acpigen_pop_len();
|
case ACPI_DP_TYPE_ARRAY:
|
||||||
dp_count++;
|
acpi_dp_free(dp->array);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(dp);
|
||||||
|
dp = p;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void acpi_dp_write(struct acpi_dp *table)
|
||||||
* Device Properties for GPIO binding
|
|
||||||
* linux/Documentation/acpi/gpio-properties.txt
|
|
||||||
*/
|
|
||||||
void acpi_dp_write_gpio(const char *key, const char *ref, int index,
|
|
||||||
int pin, int active_low)
|
|
||||||
{
|
{
|
||||||
const struct acpi_dp gpio_prop[] = {
|
struct acpi_dp *dp, *prop;
|
||||||
/* The device that has _CRS containing GpioIo()/GpioInt() */
|
char *dp_count, *prop_count;
|
||||||
ACPI_DP_REFERENCE(ref),
|
int child_count = 0;
|
||||||
/* Index of the GPIO resource in _CRS starting from zero */
|
|
||||||
ACPI_DP_INTEGER(index),
|
if (!table || table->type != ACPI_DP_TYPE_TABLE)
|
||||||
/* Pin in the GPIO resource, typically zero */
|
return;
|
||||||
ACPI_DP_INTEGER(pin),
|
|
||||||
/* Set if pin is active low */
|
/* Name (name) */
|
||||||
ACPI_DP_INTEGER(active_low)
|
acpigen_write_name(table->name);
|
||||||
};
|
|
||||||
acpi_dp_write_array(key, gpio_prop, ARRAY_SIZE(gpio_prop));
|
/* Device Property list starts with the next entry */
|
||||||
|
prop = table->next;
|
||||||
|
|
||||||
|
/* Package (DP), default to 2 elements (assuming no children) */
|
||||||
|
dp_count = acpigen_write_package(2);
|
||||||
|
|
||||||
|
/* ToUUID (ACPI_DP_UUID) */
|
||||||
|
acpigen_write_uuid(ACPI_DP_UUID);
|
||||||
|
|
||||||
|
/* Package (PROP), element count determined as it is populated */
|
||||||
|
prop_count = acpigen_write_package(0);
|
||||||
|
|
||||||
|
/* Print base properties */
|
||||||
|
for (dp = prop; dp; dp = dp->next) {
|
||||||
|
if (dp->type == ACPI_DP_TYPE_CHILD) {
|
||||||
|
child_count++;
|
||||||
|
} else {
|
||||||
|
(*prop_count)++;
|
||||||
|
acpi_dp_write_property(dp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Package (PROP) length */
|
||||||
|
acpigen_pop_len();
|
||||||
|
|
||||||
|
if (child_count) {
|
||||||
|
/* Update DP package count to 4 */
|
||||||
|
*dp_count = 4;
|
||||||
|
|
||||||
|
/* ToUUID (ACPI_DP_CHILD_UUID) */
|
||||||
|
acpigen_write_uuid(ACPI_DP_CHILD_UUID);
|
||||||
|
|
||||||
|
/* Print child pointer properties */
|
||||||
|
acpigen_write_package(child_count);
|
||||||
|
|
||||||
|
for (dp = prop; dp; dp = dp->next)
|
||||||
|
if (dp->type == ACPI_DP_TYPE_CHILD)
|
||||||
|
acpi_dp_write_property(dp);
|
||||||
|
|
||||||
|
acpigen_pop_len();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Package (DP) length */
|
||||||
|
acpigen_pop_len();
|
||||||
|
|
||||||
|
/* Recursively parse children into separate tables */
|
||||||
|
for (dp = prop; dp; dp = dp->next)
|
||||||
|
if (dp->type == ACPI_DP_TYPE_CHILD)
|
||||||
|
acpi_dp_write(dp->child);
|
||||||
|
|
||||||
|
/* Clean up */
|
||||||
|
acpi_dp_free(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct acpi_dp *acpi_dp_new(struct acpi_dp *dp, enum acpi_dp_type type,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
struct acpi_dp *new;
|
||||||
|
|
||||||
|
new = malloc(sizeof(struct acpi_dp));
|
||||||
|
if (!new)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
memset(new, 0, sizeof(*new));
|
||||||
|
new->type = type;
|
||||||
|
new->name = name;
|
||||||
|
|
||||||
|
if (dp) {
|
||||||
|
/* Add to end of property list */
|
||||||
|
while (dp->next)
|
||||||
|
dp = dp->next;
|
||||||
|
dp->next = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_dp *acpi_dp_new_table(const char *name)
|
||||||
|
{
|
||||||
|
return acpi_dp_new(NULL, ACPI_DP_TYPE_TABLE, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_dp *acpi_dp_add_integer(struct acpi_dp *dp, const char *name,
|
||||||
|
uint64_t value)
|
||||||
|
{
|
||||||
|
struct acpi_dp *new = acpi_dp_new(dp, ACPI_DP_TYPE_INTEGER, name);
|
||||||
|
|
||||||
|
if (new)
|
||||||
|
new->integer = value;
|
||||||
|
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_dp *acpi_dp_add_string(struct acpi_dp *dp, const char *name,
|
||||||
|
const char *string)
|
||||||
|
{
|
||||||
|
struct acpi_dp *new = acpi_dp_new(dp, ACPI_DP_TYPE_STRING, name);
|
||||||
|
|
||||||
|
if (new)
|
||||||
|
new->string = string;
|
||||||
|
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_dp *acpi_dp_add_reference(struct acpi_dp *dp, const char *name,
|
||||||
|
const char *reference)
|
||||||
|
{
|
||||||
|
struct acpi_dp *new = acpi_dp_new(dp, ACPI_DP_TYPE_REFERENCE, name);
|
||||||
|
|
||||||
|
if (new)
|
||||||
|
new->string = reference;
|
||||||
|
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_dp *acpi_dp_add_child(struct acpi_dp *dp, const char *name,
|
||||||
|
struct acpi_dp *child)
|
||||||
|
{
|
||||||
|
struct acpi_dp *new;
|
||||||
|
|
||||||
|
if (!child || child->type != ACPI_DP_TYPE_TABLE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
new = acpi_dp_new(dp, ACPI_DP_TYPE_CHILD, name);
|
||||||
|
if (new) {
|
||||||
|
new->child = child;
|
||||||
|
new->string = child->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_dp *acpi_dp_add_array(struct acpi_dp *dp, struct acpi_dp *array)
|
||||||
|
{
|
||||||
|
struct acpi_dp *new;
|
||||||
|
|
||||||
|
if (!array || array->type != ACPI_DP_TYPE_TABLE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
new = acpi_dp_new(dp, ACPI_DP_TYPE_ARRAY, array->name);
|
||||||
|
if (new)
|
||||||
|
new->array = array;
|
||||||
|
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_dp *acpi_dp_add_integer_array(struct acpi_dp *dp, const char *name,
|
||||||
|
uint64_t *array, int len)
|
||||||
|
{
|
||||||
|
struct acpi_dp *dp_array;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (len <= 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dp_array = acpi_dp_new_table(name);
|
||||||
|
if (!dp_array)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
if (!acpi_dp_add_integer(dp_array, NULL, array[i]))
|
||||||
|
break;
|
||||||
|
|
||||||
|
acpi_dp_add_array(dp, dp_array);
|
||||||
|
|
||||||
|
return dp_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_dp *acpi_dp_add_gpio(struct acpi_dp *dp, const char *name,
|
||||||
|
const char *ref, int index, int pin,
|
||||||
|
int active_low)
|
||||||
|
{
|
||||||
|
struct acpi_dp *gpio = acpi_dp_new_table(name);
|
||||||
|
|
||||||
|
if (!gpio)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* The device that has _CRS containing GpioIO()/GpioInt() */
|
||||||
|
acpi_dp_add_reference(gpio, NULL, ref);
|
||||||
|
|
||||||
|
/* Index of the GPIO resource in _CRS starting from zero */
|
||||||
|
acpi_dp_add_integer(gpio, NULL, index);
|
||||||
|
|
||||||
|
/* Pin in the GPIO resource, typically zero */
|
||||||
|
acpi_dp_add_integer(gpio, NULL, pin);
|
||||||
|
|
||||||
|
/* Set if pin is active low */
|
||||||
|
acpi_dp_add_integer(gpio, NULL, active_low);
|
||||||
|
|
||||||
|
acpi_dp_add_array(dp, gpio);
|
||||||
|
|
||||||
|
return gpio;
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,64 +228,86 @@ struct acpi_spi {
|
||||||
/* Write SPI Bus descriptor to SSDT AML output */
|
/* Write SPI Bus descriptor to SSDT AML output */
|
||||||
void acpi_device_write_spi(const struct acpi_spi *spi);
|
void acpi_device_write_spi(const struct acpi_spi *spi);
|
||||||
|
|
||||||
/*
|
|
||||||
* Device Properties with _DSD
|
|
||||||
* http://uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define ACPI_DP_UUID "daffd814-6eba-4d8c-8a91-bc9bbf4aa301"
|
|
||||||
|
|
||||||
enum acpi_dp_type {
|
|
||||||
ACPI_DP_TYPE_INTEGER,
|
|
||||||
ACPI_DP_TYPE_STRING,
|
|
||||||
ACPI_DP_TYPE_REFERENCE,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct acpi_dp {
|
|
||||||
enum acpi_dp_type type;
|
|
||||||
union {
|
|
||||||
uint64_t integer;
|
|
||||||
const char *string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ACPI_DP_INTEGER(x) { .type = ACPI_DP_TYPE_INTEGER, .integer = x }
|
|
||||||
#define ACPI_DP_STRING(x) { .type = ACPI_DP_TYPE_STRING, .string = x }
|
|
||||||
#define ACPI_DP_REFERENCE(x) { .type = ACPI_DP_TYPE_REFERENCE, .string = x }
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Writing Device Properties objects via _DSD
|
* Writing Device Properties objects via _DSD
|
||||||
|
*
|
||||||
|
* http://uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
|
||||||
|
* http://uefi.org/sites/default/files/resources/_DSD-hierarchical-data-extension-UUID-v1.pdf
|
||||||
|
*
|
||||||
|
* The Device Property Hierarchy can be multiple levels deep with multiple
|
||||||
|
* children possible in each level. In order to support this flexibility
|
||||||
|
* the device property hierarchy must be built up before being written out.
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
*
|
||||||
|
* // Child table with string and integer
|
||||||
|
* struct acpi_dp *child = acpi_dp_new_table("CHLD");
|
||||||
|
* acpi_dp_add_string(child, "childstring", "CHILD");
|
||||||
|
* acpi_dp_add_integer(child, "childint", 100);
|
||||||
|
*
|
||||||
|
* // _DSD table with integer and gpio and child pointer
|
||||||
|
* struct acpi_dp *dsd = acpi_dp_new_table("_DSD");
|
||||||
|
* acpi_dp_add_integer(dsd, "number1", 1);
|
||||||
|
* acpi_dp_add_gpio(dsd, "gpio", "\_SB.PCI0.GPIO", 0, 0, 1);
|
||||||
|
* acpi_dp_add_child(dsd, "child", child);
|
||||||
|
*
|
||||||
|
* // Write entries into SSDT and clean up resources
|
||||||
|
* acpi_dp_write(dsd);
|
||||||
|
*
|
||||||
|
* Name(_DSD, Package() {
|
||||||
|
* ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301")
|
||||||
|
* Package() {
|
||||||
|
* Package() { "gpio", Package() { \_SB.PCI0.GPIO, 0, 0, 0 } }
|
||||||
|
* Package() { "number1", 1 }
|
||||||
|
* }
|
||||||
|
* ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b")
|
||||||
|
* Package() {
|
||||||
|
* Package() { "child", CHLD }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* Name(CHLD, Package() {
|
||||||
|
* ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301")
|
||||||
|
* Package() {
|
||||||
|
* Package() { "childstring", "CHILD" }
|
||||||
|
* Package() { "childint", 100 }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Start a set of Device Properties with _DSD and UUID */
|
struct acpi_dp;
|
||||||
void acpi_dp_write_header(void);
|
|
||||||
|
|
||||||
/* End the Device Properties set and fill in length values */
|
/* Start a new Device Property table with provided ACPI reference */
|
||||||
void acpi_dp_write_footer(void);
|
struct acpi_dp *acpi_dp_new_table(const char *ref);
|
||||||
|
|
||||||
/* Write a Device Property value, but not the key */
|
/* Add integer Device Property */
|
||||||
void acpi_dp_write_value(const struct acpi_dp *prop);
|
struct acpi_dp *acpi_dp_add_integer(struct acpi_dp *dp, const char *name,
|
||||||
|
uint64_t value);
|
||||||
|
|
||||||
/* Write a Device Property, both key and value */
|
/* Add string Device Property */
|
||||||
void acpi_dp_write_keyval(const char *key, const struct acpi_dp *prop);
|
struct acpi_dp *acpi_dp_add_string(struct acpi_dp *dp, const char *name,
|
||||||
|
const char *string);
|
||||||
|
|
||||||
/* Write an integer as a Device Property */
|
/* Add ACPI reference Device Property */
|
||||||
void acpi_dp_write_integer(const char *key, uint64_t value);
|
struct acpi_dp *acpi_dp_add_reference(struct acpi_dp *dp, const char *name,
|
||||||
|
const char *reference);
|
||||||
|
|
||||||
/* Write a string as a Device Property */
|
/* Add an array of Device Properties */
|
||||||
void acpi_dp_write_string(const char *key, const char *value);
|
struct acpi_dp *acpi_dp_add_array(struct acpi_dp *dp, struct acpi_dp *array);
|
||||||
|
|
||||||
/* Write an ACPI reference as a Device Property */
|
/* Add an array of integers Device Property */
|
||||||
void acpi_dp_write_reference(const char *key, const char *value);
|
struct acpi_dp *acpi_dp_add_integer_array(struct acpi_dp *dp, const char *name,
|
||||||
|
uint64_t *array, int len);
|
||||||
|
|
||||||
/* Write an array of Device Properties */
|
/* Add a GPIO binding Device Property */
|
||||||
void acpi_dp_write_array(const char *key, const struct acpi_dp *array, int len);
|
struct acpi_dp *acpi_dp_add_gpio(struct acpi_dp *dp, const char *name,
|
||||||
|
const char *ref, int index, int pin,
|
||||||
|
int active_low);
|
||||||
|
|
||||||
/* Write an array of integers as Device Properties */
|
/* Add a child table of Device Properties */
|
||||||
void acpi_dp_write_integer_array(const char *key, uint64_t *array, int len);
|
struct acpi_dp *acpi_dp_add_child(struct acpi_dp *dp, const char *name,
|
||||||
|
struct acpi_dp *child);
|
||||||
|
|
||||||
/* Write a GPIO binding Device Property */
|
/* Write Device Property hierarchy and clean up resources */
|
||||||
void acpi_dp_write_gpio(const char *key, const char *ref, int index,
|
void acpi_dp_write(struct acpi_dp *table);
|
||||||
int pin, int active_low);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -32,6 +32,7 @@ static void max98357a_fill_ssdt(struct device *dev)
|
||||||
{
|
{
|
||||||
struct drivers_generic_max98357a_config *config = dev->chip_info;
|
struct drivers_generic_max98357a_config *config = dev->chip_info;
|
||||||
const char *path;
|
const char *path;
|
||||||
|
struct acpi_dp *dp;
|
||||||
|
|
||||||
if (!dev->enabled || !config)
|
if (!dev->enabled || !config)
|
||||||
return;
|
return;
|
||||||
|
@ -51,12 +52,12 @@ static void max98357a_fill_ssdt(struct device *dev)
|
||||||
acpigen_write_resourcetemplate_footer();
|
acpigen_write_resourcetemplate_footer();
|
||||||
|
|
||||||
/* _DSD for devicetree properties */
|
/* _DSD for devicetree properties */
|
||||||
acpi_dp_write_header();
|
|
||||||
/* This points to the first pin in the first gpio entry in _CRS */
|
/* This points to the first pin in the first gpio entry in _CRS */
|
||||||
path = acpi_device_path(dev);
|
path = acpi_device_path(dev);
|
||||||
acpi_dp_write_gpio("sdmode-gpio", path, 0, 0, 0);
|
dp = acpi_dp_new_table("_DSD");
|
||||||
acpi_dp_write_integer("sdmode-delay", config->sdmode_delay);
|
acpi_dp_add_gpio(dp, "sdmode-gpio", path, 0, 0, 0);
|
||||||
acpi_dp_write_footer();
|
acpi_dp_add_integer(dp, "sdmode-delay", config->sdmode_delay);
|
||||||
|
acpi_dp_write(dp);
|
||||||
|
|
||||||
acpigen_pop_len(); /* Device */
|
acpigen_pop_len(); /* Device */
|
||||||
acpigen_pop_len(); /* Scope */
|
acpigen_pop_len(); /* Scope */
|
||||||
|
|
|
@ -28,7 +28,9 @@
|
||||||
|
|
||||||
#define NAU8825_ACPI_NAME "NAU8"
|
#define NAU8825_ACPI_NAME "NAU8"
|
||||||
#define NAU8825_ACPI_HID "10508825"
|
#define NAU8825_ACPI_HID "10508825"
|
||||||
#define NAU8825_DP_INT(key,val) acpi_dp_write_integer("nuvoton," key, (val))
|
|
||||||
|
#define NAU8825_DP_INT(key,val) \
|
||||||
|
acpi_dp_add_integer(dp, "nuvoton," key, (val))
|
||||||
|
|
||||||
static void nau8825_fill_ssdt(struct device *dev)
|
static void nau8825_fill_ssdt(struct device *dev)
|
||||||
{
|
{
|
||||||
|
@ -40,6 +42,7 @@ static void nau8825_fill_ssdt(struct device *dev)
|
||||||
.speed = config->bus_speed ? : I2C_SPEED_FAST,
|
.speed = config->bus_speed ? : I2C_SPEED_FAST,
|
||||||
.resource = scope,
|
.resource = scope,
|
||||||
};
|
};
|
||||||
|
struct acpi_dp *dp = NULL;
|
||||||
|
|
||||||
if (!dev->enabled || !scope)
|
if (!dev->enabled || !scope)
|
||||||
return;
|
return;
|
||||||
|
@ -62,7 +65,7 @@ static void nau8825_fill_ssdt(struct device *dev)
|
||||||
acpigen_write_resourcetemplate_footer();
|
acpigen_write_resourcetemplate_footer();
|
||||||
|
|
||||||
/* Device Properties */
|
/* Device Properties */
|
||||||
acpi_dp_write_header();
|
dp = acpi_dp_new_table("_DSD");
|
||||||
NAU8825_DP_INT("jkdet-enable", config->jkdet_enable);
|
NAU8825_DP_INT("jkdet-enable", config->jkdet_enable);
|
||||||
NAU8825_DP_INT("jkdet-pull-enable", config->jkdet_pull_enable);
|
NAU8825_DP_INT("jkdet-pull-enable", config->jkdet_pull_enable);
|
||||||
NAU8825_DP_INT("jkdet-pull-up", config->jkdet_pull_up);
|
NAU8825_DP_INT("jkdet-pull-up", config->jkdet_pull_up);
|
||||||
|
@ -77,10 +80,9 @@ static void nau8825_fill_ssdt(struct device *dev)
|
||||||
NAU8825_DP_INT("jack-insert-debounce", config->jack_insert_debounce);
|
NAU8825_DP_INT("jack-insert-debounce", config->jack_insert_debounce);
|
||||||
NAU8825_DP_INT("jack-eject-deboune", config->jack_eject_debounce);
|
NAU8825_DP_INT("jack-eject-deboune", config->jack_eject_debounce);
|
||||||
NAU8825_DP_INT("sar-threshold-num", config->sar_threshold_num);
|
NAU8825_DP_INT("sar-threshold-num", config->sar_threshold_num);
|
||||||
acpi_dp_write_integer_array("nuvoton,sar-threshold",
|
acpi_dp_add_integer_array(dp, "nuvoton,sar-threshold",
|
||||||
config->sar_threshold,
|
config->sar_threshold, config->sar_threshold_num);
|
||||||
config->sar_threshold_num);
|
acpi_dp_write(dp);
|
||||||
acpi_dp_write_footer();
|
|
||||||
|
|
||||||
acpigen_pop_len(); /* Device */
|
acpigen_pop_len(); /* Device */
|
||||||
acpigen_pop_len(); /* Scope */
|
acpigen_pop_len(); /* Scope */
|
||||||
|
|
|
@ -38,6 +38,7 @@ static void sd_fill_ssdt(struct device *dev)
|
||||||
.pin_count = 1,
|
.pin_count = 1,
|
||||||
.pins = { config->sdcard_cd_gpio_default }
|
.pins = { config->sdcard_cd_gpio_default }
|
||||||
};
|
};
|
||||||
|
struct acpi_dp *dp;
|
||||||
|
|
||||||
if (!dev->enabled)
|
if (!dev->enabled)
|
||||||
return;
|
return;
|
||||||
|
@ -62,9 +63,9 @@ static void sd_fill_ssdt(struct device *dev)
|
||||||
acpigen_write_resourcetemplate_footer();
|
acpigen_write_resourcetemplate_footer();
|
||||||
|
|
||||||
/* Bind the cd-gpio name to the GpioInt() resource */
|
/* Bind the cd-gpio name to the GpioInt() resource */
|
||||||
acpi_dp_write_header();
|
dp = acpi_dp_new_table("_DSD");
|
||||||
acpi_dp_write_gpio("cd-gpio", path, 0, 0, 1);
|
acpi_dp_add_gpio(dp, "cd-gpio", path, 0, 0, 1);
|
||||||
acpi_dp_write_footer();
|
acpi_dp_write(dp);
|
||||||
|
|
||||||
acpigen_pop_len();
|
acpigen_pop_len();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue