Skip to content

Commit 7023b9d

Browse files
vlsunilpalmer-dabbelt
authored andcommitted
irqchip/riscv-intc: Add ACPI support
Add support for initializing the RISC-V INTC driver on ACPI platforms. Signed-off-by: Sunil V L <[email protected]> Acked-by: Rafael J. Wysocki <[email protected]> Reviewed-by: Andrew Jones <[email protected]> Reviewed-by: Conor Dooley <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 0b144c8 commit 7023b9d

File tree

1 file changed

+55
-15
lines changed

1 file changed

+55
-15
lines changed

drivers/irqchip/irq-riscv-intc.c

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
#define pr_fmt(fmt) "riscv-intc: " fmt
9+
#include <linux/acpi.h>
910
#include <linux/atomic.h>
1011
#include <linux/bits.h>
1112
#include <linux/cpu.h>
@@ -112,6 +113,30 @@ static struct fwnode_handle *riscv_intc_hwnode(void)
112113
return intc_domain->fwnode;
113114
}
114115

116+
static int __init riscv_intc_init_common(struct fwnode_handle *fn)
117+
{
118+
int rc;
119+
120+
intc_domain = irq_domain_create_linear(fn, BITS_PER_LONG,
121+
&riscv_intc_domain_ops, NULL);
122+
if (!intc_domain) {
123+
pr_err("unable to add IRQ domain\n");
124+
return -ENXIO;
125+
}
126+
127+
rc = set_handle_irq(&riscv_intc_irq);
128+
if (rc) {
129+
pr_err("failed to set irq handler\n");
130+
return rc;
131+
}
132+
133+
riscv_set_intc_hwnode_fn(riscv_intc_hwnode);
134+
135+
pr_info("%d local interrupts mapped\n", BITS_PER_LONG);
136+
137+
return 0;
138+
}
139+
115140
static int __init riscv_intc_init(struct device_node *node,
116141
struct device_node *parent)
117142
{
@@ -133,24 +158,39 @@ static int __init riscv_intc_init(struct device_node *node,
133158
if (riscv_hartid_to_cpuid(hartid) != smp_processor_id())
134159
return 0;
135160

136-
intc_domain = irq_domain_add_linear(node, BITS_PER_LONG,
137-
&riscv_intc_domain_ops, NULL);
138-
if (!intc_domain) {
139-
pr_err("unable to add IRQ domain\n");
140-
return -ENXIO;
141-
}
161+
return riscv_intc_init_common(of_node_to_fwnode(node));
162+
}
142163

143-
rc = set_handle_irq(&riscv_intc_irq);
144-
if (rc) {
145-
pr_err("failed to set irq handler\n");
146-
return rc;
147-
}
164+
IRQCHIP_DECLARE(riscv, "riscv,cpu-intc", riscv_intc_init);
148165

149-
riscv_set_intc_hwnode_fn(riscv_intc_hwnode);
166+
#ifdef CONFIG_ACPI
150167

151-
pr_info("%d local interrupts mapped\n", BITS_PER_LONG);
168+
static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
169+
const unsigned long end)
170+
{
171+
struct fwnode_handle *fn;
172+
struct acpi_madt_rintc *rintc;
152173

153-
return 0;
174+
rintc = (struct acpi_madt_rintc *)header;
175+
176+
/*
177+
* The ACPI MADT will have one INTC for each CPU (or HART)
178+
* so riscv_intc_acpi_init() function will be called once
179+
* for each INTC. We only do INTC initialization
180+
* for the INTC belonging to the boot CPU (or boot HART).
181+
*/
182+
if (riscv_hartid_to_cpuid(rintc->hart_id) != smp_processor_id())
183+
return 0;
184+
185+
fn = irq_domain_alloc_named_fwnode("RISCV-INTC");
186+
if (!fn) {
187+
pr_err("unable to allocate INTC FW node\n");
188+
return -ENOMEM;
189+
}
190+
191+
return riscv_intc_init_common(fn);
154192
}
155193

156-
IRQCHIP_DECLARE(riscv, "riscv,cpu-intc", riscv_intc_init);
194+
IRQCHIP_ACPI_DECLARE(riscv_intc, ACPI_MADT_TYPE_RINTC, NULL,
195+
ACPI_MADT_RINTC_VERSION_V1, riscv_intc_acpi_init);
196+
#endif

0 commit comments

Comments
 (0)