1717#include <linux/irqchip/chained_irq.h>
1818#include <linux/of_address.h>
1919#include <linux/of_irq.h>
20+ #include <linux/interrupt.h>
2021
2122#define APB_INT_ENABLE_L 0x00
2223#define APB_INT_ENABLE_H 0x04
2627#define APB_INT_FINALSTATUS_H 0x34
2728#define APB_INT_BASE_OFFSET 0x04
2829
30+ /* irq domain of the primary interrupt controller. */
31+ static struct irq_domain * dw_apb_ictl_irq_domain ;
32+
33+ static void __irq_entry dw_apb_ictl_handle_irq (struct pt_regs * regs )
34+ {
35+ struct irq_domain * d = dw_apb_ictl_irq_domain ;
36+ int n ;
37+
38+ for (n = 0 ; n < d -> revmap_size ; n += 32 ) {
39+ struct irq_chip_generic * gc = irq_get_domain_generic_chip (d , n );
40+ u32 stat = readl_relaxed (gc -> reg_base + APB_INT_FINALSTATUS_L );
41+
42+ while (stat ) {
43+ u32 hwirq = ffs (stat ) - 1 ;
44+
45+ handle_domain_irq (d , hwirq , regs );
46+ stat &= ~BIT (hwirq );
47+ }
48+ }
49+ }
50+
2951static void dw_apb_ictl_handle_irq_cascaded (struct irq_desc * desc )
3052{
3153 struct irq_domain * d = irq_desc_get_handler_data (desc );
@@ -50,6 +72,30 @@ static void dw_apb_ictl_handle_irq_cascaded(struct irq_desc *desc)
5072 chained_irq_exit (chip , desc );
5173}
5274
75+ static int dw_apb_ictl_irq_domain_alloc (struct irq_domain * domain , unsigned int virq ,
76+ unsigned int nr_irqs , void * arg )
77+ {
78+ int i , ret ;
79+ irq_hw_number_t hwirq ;
80+ unsigned int type = IRQ_TYPE_NONE ;
81+ struct irq_fwspec * fwspec = arg ;
82+
83+ ret = irq_domain_translate_onecell (domain , fwspec , & hwirq , & type );
84+ if (ret )
85+ return ret ;
86+
87+ for (i = 0 ; i < nr_irqs ; i ++ )
88+ irq_map_generic_chip (domain , virq + i , hwirq + i );
89+
90+ return 0 ;
91+ }
92+
93+ static const struct irq_domain_ops dw_apb_ictl_irq_domain_ops = {
94+ .translate = irq_domain_translate_onecell ,
95+ .alloc = dw_apb_ictl_irq_domain_alloc ,
96+ .free = irq_domain_free_irqs_top ,
97+ };
98+
5399#ifdef CONFIG_PM
54100static void dw_apb_ictl_resume (struct irq_data * d )
55101{
@@ -77,13 +123,18 @@ static int __init dw_apb_ictl_init(struct device_node *np,
77123 int ret , nrirqs , parent_irq , i ;
78124 u32 reg ;
79125
80- domain_ops = & irq_generic_chip_ops ;
81-
82- /* Map the parent interrupt for the chained handler */
83- parent_irq = irq_of_parse_and_map (np , 0 );
84- if (parent_irq <= 0 ) {
85- pr_err ("%pOF: unable to parse irq\n" , np );
86- return - EINVAL ;
126+ if (!parent ) {
127+ /* Used as the primary interrupt controller */
128+ parent_irq = 0 ;
129+ domain_ops = & dw_apb_ictl_irq_domain_ops ;
130+ } else {
131+ /* Map the parent interrupt for the chained handler */
132+ parent_irq = irq_of_parse_and_map (np , 0 );
133+ if (parent_irq <= 0 ) {
134+ pr_err ("%pOF: unable to parse irq\n" , np );
135+ return - EINVAL ;
136+ }
137+ domain_ops = & irq_generic_chip_ops ;
87138 }
88139
89140 ret = of_address_to_resource (np , 0 , & r );
@@ -148,8 +199,13 @@ static int __init dw_apb_ictl_init(struct device_node *np,
148199 gc -> chip_types [0 ].chip .irq_resume = dw_apb_ictl_resume ;
149200 }
150201
151- irq_set_chained_handler_and_data (parent_irq ,
202+ if (parent_irq ) {
203+ irq_set_chained_handler_and_data (parent_irq ,
152204 dw_apb_ictl_handle_irq_cascaded , domain );
205+ } else {
206+ dw_apb_ictl_irq_domain = domain ;
207+ set_handle_irq (dw_apb_ictl_handle_irq );
208+ }
153209
154210 return 0 ;
155211
0 commit comments