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