u-boot/include/acpi/acpi_dp.h
Simon Glass 0667900049 acpi: Support copying properties from device tree to ACPI
Some drivers in Linux support both device tree and ACPI. U-Boot itself
uses Linux device-tree bindings for its own configuration but does not use
ACPI.

It is convenient to copy these values over to the ACPI DP table for
passing to linux. Add some convenience functions to help with this.

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>
2020-07-17 14:32:24 +08:00

287 lines
8.8 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Device properties, a temporary data structure for adding to ACPI code
*
* Copyright 2019 Google LLC
* Mostly taken from coreboot file acpi_device.h
*/
#ifndef __ACPI_DP_H
#define __ACPI_DP_H
struct acpi_ctx;
#include <acpi/acpi_device.h>
/*
* Writing Device Properties objects via _DSD
*
* This is described in ACPI 6.3 section 6.2.5
*
* This provides a structure to handle nested device-specific data which ends
* up in a _DSD table.
*
* https://www.kernel.org/doc/html/latest/firmware-guide/acpi/DSD-properties-rules.html
* https://uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
* https://uefi.org/sites/default/files/resources/_DSD-hierarchical-data-extension-UUID-v1.1.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 }
* }
* }
*/
#define ACPI_DP_UUID "daffd814-6eba-4d8c-8a91-bc9bbf4aa301"
#define ACPI_DP_CHILD_UUID "dbb8e3e6-5886-4ba6-8795-1319f52a966b"
/**
* enum acpi_dp_type - types of device property objects
*
* These refer to the types defined by struct acpi_dp below
*
* @ACPI_DP_TYPE_UNKNOWN: Unknown / do not use
* @ACPI_DP_TYPE_INTEGER: Integer value (u64) in @integer
* @ACPI_DP_TYPE_STRING: String value in @string
* @ACPI_DP_TYPE_REFERENCE: Reference to another object, with value in @string
* @ACPI_DP_TYPE_TABLE: Type for a top-level table which may have children
* @ACPI_DP_TYPE_ARRAY: Array of items with first item in @array and following
* items linked from that item's @next
* @ACPI_DP_TYPE_CHILD: Child object, with siblings in that child's @next
*/
enum acpi_dp_type {
ACPI_DP_TYPE_UNKNOWN,
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 - ACPI device properties
*
* @type: Table type
* @name: Name of object, typically _DSD but could be CHLD for a child object.
* This can be NULL if there is no name
* @next: Next object in list (next array element or next sibling)
* @child: Pointer to first child, if @type == ACPI_DP_TYPE_CHILD, else NULL
* @array: First array element, if @type == ACPI_DP_TYPE_ARRAY, else NULL
* @integer: Integer value of the property, if @type == ACPI_DP_TYPE_INTEGER
* @string: String value of the property, if @type == ACPI_DP_TYPE_STRING;
* child name if @type == ACPI_DP_TYPE_CHILD;
* reference name if @type == ACPI_DP_TYPE_REFERENCE;
*/
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 {
u64 integer;
const char *string;
};
};
/**
* acpi_dp_new_table() - Start a new Device Property table
*
* @ref: ACPI reference (e.g. "_DSD")
* @return pointer to table, or NULL if out of memory
*/
struct acpi_dp *acpi_dp_new_table(const char *ref);
/**
* acpi_dp_add_integer() - Add integer Device Property
*
* A new node is added to the end of the property list of @dp
*
* @dp: Table to add this property to
* @name: Name of property, or NULL for none
* @value: Integer value
* @return pointer to new node, or NULL if out of memory
*/
struct acpi_dp *acpi_dp_add_integer(struct acpi_dp *dp, const char *name,
u64 value);
/**
* acpi_dp_add_string() - Add string Device Property
*
* A new node is added to the end of the property list of @dp
*
* @dp: Table to add this property to
* @name: Name of property, or NULL for none
* @string: String value
* @return pointer to new node, or NULL if out of memory
*/
struct acpi_dp *acpi_dp_add_string(struct acpi_dp *dp, const char *name,
const char *string);
/**
* acpi_dp_add_reference() - Add reference Device Property
*
* A new node is added to the end of the property list of @dp
*
* @dp: Table to add this property to
* @name: Name of property, or NULL for none
* @reference: Reference value
* @return pointer to new node, or NULL if out of memory
*/
struct acpi_dp *acpi_dp_add_reference(struct acpi_dp *dp, const char *name,
const char *reference);
/**
* acpi_dp_add_array() - Add array Device Property
*
* A new node is added to the end of the property list of @dp, with the array
* attached to that.
*
* @dp: Table to add this property to
* @name: Name of property, or NULL for none
* @return pointer to new node, or NULL if out of memory
*/
struct acpi_dp *acpi_dp_add_array(struct acpi_dp *dp, struct acpi_dp *array);
/**
* acpi_dp_add_integer_array() - Add an array of integers
*
* A new node is added to the end of the property list of @dp, with the array
* attached to that. Each element of the array becomes a new node.
*
* @dp: Table to add this property to
* @name: Name of property, or NULL for none
* @return pointer to new array node, or NULL if out of memory
*/
struct acpi_dp *acpi_dp_add_integer_array(struct acpi_dp *dp, const char *name,
u64 *array, int len);
/**
* acpi_dp_add_child() - Add a child table of Device Properties
*
* A new node is added as a child of @dp
*
* @dp: Table to add this child to
* @name: Name of child, or NULL for none
* @child: Child node to add
* @return pointer to new child node, or NULL if out of memory
*/
struct acpi_dp *acpi_dp_add_child(struct acpi_dp *dp, const char *name,
struct acpi_dp *child);
/**
* acpi_dp_add_gpio() - Add a GPIO to a list of Device Properties
*
* A new node is added to the end of the property list of @dp, with the
* GPIO properties added to the the new node
*
* @dp: Table to add this property to
* @name: Name of property
* @ref: Reference to device with a _CRS containing GpioIO or GpioInt
* @index: Index of the GPIO resource in _CRS starting from zero
* @pin: Pin in the GPIO resource, typically zero
* @polarity: GPIO polarity. Note that ACPI_IRQ_ACTIVE_BOTH is not supported
* @return pointer to new node, or NULL if out of memory
*/
struct acpi_dp *acpi_dp_add_gpio(struct acpi_dp *dp, const char *name,
const char *ref, int index, int pin,
enum acpi_irq_polarity polarity);
/**
* acpi_dp_write() - Write Device Property hierarchy and clean up resources
*
* This writes the table using acpigen and then frees it
*
* @ctx: ACPI context
* @table: Table to write
* @return 0 if OK, -ve on error
*/
int acpi_dp_write(struct acpi_ctx *ctx, struct acpi_dp *table);
/**
* acpi_dp_ofnode_copy_int() - Copy a property from device tree to DP
*
* This copies an integer property from the device tree to the ACPI DP table.
*
* @node: Node to copy from
* @dp: DP to copy to
* @prop: Property name to copy
* @return 0 if OK, -ve on error
*/
int acpi_dp_ofnode_copy_int(ofnode node, struct acpi_dp *dp, const char *prop);
/**
* acpi_dp_ofnode_copy_str() - Copy a property from device tree to DP
*
* This copies a string property from the device tree to the ACPI DP table.
*
* @node: Node to copy from
* @dp: DP to copy to
* @prop: Property name to copy
* @return 0 if OK, -ve on error
*/
int acpi_dp_ofnode_copy_str(ofnode node, struct acpi_dp *dp, const char *prop);
/**
* acpi_dp_dev_copy_int() - Copy a property from device tree to DP
*
* This copies an integer property from the device tree to the ACPI DP table.
*
* @dev: Device to copy from
* @dp: DP to copy to
* @prop: Property name to copy
* @return 0 if OK, -ve on error
*/
int acpi_dp_dev_copy_int(const struct udevice *dev, struct acpi_dp *dp,
const char *prop);
/**
* acpi_dp_dev_copy_str() - Copy a property from device tree to DP
*
* This copies a string property from the device tree to the ACPI DP table.
*
* @dev: Device to copy from
* @dp: DP to copy to
* @prop: Property name to copy
* @return 0 if OK, -ve on error
*/
int acpi_dp_dev_copy_str(const struct udevice *dev, struct acpi_dp *dp,
const char *prop);
#endif