diff options
author | Viresh Kumar <viresh.kumar@linaro.org> | 2012-11-12 12:26:03 -0500 |
---|---|---|
committer | Viresh Kumar <viresh.kumar@linaro.org> | 2012-11-26 06:25:33 -0500 |
commit | df1590d9ae5e37e07e7cf91107e4c2c946ce8bf4 (patch) | |
tree | 7e17333920f4ab9986f3f40e881b4bc890a91724 /arch/arm/plat-spear | |
parent | e2eb69183ec4156eb814e67672e492bf902bbcd2 (diff) |
ARM: SPEAr3xx: Shirq: Move shirq controller out of plat/
This patch moves shirq interrupt controllers driver and header file out of
plat-spear directory. It is moved to drivers/irqchip/ directory.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Diffstat (limited to 'arch/arm/plat-spear')
-rw-r--r-- | arch/arm/plat-spear/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/plat-spear/include/plat/shirq.h | 66 | ||||
-rw-r--r-- | arch/arm/plat-spear/shirq.c | 315 |
3 files changed, 1 insertions, 382 deletions
diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile index 2607bd05c525..01e88532a5db 100644 --- a/arch/arm/plat-spear/Makefile +++ b/arch/arm/plat-spear/Makefile | |||
@@ -5,5 +5,5 @@ | |||
5 | # Common support | 5 | # Common support |
6 | obj-y := restart.o time.o | 6 | obj-y := restart.o time.o |
7 | 7 | ||
8 | obj-$(CONFIG_ARCH_SPEAR3XX) += pl080.o shirq.o | 8 | obj-$(CONFIG_ARCH_SPEAR3XX) += pl080.o |
9 | obj-$(CONFIG_ARCH_SPEAR6XX) += pl080.o | 9 | obj-$(CONFIG_ARCH_SPEAR6XX) += pl080.o |
diff --git a/arch/arm/plat-spear/include/plat/shirq.h b/arch/arm/plat-spear/include/plat/shirq.h deleted file mode 100644 index c51b355f00de..000000000000 --- a/arch/arm/plat-spear/include/plat/shirq.h +++ /dev/null | |||
@@ -1,66 +0,0 @@ | |||
1 | /* | ||
2 | * arch/arm/plat-spear/include/plat/shirq.h | ||
3 | * | ||
4 | * SPEAr platform shared irq layer header file | ||
5 | * | ||
6 | * Copyright (C) 2009 ST Microelectronics | ||
7 | * Viresh Kumar <viresh.linux@gmail.com> | ||
8 | * | ||
9 | * This file is licensed under the terms of the GNU General Public | ||
10 | * License version 2. This program is licensed "as is" without any | ||
11 | * warranty of any kind, whether express or implied. | ||
12 | */ | ||
13 | |||
14 | #ifndef __PLAT_SHIRQ_H | ||
15 | #define __PLAT_SHIRQ_H | ||
16 | |||
17 | #include <linux/irq.h> | ||
18 | #include <linux/types.h> | ||
19 | |||
20 | /* | ||
21 | * struct shirq_regs: shared irq register configuration | ||
22 | * | ||
23 | * enb_reg: enable register offset | ||
24 | * reset_to_enb: val 1 indicates, we need to clear bit for enabling interrupt | ||
25 | * status_reg: status register offset | ||
26 | * status_reg_mask: status register valid mask | ||
27 | * clear_reg: clear register offset | ||
28 | * reset_to_clear: val 1 indicates, we need to clear bit for clearing interrupt | ||
29 | */ | ||
30 | struct shirq_regs { | ||
31 | u32 enb_reg; | ||
32 | u32 reset_to_enb; | ||
33 | u32 status_reg; | ||
34 | u32 clear_reg; | ||
35 | u32 reset_to_clear; | ||
36 | }; | ||
37 | |||
38 | /* | ||
39 | * struct spear_shirq: shared irq structure | ||
40 | * | ||
41 | * irq: hardware irq number | ||
42 | * irq_base: base irq in linux domain | ||
43 | * irq_nr: no. of shared interrupts in a particular block | ||
44 | * irq_bit_off: starting bit offset in the status register | ||
45 | * invalid_irq: irq group is currently disabled | ||
46 | * base: base address of shared irq register | ||
47 | * regs: register configuration for shared irq block | ||
48 | */ | ||
49 | struct spear_shirq { | ||
50 | u32 irq; | ||
51 | u32 irq_base; | ||
52 | u32 irq_nr; | ||
53 | u32 irq_bit_off; | ||
54 | int invalid_irq; | ||
55 | void __iomem *base; | ||
56 | struct shirq_regs regs; | ||
57 | }; | ||
58 | |||
59 | int __init spear300_shirq_of_init(struct device_node *np, | ||
60 | struct device_node *parent); | ||
61 | int __init spear310_shirq_of_init(struct device_node *np, | ||
62 | struct device_node *parent); | ||
63 | int __init spear320_shirq_of_init(struct device_node *np, | ||
64 | struct device_node *parent); | ||
65 | |||
66 | #endif /* __PLAT_SHIRQ_H */ | ||
diff --git a/arch/arm/plat-spear/shirq.c b/arch/arm/plat-spear/shirq.c deleted file mode 100644 index 955c7249a5c1..000000000000 --- a/arch/arm/plat-spear/shirq.c +++ /dev/null | |||
@@ -1,315 +0,0 @@ | |||
1 | /* | ||
2 | * arch/arm/plat-spear/shirq.c | ||
3 | * | ||
4 | * SPEAr platform shared irq layer source file | ||
5 | * | ||
6 | * Copyright (C) 2009 ST Microelectronics | ||
7 | * Viresh Kumar <viresh.linux@gmail.com> | ||
8 | * | ||
9 | * This file is licensed under the terms of the GNU General Public | ||
10 | * License version 2. This program is licensed "as is" without any | ||
11 | * warranty of any kind, whether express or implied. | ||
12 | */ | ||
13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
14 | |||
15 | #include <linux/err.h> | ||
16 | #include <linux/export.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/irqdomain.h> | ||
21 | #include <linux/of.h> | ||
22 | #include <linux/of_address.h> | ||
23 | #include <linux/of_irq.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <plat/shirq.h> | ||
26 | |||
27 | static DEFINE_SPINLOCK(lock); | ||
28 | |||
29 | /* spear300 shared irq registers offsets and masks */ | ||
30 | #define SPEAR300_INT_ENB_MASK_REG 0x54 | ||
31 | #define SPEAR300_INT_STS_MASK_REG 0x58 | ||
32 | |||
33 | static struct spear_shirq spear300_shirq_ras1 = { | ||
34 | .irq_nr = 9, | ||
35 | .irq_bit_off = 0, | ||
36 | .regs = { | ||
37 | .enb_reg = SPEAR300_INT_ENB_MASK_REG, | ||
38 | .status_reg = SPEAR300_INT_STS_MASK_REG, | ||
39 | .clear_reg = -1, | ||
40 | }, | ||
41 | }; | ||
42 | |||
43 | static struct spear_shirq *spear300_shirq_blocks[] = { | ||
44 | &spear300_shirq_ras1, | ||
45 | }; | ||
46 | |||
47 | /* spear310 shared irq registers offsets and masks */ | ||
48 | #define SPEAR310_INT_STS_MASK_REG 0x04 | ||
49 | |||
50 | static struct spear_shirq spear310_shirq_ras1 = { | ||
51 | .irq_nr = 8, | ||
52 | .irq_bit_off = 0, | ||
53 | .regs = { | ||
54 | .enb_reg = -1, | ||
55 | .status_reg = SPEAR310_INT_STS_MASK_REG, | ||
56 | .clear_reg = -1, | ||
57 | }, | ||
58 | }; | ||
59 | |||
60 | static struct spear_shirq spear310_shirq_ras2 = { | ||
61 | .irq_nr = 5, | ||
62 | .irq_bit_off = 8, | ||
63 | .regs = { | ||
64 | .enb_reg = -1, | ||
65 | .status_reg = SPEAR310_INT_STS_MASK_REG, | ||
66 | .clear_reg = -1, | ||
67 | }, | ||
68 | }; | ||
69 | |||
70 | static struct spear_shirq spear310_shirq_ras3 = { | ||
71 | .irq_nr = 1, | ||
72 | .irq_bit_off = 13, | ||
73 | .regs = { | ||
74 | .enb_reg = -1, | ||
75 | .status_reg = SPEAR310_INT_STS_MASK_REG, | ||
76 | .clear_reg = -1, | ||
77 | }, | ||
78 | }; | ||
79 | |||
80 | static struct spear_shirq spear310_shirq_intrcomm_ras = { | ||
81 | .irq_nr = 3, | ||
82 | .irq_bit_off = 14, | ||
83 | .regs = { | ||
84 | .enb_reg = -1, | ||
85 | .status_reg = SPEAR310_INT_STS_MASK_REG, | ||
86 | .clear_reg = -1, | ||
87 | }, | ||
88 | }; | ||
89 | |||
90 | static struct spear_shirq *spear310_shirq_blocks[] = { | ||
91 | &spear310_shirq_ras1, | ||
92 | &spear310_shirq_ras2, | ||
93 | &spear310_shirq_ras3, | ||
94 | &spear310_shirq_intrcomm_ras, | ||
95 | }; | ||
96 | |||
97 | /* spear320 shared irq registers offsets and masks */ | ||
98 | #define SPEAR320_INT_STS_MASK_REG 0x04 | ||
99 | #define SPEAR320_INT_CLR_MASK_REG 0x04 | ||
100 | #define SPEAR320_INT_ENB_MASK_REG 0x08 | ||
101 | |||
102 | static struct spear_shirq spear320_shirq_ras1 = { | ||
103 | .irq_nr = 3, | ||
104 | .irq_bit_off = 7, | ||
105 | .regs = { | ||
106 | .enb_reg = -1, | ||
107 | .status_reg = SPEAR320_INT_STS_MASK_REG, | ||
108 | .clear_reg = SPEAR320_INT_CLR_MASK_REG, | ||
109 | .reset_to_clear = 1, | ||
110 | }, | ||
111 | }; | ||
112 | |||
113 | static struct spear_shirq spear320_shirq_ras2 = { | ||
114 | .irq_nr = 1, | ||
115 | .irq_bit_off = 10, | ||
116 | .regs = { | ||
117 | .enb_reg = -1, | ||
118 | .status_reg = SPEAR320_INT_STS_MASK_REG, | ||
119 | .clear_reg = SPEAR320_INT_CLR_MASK_REG, | ||
120 | .reset_to_clear = 1, | ||
121 | }, | ||
122 | }; | ||
123 | |||
124 | static struct spear_shirq spear320_shirq_ras3 = { | ||
125 | .irq_nr = 3, | ||
126 | .irq_bit_off = 0, | ||
127 | .invalid_irq = 1, | ||
128 | .regs = { | ||
129 | .enb_reg = SPEAR320_INT_ENB_MASK_REG, | ||
130 | .reset_to_enb = 1, | ||
131 | .status_reg = SPEAR320_INT_STS_MASK_REG, | ||
132 | .clear_reg = SPEAR320_INT_CLR_MASK_REG, | ||
133 | .reset_to_clear = 1, | ||
134 | }, | ||
135 | }; | ||
136 | |||
137 | static struct spear_shirq spear320_shirq_intrcomm_ras = { | ||
138 | .irq_nr = 11, | ||
139 | .irq_bit_off = 11, | ||
140 | .regs = { | ||
141 | .enb_reg = -1, | ||
142 | .status_reg = SPEAR320_INT_STS_MASK_REG, | ||
143 | .clear_reg = SPEAR320_INT_CLR_MASK_REG, | ||
144 | .reset_to_clear = 1, | ||
145 | }, | ||
146 | }; | ||
147 | |||
148 | static struct spear_shirq *spear320_shirq_blocks[] = { | ||
149 | &spear320_shirq_ras3, | ||
150 | &spear320_shirq_ras1, | ||
151 | &spear320_shirq_ras2, | ||
152 | &spear320_shirq_intrcomm_ras, | ||
153 | }; | ||
154 | |||
155 | static void shirq_irq_mask_unmask(struct irq_data *d, bool mask) | ||
156 | { | ||
157 | struct spear_shirq *shirq = irq_data_get_irq_chip_data(d); | ||
158 | u32 val, offset = d->irq - shirq->irq_base; | ||
159 | unsigned long flags; | ||
160 | |||
161 | if (shirq->regs.enb_reg == -1) | ||
162 | return; | ||
163 | |||
164 | spin_lock_irqsave(&lock, flags); | ||
165 | val = readl(shirq->base + shirq->regs.enb_reg); | ||
166 | |||
167 | if (mask ^ shirq->regs.reset_to_enb) | ||
168 | val &= ~(0x1 << shirq->irq_bit_off << offset); | ||
169 | else | ||
170 | val |= 0x1 << shirq->irq_bit_off << offset; | ||
171 | |||
172 | writel(val, shirq->base + shirq->regs.enb_reg); | ||
173 | spin_unlock_irqrestore(&lock, flags); | ||
174 | |||
175 | } | ||
176 | |||
177 | static void shirq_irq_mask(struct irq_data *d) | ||
178 | { | ||
179 | shirq_irq_mask_unmask(d, 1); | ||
180 | } | ||
181 | |||
182 | static void shirq_irq_unmask(struct irq_data *d) | ||
183 | { | ||
184 | shirq_irq_mask_unmask(d, 0); | ||
185 | } | ||
186 | |||
187 | static struct irq_chip shirq_chip = { | ||
188 | .name = "spear-shirq", | ||
189 | .irq_ack = shirq_irq_mask, | ||
190 | .irq_mask = shirq_irq_mask, | ||
191 | .irq_unmask = shirq_irq_unmask, | ||
192 | }; | ||
193 | |||
194 | static void shirq_handler(unsigned irq, struct irq_desc *desc) | ||
195 | { | ||
196 | u32 i, j, val, mask, tmp; | ||
197 | struct irq_chip *chip; | ||
198 | struct spear_shirq *shirq = irq_get_handler_data(irq); | ||
199 | |||
200 | chip = irq_get_chip(irq); | ||
201 | chip->irq_ack(&desc->irq_data); | ||
202 | |||
203 | mask = ((0x1 << shirq->irq_nr) - 1) << shirq->irq_bit_off; | ||
204 | while ((val = readl(shirq->base + shirq->regs.status_reg) & | ||
205 | mask)) { | ||
206 | |||
207 | val >>= shirq->irq_bit_off; | ||
208 | for (i = 0, j = 1; i < shirq->irq_nr; i++, j <<= 1) { | ||
209 | |||
210 | if (!(j & val)) | ||
211 | continue; | ||
212 | |||
213 | generic_handle_irq(shirq->irq_base + i); | ||
214 | |||
215 | /* clear interrupt */ | ||
216 | if (shirq->regs.clear_reg == -1) | ||
217 | continue; | ||
218 | |||
219 | tmp = readl(shirq->base + shirq->regs.clear_reg); | ||
220 | if (shirq->regs.reset_to_clear) | ||
221 | tmp &= ~(j << shirq->irq_bit_off); | ||
222 | else | ||
223 | tmp |= (j << shirq->irq_bit_off); | ||
224 | writel(tmp, shirq->base + shirq->regs.clear_reg); | ||
225 | } | ||
226 | } | ||
227 | chip->irq_unmask(&desc->irq_data); | ||
228 | } | ||
229 | |||
230 | static void __init spear_shirq_register(struct spear_shirq *shirq) | ||
231 | { | ||
232 | int i; | ||
233 | |||
234 | if (shirq->invalid_irq) | ||
235 | return; | ||
236 | |||
237 | irq_set_chained_handler(shirq->irq, shirq_handler); | ||
238 | for (i = 0; i < shirq->irq_nr; i++) { | ||
239 | irq_set_chip_and_handler(shirq->irq_base + i, | ||
240 | &shirq_chip, handle_simple_irq); | ||
241 | set_irq_flags(shirq->irq_base + i, IRQF_VALID); | ||
242 | irq_set_chip_data(shirq->irq_base + i, shirq); | ||
243 | } | ||
244 | |||
245 | irq_set_handler_data(shirq->irq, shirq); | ||
246 | } | ||
247 | |||
248 | static int __init shirq_init(struct spear_shirq **shirq_blocks, int block_nr, | ||
249 | struct device_node *np) | ||
250 | { | ||
251 | int i, irq_base, hwirq = 0, irq_nr = 0; | ||
252 | static struct irq_domain *shirq_domain; | ||
253 | void __iomem *base; | ||
254 | |||
255 | base = of_iomap(np, 0); | ||
256 | if (!base) { | ||
257 | pr_err("%s: failed to map shirq registers\n", __func__); | ||
258 | return -ENXIO; | ||
259 | } | ||
260 | |||
261 | for (i = 0; i < block_nr; i++) | ||
262 | irq_nr += shirq_blocks[i]->irq_nr; | ||
263 | |||
264 | irq_base = irq_alloc_descs(-1, 0, irq_nr, 0); | ||
265 | if (IS_ERR_VALUE(irq_base)) { | ||
266 | pr_err("%s: irq desc alloc failed\n", __func__); | ||
267 | goto err_unmap; | ||
268 | } | ||
269 | |||
270 | shirq_domain = irq_domain_add_legacy(np, irq_nr, irq_base, 0, | ||
271 | &irq_domain_simple_ops, NULL); | ||
272 | if (WARN_ON(!shirq_domain)) { | ||
273 | pr_warn("%s: irq domain init failed\n", __func__); | ||
274 | goto err_free_desc; | ||
275 | } | ||
276 | |||
277 | for (i = 0; i < block_nr; i++) { | ||
278 | shirq_blocks[i]->base = base; | ||
279 | shirq_blocks[i]->irq_base = irq_find_mapping(shirq_domain, | ||
280 | hwirq); | ||
281 | shirq_blocks[i]->irq = irq_of_parse_and_map(np, i); | ||
282 | |||
283 | spear_shirq_register(shirq_blocks[i]); | ||
284 | hwirq += shirq_blocks[i]->irq_nr; | ||
285 | } | ||
286 | |||
287 | return 0; | ||
288 | |||
289 | err_free_desc: | ||
290 | irq_free_descs(irq_base, irq_nr); | ||
291 | err_unmap: | ||
292 | iounmap(base); | ||
293 | return -ENXIO; | ||
294 | } | ||
295 | |||
296 | int __init spear300_shirq_of_init(struct device_node *np, | ||
297 | struct device_node *parent) | ||
298 | { | ||
299 | return shirq_init(spear300_shirq_blocks, | ||
300 | ARRAY_SIZE(spear300_shirq_blocks), np); | ||
301 | } | ||
302 | |||
303 | int __init spear310_shirq_of_init(struct device_node *np, | ||
304 | struct device_node *parent) | ||
305 | { | ||
306 | return shirq_init(spear310_shirq_blocks, | ||
307 | ARRAY_SIZE(spear310_shirq_blocks), np); | ||
308 | } | ||
309 | |||
310 | int __init spear320_shirq_of_init(struct device_node *np, | ||
311 | struct device_node *parent) | ||
312 | { | ||
313 | return shirq_init(spear320_shirq_blocks, | ||
314 | ARRAY_SIZE(spear320_shirq_blocks), np); | ||
315 | } | ||