1 /*
2 * Copyright (c) 2023 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #ifndef ZEPHYR_INCLUDE_DRIVERS_ACPI_H_
7 #define ZEPHYR_INCLUDE_DRIVERS_ACPI_H_
8 #include <acpica/source/include/acpi.h>
9 #include <zephyr/drivers/pcie/pcie.h>
10
11 #define ACPI_RES_INVALID ACPI_RESOURCE_TYPE_MAX
12
13 #define ACPI_DRHD_FLAG_INCLUDE_PCI_ALL BIT(0)
14 #define ACPI_DMAR_FLAG_INTR_REMAP BIT(0)
15 #define ACPI_DMAR_FLAG_X2APIC_OPT_OUT BIT(1)
16 #define ACPI_DMAR_FLAG_DMA_CTRL_PLATFORM_OPT_IN BIT(2)
17
18 #define ACPI_MMIO_GET(res) (res)->reg_base[0].mmio
19 #define ACPI_IO_GET(res) (res)->reg_base[0].port
20 #define ACPI_RESOURCE_SIZE_GET(res) (res)->reg_base[0].length
21 #define ACPI_RESOURCE_TYPE_GET(res) (res)->reg_base[0].type
22
23 #define ACPI_MULTI_MMIO_GET(res, idx) (res)->reg_base[idx].mmio
24 #define ACPI_MULTI_IO_GET(res, idx) (res)->reg_base[idx].port
25 #define ACPI_MULTI_RESOURCE_SIZE_GET(res, idx) (res)->reg_base[idx].length
26 #define ACPI_MULTI_RESOURCE_TYPE_GET(res, idx) (res)->reg_base[idx].type
27
28 #define ACPI_RESOURCE_COUNT_GET(res) (res)->mmio_max
29
30 enum acpi_res_type {
31 /** IO mapped Resource type */
32 ACPI_RES_TYPE_IO,
33 /** Memory mapped Resource type */
34 ACPI_RES_TYPE_MEM,
35 /** Unknown Resource type */
36 ACPI_RES_TYPE_UNKNOWN,
37 };
38
39 struct acpi_dev {
40 ACPI_HANDLE handle;
41 char *path;
42 ACPI_RESOURCE *res_lst;
43 int res_type;
44 ACPI_DEVICE_INFO *dev_info;
45 };
46
47 union acpi_dmar_id {
48 struct {
49 uint16_t function: 3;
50 uint16_t device: 5;
51 uint16_t bus: 8;
52 } bits;
53
54 uint16_t raw;
55 };
56
57 struct acpi_mcfg {
58 ACPI_TABLE_HEADER header;
59 uint64_t _reserved;
60 ACPI_MCFG_ALLOCATION pci_segs[];
61 } __packed;
62
63 struct acpi_irq_resource {
64 uint32_t flags;
65 uint8_t irq_vector_max;
66 uint16_t *irqs;
67 };
68
69 struct acpi_reg_base {
70 enum acpi_res_type type;
71 union {
72 uintptr_t mmio;
73 uintptr_t port;
74 };
75 uint32_t length;
76 };
77
78 struct acpi_mmio_resource {
79 uint8_t mmio_max;
80 struct acpi_reg_base *reg_base;
81 };
82
83 /**
84 * @brief Get the ACPI HID for a node
85 *
86 * @param node_id DTS node identifier
87 * @return The HID of the ACPI node
88 */
89 #define ACPI_DT_HID(node_id) DT_PROP(node_id, acpi_hid)
90
91 /**
92 * @brief Get the ACPI UID for a node if one exist
93 *
94 * @param node_id DTS node identifier
95 * @return The UID of the ACPI node else NULL if does not exist
96 */
97 #define ACPI_DT_UID(node_id) DT_PROP_OR(node_id, acpi_uid, NULL)
98
99 /**
100 * @brief check whether the node has ACPI HID property or not
101 *
102 * @param node_id DTS node identifier
103 * @return 1 if the node has the HID, 0 otherwise.
104 */
105 #define ACPI_DT_HAS_HID(node_id) DT_NODE_HAS_PROP(node_id, acpi_hid)
106
107 /**
108 * @brief check whether the node has ACPI UID property or not
109 *
110 * @param node_id DTS node identifier
111 * @return 1 if the node has the UID, 0 otherwise.
112 */
113 #define ACPI_DT_HAS_UID(node_id) DT_NODE_HAS_PROP(node_id, acpi_uid)
114
115 /**
116 * @brief Init legacy interrupt routing table information from ACPI.
117 * Currently assume platform have only one PCI bus.
118 *
119 * @param hid the hardware id of the ACPI child device
120 * @param uid the unique id of the ACPI child device. The uid can be
121 * NULL if only one device with given hid present in the platform.
122 * @return return 0 on success or error code
123 */
124 int acpi_legacy_irq_init(const char *hid, const char *uid);
125
126 /**
127 * @brief Retrieve a legacy interrupt number for a PCI device.
128 *
129 * @param bdf the BDF of endpoint/PCI device
130 * @return return IRQ number or UINT_MAX if not found
131 */
132 uint32_t acpi_legacy_irq_get(pcie_bdf_t bdf);
133
134 /**
135 * @brief Retrieve the current resource settings of a device.
136 *
137 * @param dev_name the name of the device
138 * @param res the list of acpi resource list
139 * @return return 0 on success or error code
140 */
141 int acpi_current_resource_get(char *dev_name, ACPI_RESOURCE **res);
142
143 /**
144 * @brief Retrieve possible resource settings of a device.
145 *
146 * @param dev_name the name of the device
147 * @param res the list of acpi resource list
148 * @return return 0 on success or error code
149 */
150 int acpi_possible_resource_get(char *dev_name, ACPI_RESOURCE **res);
151
152 /**
153 * @brief Free current resource list memory which is retrieved by
154 * acpi_current_resource_get().
155 *
156 * @param res the list of acpi resource list
157 * @return return 0 on success or error code
158 */
159 int acpi_current_resource_free(ACPI_RESOURCE *res);
160
161 /**
162 * @brief Parse resource table for a given resource type.
163 *
164 * @param res the list of acpi resource list
165 * @param res_type the acpi resource type
166 * @return resource list for the given type on success or NULL
167 */
168 ACPI_RESOURCE *acpi_resource_parse(ACPI_RESOURCE *res, int res_type);
169
170 /**
171 * @brief Retrieve ACPI device info for given hardware id and unique id.
172 *
173 * @param hid the hardware id of the ACPI child device
174 * @param uid the unique id of the ACPI child device. The uid can be
175 * NULL if only one device with given HID present in the platform.
176 * @return ACPI child device info on success or NULL
177 */
178 struct acpi_dev *acpi_device_get(const char *hid, const char *uid);
179
180 /**
181 * @brief Retrieve acpi device info from the index.
182 *
183 * @param index the device index of an acpi child device
184 * @return acpi child device info on success or NULL
185 */
186 struct acpi_dev *acpi_device_by_index_get(int index);
187
188 /**
189 * @brief Parse resource table for irq info.
190 *
191 * @param res_lst the list of acpi resource list
192 * @return irq resource list on success or NULL
193 */
acpi_irq_res_get(ACPI_RESOURCE * res_lst)194 static inline ACPI_RESOURCE_IRQ *acpi_irq_res_get(ACPI_RESOURCE *res_lst)
195 {
196 ACPI_RESOURCE *res = acpi_resource_parse(res_lst, ACPI_RESOURCE_TYPE_IRQ);
197
198 return res ? &res->Data.Irq : NULL;
199 }
200
201 /**
202 * @brief Parse resource table for irq info.
203 *
204 * @param child_dev the device object of the ACPI node
205 * @param irq_res irq resource info
206 * @return return 0 on success or error code
207 */
208 int acpi_device_irq_get(struct acpi_dev *child_dev, struct acpi_irq_resource *irq_res);
209
210 /**
211 * @brief Parse resource table for MMIO info.
212 *
213 * @param child_dev the device object of the ACPI node
214 * @param mmio_res MMIO resource info
215 * @return return 0 on success or error code
216 */
217 int acpi_device_mmio_get(struct acpi_dev *child_dev, struct acpi_mmio_resource *mmio_res);
218
219 /**
220 * @brief Parse resource table for identify resource type.
221 *
222 * @param res the list of acpi resource list
223 * @return resource type on success or invalid resource type
224 */
225 int acpi_device_type_get(ACPI_RESOURCE *res);
226
227 /**
228 * @brief Retrieve acpi table for the given signature.
229 *
230 * @param signature pointer to the 4-character ACPI signature for the requested table
231 * @param inst instance number for the requested table
232 * @return acpi_table pointer to the acpi table on success else return NULL
233 */
234 void *acpi_table_get(char *signature, int inst);
235
236 /**
237 * @brief retrieve acpi MAD table for the given type.
238 *
239 * @param type type of requested MAD table
240 * @param tables pointer to the MAD table
241 * @param num_inst number of instance for the requested table
242 * @return return 0 on success or error code
243 */
244 int acpi_madt_entry_get(int type, ACPI_SUBTABLE_HEADER **tables, int *num_inst);
245
246 /**
247 * @brief retrieve DMA remapping structure for the given type.
248 *
249 * @param type type of remapping structure
250 * @param tables pointer to the dmar id structure
251 * @return return 0 on success or error code
252 */
253 int acpi_dmar_entry_get(enum AcpiDmarType type, ACPI_SUBTABLE_HEADER **tables);
254
255 /**
256 * @brief retrieve acpi DRHD info for the given scope.
257 *
258 * @param scope scope of requested DHRD table
259 * @param dev_scope pointer to the sub table (optional)
260 * @param dmar_id pointer to the DHRD info
261 * @param num_inst number of instance for the requested table
262 * @param max_inst maximum number of entry for the given dmar_id buffer
263 * @return return 0 on success or error code
264 */
265 int acpi_drhd_get(enum AcpiDmarScopeType scope, ACPI_DMAR_DEVICE_SCOPE *dev_scope,
266 union acpi_dmar_id *dmar_id, int *num_inst, int max_inst);
267
268 typedef void (*dmar_foreach_subtable_func_t)(ACPI_DMAR_HEADER *subtable, void *arg);
269 typedef void (*dmar_foreach_devscope_func_t)(ACPI_DMAR_DEVICE_SCOPE *devscope, void *arg);
270
271 void acpi_dmar_foreach_subtable(ACPI_TABLE_DMAR *dmar, dmar_foreach_subtable_func_t func,
272 void *arg);
273 void acpi_dmar_foreach_devscope(ACPI_DMAR_HARDWARE_UNIT *hu,
274 dmar_foreach_devscope_func_t func, void *arg);
275
276 /**
277 * @brief Retrieve IOAPIC id
278 *
279 * @param ioapic_id IOAPIC id
280 * @return return 0 on success or error code
281 */
282 int acpi_dmar_ioapic_get(uint16_t *ioapic_id);
283
284 /**
285 * @brief Retrieve the 'n'th enabled local apic info.
286 *
287 * @param cpu_num the cpu number
288 * @return local apic info on success or NULL otherwise
289 */
290 ACPI_MADT_LOCAL_APIC *acpi_local_apic_get(int cpu_num);
291
292 /**
293 * @brief invoke an ACPI method and return the result.
294 *
295 * @param path the path name of the ACPI object
296 * @param arg_list the list of arguments to be pass down
297 * @param ret_obj the ACPI result to be return
298 * @return return 0 on success or error code
299 */
300 int acpi_invoke_method(char *path, ACPI_OBJECT_LIST *arg_list, ACPI_OBJECT *ret_obj);
301
302 #endif
303