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>
35 /* Register offsets in the L2 interrupt controller */
36 #define CPU_STATUS 0x00
38 #define CPU_CLEAR 0x08
39 #define CPU_MASK_STATUS 0x0c
40 #define CPU_MASK_SET 0x10
41 #define CPU_MASK_CLEAR 0x14
43 /* L2 intc private data structure */
44 struct brcmstb_l2_intc_data
{
47 struct irq_domain
*domain
;
49 u32 saved_mask
; /* for suspend/resume */
52 static void brcmstb_l2_intc_irq_handle(struct irq_desc
*desc
)
54 struct brcmstb_l2_intc_data
*b
= irq_desc_get_handler_data(desc
);
55 struct irq_chip_generic
*gc
= irq_get_domain_generic_chip(b
->domain
, 0);
56 struct irq_chip
*chip
= irq_desc_get_chip(desc
);
60 chained_irq_enter(chip
, desc
);
62 status
= irq_reg_readl(gc
, CPU_STATUS
) &
63 ~(irq_reg_readl(gc
, CPU_MASK_STATUS
));
66 raw_spin_lock(&desc
->lock
);
68 raw_spin_unlock(&desc
->lock
);
73 irq
= ffs(status
) - 1;
74 /* ack at our level */
75 irq_reg_writel(gc
, 1 << irq
, CPU_CLEAR
);
76 status
&= ~(1 << irq
);
77 generic_handle_irq(irq_find_mapping(b
->domain
, irq
));
80 chained_irq_exit(chip
, desc
);
83 static void brcmstb_l2_intc_suspend(struct irq_data
*d
)
85 struct irq_chip_generic
*gc
= irq_data_get_irq_chip_data(d
);
86 struct brcmstb_l2_intc_data
*b
= gc
->private;
89 /* Save the current mask */
90 b
->saved_mask
= irq_reg_readl(gc
, CPU_MASK_STATUS
);
93 /* Program the wakeup mask */
94 irq_reg_writel(gc
, ~gc
->wake_active
, CPU_MASK_SET
);
95 irq_reg_writel(gc
, gc
->wake_active
, CPU_MASK_CLEAR
);
100 static void brcmstb_l2_intc_resume(struct irq_data
*d
)
102 struct irq_chip_generic
*gc
= irq_data_get_irq_chip_data(d
);
103 struct brcmstb_l2_intc_data
*b
= gc
->private;
106 /* Clear unmasked non-wakeup interrupts */
107 irq_reg_writel(gc
, ~b
->saved_mask
& ~gc
->wake_active
, CPU_CLEAR
);
109 /* Restore the saved mask */
110 irq_reg_writel(gc
, b
->saved_mask
, CPU_MASK_SET
);
111 irq_reg_writel(gc
, ~b
->saved_mask
, CPU_MASK_CLEAR
);
115 int __init
brcmstb_l2_intc_of_init(struct device_node
*np
,
116 struct device_node
*parent
)
118 unsigned int clr
= IRQ_NOREQUEST
| IRQ_NOPROBE
| IRQ_NOAUTOEN
;
119 struct brcmstb_l2_intc_data
*data
;
120 struct irq_chip_generic
*gc
;
121 struct irq_chip_type
*ct
;
125 data
= kzalloc(sizeof(*data
), GFP_KERNEL
);
129 data
->base
= of_iomap(np
, 0);
131 pr_err("failed to remap intc L2 registers\n");
136 /* Disable all interrupts by default */
137 writel(0xffffffff, data
->base
+ CPU_MASK_SET
);
139 /* Wakeup interrupts may be retained from S5 (cold boot) */
140 data
->can_wake
= of_property_read_bool(np
, "brcm,irq-can-wake");
142 writel(0xffffffff, data
->base
+ CPU_CLEAR
);
144 data
->parent_irq
= irq_of_parse_and_map(np
, 0);
145 if (!data
->parent_irq
) {
146 pr_err("failed to find parent interrupt\n");
151 data
->domain
= irq_domain_add_linear(np
, 32,
152 &irq_generic_chip_ops
, NULL
);
158 /* MIPS chips strapped for BE will automagically configure the
159 * peripheral registers for CPU-native byte order.
162 if (IS_ENABLED(CONFIG_MIPS
) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN
))
163 flags
|= IRQ_GC_BE_IO
;
165 /* Allocate a single Generic IRQ chip for this node */
166 ret
= irq_alloc_domain_generic_chips(data
->domain
, 32, 1,
167 np
->full_name
, handle_edge_irq
, clr
, 0, flags
);
169 pr_err("failed to allocate generic irq chip\n");
170 goto out_free_domain
;
173 /* Set the IRQ chaining logic */
174 irq_set_chained_handler_and_data(data
->parent_irq
,
175 brcmstb_l2_intc_irq_handle
, data
);
177 gc
= irq_get_domain_generic_chip(data
->domain
, 0);
178 gc
->reg_base
= data
->base
;
182 ct
->chip
.irq_ack
= irq_gc_ack_set_bit
;
183 ct
->regs
.ack
= CPU_CLEAR
;
185 ct
->chip
.irq_mask
= irq_gc_mask_disable_reg
;
186 ct
->regs
.disable
= CPU_MASK_SET
;
188 ct
->chip
.irq_unmask
= irq_gc_unmask_enable_reg
;
189 ct
->regs
.enable
= CPU_MASK_CLEAR
;
191 ct
->chip
.irq_suspend
= brcmstb_l2_intc_suspend
;
192 ct
->chip
.irq_resume
= brcmstb_l2_intc_resume
;
194 if (data
->can_wake
) {
195 /* This IRQ chip can wake the system, set all child interrupts
196 * in wake_enabled mask
198 gc
->wake_enabled
= 0xffffffff;
199 ct
->chip
.irq_set_wake
= irq_gc_set_wake
;
202 pr_info("registered L2 intc (mem: 0x%p, parent irq: %d)\n",
203 data
->base
, data
->parent_irq
);
208 irq_domain_remove(data
->domain
);
215 IRQCHIP_DECLARE(brcmstb_l2_intc
, "brcm,l2-intc", brcmstb_l2_intc_of_init
);