2 * Broadcom BCM7120 style Level 2 interrupt controller driver
4 * Copyright (C) 2014 Broadcom Corporation
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13 #include <linux/init.h>
14 #include <linux/slab.h>
15 #include <linux/module.h>
16 #include <linux/kconfig.h>
17 #include <linux/platform_device.h>
19 #include <linux/of_irq.h>
20 #include <linux/of_address.h>
21 #include <linux/of_platform.h>
22 #include <linux/interrupt.h>
23 #include <linux/irq.h>
25 #include <linux/irqdomain.h>
26 #include <linux/reboot.h>
27 #include <linux/bitops.h>
28 #include <linux/irqchip/chained_irq.h>
32 /* Register offset in the L2 interrupt controller */
37 #define IRQS_PER_WORD 32
39 struct bcm7120_l2_intc_data
{
41 void __iomem
*base
[MAX_WORDS
];
42 struct irq_domain
*domain
;
44 u32 irq_fwd_mask
[MAX_WORDS
];
45 u32 irq_map_mask
[MAX_WORDS
];
48 static void bcm7120_l2_intc_irq_handle(unsigned int irq
, struct irq_desc
*desc
)
50 struct bcm7120_l2_intc_data
*b
= irq_desc_get_handler_data(desc
);
51 struct irq_chip
*chip
= irq_desc_get_chip(desc
);
54 chained_irq_enter(chip
, desc
);
56 for (idx
= 0; idx
< b
->n_words
; idx
++) {
57 int base
= idx
* IRQS_PER_WORD
;
58 struct irq_chip_generic
*gc
=
59 irq_get_domain_generic_chip(b
->domain
, base
);
60 unsigned long pending
;
64 pending
= irq_reg_readl(gc
, IRQSTAT
) & gc
->mask_cache
;
67 for_each_set_bit(hwirq
, &pending
, IRQS_PER_WORD
) {
68 generic_handle_irq(irq_find_mapping(b
->domain
,
73 chained_irq_exit(chip
, desc
);
76 static void bcm7120_l2_intc_suspend(struct irq_data
*d
)
78 struct irq_chip_generic
*gc
= irq_data_get_irq_chip_data(d
);
79 struct bcm7120_l2_intc_data
*b
= gc
->private;
83 irq_reg_writel(gc
, gc
->mask_cache
| gc
->wake_active
, IRQEN
);
87 static void bcm7120_l2_intc_resume(struct irq_data
*d
)
89 struct irq_chip_generic
*gc
= irq_data_get_irq_chip_data(d
);
91 /* Restore the saved mask */
93 irq_reg_writel(gc
, gc
->mask_cache
, IRQEN
);
97 static int bcm7120_l2_intc_init_one(struct device_node
*dn
,
98 struct bcm7120_l2_intc_data
*data
,
99 int irq
, const __be32
*map_mask
)
104 parent_irq
= irq_of_parse_and_map(dn
, irq
);
106 pr_err("failed to map interrupt %d\n", irq
);
110 /* For multiple parent IRQs with multiple words, this looks like:
111 * <irq0_w0 irq0_w1 irq1_w0 irq1_w1 ...>
113 for (idx
= 0; idx
< data
->n_words
; idx
++)
114 data
->irq_map_mask
[idx
] |=
115 be32_to_cpup(map_mask
+ irq
* data
->n_words
+ idx
);
117 irq_set_handler_data(parent_irq
, data
);
118 irq_set_chained_handler(parent_irq
, bcm7120_l2_intc_irq_handle
);
123 int __init
bcm7120_l2_intc_of_init(struct device_node
*dn
,
124 struct device_node
*parent
)
126 unsigned int clr
= IRQ_NOREQUEST
| IRQ_NOPROBE
| IRQ_NOAUTOEN
;
127 struct bcm7120_l2_intc_data
*data
;
128 struct irq_chip_generic
*gc
;
129 struct irq_chip_type
*ct
;
130 const __be32
*map_mask
;
133 unsigned int idx
, irq
, flags
;
135 data
= kzalloc(sizeof(*data
), GFP_KERNEL
);
139 for (idx
= 0; idx
< MAX_WORDS
; idx
++) {
140 data
->base
[idx
] = of_iomap(dn
, idx
);
141 if (!data
->base
[idx
])
143 data
->n_words
= idx
+ 1;
145 if (!data
->n_words
) {
146 pr_err("failed to remap intc L2 registers\n");
151 /* Enable all interrupts specified in the interrupt forward mask;
152 * disable all others. If the property doesn't exist (-EINVAL),
155 ret
= of_property_read_u32_array(dn
, "brcm,int-fwd-mask",
156 data
->irq_fwd_mask
, data
->n_words
);
157 if (ret
== 0 || ret
== -EINVAL
) {
158 for (idx
= 0; idx
< data
->n_words
; idx
++)
159 __raw_writel(data
->irq_fwd_mask
[idx
],
160 data
->base
[idx
] + IRQEN
);
162 /* property exists but has the wrong number of words */
163 pr_err("invalid int-fwd-mask property\n");
168 num_parent_irqs
= of_irq_count(dn
);
169 if (num_parent_irqs
<= 0) {
170 pr_err("invalid number of parent interrupts\n");
175 map_mask
= of_get_property(dn
, "brcm,int-map-mask", &len
);
177 (len
!= (sizeof(*map_mask
) * num_parent_irqs
* data
->n_words
))) {
178 pr_err("invalid brcm,int-map-mask property\n");
183 for (irq
= 0; irq
< num_parent_irqs
; irq
++) {
184 ret
= bcm7120_l2_intc_init_one(dn
, data
, irq
, map_mask
);
189 data
->domain
= irq_domain_add_linear(dn
, IRQS_PER_WORD
* data
->n_words
,
190 &irq_generic_chip_ops
, NULL
);
196 /* MIPS chips strapped for BE will automagically configure the
197 * peripheral registers for CPU-native byte order.
199 flags
= IRQ_GC_INIT_MASK_CACHE
;
200 if (IS_ENABLED(CONFIG_MIPS
) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN
))
201 flags
|= IRQ_GC_BE_IO
;
203 ret
= irq_alloc_domain_generic_chips(data
->domain
, IRQS_PER_WORD
, 1,
204 dn
->full_name
, handle_level_irq
, clr
, 0, flags
);
206 pr_err("failed to allocate generic irq chip\n");
207 goto out_free_domain
;
210 if (of_property_read_bool(dn
, "brcm,irq-can-wake"))
211 data
->can_wake
= true;
213 for (idx
= 0; idx
< data
->n_words
; idx
++) {
214 irq
= idx
* IRQS_PER_WORD
;
215 gc
= irq_get_domain_generic_chip(data
->domain
, irq
);
217 gc
->unused
= 0xffffffff & ~data
->irq_map_mask
[idx
];
218 gc
->reg_base
= data
->base
[idx
];
222 ct
->regs
.mask
= IRQEN
;
223 ct
->chip
.irq_mask
= irq_gc_mask_clr_bit
;
224 ct
->chip
.irq_unmask
= irq_gc_mask_set_bit
;
225 ct
->chip
.irq_ack
= irq_gc_noop
;
226 ct
->chip
.irq_suspend
= bcm7120_l2_intc_suspend
;
227 ct
->chip
.irq_resume
= bcm7120_l2_intc_resume
;
229 if (data
->can_wake
) {
230 /* This IRQ chip can wake the system, set all
231 * relevant child interupts in wake_enabled mask
233 gc
->wake_enabled
= 0xffffffff;
234 gc
->wake_enabled
&= ~gc
->unused
;
235 ct
->chip
.irq_set_wake
= irq_gc_set_wake
;
239 pr_info("registered BCM7120 L2 intc (mem: 0x%p, parent IRQ(s): %d)\n",
240 data
->base
[0], num_parent_irqs
);
245 irq_domain_remove(data
->domain
);
247 for (idx
= 0; idx
< MAX_WORDS
; idx
++) {
249 iounmap(data
->base
[idx
]);
254 IRQCHIP_DECLARE(bcm7120_l2_intc
, "brcm,bcm7120-l2-intc",
255 bcm7120_l2_intc_of_init
);