1 // SPDX-License-Identifier: GPL-2.0
3 * VexRiscv interrupt controller driver
5 * Copyright (C) 2019 Antmicro Ltd. <www.antmicro.com>
9 #include <linux/irqchip.h>
10 #include <linux/irqdesc.h>
12 #include <linux/of_irq.h>
13 #include <linux/of_address.h>
15 #define IRQ_MASK CONFIG_LITEX_VEXRISCV_CSR_MASK
16 #define IRQ_PENDING CONFIG_LITEX_VEXRISCV_CSR_PENDING
19 static struct irq_domain
*root_domain
;
21 struct litex_vexriscv_intc
{
23 irq_flow_handler_t handle
;
27 static unsigned int litex_vexriscv_irq_getie(void)
29 return (csr_read(sstatus
) & IE_SIE
) != 0;
32 static void litex_vexriscv_irq_setie(unsigned int ie
)
35 csr_write(sstatus
, IE_SIE
);
37 csr_clear(sstatus
, IE_SIE
);
40 static unsigned int litex_vexriscv_irq_getmask(void)
44 __asm__
__volatile__ ("csrr %0, %1" : "=r"(mask
) : "i"(IRQ_MASK
));
48 static void litex_vexriscv_irq_setmask(unsigned int mask
)
50 __asm__
volatile ("csrw %0, %1" :: "i"(IRQ_MASK
), "r"(mask
));
53 static unsigned int litex_vexriscv_irq_pending(void)
57 __asm__
__volatile__ ("csrr %0, %1" : "=r"(pending
) : "i"(IRQ_PENDING
));
61 static int litex_vexriscv_intc_map(struct irq_domain
*d
, unsigned int irq
,
64 struct litex_vexriscv_intc
*intc
= d
->host_data
;
66 pr_debug("irqchip: LiteX Vexriscv irqmap: %d\n", irq
);
67 irq_set_chip_and_handler(irq
, &intc
->chip
, intc
->handle
);
68 irq_set_status_flags(irq
, intc
->flags
);
70 pr_debug("irqchip: mapcount: %d\n", d
->mapcount
);
75 static void litex_vexriscv_intc_mask(struct irq_data
*data
)
77 unsigned int mask
= litex_vexriscv_irq_getmask();
78 unsigned int irqbit
= BIT(data
->hwirq
);
80 pr_debug("irqchip: LiteX VexRiscv irqchip mask: 0x%08x -> 0x%08x",
81 mask
, mask
& ~irqbit
);
83 litex_vexriscv_irq_setmask(mask
);
86 litex_vexriscv_irq_setie(0);
89 static void litex_vexriscv_intc_unmask(struct irq_data
*data
)
91 unsigned int mask
= litex_vexriscv_irq_getmask();
92 unsigned int irqbit
= BIT(data
->hwirq
);
94 pr_debug("irqchip: LiteX VexRiscv irqchip mask: 0x%08x -> 0x%08x",
97 litex_vexriscv_irq_setmask(mask
);
99 if (!litex_vexriscv_irq_getie())
100 litex_vexriscv_irq_setie(1);
103 static void litex_vexriscv_intc_ack(struct irq_data
*data
)
105 /* no need to ack IRQs */
108 static void litex_vexriscv_intc_handle_irq(struct pt_regs
*regs
)
113 irq
= litex_vexriscv_irq_pending() & litex_vexriscv_irq_getmask();
114 pr_debug("irqchip: Litex Vexriscv irqchip mask: 0x%08x pending: 0x%08x",
115 litex_vexriscv_irq_getmask(),
116 litex_vexriscv_irq_pending());
118 for (i
= 0; i
< IRQ_VEC_SZ
; i
++) {
119 pr_debug("irqchip: i %d, irq 0x%08x, trying 0x%08lx\n", i
, irq
, BIT(i
));
122 pr_debug("irqchip: handling at i = %d\n", i
);
123 handle_domain_irq(root_domain
, i
, regs
);
128 static const struct irq_domain_ops litex_vexriscv_domain_ops
= {
129 .xlate
= irq_domain_xlate_onecell
,
130 .map
= litex_vexriscv_intc_map
,
133 static struct litex_vexriscv_intc litex_vexriscv_intc0
= {
134 .handle
= handle_edge_irq
,
135 .flags
= IRQ_TYPE_DEFAULT
| IRQ_TYPE_PROBE
,
137 .name
= "litex-vexriscv-intc0",
138 .irq_mask
= litex_vexriscv_intc_mask
,
139 .irq_unmask
= litex_vexriscv_intc_unmask
,
140 .irq_ack
= litex_vexriscv_intc_ack
,
144 static int __init
litex_vexriscv_intc_init(struct device_node
*node
, struct device_node
*parent
)
146 /* clear interrupts for init */
147 litex_vexriscv_irq_setie(0);
148 litex_vexriscv_irq_setmask(0);
150 root_domain
= irq_domain_add_linear(node
, IRQ_VEC_SZ
,
151 &litex_vexriscv_domain_ops
,
152 &litex_vexriscv_intc0
);
153 irq_set_default_host(root_domain
);
154 set_handle_irq(litex_vexriscv_intc_handle_irq
);
156 /* print device info */
157 pr_info("irqchip: LiteX VexRiscv irqchip driver initialized. "
158 "IE: %d, mask: 0x%08x, pending: 0x%08x\n",
159 litex_vexriscv_irq_getie(),
160 litex_vexriscv_irq_getmask(),
161 litex_vexriscv_irq_pending());
162 pr_info("irqchip: LiteX VexRiscv irqchip settings: "
163 "mask CSR 0x%03x, pending CSR 0x%03x\n", IRQ_MASK
,
169 IRQCHIP_DECLARE(litex_vexriscv_intc0
, "vexriscv,intc0", litex_vexriscv_intc_init
);