Skip to content

Commit 3c46fc5

Browse files
avpatelKAGA-KOKO
authored andcommitted
irqchip/riscv-intc: Add support for RISC-V AIA
The RISC-V advanced interrupt architecture (AIA) extends the per-HART local interrupts in following ways: 1. Minimum 64 local interrupts for both RV32 and RV64 2. Ability to process multiple pending local interrupts in same interrupt handler 3. Priority configuration for each local interrupts 4. Special CSRs to configure/access the per-HART MSI controller Add support for #1 and #2 described above in the RISC-V intc driver. Signed-off-by: Anup Patel <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent abb7205 commit 3c46fc5

File tree

1 file changed

+23
-9
lines changed

1 file changed

+23
-9
lines changed

drivers/irqchip/irq-riscv-intc.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include <linux/smp.h>
2020
#include <linux/soc/andes/irq.h>
2121

22+
#include <asm/hwcap.h>
23+
2224
static struct irq_domain *intc_domain;
2325
static unsigned int riscv_intc_nr_irqs __ro_after_init = BITS_PER_LONG;
2426
static unsigned int riscv_intc_custom_base __ro_after_init = BITS_PER_LONG;
@@ -32,6 +34,14 @@ static asmlinkage void riscv_intc_irq(struct pt_regs *regs)
3234
pr_warn_ratelimited("Failed to handle interrupt (cause: %ld)\n", cause);
3335
}
3436

37+
static asmlinkage void riscv_intc_aia_irq(struct pt_regs *regs)
38+
{
39+
unsigned long topi;
40+
41+
while ((topi = csr_read(CSR_TOPI)))
42+
generic_handle_domain_irq(intc_domain, topi >> TOPI_IID_SHIFT);
43+
}
44+
3545
/*
3646
* On RISC-V systems local interrupts are masked or unmasked by writing
3747
* the SIE (Supervisor Interrupt Enable) CSR. As CSRs can only be written
@@ -41,12 +51,18 @@ static asmlinkage void riscv_intc_irq(struct pt_regs *regs)
4151

4252
static void riscv_intc_irq_mask(struct irq_data *d)
4353
{
44-
csr_clear(CSR_IE, BIT(d->hwirq));
54+
if (IS_ENABLED(CONFIG_32BIT) && d->hwirq >= BITS_PER_LONG)
55+
csr_clear(CSR_IEH, BIT(d->hwirq - BITS_PER_LONG));
56+
else
57+
csr_clear(CSR_IE, BIT(d->hwirq));
4558
}
4659

4760
static void riscv_intc_irq_unmask(struct irq_data *d)
4861
{
49-
csr_set(CSR_IE, BIT(d->hwirq));
62+
if (IS_ENABLED(CONFIG_32BIT) && d->hwirq >= BITS_PER_LONG)
63+
csr_set(CSR_IEH, BIT(d->hwirq - BITS_PER_LONG));
64+
else
65+
csr_set(CSR_IE, BIT(d->hwirq));
5066
}
5167

5268
static void andes_intc_irq_mask(struct irq_data *d)
@@ -157,8 +173,7 @@ static struct fwnode_handle *riscv_intc_hwnode(void)
157173
return intc_domain->fwnode;
158174
}
159175

160-
static int __init riscv_intc_init_common(struct fwnode_handle *fn,
161-
struct irq_chip *chip)
176+
static int __init riscv_intc_init_common(struct fwnode_handle *fn, struct irq_chip *chip)
162177
{
163178
int rc;
164179

@@ -176,11 +191,10 @@ static int __init riscv_intc_init_common(struct fwnode_handle *fn,
176191

177192
riscv_set_intc_hwnode_fn(riscv_intc_hwnode);
178193

179-
pr_info("%d local interrupts mapped\n", riscv_intc_nr_irqs);
180-
if (riscv_intc_custom_nr_irqs) {
181-
pr_info("%d custom local interrupts mapped\n",
182-
riscv_intc_custom_nr_irqs);
183-
}
194+
pr_info("%d local interrupts mapped\n",
195+
riscv_isa_extension_available(NULL, SxAIA) ? 64 : riscv_intc_nr_irqs);
196+
if (riscv_intc_custom_nr_irqs)
197+
pr_info("%d custom local interrupts mapped\n", riscv_intc_custom_nr_irqs);
184198

185199
return 0;
186200
}

0 commit comments

Comments
 (0)