1717#include <linux/module.h>
1818#include <linux/of.h>
1919#include <linux/smp.h>
20+ #include <linux/soc/andes/irq.h>
2021
2122static struct irq_domain * intc_domain ;
23+ static unsigned int riscv_intc_nr_irqs __ro_after_init = BITS_PER_LONG ;
24+ static unsigned int riscv_intc_custom_base __ro_after_init = BITS_PER_LONG ;
25+ static unsigned int riscv_intc_custom_nr_irqs __ro_after_init ;
2226
2327static asmlinkage void riscv_intc_irq (struct pt_regs * regs )
2428{
2529 unsigned long cause = regs -> cause & ~CAUSE_IRQ_FLAG ;
2630
27- if (unlikely (cause >= BITS_PER_LONG ))
28- panic ("unexpected interrupt cause" );
29-
30- generic_handle_domain_irq (intc_domain , cause );
31+ if (generic_handle_domain_irq (intc_domain , cause ))
32+ pr_warn_ratelimited ("Failed to handle interrupt (cause: %ld)\n" , cause );
3133}
3234
3335/*
@@ -47,6 +49,31 @@ static void riscv_intc_irq_unmask(struct irq_data *d)
4749 csr_set (CSR_IE , BIT (d -> hwirq ));
4850}
4951
52+ static void andes_intc_irq_mask (struct irq_data * d )
53+ {
54+ /*
55+ * Andes specific S-mode local interrupt causes (hwirq)
56+ * are defined as (256 + n) and controlled by n-th bit
57+ * of SLIE.
58+ */
59+ unsigned int mask = BIT (d -> hwirq % BITS_PER_LONG );
60+
61+ if (d -> hwirq < ANDES_SLI_CAUSE_BASE )
62+ csr_clear (CSR_IE , mask );
63+ else
64+ csr_clear (ANDES_CSR_SLIE , mask );
65+ }
66+
67+ static void andes_intc_irq_unmask (struct irq_data * d )
68+ {
69+ unsigned int mask = BIT (d -> hwirq % BITS_PER_LONG );
70+
71+ if (d -> hwirq < ANDES_SLI_CAUSE_BASE )
72+ csr_set (CSR_IE , mask );
73+ else
74+ csr_set (ANDES_CSR_SLIE , mask );
75+ }
76+
5077static void riscv_intc_irq_eoi (struct irq_data * d )
5178{
5279 /*
@@ -70,12 +97,21 @@ static struct irq_chip riscv_intc_chip = {
7097 .irq_eoi = riscv_intc_irq_eoi ,
7198};
7299
100+ static struct irq_chip andes_intc_chip = {
101+ .name = "RISC-V INTC" ,
102+ .irq_mask = andes_intc_irq_mask ,
103+ .irq_unmask = andes_intc_irq_unmask ,
104+ .irq_eoi = riscv_intc_irq_eoi ,
105+ };
106+
73107static int riscv_intc_domain_map (struct irq_domain * d , unsigned int irq ,
74108 irq_hw_number_t hwirq )
75109{
110+ struct irq_chip * chip = d -> host_data ;
111+
76112 irq_set_percpu_devid (irq );
77- irq_domain_set_info (d , irq , hwirq , & riscv_intc_chip , d -> host_data ,
78- handle_percpu_devid_irq , NULL , NULL );
113+ irq_domain_set_info (d , irq , hwirq , chip , NULL , handle_percpu_devid_irq ,
114+ NULL , NULL );
79115
80116 return 0 ;
81117}
@@ -93,6 +129,14 @@ static int riscv_intc_domain_alloc(struct irq_domain *domain,
93129 if (ret )
94130 return ret ;
95131
132+ /*
133+ * Only allow hwirq for which we have corresponding standard or
134+ * custom interrupt enable register.
135+ */
136+ if ((hwirq >= riscv_intc_nr_irqs && hwirq < riscv_intc_custom_base ) ||
137+ (hwirq >= riscv_intc_custom_base + riscv_intc_custom_nr_irqs ))
138+ return - EINVAL ;
139+
96140 for (i = 0 ; i < nr_irqs ; i ++ ) {
97141 ret = riscv_intc_domain_map (domain , virq + i , hwirq + i );
98142 if (ret )
@@ -113,12 +157,12 @@ static struct fwnode_handle *riscv_intc_hwnode(void)
113157 return intc_domain -> fwnode ;
114158}
115159
116- static int __init riscv_intc_init_common (struct fwnode_handle * fn )
160+ static int __init riscv_intc_init_common (struct fwnode_handle * fn ,
161+ struct irq_chip * chip )
117162{
118163 int rc ;
119164
120- intc_domain = irq_domain_create_linear (fn , BITS_PER_LONG ,
121- & riscv_intc_domain_ops , NULL );
165+ intc_domain = irq_domain_create_tree (fn , & riscv_intc_domain_ops , chip );
122166 if (!intc_domain ) {
123167 pr_err ("unable to add IRQ domain\n" );
124168 return - ENXIO ;
@@ -132,16 +176,21 @@ static int __init riscv_intc_init_common(struct fwnode_handle *fn)
132176
133177 riscv_set_intc_hwnode_fn (riscv_intc_hwnode );
134178
135- pr_info ("%d local interrupts mapped\n" , BITS_PER_LONG );
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+ }
136184
137185 return 0 ;
138186}
139187
140188static int __init riscv_intc_init (struct device_node * node ,
141189 struct device_node * parent )
142190{
143- int rc ;
191+ struct irq_chip * chip = & riscv_intc_chip ;
144192 unsigned long hartid ;
193+ int rc ;
145194
146195 rc = riscv_of_parent_hartid (node , & hartid );
147196 if (rc < 0 ) {
@@ -166,10 +215,17 @@ static int __init riscv_intc_init(struct device_node *node,
166215 return 0 ;
167216 }
168217
169- return riscv_intc_init_common (of_node_to_fwnode (node ));
218+ if (of_device_is_compatible (node , "andestech,cpu-intc" )) {
219+ riscv_intc_custom_base = ANDES_SLI_CAUSE_BASE ;
220+ riscv_intc_custom_nr_irqs = ANDES_RV_IRQ_LAST ;
221+ chip = & andes_intc_chip ;
222+ }
223+
224+ return riscv_intc_init_common (of_node_to_fwnode (node ), chip );
170225}
171226
172227IRQCHIP_DECLARE (riscv , "riscv,cpu-intc" , riscv_intc_init );
228+ IRQCHIP_DECLARE (andes , "andestech,cpu-intc" , riscv_intc_init );
173229
174230#ifdef CONFIG_ACPI
175231
@@ -196,7 +252,7 @@ static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
196252 return - ENOMEM ;
197253 }
198254
199- return riscv_intc_init_common (fn );
255+ return riscv_intc_init_common (fn , & riscv_intc_chip );
200256}
201257
202258IRQCHIP_ACPI_DECLARE (riscv_intc , ACPI_MADT_TYPE_RINTC , NULL ,
0 commit comments