1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2012 Regents of the University of California
4 * Copyright (C) 2017-2018 SiFive
5 * Copyright (C) 2020 Western Digital Corporation or its affiliates.
8 #define pr_fmt(fmt) "riscv-intc: " fmt
9 #include <linux/acpi.h>
10 #include <linux/atomic.h>
11 #include <linux/bits.h>
12 #include <linux/cpu.h>
13 #include <linux/irq.h>
14 #include <linux/irqchip.h>
15 #include <linux/irqdomain.h>
16 #include <linux/interrupt.h>
17 #include <linux/module.h>
19 #include <linux/smp.h>
20 #include <linux/soc/andes/irq.h>
22 #include <asm/hwcap.h>
24 static struct irq_domain
*intc_domain
;
25 static unsigned int riscv_intc_nr_irqs __ro_after_init
= BITS_PER_LONG
;
26 static unsigned int riscv_intc_custom_base __ro_after_init
= BITS_PER_LONG
;
27 static unsigned int riscv_intc_custom_nr_irqs __ro_after_init
;
29 static void riscv_intc_irq(struct pt_regs
*regs
)
31 unsigned long cause
= regs
->cause
& ~CAUSE_IRQ_FLAG
;
33 if (generic_handle_domain_irq(intc_domain
, cause
))
34 pr_warn_ratelimited("Failed to handle interrupt (cause: %ld)\n", cause
);
37 static void riscv_intc_aia_irq(struct pt_regs
*regs
)
41 while ((topi
= csr_read(CSR_TOPI
)))
42 generic_handle_domain_irq(intc_domain
, topi
>> TOPI_IID_SHIFT
);
46 * On RISC-V systems local interrupts are masked or unmasked by writing
47 * the SIE (Supervisor Interrupt Enable) CSR. As CSRs can only be written
48 * on the local hart, these functions can only be called on the hart that
49 * corresponds to the IRQ chip.
52 static void riscv_intc_irq_mask(struct irq_data
*d
)
54 if (IS_ENABLED(CONFIG_32BIT
) && d
->hwirq
>= BITS_PER_LONG
)
55 csr_clear(CSR_IEH
, BIT(d
->hwirq
- BITS_PER_LONG
));
57 csr_clear(CSR_IE
, BIT(d
->hwirq
));
60 static void riscv_intc_irq_unmask(struct irq_data
*d
)
62 if (IS_ENABLED(CONFIG_32BIT
) && d
->hwirq
>= BITS_PER_LONG
)
63 csr_set(CSR_IEH
, BIT(d
->hwirq
- BITS_PER_LONG
));
65 csr_set(CSR_IE
, BIT(d
->hwirq
));
68 static void andes_intc_irq_mask(struct irq_data
*d
)
71 * Andes specific S-mode local interrupt causes (hwirq)
72 * are defined as (256 + n) and controlled by n-th bit
75 unsigned int mask
= BIT(d
->hwirq
% BITS_PER_LONG
);
77 if (d
->hwirq
< ANDES_SLI_CAUSE_BASE
)
78 csr_clear(CSR_IE
, mask
);
80 csr_clear(ANDES_CSR_SLIE
, mask
);
83 static void andes_intc_irq_unmask(struct irq_data
*d
)
85 unsigned int mask
= BIT(d
->hwirq
% BITS_PER_LONG
);
87 if (d
->hwirq
< ANDES_SLI_CAUSE_BASE
)
88 csr_set(CSR_IE
, mask
);
90 csr_set(ANDES_CSR_SLIE
, mask
);
93 static void riscv_intc_irq_eoi(struct irq_data
*d
)
96 * The RISC-V INTC driver uses handle_percpu_devid_irq() flow
97 * for the per-HART local interrupts and child irqchip drivers
98 * (such as PLIC, SBI IPI, CLINT, APLIC, IMSIC, etc) implement
99 * chained handlers for the per-HART local interrupts.
101 * In the absence of irq_eoi(), the chained_irq_enter() and
102 * chained_irq_exit() functions (used by child irqchip drivers)
103 * will do unnecessary mask/unmask of per-HART local interrupts
104 * at the time of handling interrupts. To avoid this, we provide
105 * an empty irq_eoi() callback for RISC-V INTC irqchip.
109 static struct irq_chip riscv_intc_chip
= {
110 .name
= "RISC-V INTC",
111 .irq_mask
= riscv_intc_irq_mask
,
112 .irq_unmask
= riscv_intc_irq_unmask
,
113 .irq_eoi
= riscv_intc_irq_eoi
,
116 static struct irq_chip andes_intc_chip
= {
117 .name
= "RISC-V INTC",
118 .irq_mask
= andes_intc_irq_mask
,
119 .irq_unmask
= andes_intc_irq_unmask
,
120 .irq_eoi
= riscv_intc_irq_eoi
,
123 static int riscv_intc_domain_map(struct irq_domain
*d
, unsigned int irq
,
124 irq_hw_number_t hwirq
)
126 struct irq_chip
*chip
= d
->host_data
;
128 irq_set_percpu_devid(irq
);
129 irq_domain_set_info(d
, irq
, hwirq
, chip
, NULL
, handle_percpu_devid_irq
,
135 static int riscv_intc_domain_alloc(struct irq_domain
*domain
,
136 unsigned int virq
, unsigned int nr_irqs
,
140 irq_hw_number_t hwirq
;
141 unsigned int type
= IRQ_TYPE_NONE
;
142 struct irq_fwspec
*fwspec
= arg
;
144 ret
= irq_domain_translate_onecell(domain
, fwspec
, &hwirq
, &type
);
149 * Only allow hwirq for which we have corresponding standard or
150 * custom interrupt enable register.
152 if (hwirq
>= riscv_intc_nr_irqs
&&
153 (hwirq
< riscv_intc_custom_base
||
154 hwirq
>= riscv_intc_custom_base
+ riscv_intc_custom_nr_irqs
))
157 for (i
= 0; i
< nr_irqs
; i
++) {
158 ret
= riscv_intc_domain_map(domain
, virq
+ i
, hwirq
+ i
);
166 static const struct irq_domain_ops riscv_intc_domain_ops
= {
167 .map
= riscv_intc_domain_map
,
168 .xlate
= irq_domain_xlate_onecell
,
169 .alloc
= riscv_intc_domain_alloc
172 static struct fwnode_handle
*riscv_intc_hwnode(void)
174 return intc_domain
->fwnode
;
177 static int __init
riscv_intc_init_common(struct fwnode_handle
*fn
, struct irq_chip
*chip
)
181 intc_domain
= irq_domain_create_tree(fn
, &riscv_intc_domain_ops
, chip
);
183 pr_err("unable to add IRQ domain\n");
187 if (riscv_isa_extension_available(NULL
, SxAIA
)) {
188 riscv_intc_nr_irqs
= 64;
189 rc
= set_handle_irq(&riscv_intc_aia_irq
);
191 rc
= set_handle_irq(&riscv_intc_irq
);
194 pr_err("failed to set irq handler\n");
198 riscv_set_intc_hwnode_fn(riscv_intc_hwnode
);
200 pr_info("%d local interrupts mapped%s\n",
202 riscv_isa_extension_available(NULL
, SxAIA
) ? " using AIA" : "");
203 if (riscv_intc_custom_nr_irqs
)
204 pr_info("%d custom local interrupts mapped\n", riscv_intc_custom_nr_irqs
);
209 static int __init
riscv_intc_init(struct device_node
*node
,
210 struct device_node
*parent
)
212 struct irq_chip
*chip
= &riscv_intc_chip
;
213 unsigned long hartid
;
216 rc
= riscv_of_parent_hartid(node
, &hartid
);
218 pr_warn("unable to find hart id for %pOF\n", node
);
223 * The DT will have one INTC DT node under each CPU (or HART)
224 * DT node so riscv_intc_init() function will be called once
225 * for each INTC DT node. We only need to do INTC initialization
226 * for the INTC DT node belonging to boot CPU (or boot HART).
228 if (riscv_hartid_to_cpuid(hartid
) != smp_processor_id()) {
230 * The INTC nodes of each CPU are suppliers for downstream
231 * interrupt controllers (such as PLIC, IMSIC and APLIC
232 * direct-mode) so we should mark an INTC node as initialized
233 * if we are not creating IRQ domain for it.
235 fwnode_dev_initialized(of_fwnode_handle(node
), true);
239 if (of_device_is_compatible(node
, "andestech,cpu-intc")) {
240 riscv_intc_custom_base
= ANDES_SLI_CAUSE_BASE
;
241 riscv_intc_custom_nr_irqs
= ANDES_RV_IRQ_LAST
;
242 chip
= &andes_intc_chip
;
245 return riscv_intc_init_common(of_node_to_fwnode(node
), chip
);
248 IRQCHIP_DECLARE(riscv
, "riscv,cpu-intc", riscv_intc_init
);
249 IRQCHIP_DECLARE(andes
, "andestech,cpu-intc", riscv_intc_init
);
262 unsigned long hart_id
;
268 static struct rintc_data
**rintc_acpi_data
;
270 #define for_each_matching_plic(_plic_id) \
271 unsigned int _plic; \
273 for (_plic = 0; _plic < nr_rintc; _plic++) \
274 if (rintc_acpi_data[_plic]->aplic_plic_id != _plic_id) \
278 unsigned int acpi_rintc_get_plic_nr_contexts(unsigned int plic_id
)
280 unsigned int nctx
= 0;
282 for_each_matching_plic(plic_id
)
288 static struct rintc_data
*get_plic_context(unsigned int plic_id
, unsigned int ctxt_idx
)
290 unsigned int ctxt
= 0;
292 for_each_matching_plic(plic_id
) {
293 if (ctxt
== ctxt_idx
)
294 return rintc_acpi_data
[_plic
];
302 unsigned long acpi_rintc_ext_parent_to_hartid(unsigned int plic_id
, unsigned int ctxt_idx
)
304 struct rintc_data
*data
= get_plic_context(plic_id
, ctxt_idx
);
306 return data
? data
->hart_id
: INVALID_HARTID
;
309 unsigned int acpi_rintc_get_plic_context(unsigned int plic_id
, unsigned int ctxt_idx
)
311 struct rintc_data
*data
= get_plic_context(plic_id
, ctxt_idx
);
313 return data
? data
->context_id
: INVALID_CONTEXT
;
316 unsigned long acpi_rintc_index_to_hartid(u32 index
)
318 return index
>= nr_rintc
? INVALID_HARTID
: rintc_acpi_data
[index
]->hart_id
;
321 int acpi_rintc_get_imsic_mmio_info(u32 index
, struct resource
*res
)
323 if (index
>= nr_rintc
)
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
;
332 static int __init
riscv_intc_acpi_match(union acpi_subtable_headers
*header
,
333 const unsigned long end
)
338 static int __init
riscv_intc_acpi_init(union acpi_subtable_headers
*header
,
339 const unsigned long end
)
341 struct acpi_madt_rintc
*rintc
;
342 struct fwnode_handle
*fn
;
346 if (!rintc_acpi_data
) {
347 count
= acpi_table_parse_madt(ACPI_MADT_TYPE_RINTC
, riscv_intc_acpi_match
, 0);
351 rintc_acpi_data
= kcalloc(count
, sizeof(*rintc_acpi_data
), GFP_KERNEL
);
352 if (!rintc_acpi_data
)
356 rintc
= (struct acpi_madt_rintc
*)header
;
357 rintc_acpi_data
[nr_rintc
] = kzalloc(sizeof(*rintc_acpi_data
[0]), GFP_KERNEL
);
358 if (!rintc_acpi_data
[nr_rintc
])
361 rintc_acpi_data
[nr_rintc
]->ext_intc_id
= rintc
->ext_intc_id
;
362 rintc_acpi_data
[nr_rintc
]->hart_id
= rintc
->hart_id
;
363 rintc_acpi_data
[nr_rintc
]->imsic_addr
= rintc
->imsic_addr
;
364 rintc_acpi_data
[nr_rintc
]->imsic_size
= rintc
->imsic_size
;
368 * The ACPI MADT will have one INTC for each CPU (or HART)
369 * so riscv_intc_acpi_init() function will be called once
370 * for each INTC. We only do INTC initialization
371 * for the INTC belonging to the boot CPU (or boot HART).
373 if (riscv_hartid_to_cpuid(rintc
->hart_id
) != smp_processor_id())
376 fn
= irq_domain_alloc_named_fwnode("RISCV-INTC");
378 pr_err("unable to allocate INTC FW node\n");
382 rc
= riscv_intc_init_common(fn
, &riscv_intc_chip
);
384 irq_domain_free_fwnode(fn
);
386 acpi_set_irq_model(ACPI_IRQ_MODEL_RINTC
, riscv_acpi_get_gsi_domain_id
);
391 IRQCHIP_ACPI_DECLARE(riscv_intc
, ACPI_MADT_TYPE_RINTC
, NULL
,
392 ACPI_MADT_RINTC_VERSION_V1
, riscv_intc_acpi_init
);