2 * SPEAr platform shared irq layer source file
4 * Copyright (C) 2009-2012 ST Microelectronics
5 * Viresh Kumar <viresh.linux@gmail.com>
7 * Copyright (C) 2012 ST Microelectronics
8 * Shiraz Hashim <shiraz.hashim@st.com>
10 * This file is licensed under the terms of the GNU General Public
11 * License version 2. This program is licensed "as is" without any
12 * warranty of any kind, whether express or implied.
14 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16 #include <linux/err.h>
17 #include <linux/export.h>
18 #include <linux/interrupt.h>
20 #include <linux/irq.h>
21 #include <linux/irqdomain.h>
22 #include <linux/irqchip/spear-shirq.h>
24 #include <linux/of_address.h>
25 #include <linux/of_irq.h>
26 #include <linux/spinlock.h>
28 static DEFINE_SPINLOCK(lock
);
30 /* spear300 shared irq registers offsets and masks */
31 #define SPEAR300_INT_ENB_MASK_REG 0x54
32 #define SPEAR300_INT_STS_MASK_REG 0x58
34 static struct spear_shirq spear300_shirq_ras1
= {
38 .enb_reg
= SPEAR300_INT_ENB_MASK_REG
,
39 .status_reg
= SPEAR300_INT_STS_MASK_REG
,
44 static struct spear_shirq
*spear300_shirq_blocks
[] = {
48 /* spear310 shared irq registers offsets and masks */
49 #define SPEAR310_INT_STS_MASK_REG 0x04
51 static struct spear_shirq spear310_shirq_ras1
= {
56 .status_reg
= SPEAR310_INT_STS_MASK_REG
,
61 static struct spear_shirq spear310_shirq_ras2
= {
66 .status_reg
= SPEAR310_INT_STS_MASK_REG
,
71 static struct spear_shirq spear310_shirq_ras3
= {
76 .status_reg
= SPEAR310_INT_STS_MASK_REG
,
81 static struct spear_shirq spear310_shirq_intrcomm_ras
= {
86 .status_reg
= SPEAR310_INT_STS_MASK_REG
,
91 static struct spear_shirq
*spear310_shirq_blocks
[] = {
95 &spear310_shirq_intrcomm_ras
,
98 /* spear320 shared irq registers offsets and masks */
99 #define SPEAR320_INT_STS_MASK_REG 0x04
100 #define SPEAR320_INT_CLR_MASK_REG 0x04
101 #define SPEAR320_INT_ENB_MASK_REG 0x08
103 static struct spear_shirq spear320_shirq_ras1
= {
108 .status_reg
= SPEAR320_INT_STS_MASK_REG
,
109 .clear_reg
= SPEAR320_INT_CLR_MASK_REG
,
114 static struct spear_shirq spear320_shirq_ras2
= {
119 .status_reg
= SPEAR320_INT_STS_MASK_REG
,
120 .clear_reg
= SPEAR320_INT_CLR_MASK_REG
,
125 static struct spear_shirq spear320_shirq_ras3
= {
130 .enb_reg
= SPEAR320_INT_ENB_MASK_REG
,
132 .status_reg
= SPEAR320_INT_STS_MASK_REG
,
133 .clear_reg
= SPEAR320_INT_CLR_MASK_REG
,
138 static struct spear_shirq spear320_shirq_intrcomm_ras
= {
143 .status_reg
= SPEAR320_INT_STS_MASK_REG
,
144 .clear_reg
= SPEAR320_INT_CLR_MASK_REG
,
149 static struct spear_shirq
*spear320_shirq_blocks
[] = {
150 &spear320_shirq_ras3
,
151 &spear320_shirq_ras1
,
152 &spear320_shirq_ras2
,
153 &spear320_shirq_intrcomm_ras
,
156 static void shirq_irq_mask_unmask(struct irq_data
*d
, bool mask
)
158 struct spear_shirq
*shirq
= irq_data_get_irq_chip_data(d
);
159 u32 val
, offset
= d
->irq
- shirq
->irq_base
;
162 if (shirq
->regs
.enb_reg
== -1)
165 spin_lock_irqsave(&lock
, flags
);
166 val
= readl(shirq
->base
+ shirq
->regs
.enb_reg
);
168 if (mask
^ shirq
->regs
.reset_to_enb
)
169 val
&= ~(0x1 << shirq
->irq_bit_off
<< offset
);
171 val
|= 0x1 << shirq
->irq_bit_off
<< offset
;
173 writel(val
, shirq
->base
+ shirq
->regs
.enb_reg
);
174 spin_unlock_irqrestore(&lock
, flags
);
178 static void shirq_irq_mask(struct irq_data
*d
)
180 shirq_irq_mask_unmask(d
, 1);
183 static void shirq_irq_unmask(struct irq_data
*d
)
185 shirq_irq_mask_unmask(d
, 0);
188 static struct irq_chip shirq_chip
= {
189 .name
= "spear-shirq",
190 .irq_ack
= shirq_irq_mask
,
191 .irq_mask
= shirq_irq_mask
,
192 .irq_unmask
= shirq_irq_unmask
,
195 static void shirq_handler(unsigned irq
, struct irq_desc
*desc
)
197 u32 i
, j
, val
, mask
, tmp
;
198 struct irq_chip
*chip
;
199 struct spear_shirq
*shirq
= irq_get_handler_data(irq
);
201 chip
= irq_get_chip(irq
);
202 chip
->irq_ack(&desc
->irq_data
);
204 mask
= ((0x1 << shirq
->irq_nr
) - 1) << shirq
->irq_bit_off
;
205 while ((val
= readl(shirq
->base
+ shirq
->regs
.status_reg
) &
208 val
>>= shirq
->irq_bit_off
;
209 for (i
= 0, j
= 1; i
< shirq
->irq_nr
; i
++, j
<<= 1) {
214 generic_handle_irq(shirq
->irq_base
+ i
);
216 /* clear interrupt */
217 if (shirq
->regs
.clear_reg
== -1)
220 tmp
= readl(shirq
->base
+ shirq
->regs
.clear_reg
);
221 if (shirq
->regs
.reset_to_clear
)
222 tmp
&= ~(j
<< shirq
->irq_bit_off
);
224 tmp
|= (j
<< shirq
->irq_bit_off
);
225 writel(tmp
, shirq
->base
+ shirq
->regs
.clear_reg
);
228 chip
->irq_unmask(&desc
->irq_data
);
231 static void __init
spear_shirq_register(struct spear_shirq
*shirq
)
235 if (shirq
->invalid_irq
)
238 irq_set_chained_handler(shirq
->irq
, shirq_handler
);
239 for (i
= 0; i
< shirq
->irq_nr
; i
++) {
240 irq_set_chip_and_handler(shirq
->irq_base
+ i
,
241 &shirq_chip
, handle_simple_irq
);
242 set_irq_flags(shirq
->irq_base
+ i
, IRQF_VALID
);
243 irq_set_chip_data(shirq
->irq_base
+ i
, shirq
);
246 irq_set_handler_data(shirq
->irq
, shirq
);
249 static int __init
shirq_init(struct spear_shirq
**shirq_blocks
, int block_nr
,
250 struct device_node
*np
)
252 int i
, irq_base
, hwirq
= 0, irq_nr
= 0;
253 static struct irq_domain
*shirq_domain
;
256 base
= of_iomap(np
, 0);
258 pr_err("%s: failed to map shirq registers\n", __func__
);
262 for (i
= 0; i
< block_nr
; i
++)
263 irq_nr
+= shirq_blocks
[i
]->irq_nr
;
265 irq_base
= irq_alloc_descs(-1, 0, irq_nr
, 0);
266 if (IS_ERR_VALUE(irq_base
)) {
267 pr_err("%s: irq desc alloc failed\n", __func__
);
271 shirq_domain
= irq_domain_add_legacy(np
, irq_nr
, irq_base
, 0,
272 &irq_domain_simple_ops
, NULL
);
273 if (WARN_ON(!shirq_domain
)) {
274 pr_warn("%s: irq domain init failed\n", __func__
);
278 for (i
= 0; i
< block_nr
; i
++) {
279 shirq_blocks
[i
]->base
= base
;
280 shirq_blocks
[i
]->irq_base
= irq_find_mapping(shirq_domain
,
282 shirq_blocks
[i
]->irq
= irq_of_parse_and_map(np
, i
);
284 spear_shirq_register(shirq_blocks
[i
]);
285 hwirq
+= shirq_blocks
[i
]->irq_nr
;
291 irq_free_descs(irq_base
, irq_nr
);
297 int __init
spear300_shirq_of_init(struct device_node
*np
,
298 struct device_node
*parent
)
300 return shirq_init(spear300_shirq_blocks
,
301 ARRAY_SIZE(spear300_shirq_blocks
), np
);
304 int __init
spear310_shirq_of_init(struct device_node
*np
,
305 struct device_node
*parent
)
307 return shirq_init(spear310_shirq_blocks
,
308 ARRAY_SIZE(spear310_shirq_blocks
), np
);
311 int __init
spear320_shirq_of_init(struct device_node
*np
,
312 struct device_node
*parent
)
314 return shirq_init(spear320_shirq_blocks
,
315 ARRAY_SIZE(spear320_shirq_blocks
), np
);