Skip to content

Commit f8619b6

Browse files
vlsunilrafaeljw
authored andcommitted
irqchip/riscv-intc: Add ACPI support for AIA
The RINTC subtype structure in MADT also has information about other interrupt controllers. Save this information and provide interfaces to retrieve them when required by corresponding drivers. Signed-off-by: Sunil V L <[email protected]> Reviewed-by: Anup Patel <[email protected]> Tested-by: Björn Töpel <[email protected]> Acked-by: Thomas Gleixner <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 1b173cc commit f8619b6

File tree

2 files changed

+123
-0
lines changed

2 files changed

+123
-0
lines changed

arch/riscv/include/asm/irq.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
#include <asm-generic/irq.h>
1414

15+
#define INVALID_CONTEXT UINT_MAX
16+
1517
void riscv_set_intc_hwnode_fn(struct fwnode_handle *(*fn)(void));
1618

1719
struct fwnode_handle *riscv_get_intc_hwnode(void);
@@ -28,6 +30,11 @@ enum riscv_irqchip_type {
2830
int riscv_acpi_get_gsi_info(struct fwnode_handle *fwnode, u32 *gsi_base,
2931
u32 *id, u32 *nr_irqs, u32 *nr_idcs);
3032
struct fwnode_handle *riscv_acpi_get_gsi_domain_id(u32 gsi);
33+
unsigned long acpi_rintc_index_to_hartid(u32 index);
34+
unsigned long acpi_rintc_ext_parent_to_hartid(unsigned int plic_id, unsigned int ctxt_idx);
35+
unsigned int acpi_rintc_get_plic_nr_contexts(unsigned int plic_id);
36+
unsigned int acpi_rintc_get_plic_context(unsigned int plic_id, unsigned int ctxt_idx);
37+
int __init acpi_rintc_get_imsic_mmio_info(u32 index, struct resource *res);
3138

3239
#else
3340
static inline int riscv_acpi_get_gsi_info(struct fwnode_handle *fwnode, u32 *gsi_base,
@@ -36,6 +43,32 @@ static inline int riscv_acpi_get_gsi_info(struct fwnode_handle *fwnode, u32 *gsi
3643
return 0;
3744
}
3845

46+
static inline unsigned long acpi_rintc_index_to_hartid(u32 index)
47+
{
48+
return INVALID_HARTID;
49+
}
50+
51+
static inline unsigned long acpi_rintc_ext_parent_to_hartid(unsigned int plic_id,
52+
unsigned int ctxt_idx)
53+
{
54+
return INVALID_HARTID;
55+
}
56+
57+
static inline unsigned int acpi_rintc_get_plic_nr_contexts(unsigned int plic_id)
58+
{
59+
return INVALID_CONTEXT;
60+
}
61+
62+
static inline unsigned int acpi_rintc_get_plic_context(unsigned int plic_id, unsigned int ctxt_idx)
63+
{
64+
return INVALID_CONTEXT;
65+
}
66+
67+
static inline int __init acpi_rintc_get_imsic_mmio_info(u32 index, struct resource *res)
68+
{
69+
return 0;
70+
}
71+
3972
#endif /* CONFIG_ACPI */
4073

4174
#endif /* _ASM_RISCV_IRQ_H */

drivers/irqchip/irq-riscv-intc.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,85 @@ IRQCHIP_DECLARE(andes, "andestech,cpu-intc", riscv_intc_init);
250250

251251
#ifdef CONFIG_ACPI
252252

253+
struct rintc_data {
254+
union {
255+
u32 ext_intc_id;
256+
struct {
257+
u32 context_id : 16,
258+
reserved : 8,
259+
aplic_plic_id : 8;
260+
};
261+
};
262+
unsigned long hart_id;
263+
u64 imsic_addr;
264+
u32 imsic_size;
265+
};
266+
267+
static u32 nr_rintc;
268+
static struct rintc_data *rintc_acpi_data[NR_CPUS];
269+
270+
#define for_each_matching_plic(_plic_id) \
271+
unsigned int _plic; \
272+
\
273+
for (_plic = 0; _plic < nr_rintc; _plic++) \
274+
if (rintc_acpi_data[_plic]->aplic_plic_id != _plic_id) \
275+
continue; \
276+
else
277+
278+
unsigned int acpi_rintc_get_plic_nr_contexts(unsigned int plic_id)
279+
{
280+
unsigned int nctx = 0;
281+
282+
for_each_matching_plic(plic_id)
283+
nctx++;
284+
285+
return nctx;
286+
}
287+
288+
static struct rintc_data *get_plic_context(unsigned int plic_id, unsigned int ctxt_idx)
289+
{
290+
unsigned int ctxt = 0;
291+
292+
for_each_matching_plic(plic_id) {
293+
if (ctxt == ctxt_idx)
294+
return rintc_acpi_data[_plic];
295+
296+
ctxt++;
297+
}
298+
299+
return NULL;
300+
}
301+
302+
unsigned long acpi_rintc_ext_parent_to_hartid(unsigned int plic_id, unsigned int ctxt_idx)
303+
{
304+
struct rintc_data *data = get_plic_context(plic_id, ctxt_idx);
305+
306+
return data ? data->hart_id : INVALID_HARTID;
307+
}
308+
309+
unsigned int acpi_rintc_get_plic_context(unsigned int plic_id, unsigned int ctxt_idx)
310+
{
311+
struct rintc_data *data = get_plic_context(plic_id, ctxt_idx);
312+
313+
return data ? data->context_id : INVALID_CONTEXT;
314+
}
315+
316+
unsigned long acpi_rintc_index_to_hartid(u32 index)
317+
{
318+
return index >= nr_rintc ? INVALID_HARTID : rintc_acpi_data[index]->hart_id;
319+
}
320+
321+
int acpi_rintc_get_imsic_mmio_info(u32 index, struct resource *res)
322+
{
323+
if (index >= nr_rintc)
324+
return -1;
325+
326+
res->start = rintc_acpi_data[index]->imsic_addr;
327+
res->end = res->start + rintc_acpi_data[index]->imsic_size - 1;
328+
res->flags = IORESOURCE_MEM;
329+
return 0;
330+
}
331+
253332
static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
254333
const unsigned long end)
255334
{
@@ -258,6 +337,15 @@ static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
258337
int rc;
259338

260339
rintc = (struct acpi_madt_rintc *)header;
340+
rintc_acpi_data[nr_rintc] = kzalloc(sizeof(*rintc_acpi_data[0]), GFP_KERNEL);
341+
if (!rintc_acpi_data[nr_rintc])
342+
return -ENOMEM;
343+
344+
rintc_acpi_data[nr_rintc]->ext_intc_id = rintc->ext_intc_id;
345+
rintc_acpi_data[nr_rintc]->hart_id = rintc->hart_id;
346+
rintc_acpi_data[nr_rintc]->imsic_addr = rintc->imsic_addr;
347+
rintc_acpi_data[nr_rintc]->imsic_size = rintc->imsic_size;
348+
nr_rintc++;
261349

262350
/*
263351
* The ACPI MADT will have one INTC for each CPU (or HART)
@@ -277,6 +365,8 @@ static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
277365
rc = riscv_intc_init_common(fn, &riscv_intc_chip);
278366
if (rc)
279367
irq_domain_free_fwnode(fn);
368+
else
369+
acpi_set_irq_model(ACPI_IRQ_MODEL_RINTC, riscv_acpi_get_gsi_domain_id);
280370

281371
return rc;
282372
}

0 commit comments

Comments
 (0)