Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | /* 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_gpio_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 |