acpi: Support writing Device Properties objects via _DSD
[platform/kernel/u-boot.git] / include / acpi / acpi_dp.h
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 /*
15  * Writing Device Properties objects via _DSD
16  *
17  * This is described in ACPI 6.3 section 6.2.5
18  *
19  * This provides a structure to handle nested device-specific data which ends
20  * up in a _DSD table.
21  *
22  * https://www.kernel.org/doc/html/latest/firmware-guide/acpi/DSD-properties-rules.html
23  * https://uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
24  * https://uefi.org/sites/default/files/resources/_DSD-hierarchical-data-extension-UUID-v1.1.pdf
25  *
26  * The Device Property Hierarchy can be multiple levels deep with multiple
27  * children possible in each level.  In order to support this flexibility
28  * the device property hierarchy must be built up before being written out.
29  *
30  * For example:
31  *
32  * Child table with string and integer:
33  * struct acpi_dp *child = acpi_dp_new_table("CHLD");
34  * acpi_dp_add_string(child, "childstring", "CHILD");
35  * acpi_dp_add_integer(child, "childint", 100);
36  *
37  * _DSD table with integer and gpio and child pointer:
38  * struct acpi_dp *dsd = acpi_dp_new_table("_DSD");
39  * acpi_dp_add_integer(dsd, "number1", 1);
40  * acpi_dp_add_gpio(dsd, "gpio", "\_SB.PCI0.GPIO", 0, 0, 1);
41  * acpi_dp_add_child(dsd, "child", child);
42  *
43  * Write entries into SSDT and clean up resources:
44  * acpi_dp_write(dsd);
45  *
46  * Name(_DSD, Package() {
47  *   ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301")
48  *   Package() {
49  *     Package() { "gpio", Package() { \_SB.PCI0.GPIO, 0, 0, 0 } }
50  *     Package() { "number1", 1 }
51  *   }
52  *   ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b")
53  *   Package() {
54  *     Package() { "child", CHLD }
55  *   }
56  * }
57  * Name(CHLD, Package() {
58  *   ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301")
59  *   Package() {
60  *     Package() { "childstring", "CHILD" }
61  *     Package() { "childint", 100 }
62  *   }
63  * }
64  */
65
66 #define ACPI_DP_UUID            "daffd814-6eba-4d8c-8a91-bc9bbf4aa301"
67 #define ACPI_DP_CHILD_UUID      "dbb8e3e6-5886-4ba6-8795-1319f52a966b"
68
69 /**
70  * enum acpi_dp_type - types of device property objects
71  *
72  * These refer to the types defined by struct acpi_dp below
73  *
74  * @ACPI_DP_TYPE_UNKNOWN: Unknown / do not use
75  * @ACPI_DP_TYPE_INTEGER: Integer value (u64) in @integer
76  * @ACPI_DP_TYPE_STRING: String value in @string
77  * @ACPI_DP_TYPE_REFERENCE: Reference to another object, with value in @string
78  * @ACPI_DP_TYPE_TABLE: Type for a top-level table which may have children
79  * @ACPI_DP_TYPE_ARRAY: Array of items with first item in @array and following
80  *      items linked from that item's @next
81  * @ACPI_DP_TYPE_CHILD: Child object, with siblings in that child's @next
82  */
83 enum acpi_dp_type {
84         ACPI_DP_TYPE_UNKNOWN,
85         ACPI_DP_TYPE_INTEGER,
86         ACPI_DP_TYPE_STRING,
87         ACPI_DP_TYPE_REFERENCE,
88         ACPI_DP_TYPE_TABLE,
89         ACPI_DP_TYPE_ARRAY,
90         ACPI_DP_TYPE_CHILD,
91 };
92
93 /**
94  * struct acpi_dp - ACPI device properties
95  *
96  * @type: Table type
97  * @name: Name of object, typically _DSD but could be CHLD for a child object.
98  *      This can be NULL if there is no name
99  * @next: Next object in list (next array element or next sibling)
100  * @child: Pointer to first child, if @type == ACPI_DP_TYPE_CHILD, else NULL
101  * @array: First array element, if @type == ACPI_DP_TYPE_ARRAY, else NULL
102  * @integer: Integer value of the property, if @type == ACPI_DP_TYPE_INTEGER
103  * @string: String value of the property, if @type == ACPI_DP_TYPE_STRING;
104  *      child name if @type == ACPI_DP_TYPE_CHILD;
105  *      reference name if @type == ACPI_DP_TYPE_REFERENCE;
106  */
107 struct acpi_dp {
108         enum acpi_dp_type type;
109         const char *name;
110         struct acpi_dp *next;
111         union {
112                 struct acpi_dp *child;
113                 struct acpi_dp *array;
114         };
115         union {
116                 u64 integer;
117                 const char *string;
118         };
119 };
120
121 /**
122  * acpi_dp_new_table() - Start a new Device Property table
123  *
124  * @ref: ACPI reference (e.g. "_DSD")
125  * @return pointer to table, or NULL if out of memory
126  */
127 struct acpi_dp *acpi_dp_new_table(const char *ref);
128
129 /**
130  * acpi_dp_add_integer() - Add integer Device Property
131  *
132  * A new node is added to the end of the property list of @dp
133  *
134  * @dp: Table to add this property to
135  * @name: Name of property, or NULL for none
136  * @value: Integer value
137  * @return pointer to new node, or NULL if out of memory
138  */
139 struct acpi_dp *acpi_dp_add_integer(struct acpi_dp *dp, const char *name,
140                                     u64 value);
141
142 /**
143  * acpi_dp_add_string() - Add string Device Property
144  *
145  * A new node is added to the end of the property list of @dp
146  *
147  * @dp: Table to add this property to
148  * @name: Name of property, or NULL for none
149  * @string: String value
150  * @return pointer to new node, or NULL if out of memory
151  */
152 struct acpi_dp *acpi_dp_add_string(struct acpi_dp *dp, const char *name,
153                                    const char *string);
154
155 /**
156  * acpi_dp_add_reference() - Add reference Device Property
157  *
158  * A new node is added to the end of the property list of @dp
159  *
160  * @dp: Table to add this property to
161  * @name: Name of property, or NULL for none
162  * @reference: Reference value
163  * @return pointer to new node, or NULL if out of memory
164  */
165 struct acpi_dp *acpi_dp_add_reference(struct acpi_dp *dp, const char *name,
166                                       const char *reference);
167
168 /**
169  * acpi_dp_add_array() - Add array Device Property
170  *
171  * A new node is added to the end of the property list of @dp, with the array
172  * attached to that.
173  *
174  * @dp: Table to add this property to
175  * @name: Name of property, or NULL for none
176  * @return pointer to new node, or NULL if out of memory
177  */
178 struct acpi_dp *acpi_dp_add_array(struct acpi_dp *dp, struct acpi_dp *array);
179
180 /**
181  * acpi_dp_add_integer_array() - Add an array of integers
182  *
183  * A new node is added to the end of the property list of @dp, with the array
184  * attached to that. Each element of the array becomes a new node.
185  *
186  * @dp: Table to add this property to
187  * @name: Name of property, or NULL for none
188  * @return pointer to new array node, or NULL if out of memory
189  */
190 struct acpi_dp *acpi_dp_add_integer_array(struct acpi_dp *dp, const char *name,
191                                           u64 *array, int len);
192
193 /**
194  * acpi_dp_add_child() - Add a child table of Device Properties
195  *
196  * A new node is added as a child of @dp
197  *
198  * @dp: Table to add this child to
199  * @name: Name of child, or NULL for none
200  * @child: Child node to add
201  * @return pointer to new child node, or NULL if out of memory
202  */
203 struct acpi_dp *acpi_dp_add_child(struct acpi_dp *dp, const char *name,
204                                   struct acpi_dp *child);
205
206 /**
207  * acpi_dp_write() - Write Device Property hierarchy and clean up resources
208  *
209  * This writes the table using acpigen and then frees it
210  *
211  * @ctx: ACPI context
212  * @table: Table to write
213  * @return 0 if OK, -ve on error
214  */
215 int acpi_dp_write(struct acpi_ctx *ctx, struct acpi_dp *table);
216
217 #endif