2 * Generic Broadcom Set Top Box 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.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18 #include <linux/init.h>
19 #include <linux/slab.h>
20 #include <linux/module.h>
21 #include <linux/kconfig.h>
22 #include <linux/platform_device.h>
23 #include <linux/spinlock.h>
25 #include <linux/of_irq.h>
26 #include <linux/of_address.h>
27 #include <linux/of_platform.h>
28 #include <linux/interrupt.h>
29 #include <linux/irq.h>
31 #include <linux/irqdomain.h>
32 #include <linux/irqchip.h>
33 #include <linux/irqchip/chained_irq.h>
37 /* Register offsets in the L2 interrupt controller */
38 #define CPU_STATUS 0x00
40 #define CPU_CLEAR 0x08
41 #define CPU_MASK_STATUS 0x0c
42 #define CPU_MASK_SET 0x10
43 #define CPU_MASK_CLEAR 0x14
45 /* L2 intc private data structure */
46 struct brcmstb_l2_intc_data
{
49 struct irq_domain
*domain
;
51 u32 saved_mask
; /* for suspend/resume */
54 static void brcmstb_l2_intc_irq_handle(unsigned int irq
, struct irq_desc
*desc
)
56 struct brcmstb_l2_intc_data
*b
= irq_desc_get_handler_data(desc
);
57 struct irq_chip_generic
*gc
= irq_get_domain_generic_chip(b
->domain
, 0);
58 struct irq_chip
*chip
= irq_desc_get_chip(desc
);
61 chained_irq_enter(chip
, desc
);
63 status
= irq_reg_readl(gc
, CPU_STATUS
) &
64 ~(irq_reg_readl(gc
, CPU_MASK_STATUS
));
67 raw_spin_lock(&desc
->lock
);
68 handle_bad_irq(irq
, desc
);
69 raw_spin_unlock(&desc
->lock
);
74 irq
= ffs(status
) - 1;
75 /* ack at our level */
76 irq_reg_writel(gc
, 1 << irq
, CPU_CLEAR
);
77 status
&= ~(1 << irq
);
78 generic_handle_irq(irq_find_mapping(b
->domain
, irq
));
81 chained_irq_exit(chip
, desc
);
84 static void brcmstb_l2_intc_suspend(struct irq_data
*d
)
86 struct irq_chip_generic
*gc
= irq_data_get_irq_chip_data(d
);
87 struct brcmstb_l2_intc_data
*b
= gc
->private;
90 /* Save the current mask */
91 b
->saved_mask
= irq_reg_readl(gc
, CPU_MASK_STATUS
);
94 /* Program the wakeup mask */
95 irq_reg_writel(gc
, ~gc
->wake_active
, CPU_MASK_SET
);
96 irq_reg_writel(gc
, gc
->wake_active
, CPU_MASK_CLEAR
);
101 static void brcmstb_l2_intc_resume(struct irq_data
*d
)
103 struct irq_chip_generic
*gc
= irq_data_get_irq_chip_data(d
);
104 struct brcmstb_l2_intc_data
*b
= gc
->private;
107 /* Clear unmasked non-wakeup interrupts */
108 irq_reg_writel(gc
, ~b
->saved_mask
& ~gc
->wake_active
, CPU_CLEAR
);
110 /* Restore the saved mask */
111 irq_reg_writel(gc
, b
->saved_mask
, CPU_MASK_SET
);
112 irq_reg_writel(gc
, ~b
->saved_mask
, CPU_MASK_CLEAR
);
116 int __init
brcmstb_l2_intc_of_init(struct device_node
*np
,
117 struct device_node
*parent
)
119 unsigned int clr
= IRQ_NOREQUEST
| IRQ_NOPROBE
| IRQ_NOAUTOEN
;
120 struct brcmstb_l2_intc_data
*data
;
121 struct irq_chip_generic
*gc
;
122 struct irq_chip_type
*ct
;
126 data
= kzalloc(sizeof(*data
), GFP_KERNEL
);
130 data
->base
= of_iomap(np
, 0);
132 pr_err("failed to remap intc L2 registers\n");
137 /* Disable all interrupts by default */
138 writel(0xffffffff, data
->base
+ CPU_MASK_SET
);
140 /* Wakeup interrupts may be retained from S5 (cold boot) */
141 data
->can_wake
= of_property_read_bool(np
, "brcm,irq-can-wake");
143 writel(0xffffffff, data
->base
+ CPU_CLEAR
);
145 data
->parent_irq
= irq_of_parse_and_map(np
, 0);
146 if (!data
->parent_irq
) {
147 pr_err("failed to find parent interrupt\n");
152 data
->domain
= irq_domain_add_linear(np
, 32,
153 &irq_generic_chip_ops
, NULL
);
159 /* MIPS chips strapped for BE will automagically configure the
160 * peripheral registers for CPU-native byte order.
163 if (IS_ENABLED(CONFIG_MIPS
) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN
))
164 flags
|= IRQ_GC_BE_IO
;
166 /* Allocate a single Generic IRQ chip for this node */
167 ret
= irq_alloc_domain_generic_chips(data
->domain
, 32, 1,
168 np
->full_name
, handle_edge_irq
, clr
, 0, flags
);
170 pr_err("failed to allocate generic irq chip\n");
171 goto out_free_domain
;
174 /* Set the IRQ chaining logic */
175 irq_set_handler_data(data
->parent_irq
, data
);
176 irq_set_chained_handler(data
->parent_irq
, brcmstb_l2_intc_irq_handle
);
178 gc
= irq_get_domain_generic_chip(data
->domain
, 0);
179 gc
->reg_base
= data
->base
;
183 ct
->chip
.irq_ack
= irq_gc_ack_set_bit
;
184 ct
->regs
.ack
= CPU_CLEAR
;
186 ct
->chip
.irq_mask
= irq_gc_mask_disable_reg
;
187 ct
->regs
.disable
= CPU_MASK_SET
;
189 ct
->chip
.irq_unmask
= irq_gc_unmask_enable_reg
;
190 ct
->regs
.enable
= CPU_MASK_CLEAR
;
192 ct
->chip
.irq_suspend
= brcmstb_l2_intc_suspend
;
193 ct
->chip
.irq_resume
= brcmstb_l2_intc_resume
;
195 if (data
->can_wake
) {
196 /* This IRQ chip can wake the system, set all child interrupts
197 * in wake_enabled mask
199 gc
->wake_enabled
= 0xffffffff;
200 ct
->chip
.irq_set_wake
= irq_gc_set_wake
;
203 pr_info("registered L2 intc (mem: 0x%p, parent irq: %d)\n",
204 data
->base
, data
->parent_irq
);
209 irq_domain_remove(data
->domain
);
216 IRQCHIP_DECLARE(brcmstb_l2_intc
, "brcm,l2-intc", brcmstb_l2_intc_of_init
);