1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Device properties, a temporary data structure for adding to ACPI code 4 * 5 * Copyright 2019 Google LLC 6 * Mostly taken from coreboot file acpi_device.h 7 */ 8 9 #ifndef __ACPI_DP_H 10 #define __ACPI_DP_H 11 12 struct acpi_ctx; 13 14 #include <acpi/acpi_device.h> 15 16 /* 17 * Writing Device Properties objects via _DSD 18 * 19 * This is described in ACPI 6.3 section 6.2.5 20 * 21 * This provides a structure to handle nested device-specific data which ends 22 * up in a _DSD table. 23 * 24 * https://www.kernel.org/doc/html/latest/firmware-guide/acpi/DSD-properties-rules.html 25 * https://uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf 26 * https://uefi.org/sites/default/files/resources/_DSD-hierarchical-data-extension-UUID-v1.1.pdf 27 * 28 * The Device Property Hierarchy can be multiple levels deep with multiple 29 * children possible in each level. In order to support this flexibility 30 * the device property hierarchy must be built up before being written out. 31 * 32 * For example: 33 * 34 * Child table with string and integer: 35 * struct acpi_dp *child = acpi_dp_new_table("CHLD"); 36 * acpi_dp_add_string(child, "childstring", "CHILD"); 37 * acpi_dp_add_integer(child, "childint", 100); 38 * 39 * _DSD table with integer and gpio and child pointer: 40 * struct acpi_dp *dsd = acpi_dp_new_table("_DSD"); 41 * acpi_dp_add_integer(dsd, "number1", 1); 42 * acpi_dp_add_gpio(dsd, "gpio", "\_SB.PCI0.GPIO", 0, 0, 1); 43 * acpi_dp_add_child(dsd, "child", child); 44 * 45 * Write entries into SSDT and clean up resources: 46 * acpi_dp_write(dsd); 47 * 48 * Name(_DSD, Package() { 49 * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301") 50 * Package() { 51 * Package() { "gpio", Package() { \_SB.PCI0.GPIO, 0, 0, 0 } } 52 * Package() { "number1", 1 } 53 * } 54 * ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b") 55 * Package() { 56 * Package() { "child", CHLD } 57 * } 58 * } 59 * Name(CHLD, Package() { 60 * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301") 61 * Package() { 62 * Package() { "childstring", "CHILD" } 63 * Package() { "childint", 100 } 64 * } 65 * } 66 */ 67 68 #define ACPI_DP_UUID "daffd814-6eba-4d8c-8a91-bc9bbf4aa301" 69 #define ACPI_DP_CHILD_UUID "dbb8e3e6-5886-4ba6-8795-1319f52a966b" 70 71 /** 72 * enum acpi_dp_type - types of device property objects 73 * 74 * These refer to the types defined by struct acpi_dp below 75 * 76 * @ACPI_DP_TYPE_UNKNOWN: Unknown / do not use 77 * @ACPI_DP_TYPE_INTEGER: Integer value (u64) in @integer 78 * @ACPI_DP_TYPE_STRING: String value in @string 79 * @ACPI_DP_TYPE_REFERENCE: Reference to another object, with value in @string 80 * @ACPI_DP_TYPE_TABLE: Type for a top-level table which may have children 81 * @ACPI_DP_TYPE_ARRAY: Array of items with first item in @array and following 82 * items linked from that item's @next 83 * @ACPI_DP_TYPE_CHILD: Child object, with siblings in that child's @next 84 */ 85 enum acpi_dp_type { 86 ACPI_DP_TYPE_UNKNOWN, 87 ACPI_DP_TYPE_INTEGER, 88 ACPI_DP_TYPE_STRING, 89 ACPI_DP_TYPE_REFERENCE, 90 ACPI_DP_TYPE_TABLE, 91 ACPI_DP_TYPE_ARRAY, 92 ACPI_DP_TYPE_CHILD, 93 }; 94 95 /** 96 * struct acpi_dp - ACPI device properties 97 * 98 * @type: Table type 99 * @name: Name of object, typically _DSD but could be CHLD for a child object. 100 * This can be NULL if there is no name 101 * @next: Next object in list (next array element or next sibling) 102 * @child: Pointer to first child, if @type == ACPI_DP_TYPE_CHILD, else NULL 103 * @array: First array element, if @type == ACPI_DP_TYPE_ARRAY, else NULL 104 * @integer: Integer value of the property, if @type == ACPI_DP_TYPE_INTEGER 105 * @string: String value of the property, if @type == ACPI_DP_TYPE_STRING; 106 * child name if @type == ACPI_DP_TYPE_CHILD; 107 * reference name if @type == ACPI_DP_TYPE_REFERENCE; 108 */ 109 struct acpi_dp { 110 enum acpi_dp_type type; 111 const char *name; 112 struct acpi_dp *next; 113 union { 114 struct acpi_dp *child; 115 struct acpi_dp *array; 116 }; 117 union { 118 u64 integer; 119 const char *string; 120 }; 121 }; 122 123 /** 124 * acpi_dp_new_table() - Start a new Device Property table 125 * 126 * @ref: ACPI reference (e.g. "_DSD") 127 * @return pointer to table, or NULL if out of memory 128 */ 129 struct acpi_dp *acpi_dp_new_table(const char *ref); 130 131 /** 132 * acpi_dp_add_integer() - Add integer Device Property 133 * 134 * A new node is added to the end of the property list of @dp 135 * 136 * @dp: Table to add this property to 137 * @name: Name of property, or NULL for none 138 * @value: Integer value 139 * @return pointer to new node, or NULL if out of memory 140 */ 141 struct acpi_dp *acpi_dp_add_integer(struct acpi_dp *dp, const char *name, 142 u64 value); 143 144 /** 145 * acpi_dp_add_string() - Add string Device Property 146 * 147 * A new node is added to the end of the property list of @dp 148 * 149 * @dp: Table to add this property to 150 * @name: Name of property, or NULL for none 151 * @string: String value 152 * @return pointer to new node, or NULL if out of memory 153 */ 154 struct acpi_dp *acpi_dp_add_string(struct acpi_dp *dp, const char *name, 155 const char *string); 156 157 /** 158 * acpi_dp_add_reference() - Add reference Device Property 159 * 160 * A new node is added to the end of the property list of @dp 161 * 162 * @dp: Table to add this property to 163 * @name: Name of property, or NULL for none 164 * @reference: Reference value 165 * @return pointer to new node, or NULL if out of memory 166 */ 167 struct acpi_dp *acpi_dp_add_reference(struct acpi_dp *dp, const char *name, 168 const char *reference); 169 170 /** 171 * acpi_dp_add_array() - Add array Device Property 172 * 173 * A new node is added to the end of the property list of @dp, with the array 174 * attached to that. 175 * 176 * @dp: Table to add this property to 177 * @name: Name of property, or NULL for none 178 * @return pointer to new node, or NULL if out of memory 179 */ 180 struct acpi_dp *acpi_dp_add_array(struct acpi_dp *dp, struct acpi_dp *array); 181 182 /** 183 * acpi_dp_add_integer_array() - Add an array of integers 184 * 185 * A new node is added to the end of the property list of @dp, with the array 186 * attached to that. Each element of the array becomes a new node. 187 * 188 * @dp: Table to add this property to 189 * @name: Name of property, or NULL for none 190 * @return pointer to new array node, or NULL if out of memory 191 */ 192 struct acpi_dp *acpi_dp_add_integer_array(struct acpi_dp *dp, const char *name, 193 u64 *array, int len); 194 195 /** 196 * acpi_dp_add_child() - Add a child table of Device Properties 197 * 198 * A new node is added as a child of @dp 199 * 200 * @dp: Table to add this child to 201 * @name: Name of child, or NULL for none 202 * @child: Child node to add 203 * @return pointer to new child node, or NULL if out of memory 204 */ 205 struct acpi_dp *acpi_dp_add_child(struct acpi_dp *dp, const char *name, 206 struct acpi_dp *child); 207 208 /** 209 * acpi_dp_add_gpio() - Add a GPIO to a list of Device Properties 210 * 211 * A new node is added to the end of the property list of @dp, with the 212 * GPIO properties added to the the new node 213 * 214 * @dp: Table to add this property to 215 * @name: Name of property 216 * @ref: Reference to device with a _CRS containing GpioIO or GpioInt 217 * @index: Index of the GPIO resource in _CRS starting from zero 218 * @pin: Pin in the GPIO resource, typically zero 219 * @polarity: GPIO polarity. Note that ACPI_IRQ_ACTIVE_BOTH is not supported 220 * @return pointer to new node, or NULL if out of memory 221 */ 222 struct acpi_dp *acpi_dp_add_gpio(struct acpi_dp *dp, const char *name, 223 const char *ref, int index, int pin, 224 enum acpi_gpio_polarity polarity); 225 226 /** 227 * acpi_dp_write() - Write Device Property hierarchy and clean up resources 228 * 229 * This writes the table using acpigen and then frees it 230 * 231 * @ctx: ACPI context 232 * @table: Table to write 233 * @return 0 if OK, -ve on error 234 */ 235 int acpi_dp_write(struct acpi_ctx *ctx, struct acpi_dp *table); 236 237 /** 238 * acpi_dp_ofnode_copy_int() - Copy a property from device tree to DP 239 * 240 * This copies an integer property from the device tree to the ACPI DP table. 241 * 242 * @node: Node to copy from 243 * @dp: DP to copy to 244 * @prop: Property name to copy 245 * @return 0 if OK, -ve on error 246 */ 247 int acpi_dp_ofnode_copy_int(ofnode node, struct acpi_dp *dp, const char *prop); 248 249 /** 250 * acpi_dp_ofnode_copy_str() - Copy a property from device tree to DP 251 * 252 * This copies a string property from the device tree to the ACPI DP table. 253 * 254 * @node: Node to copy from 255 * @dp: DP to copy to 256 * @prop: Property name to copy 257 * @return 0 if OK, -ve on error 258 */ 259 int acpi_dp_ofnode_copy_str(ofnode node, struct acpi_dp *dp, const char *prop); 260 261 /** 262 * acpi_dp_dev_copy_int() - Copy a property from device tree to DP 263 * 264 * This copies an integer property from the device tree to the ACPI DP table. 265 * 266 * @dev: Device to copy from 267 * @dp: DP to copy to 268 * @prop: Property name to copy 269 * @return 0 if OK, -ve on error 270 */ 271 int acpi_dp_dev_copy_int(const struct udevice *dev, struct acpi_dp *dp, 272 const char *prop); 273 274 /** 275 * acpi_dp_dev_copy_str() - Copy a property from device tree to DP 276 * 277 * This copies a string property from the device tree to the ACPI DP table. 278 * 279 * @dev: Device to copy from 280 * @dp: DP to copy to 281 * @prop: Property name to copy 282 * @return 0 if OK, -ve on error 283 */ 284 int acpi_dp_dev_copy_str(const struct udevice *dev, struct acpi_dp *dp, 285 const char *prop); 286 287 #endif 288