1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) 2023-2024, Ventana Micro Systems Inc
4 * Author: Sunil V L <sunilvl@ventanamicro.com>
5 */
6
7 #include <linux/acpi.h>
8 #include <linux/sort.h>
9 #include <linux/irq.h>
10
11 #include "init.h"
12
13 #define RISCV_ACPI_INTC_FLAG_PENDING BIT(0)
14
15 struct riscv_ext_intc_list {
16 acpi_handle handle;
17 u32 gsi_base;
18 u32 nr_irqs;
19 u32 nr_idcs;
20 u32 id;
21 u32 type;
22 u32 flag;
23 struct list_head list;
24 };
25
26 struct acpi_irq_dep_ctx {
27 int rc;
28 unsigned int index;
29 acpi_handle handle;
30 };
31
32 LIST_HEAD(ext_intc_list);
33
irqchip_cmp_func(const void * in0,const void * in1)34 static int irqchip_cmp_func(const void *in0, const void *in1)
35 {
36 struct acpi_probe_entry *elem0 = (struct acpi_probe_entry *)in0;
37 struct acpi_probe_entry *elem1 = (struct acpi_probe_entry *)in1;
38
39 return (elem0->type > elem1->type) - (elem0->type < elem1->type);
40 }
41
42 /*
43 * On RISC-V, RINTC structures in MADT should be probed before any other
44 * interrupt controller structures and IMSIC before APLIC. The interrupt
45 * controller subtypes in MADT of ACPI spec for RISC-V are defined in
46 * the incremental order like RINTC(24)->IMSIC(25)->APLIC(26)->PLIC(27).
47 * Hence, simply sorting the subtypes in incremental order will
48 * establish the required order.
49 */
arch_sort_irqchip_probe(struct acpi_probe_entry * ap_head,int nr)50 void arch_sort_irqchip_probe(struct acpi_probe_entry *ap_head, int nr)
51 {
52 struct acpi_probe_entry *ape = ap_head;
53
54 if (nr == 1 || !ACPI_COMPARE_NAMESEG(ACPI_SIG_MADT, ape->id))
55 return;
56 sort(ape, nr, sizeof(*ape), irqchip_cmp_func, NULL);
57 }
58
riscv_acpi_update_gsi_handle(u32 gsi_base,acpi_handle handle)59 static acpi_status riscv_acpi_update_gsi_handle(u32 gsi_base, acpi_handle handle)
60 {
61 struct riscv_ext_intc_list *ext_intc_element;
62 struct list_head *i, *tmp;
63
64 list_for_each_safe(i, tmp, &ext_intc_list) {
65 ext_intc_element = list_entry(i, struct riscv_ext_intc_list, list);
66 if (gsi_base == ext_intc_element->gsi_base) {
67 ext_intc_element->handle = handle;
68 return AE_OK;
69 }
70 }
71
72 return AE_NOT_FOUND;
73 }
74
riscv_acpi_update_gsi_range(u32 gsi_base,u32 nr_irqs)75 int riscv_acpi_update_gsi_range(u32 gsi_base, u32 nr_irqs)
76 {
77 struct riscv_ext_intc_list *ext_intc_element;
78
79 list_for_each_entry(ext_intc_element, &ext_intc_list, list) {
80 if (gsi_base == ext_intc_element->gsi_base &&
81 (ext_intc_element->flag & RISCV_ACPI_INTC_FLAG_PENDING)) {
82 ext_intc_element->nr_irqs = nr_irqs;
83 ext_intc_element->flag &= ~RISCV_ACPI_INTC_FLAG_PENDING;
84 return 0;
85 }
86 }
87
88 return -ENODEV;
89 }
90
riscv_acpi_get_gsi_info(struct fwnode_handle * fwnode,u32 * gsi_base,u32 * id,u32 * nr_irqs,u32 * nr_idcs)91 int riscv_acpi_get_gsi_info(struct fwnode_handle *fwnode, u32 *gsi_base,
92 u32 *id, u32 *nr_irqs, u32 *nr_idcs)
93 {
94 struct riscv_ext_intc_list *ext_intc_element;
95 struct list_head *i;
96
97 list_for_each(i, &ext_intc_list) {
98 ext_intc_element = list_entry(i, struct riscv_ext_intc_list, list);
99 if (ext_intc_element->handle == ACPI_HANDLE_FWNODE(fwnode)) {
100 *gsi_base = ext_intc_element->gsi_base;
101 *id = ext_intc_element->id;
102 *nr_irqs = ext_intc_element->nr_irqs;
103 if (nr_idcs)
104 *nr_idcs = ext_intc_element->nr_idcs;
105
106 return 0;
107 }
108 }
109
110 return -ENODEV;
111 }
112
riscv_acpi_get_gsi_domain_id(u32 gsi)113 struct fwnode_handle *riscv_acpi_get_gsi_domain_id(u32 gsi)
114 {
115 struct riscv_ext_intc_list *ext_intc_element;
116 struct acpi_device *adev;
117 struct list_head *i;
118
119 list_for_each(i, &ext_intc_list) {
120 ext_intc_element = list_entry(i, struct riscv_ext_intc_list, list);
121 if (gsi >= ext_intc_element->gsi_base &&
122 gsi < (ext_intc_element->gsi_base + ext_intc_element->nr_irqs)) {
123 adev = acpi_fetch_acpi_dev(ext_intc_element->handle);
124 if (!adev)
125 return NULL;
126
127 return acpi_fwnode_handle(adev);
128 }
129 }
130
131 return NULL;
132 }
133
riscv_acpi_register_ext_intc(u32 gsi_base,u32 nr_irqs,u32 nr_idcs,u32 id,u32 type)134 static int __init riscv_acpi_register_ext_intc(u32 gsi_base, u32 nr_irqs, u32 nr_idcs,
135 u32 id, u32 type)
136 {
137 struct riscv_ext_intc_list *ext_intc_element, *node, *prev;
138
139 ext_intc_element = kzalloc_obj(*ext_intc_element);
140 if (!ext_intc_element)
141 return -ENOMEM;
142
143 ext_intc_element->gsi_base = gsi_base;
144
145 /* If nr_irqs is zero, indicate it in flag and set to max range possible */
146 if (nr_irqs) {
147 ext_intc_element->nr_irqs = nr_irqs;
148 } else {
149 ext_intc_element->flag |= RISCV_ACPI_INTC_FLAG_PENDING;
150 ext_intc_element->nr_irqs = U32_MAX - ext_intc_element->gsi_base;
151 }
152
153 ext_intc_element->nr_idcs = nr_idcs;
154 ext_intc_element->id = id;
155 list_for_each_entry(node, &ext_intc_list, list) {
156 if (node->gsi_base < ext_intc_element->gsi_base)
157 break;
158 }
159
160 /* Adjust the previous node's GSI range if that has pending registration */
161 prev = list_prev_entry(node, list);
162 if (!list_entry_is_head(prev, &ext_intc_list, list)) {
163 if (prev->flag & RISCV_ACPI_INTC_FLAG_PENDING)
164 prev->nr_irqs = ext_intc_element->gsi_base - prev->gsi_base;
165 }
166
167 list_add_tail(&ext_intc_element->list, &node->list);
168 return 0;
169 }
170
riscv_acpi_create_gsi_map_smsi(acpi_handle handle,u32 level,void * context,void ** return_value)171 static acpi_status __init riscv_acpi_create_gsi_map_smsi(acpi_handle handle, u32 level,
172 void *context, void **return_value)
173 {
174 acpi_status status;
175 u64 gbase;
176
177 if (!acpi_has_method(handle, "_GSB")) {
178 acpi_handle_err(handle, "_GSB method not found\n");
179 return AE_ERROR;
180 }
181
182 status = acpi_evaluate_integer(handle, "_GSB", NULL, &gbase);
183 if (ACPI_FAILURE(status)) {
184 acpi_handle_err(handle, "failed to evaluate _GSB method\n");
185 return status;
186 }
187
188 riscv_acpi_register_ext_intc(gbase, 0, 0, 0, ACPI_RISCV_IRQCHIP_SMSI);
189 status = riscv_acpi_update_gsi_handle((u32)gbase, handle);
190 if (ACPI_FAILURE(status)) {
191 acpi_handle_err(handle, "failed to find the GSI mapping entry\n");
192 return status;
193 }
194
195 return AE_OK;
196 }
197
riscv_acpi_create_gsi_map(acpi_handle handle,u32 level,void * context,void ** return_value)198 static acpi_status __init riscv_acpi_create_gsi_map(acpi_handle handle, u32 level,
199 void *context, void **return_value)
200 {
201 acpi_status status;
202 u64 gbase;
203
204 if (!acpi_has_method(handle, "_GSB")) {
205 acpi_handle_err(handle, "_GSB method not found\n");
206 return AE_ERROR;
207 }
208
209 status = acpi_evaluate_integer(handle, "_GSB", NULL, &gbase);
210 if (ACPI_FAILURE(status)) {
211 acpi_handle_err(handle, "failed to evaluate _GSB method\n");
212 return status;
213 }
214
215 status = riscv_acpi_update_gsi_handle((u32)gbase, handle);
216 if (ACPI_FAILURE(status)) {
217 acpi_handle_err(handle, "failed to find the GSI mapping entry\n");
218 return status;
219 }
220
221 return AE_OK;
222 }
223
riscv_acpi_aplic_parse_madt(union acpi_subtable_headers * header,const unsigned long end)224 static int __init riscv_acpi_aplic_parse_madt(union acpi_subtable_headers *header,
225 const unsigned long end)
226 {
227 struct acpi_madt_aplic *aplic = (struct acpi_madt_aplic *)header;
228
229 return riscv_acpi_register_ext_intc(aplic->gsi_base, aplic->num_sources, aplic->num_idcs,
230 aplic->id, ACPI_RISCV_IRQCHIP_APLIC);
231 }
232
riscv_acpi_plic_parse_madt(union acpi_subtable_headers * header,const unsigned long end)233 static int __init riscv_acpi_plic_parse_madt(union acpi_subtable_headers *header,
234 const unsigned long end)
235 {
236 struct acpi_madt_plic *plic = (struct acpi_madt_plic *)header;
237
238 return riscv_acpi_register_ext_intc(plic->gsi_base, plic->num_irqs, 0,
239 plic->id, ACPI_RISCV_IRQCHIP_PLIC);
240 }
241
riscv_acpi_init_gsi_mapping(void)242 void __init riscv_acpi_init_gsi_mapping(void)
243 {
244 /* There can be either PLIC or APLIC */
245 if (acpi_table_parse_madt(ACPI_MADT_TYPE_PLIC, riscv_acpi_plic_parse_madt, 0) > 0) {
246 acpi_get_devices("RSCV0001", riscv_acpi_create_gsi_map, NULL, NULL);
247 return;
248 }
249
250 if (acpi_table_parse_madt(ACPI_MADT_TYPE_APLIC, riscv_acpi_aplic_parse_madt, 0) > 0)
251 acpi_get_devices("RSCV0002", riscv_acpi_create_gsi_map, NULL, NULL);
252
253 /* Unlike PLIC/APLIC, SYSMSI doesn't have MADT */
254 acpi_get_devices("RSCV0006", riscv_acpi_create_gsi_map_smsi, NULL, NULL);
255 }
256
riscv_acpi_get_gsi_handle(u32 gsi)257 static acpi_handle riscv_acpi_get_gsi_handle(u32 gsi)
258 {
259 struct riscv_ext_intc_list *ext_intc_element;
260 struct list_head *i;
261
262 list_for_each(i, &ext_intc_list) {
263 ext_intc_element = list_entry(i, struct riscv_ext_intc_list, list);
264 if (gsi >= ext_intc_element->gsi_base &&
265 gsi < (ext_intc_element->gsi_base + ext_intc_element->nr_irqs))
266 return ext_intc_element->handle;
267 }
268
269 return NULL;
270 }
271
riscv_acpi_irq_get_parent(struct acpi_resource * ares,void * context)272 static acpi_status riscv_acpi_irq_get_parent(struct acpi_resource *ares, void *context)
273 {
274 struct acpi_irq_dep_ctx *ctx = context;
275 struct acpi_resource_irq *irq;
276 struct acpi_resource_extended_irq *eirq;
277
278 switch (ares->type) {
279 case ACPI_RESOURCE_TYPE_IRQ:
280 irq = &ares->data.irq;
281 if (ctx->index >= irq->interrupt_count) {
282 ctx->index -= irq->interrupt_count;
283 return AE_OK;
284 }
285 ctx->handle = riscv_acpi_get_gsi_handle(irq->interrupts[ctx->index]);
286 return AE_CTRL_TERMINATE;
287 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
288 eirq = &ares->data.extended_irq;
289 if (eirq->producer_consumer == ACPI_PRODUCER)
290 return AE_OK;
291
292 if (ctx->index >= eirq->interrupt_count) {
293 ctx->index -= eirq->interrupt_count;
294 return AE_OK;
295 }
296
297 /* Support GSIs only */
298 if (eirq->resource_source.string_length)
299 return AE_OK;
300
301 ctx->handle = riscv_acpi_get_gsi_handle(eirq->interrupts[ctx->index]);
302 return AE_CTRL_TERMINATE;
303 }
304
305 return AE_OK;
306 }
307
riscv_acpi_irq_get_dep(acpi_handle handle,unsigned int index,acpi_handle * gsi_handle)308 static int riscv_acpi_irq_get_dep(acpi_handle handle, unsigned int index, acpi_handle *gsi_handle)
309 {
310 struct acpi_irq_dep_ctx ctx = {-EINVAL, index, NULL};
311
312 if (!gsi_handle)
313 return 0;
314
315 acpi_walk_resources(handle, METHOD_NAME__CRS, riscv_acpi_irq_get_parent, &ctx);
316 *gsi_handle = ctx.handle;
317 if (*gsi_handle)
318 return 1;
319
320 return 0;
321 }
322
riscv_acpi_add_prt_dep(acpi_handle handle)323 static u32 riscv_acpi_add_prt_dep(acpi_handle handle)
324 {
325 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
326 struct acpi_pci_routing_table *entry;
327 struct acpi_handle_list dep_devices;
328 acpi_handle gsi_handle;
329 acpi_handle link_handle;
330 acpi_status status;
331 u32 count = 0;
332
333 status = acpi_get_irq_routing_table(handle, &buffer);
334 if (ACPI_FAILURE(status)) {
335 acpi_handle_err(handle, "failed to get IRQ routing table\n");
336 kfree(buffer.pointer);
337 return 0;
338 }
339
340 entry = buffer.pointer;
341 while (entry && (entry->length > 0)) {
342 if (entry->source[0]) {
343 acpi_get_handle(handle, entry->source, &link_handle);
344 dep_devices.count = 1;
345 dep_devices.handles = kzalloc_objs(*dep_devices.handles,
346 1);
347 if (!dep_devices.handles) {
348 acpi_handle_err(handle, "failed to allocate memory\n");
349 continue;
350 }
351
352 dep_devices.handles[0] = link_handle;
353 count += acpi_scan_add_dep(handle, &dep_devices);
354 } else {
355 gsi_handle = riscv_acpi_get_gsi_handle(entry->source_index);
356 dep_devices.count = 1;
357 dep_devices.handles = kzalloc_objs(*dep_devices.handles,
358 1);
359 if (!dep_devices.handles) {
360 acpi_handle_err(handle, "failed to allocate memory\n");
361 continue;
362 }
363
364 dep_devices.handles[0] = gsi_handle;
365 count += acpi_scan_add_dep(handle, &dep_devices);
366 }
367
368 entry = (struct acpi_pci_routing_table *)
369 ((unsigned long)entry + entry->length);
370 }
371
372 kfree(buffer.pointer);
373 return count;
374 }
375
riscv_acpi_add_irq_dep(acpi_handle handle)376 static u32 riscv_acpi_add_irq_dep(acpi_handle handle)
377 {
378 struct acpi_handle_list dep_devices;
379 acpi_handle gsi_handle;
380 u32 count = 0;
381 int i;
382
383 for (i = 0;
384 riscv_acpi_irq_get_dep(handle, i, &gsi_handle);
385 i++) {
386 dep_devices.count = 1;
387 dep_devices.handles = kzalloc_objs(*dep_devices.handles, 1);
388 if (!dep_devices.handles) {
389 acpi_handle_err(handle, "failed to allocate memory\n");
390 continue;
391 }
392
393 dep_devices.handles[0] = gsi_handle;
394 count += acpi_scan_add_dep(handle, &dep_devices);
395 }
396
397 return count;
398 }
399
arch_acpi_add_auto_dep(acpi_handle handle)400 u32 arch_acpi_add_auto_dep(acpi_handle handle)
401 {
402 if (acpi_has_method(handle, "_PRT"))
403 return riscv_acpi_add_prt_dep(handle);
404
405 return riscv_acpi_add_irq_dep(handle);
406 }
407