aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-spear3xx/include/mach/irqs.h101
-rw-r--r--arch/arm/mach-spear3xx/include/mach/spear300.h16
-rw-r--r--arch/arm/mach-spear3xx/include/mach/spear310.h24
-rw-r--r--arch/arm/mach-spear3xx/include/mach/spear320.h26
-rw-r--r--arch/arm/mach-spear3xx/spear300.c67
-rw-r--r--arch/arm/mach-spear3xx/spear310.c148
-rw-r--r--arch/arm/mach-spear3xx/spear320.c150
-rw-r--r--arch/arm/mach-spear6xx/include/mach/irqs.h1
-rw-r--r--arch/arm/plat-spear/Makefile2
-rw-r--r--arch/arm/plat-spear/include/plat/shirq.h73
-rw-r--r--arch/arm/plat-spear/shirq.c118
11 files changed, 718 insertions, 8 deletions
diff --git a/arch/arm/mach-spear3xx/include/mach/irqs.h b/arch/arm/mach-spear3xx/include/mach/irqs.h
index fe980e07b6ab..7f940b818473 100644
--- a/arch/arm/mach-spear3xx/include/mach/irqs.h
+++ b/arch/arm/mach-spear3xx/include/mach/irqs.h
@@ -14,7 +14,7 @@
14#ifndef __MACH_IRQS_H 14#ifndef __MACH_IRQS_H
15#define __MACH_IRQS_H 15#define __MACH_IRQS_H
16 16
17/* IRQ definitions */ 17/* SPEAr3xx IRQ definitions */
18#define IRQ_HW_ACCEL_MOD_0 0 18#define IRQ_HW_ACCEL_MOD_0 0
19#define IRQ_INTRCOMM_RAS_ARM 1 19#define IRQ_INTRCOMM_RAS_ARM 1
20#define IRQ_CPU_GPT1_1 2 20#define IRQ_CPU_GPT1_1 2
@@ -50,16 +50,103 @@
50#define IRQ_HW_ACCEL_MOD_1 31 50#define IRQ_HW_ACCEL_MOD_1 31
51#define IRQ_VIC_END 32 51#define IRQ_VIC_END 32
52 52
53#define SPEAR_GPIO_INT_BASE IRQ_VIC_END 53#define VIRQ_START IRQ_VIC_END
54 54
55/* SPEAr300 Virtual irq definitions */
55#ifdef CONFIG_MACH_SPEAR300 56#ifdef CONFIG_MACH_SPEAR300
56#define SPEAR_GPIO1_INT_BASE (SPEAR_GPIO_INT_BASE + 8) 57/* IRQs sharing IRQ_GEN_RAS_1 */
57#define SPEAR_GPIO_INT_END (SPEAR_GPIO1_INT_BASE + 8) 58#define VIRQ_IT_PERS_S (VIRQ_START + 0)
59#define VIRQ_IT_CHANGE_S (VIRQ_START + 1)
60#define VIRQ_I2S (VIRQ_START + 2)
61#define VIRQ_TDM (VIRQ_START + 3)
62#define VIRQ_CAMERA_L (VIRQ_START + 4)
63#define VIRQ_CAMERA_F (VIRQ_START + 5)
64#define VIRQ_CAMERA_V (VIRQ_START + 6)
65#define VIRQ_KEYBOARD (VIRQ_START + 7)
66#define VIRQ_GPIO1 (VIRQ_START + 8)
67
68/* IRQs sharing IRQ_GEN_RAS_3 */
69#define IRQ_CLCD IRQ_GEN_RAS_3
70
71/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
72#define IRQ_SDIO IRQ_INTRCOMM_RAS_ARM
73
74/* GPIO pins virtual irqs */
75#define SPEAR_GPIO_INT_BASE (VIRQ_START + 9)
76#define SPEAR_GPIO1_INT_BASE (SPEAR_GPIO_INT_BASE + 8)
77#define SPEAR_GPIO_INT_END (SPEAR_GPIO1_INT_BASE + 8)
78
79/* SPEAr310 Virtual irq definitions */
80#elif defined(CONFIG_MACH_SPEAR310)
81/* IRQs sharing IRQ_GEN_RAS_1 */
82#define VIRQ_SMII0 (VIRQ_START + 0)
83#define VIRQ_SMII1 (VIRQ_START + 1)
84#define VIRQ_SMII2 (VIRQ_START + 2)
85#define VIRQ_SMII3 (VIRQ_START + 3)
86#define VIRQ_WAKEUP_SMII0 (VIRQ_START + 4)
87#define VIRQ_WAKEUP_SMII1 (VIRQ_START + 5)
88#define VIRQ_WAKEUP_SMII2 (VIRQ_START + 6)
89#define VIRQ_WAKEUP_SMII3 (VIRQ_START + 7)
90
91/* IRQs sharing IRQ_GEN_RAS_2 */
92#define VIRQ_UART1 (VIRQ_START + 8)
93#define VIRQ_UART2 (VIRQ_START + 9)
94#define VIRQ_UART3 (VIRQ_START + 10)
95#define VIRQ_UART4 (VIRQ_START + 11)
96#define VIRQ_UART5 (VIRQ_START + 12)
97
98/* IRQs sharing IRQ_GEN_RAS_3 */
99#define VIRQ_EMI (VIRQ_START + 13)
100#define VIRQ_PLGPIO (VIRQ_START + 14)
101
102/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
103#define VIRQ_TDM_HDLC (VIRQ_START + 15)
104#define VIRQ_RS485_0 (VIRQ_START + 16)
105#define VIRQ_RS485_1 (VIRQ_START + 17)
106
107/* GPIO pins virtual irqs */
108#define SPEAR_GPIO_INT_BASE (VIRQ_START + 18)
109
110/* SPEAr320 Virtual irq definitions */
58#else 111#else
59#define SPEAR_GPIO_INT_END (SPEAR_GPIO_INT_BASE + 8) 112/* IRQs sharing IRQ_GEN_RAS_1 */
113#define VIRQ_EMI (VIRQ_START + 0)
114#define VIRQ_CLCD (VIRQ_START + 1)
115#define VIRQ_SPP (VIRQ_START + 2)
116
117/* IRQs sharing IRQ_GEN_RAS_2 */
118#define IRQ_SDIO IRQ_GEN_RAS_2
119
120/* IRQs sharing IRQ_GEN_RAS_3 */
121#define VIRQ_PLGPIO (VIRQ_START + 3)
122#define VIRQ_I2S_PLAY (VIRQ_START + 4)
123#define VIRQ_I2S_REC (VIRQ_START + 5)
124
125/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
126#define VIRQ_CANU (VIRQ_START + 6)
127#define VIRQ_CANL (VIRQ_START + 7)
128#define VIRQ_UART1 (VIRQ_START + 8)
129#define VIRQ_UART2 (VIRQ_START + 9)
130#define VIRQ_SSP1 (VIRQ_START + 10)
131#define VIRQ_SSP2 (VIRQ_START + 11)
132#define VIRQ_SMII0 (VIRQ_START + 12)
133#define VIRQ_MII1_SMII1 (VIRQ_START + 13)
134#define VIRQ_WAKEUP_SMII0 (VIRQ_START + 14)
135#define VIRQ_WAKEUP_MII1_SMII1 (VIRQ_START + 15)
136#define VIRQ_I2C (VIRQ_START + 16)
137
138/* GPIO pins virtual irqs */
139#define SPEAR_GPIO_INT_BASE (VIRQ_START + 17)
140
141#endif
142
143/* PLGPIO Virtual IRQs */
144#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
145#define SPEAR_PLGPIO_INT_BASE (SPEAR_GPIO_INT_BASE + 8)
146#define SPEAR_GPIO_INT_END (SPEAR_PLGPIO_INT_BASE + 102)
60#endif 147#endif
61 148
62#define VIRTUAL_IRQS (SPEAR_GPIO_INT_END - IRQ_VIC_END) 149#define VIRQ_END SPEAR_GPIO_INT_END
63#define NR_IRQS (IRQ_VIC_END + VIRTUAL_IRQS) 150#define NR_IRQS VIRQ_END
64 151
65#endif /* __MACH_IRQS_H */ 152#endif /* __MACH_IRQS_H */
diff --git a/arch/arm/mach-spear3xx/include/mach/spear300.h b/arch/arm/mach-spear3xx/include/mach/spear300.h
index 40c16f385cfa..ccaa76522ee2 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear300.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear300.h
@@ -20,6 +20,22 @@
20#define SPEAR300_TELECOM_BASE 0x50000000 20#define SPEAR300_TELECOM_BASE 0x50000000
21#define SPEAR300_TELECOM_SIZE 0x10000000 21#define SPEAR300_TELECOM_SIZE 0x10000000
22 22
23/* Interrupt registers offsets and masks */
24#define SPEAR300_TELECOM_REG_SIZE 0x00010000
25#define INT_ENB_MASK_REG 0x54
26#define INT_STS_MASK_REG 0x58
27#define IT_PERS_S_IRQ_MASK (1 << 0)
28#define IT_CHANGE_S_IRQ_MASK (1 << 1)
29#define I2S_IRQ_MASK (1 << 2)
30#define TDM_IRQ_MASK (1 << 3)
31#define CAMERA_L_IRQ_MASK (1 << 4)
32#define CAMERA_F_IRQ_MASK (1 << 5)
33#define CAMERA_V_IRQ_MASK (1 << 6)
34#define KEYBOARD_IRQ_MASK (1 << 7)
35#define GPIO1_IRQ_MASK (1 << 8)
36
37#define SHIRQ_RAS1_MASK 0x1FF
38
23#define SPEAR300_CLCD_BASE 0x60000000 39#define SPEAR300_CLCD_BASE 0x60000000
24#define SPEAR300_CLCD_SIZE 0x10000000 40#define SPEAR300_CLCD_SIZE 0x10000000
25 41
diff --git a/arch/arm/mach-spear3xx/include/mach/spear310.h b/arch/arm/mach-spear3xx/include/mach/spear310.h
index d4f58d6469d9..b27bb8af3309 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear310.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear310.h
@@ -40,6 +40,30 @@
40 40
41#define SPEAR310_SOC_CONFIG_BASE 0xB4000000 41#define SPEAR310_SOC_CONFIG_BASE 0xB4000000
42#define SPEAR310_SOC_CONFIG_SIZE 0x00000070 42#define SPEAR310_SOC_CONFIG_SIZE 0x00000070
43/* Interrupt registers offsets and masks */
44#define INT_STS_MASK_REG 0x04
45#define SMII0_IRQ_MASK (1 << 0)
46#define SMII1_IRQ_MASK (1 << 1)
47#define SMII2_IRQ_MASK (1 << 2)
48#define SMII3_IRQ_MASK (1 << 3)
49#define WAKEUP_SMII0_IRQ_MASK (1 << 4)
50#define WAKEUP_SMII1_IRQ_MASK (1 << 5)
51#define WAKEUP_SMII2_IRQ_MASK (1 << 6)
52#define WAKEUP_SMII3_IRQ_MASK (1 << 7)
53#define UART1_IRQ_MASK (1 << 8)
54#define UART2_IRQ_MASK (1 << 9)
55#define UART3_IRQ_MASK (1 << 10)
56#define UART4_IRQ_MASK (1 << 11)
57#define UART5_IRQ_MASK (1 << 12)
58#define EMI_IRQ_MASK (1 << 13)
59#define TDM_HDLC_IRQ_MASK (1 << 14)
60#define RS485_0_IRQ_MASK (1 << 15)
61#define RS485_1_IRQ_MASK (1 << 16)
62
63#define SHIRQ_RAS1_MASK 0x000FF
64#define SHIRQ_RAS2_MASK 0x01F00
65#define SHIRQ_RAS3_MASK 0x02000
66#define SHIRQ_INTRCOMM_RAS_MASK 0x1C000
43 67
44#endif /* __MACH_SPEAR310_H */ 68#endif /* __MACH_SPEAR310_H */
45 69
diff --git a/arch/arm/mach-spear3xx/include/mach/spear320.h b/arch/arm/mach-spear3xx/include/mach/spear320.h
index e8ad2ed82e24..cacf17a958cd 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear320.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear320.h
@@ -64,6 +64,32 @@
64 64
65#define SPEAR320_SOC_CONFIG_BASE 0xB4000000 65#define SPEAR320_SOC_CONFIG_BASE 0xB4000000
66#define SPEAR320_SOC_CONFIG_SIZE 0x00000070 66#define SPEAR320_SOC_CONFIG_SIZE 0x00000070
67/* Interrupt registers offsets and masks */
68#define INT_STS_MASK_REG 0x04
69#define INT_CLR_MASK_REG 0x04
70#define INT_ENB_MASK_REG 0x08
71#define GPIO_IRQ_MASK (1 << 0)
72#define I2S_PLAY_IRQ_MASK (1 << 1)
73#define I2S_REC_IRQ_MASK (1 << 2)
74#define EMI_IRQ_MASK (1 << 7)
75#define CLCD_IRQ_MASK (1 << 8)
76#define SPP_IRQ_MASK (1 << 9)
77#define SDIO_IRQ_MASK (1 << 10)
78#define CAN_U_IRQ_MASK (1 << 11)
79#define CAN_L_IRQ_MASK (1 << 12)
80#define UART1_IRQ_MASK (1 << 13)
81#define UART2_IRQ_MASK (1 << 14)
82#define SSP1_IRQ_MASK (1 << 15)
83#define SSP2_IRQ_MASK (1 << 16)
84#define SMII0_IRQ_MASK (1 << 17)
85#define MII1_SMII1_IRQ_MASK (1 << 18)
86#define WAKEUP_SMII0_IRQ_MASK (1 << 19)
87#define WAKEUP_MII1_SMII1_IRQ_MASK (1 << 20)
88#define I2C1_IRQ_MASK (1 << 21)
89
90#define SHIRQ_RAS1_MASK 0x000380
91#define SHIRQ_RAS3_MASK 0x000007
92#define SHIRQ_INTRCOMM_RAS_MASK 0x3FF800
67 93
68#endif /* __MACH_SPEAR320_H */ 94#endif /* __MACH_SPEAR320_H */
69 95
diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index 66e7fcd8baf8..3560f8c1e723 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -17,6 +17,7 @@
17#include <asm/irq.h> 17#include <asm/irq.h>
18#include <mach/generic.h> 18#include <mach/generic.h>
19#include <mach/spear.h> 19#include <mach/spear.h>
20#include <plat/shirq.h>
20 21
21/* pad multiplexing support */ 22/* pad multiplexing support */
22/* muxing registers */ 23/* muxing registers */
@@ -386,14 +387,78 @@ struct amba_device gpio1_device = {
386 .end = SPEAR300_GPIO_BASE + SPEAR300_GPIO_SIZE - 1, 387 .end = SPEAR300_GPIO_BASE + SPEAR300_GPIO_SIZE - 1,
387 .flags = IORESOURCE_MEM, 388 .flags = IORESOURCE_MEM,
388 }, 389 },
389 .irq = {IRQ_GEN_RAS_1, NO_IRQ}, 390 .irq = {VIRQ_GPIO1, NO_IRQ},
391};
392
393/* spear3xx shared irq */
394struct shirq_dev_config shirq_ras1_config[] = {
395 {
396 .virq = VIRQ_IT_PERS_S,
397 .enb_mask = IT_PERS_S_IRQ_MASK,
398 .status_mask = IT_PERS_S_IRQ_MASK,
399 }, {
400 .virq = VIRQ_IT_CHANGE_S,
401 .enb_mask = IT_CHANGE_S_IRQ_MASK,
402 .status_mask = IT_CHANGE_S_IRQ_MASK,
403 }, {
404 .virq = VIRQ_I2S,
405 .enb_mask = I2S_IRQ_MASK,
406 .status_mask = I2S_IRQ_MASK,
407 }, {
408 .virq = VIRQ_TDM,
409 .enb_mask = TDM_IRQ_MASK,
410 .status_mask = TDM_IRQ_MASK,
411 }, {
412 .virq = VIRQ_CAMERA_L,
413 .enb_mask = CAMERA_L_IRQ_MASK,
414 .status_mask = CAMERA_L_IRQ_MASK,
415 }, {
416 .virq = VIRQ_CAMERA_F,
417 .enb_mask = CAMERA_F_IRQ_MASK,
418 .status_mask = CAMERA_F_IRQ_MASK,
419 }, {
420 .virq = VIRQ_CAMERA_V,
421 .enb_mask = CAMERA_V_IRQ_MASK,
422 .status_mask = CAMERA_V_IRQ_MASK,
423 }, {
424 .virq = VIRQ_KEYBOARD,
425 .enb_mask = KEYBOARD_IRQ_MASK,
426 .status_mask = KEYBOARD_IRQ_MASK,
427 }, {
428 .virq = VIRQ_GPIO1,
429 .enb_mask = GPIO1_IRQ_MASK,
430 .status_mask = GPIO1_IRQ_MASK,
431 },
432};
433
434struct spear_shirq shirq_ras1 = {
435 .irq = IRQ_GEN_RAS_1,
436 .dev_config = shirq_ras1_config,
437 .dev_count = ARRAY_SIZE(shirq_ras1_config),
438 .regs = {
439 .enb_reg = INT_ENB_MASK_REG,
440 .status_reg = INT_STS_MASK_REG,
441 .status_reg_mask = SHIRQ_RAS1_MASK,
442 .clear_reg = -1,
443 },
390}; 444};
391 445
392/* spear300 routines */ 446/* spear300 routines */
393void __init spear300_init(void) 447void __init spear300_init(void)
394{ 448{
449 int ret = 0;
450
395 /* call spear3xx family common init function */ 451 /* call spear3xx family common init function */
396 spear3xx_init(); 452 spear3xx_init();
453
454 /* shared irq registeration */
455 shirq_ras1.regs.base =
456 ioremap(SPEAR300_TELECOM_BASE, SPEAR300_TELECOM_REG_SIZE);
457 if (shirq_ras1.regs.base) {
458 ret = spear_shirq_register(&shirq_ras1);
459 if (ret)
460 printk(KERN_ERR "Error registering Shared IRQ\n");
461 }
397} 462}
398 463
399void spear300_pmx_init(void) 464void spear300_pmx_init(void)
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
index dd5a57282711..96a1ab824bac 100644
--- a/arch/arm/mach-spear3xx/spear310.c
+++ b/arch/arm/mach-spear3xx/spear310.c
@@ -15,6 +15,7 @@
15#include <asm/irq.h> 15#include <asm/irq.h>
16#include <mach/generic.h> 16#include <mach/generic.h>
17#include <mach/spear.h> 17#include <mach/spear.h>
18#include <plat/shirq.h>
18 19
19/* pad multiplexing support */ 20/* pad multiplexing support */
20/* muxing registers */ 21/* muxing registers */
@@ -140,11 +141,158 @@ struct pmx_driver pmx_driver = {
140 141
141/* Add spear310 specific devices here */ 142/* Add spear310 specific devices here */
142 143
144/* spear3xx shared irq */
145struct shirq_dev_config shirq_ras1_config[] = {
146 {
147 .virq = VIRQ_SMII0,
148 .status_mask = SMII0_IRQ_MASK,
149 }, {
150 .virq = VIRQ_SMII1,
151 .status_mask = SMII1_IRQ_MASK,
152 }, {
153 .virq = VIRQ_SMII2,
154 .status_mask = SMII2_IRQ_MASK,
155 }, {
156 .virq = VIRQ_SMII3,
157 .status_mask = SMII3_IRQ_MASK,
158 }, {
159 .virq = VIRQ_WAKEUP_SMII0,
160 .status_mask = WAKEUP_SMII0_IRQ_MASK,
161 }, {
162 .virq = VIRQ_WAKEUP_SMII1,
163 .status_mask = WAKEUP_SMII1_IRQ_MASK,
164 }, {
165 .virq = VIRQ_WAKEUP_SMII2,
166 .status_mask = WAKEUP_SMII2_IRQ_MASK,
167 }, {
168 .virq = VIRQ_WAKEUP_SMII3,
169 .status_mask = WAKEUP_SMII3_IRQ_MASK,
170 },
171};
172
173struct spear_shirq shirq_ras1 = {
174 .irq = IRQ_GEN_RAS_1,
175 .dev_config = shirq_ras1_config,
176 .dev_count = ARRAY_SIZE(shirq_ras1_config),
177 .regs = {
178 .enb_reg = -1,
179 .status_reg = INT_STS_MASK_REG,
180 .status_reg_mask = SHIRQ_RAS1_MASK,
181 .clear_reg = -1,
182 },
183};
184
185struct shirq_dev_config shirq_ras2_config[] = {
186 {
187 .virq = VIRQ_UART1,
188 .status_mask = UART1_IRQ_MASK,
189 }, {
190 .virq = VIRQ_UART2,
191 .status_mask = UART2_IRQ_MASK,
192 }, {
193 .virq = VIRQ_UART3,
194 .status_mask = UART3_IRQ_MASK,
195 }, {
196 .virq = VIRQ_UART4,
197 .status_mask = UART4_IRQ_MASK,
198 }, {
199 .virq = VIRQ_UART5,
200 .status_mask = UART5_IRQ_MASK,
201 },
202};
203
204struct spear_shirq shirq_ras2 = {
205 .irq = IRQ_GEN_RAS_2,
206 .dev_config = shirq_ras2_config,
207 .dev_count = ARRAY_SIZE(shirq_ras2_config),
208 .regs = {
209 .enb_reg = -1,
210 .status_reg = INT_STS_MASK_REG,
211 .status_reg_mask = SHIRQ_RAS2_MASK,
212 .clear_reg = -1,
213 },
214};
215
216struct shirq_dev_config shirq_ras3_config[] = {
217 {
218 .virq = VIRQ_EMI,
219 .status_mask = EMI_IRQ_MASK,
220 },
221};
222
223struct spear_shirq shirq_ras3 = {
224 .irq = IRQ_GEN_RAS_3,
225 .dev_config = shirq_ras3_config,
226 .dev_count = ARRAY_SIZE(shirq_ras3_config),
227 .regs = {
228 .enb_reg = -1,
229 .status_reg = INT_STS_MASK_REG,
230 .status_reg_mask = SHIRQ_RAS3_MASK,
231 .clear_reg = -1,
232 },
233};
234
235struct shirq_dev_config shirq_intrcomm_ras_config[] = {
236 {
237 .virq = VIRQ_TDM_HDLC,
238 .status_mask = TDM_HDLC_IRQ_MASK,
239 }, {
240 .virq = VIRQ_RS485_0,
241 .status_mask = RS485_0_IRQ_MASK,
242 }, {
243 .virq = VIRQ_RS485_1,
244 .status_mask = RS485_1_IRQ_MASK,
245 },
246};
247
248struct spear_shirq shirq_intrcomm_ras = {
249 .irq = IRQ_INTRCOMM_RAS_ARM,
250 .dev_config = shirq_intrcomm_ras_config,
251 .dev_count = ARRAY_SIZE(shirq_intrcomm_ras_config),
252 .regs = {
253 .enb_reg = -1,
254 .status_reg = INT_STS_MASK_REG,
255 .status_reg_mask = SHIRQ_INTRCOMM_RAS_MASK,
256 .clear_reg = -1,
257 },
258};
259
143/* spear310 routines */ 260/* spear310 routines */
144void __init spear310_init(void) 261void __init spear310_init(void)
145{ 262{
263 void __iomem *base;
264 int ret = 0;
265
146 /* call spear3xx family common init function */ 266 /* call spear3xx family common init function */
147 spear3xx_init(); 267 spear3xx_init();
268
269 /* shared irq registeration */
270 base = ioremap(SPEAR310_SOC_CONFIG_BASE, SPEAR310_SOC_CONFIG_SIZE);
271 if (base) {
272 /* shirq 1 */
273 shirq_ras1.regs.base = base;
274 ret = spear_shirq_register(&shirq_ras1);
275 if (ret)
276 printk(KERN_ERR "Error registering Shared IRQ 1\n");
277
278 /* shirq 2 */
279 shirq_ras2.regs.base = base;
280 ret = spear_shirq_register(&shirq_ras2);
281 if (ret)
282 printk(KERN_ERR "Error registering Shared IRQ 2\n");
283
284 /* shirq 3 */
285 shirq_ras3.regs.base = base;
286 ret = spear_shirq_register(&shirq_ras3);
287 if (ret)
288 printk(KERN_ERR "Error registering Shared IRQ 3\n");
289
290 /* shirq 4 */
291 shirq_intrcomm_ras.regs.base = base;
292 ret = spear_shirq_register(&shirq_intrcomm_ras);
293 if (ret)
294 printk(KERN_ERR "Error registering Shared IRQ 4\n");
295 }
148} 296}
149 297
150void spear310_pmx_init(void) 298void spear310_pmx_init(void)
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index 2cedf5eb9ec9..6a1219549369 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -15,6 +15,7 @@
15#include <asm/irq.h> 15#include <asm/irq.h>
16#include <mach/generic.h> 16#include <mach/generic.h>
17#include <mach/spear.h> 17#include <mach/spear.h>
18#include <plat/shirq.h>
18 19
19/* pad multiplexing support */ 20/* pad multiplexing support */
20/* muxing registers */ 21/* muxing registers */
@@ -385,11 +386,160 @@ struct pmx_driver pmx_driver = {
385 386
386/* Add spear320 specific devices here */ 387/* Add spear320 specific devices here */
387 388
389/* spear3xx shared irq */
390struct shirq_dev_config shirq_ras1_config[] = {
391 {
392 .virq = VIRQ_EMI,
393 .status_mask = EMI_IRQ_MASK,
394 .clear_mask = EMI_IRQ_MASK,
395 }, {
396 .virq = VIRQ_CLCD,
397 .status_mask = CLCD_IRQ_MASK,
398 .clear_mask = CLCD_IRQ_MASK,
399 }, {
400 .virq = VIRQ_SPP,
401 .status_mask = SPP_IRQ_MASK,
402 .clear_mask = SPP_IRQ_MASK,
403 },
404};
405
406struct spear_shirq shirq_ras1 = {
407 .irq = IRQ_GEN_RAS_1,
408 .dev_config = shirq_ras1_config,
409 .dev_count = ARRAY_SIZE(shirq_ras1_config),
410 .regs = {
411 .enb_reg = -1,
412 .status_reg = INT_STS_MASK_REG,
413 .status_reg_mask = SHIRQ_RAS1_MASK,
414 .clear_reg = INT_CLR_MASK_REG,
415 .reset_to_clear = 1,
416 },
417};
418
419struct shirq_dev_config shirq_ras3_config[] = {
420 {
421 .virq = VIRQ_PLGPIO,
422 .enb_mask = GPIO_IRQ_MASK,
423 .status_mask = GPIO_IRQ_MASK,
424 .clear_mask = GPIO_IRQ_MASK,
425 }, {
426 .virq = VIRQ_I2S_PLAY,
427 .enb_mask = I2S_PLAY_IRQ_MASK,
428 .status_mask = I2S_PLAY_IRQ_MASK,
429 .clear_mask = I2S_PLAY_IRQ_MASK,
430 }, {
431 .virq = VIRQ_I2S_REC,
432 .enb_mask = I2S_REC_IRQ_MASK,
433 .status_mask = I2S_REC_IRQ_MASK,
434 .clear_mask = I2S_REC_IRQ_MASK,
435 },
436};
437
438struct spear_shirq shirq_ras3 = {
439 .irq = IRQ_GEN_RAS_3,
440 .dev_config = shirq_ras3_config,
441 .dev_count = ARRAY_SIZE(shirq_ras3_config),
442 .regs = {
443 .enb_reg = INT_ENB_MASK_REG,
444 .reset_to_enb = 1,
445 .status_reg = INT_STS_MASK_REG,
446 .status_reg_mask = SHIRQ_RAS3_MASK,
447 .clear_reg = INT_CLR_MASK_REG,
448 .reset_to_clear = 1,
449 },
450};
451
452struct shirq_dev_config shirq_intrcomm_ras_config[] = {
453 {
454 .virq = VIRQ_CANU,
455 .status_mask = CAN_U_IRQ_MASK,
456 .clear_mask = CAN_U_IRQ_MASK,
457 }, {
458 .virq = VIRQ_CANL,
459 .status_mask = CAN_L_IRQ_MASK,
460 .clear_mask = CAN_L_IRQ_MASK,
461 }, {
462 .virq = VIRQ_UART1,
463 .status_mask = UART1_IRQ_MASK,
464 .clear_mask = UART1_IRQ_MASK,
465 }, {
466 .virq = VIRQ_UART2,
467 .status_mask = UART2_IRQ_MASK,
468 .clear_mask = UART2_IRQ_MASK,
469 }, {
470 .virq = VIRQ_SSP1,
471 .status_mask = SSP1_IRQ_MASK,
472 .clear_mask = SSP1_IRQ_MASK,
473 }, {
474 .virq = VIRQ_SSP2,
475 .status_mask = SSP2_IRQ_MASK,
476 .clear_mask = SSP2_IRQ_MASK,
477 }, {
478 .virq = VIRQ_SMII0,
479 .status_mask = SMII0_IRQ_MASK,
480 .clear_mask = SMII0_IRQ_MASK,
481 }, {
482 .virq = VIRQ_MII1_SMII1,
483 .status_mask = MII1_SMII1_IRQ_MASK,
484 .clear_mask = MII1_SMII1_IRQ_MASK,
485 }, {
486 .virq = VIRQ_WAKEUP_SMII0,
487 .status_mask = WAKEUP_SMII0_IRQ_MASK,
488 .clear_mask = WAKEUP_SMII0_IRQ_MASK,
489 }, {
490 .virq = VIRQ_WAKEUP_MII1_SMII1,
491 .status_mask = WAKEUP_MII1_SMII1_IRQ_MASK,
492 .clear_mask = WAKEUP_MII1_SMII1_IRQ_MASK,
493 }, {
494 .virq = VIRQ_I2C,
495 .status_mask = I2C1_IRQ_MASK,
496 .clear_mask = I2C1_IRQ_MASK,
497 },
498};
499
500struct spear_shirq shirq_intrcomm_ras = {
501 .irq = IRQ_INTRCOMM_RAS_ARM,
502 .dev_config = shirq_intrcomm_ras_config,
503 .dev_count = ARRAY_SIZE(shirq_intrcomm_ras_config),
504 .regs = {
505 .enb_reg = -1,
506 .status_reg = INT_STS_MASK_REG,
507 .status_reg_mask = SHIRQ_INTRCOMM_RAS_MASK,
508 .clear_reg = INT_CLR_MASK_REG,
509 .reset_to_clear = 1,
510 },
511};
512
388/* spear320 routines */ 513/* spear320 routines */
389void __init spear320_init(void) 514void __init spear320_init(void)
390{ 515{
516 void __iomem *base;
517 int ret = 0;
518
391 /* call spear3xx family common init function */ 519 /* call spear3xx family common init function */
392 spear3xx_init(); 520 spear3xx_init();
521
522 /* shared irq registeration */
523 base = ioremap(SPEAR320_SOC_CONFIG_BASE, SPEAR320_SOC_CONFIG_SIZE);
524 if (base) {
525 /* shirq 1 */
526 shirq_ras1.regs.base = base;
527 ret = spear_shirq_register(&shirq_ras1);
528 if (ret)
529 printk(KERN_ERR "Error registering Shared IRQ 1\n");
530
531 /* shirq 3 */
532 shirq_ras3.regs.base = base;
533 ret = spear_shirq_register(&shirq_ras3);
534 if (ret)
535 printk(KERN_ERR "Error registering Shared IRQ 3\n");
536
537 /* shirq 4 */
538 shirq_intrcomm_ras.regs.base = base;
539 ret = spear_shirq_register(&shirq_intrcomm_ras);
540 if (ret)
541 printk(KERN_ERR "Error registering Shared IRQ 4\n");
542 }
393} 543}
394 544
395void spear320_pmx_init(void) 545void spear320_pmx_init(void)
diff --git a/arch/arm/mach-spear6xx/include/mach/irqs.h b/arch/arm/mach-spear6xx/include/mach/irqs.h
index 08a3abced750..8f214b03d75d 100644
--- a/arch/arm/mach-spear6xx/include/mach/irqs.h
+++ b/arch/arm/mach-spear6xx/include/mach/irqs.h
@@ -85,6 +85,7 @@
85 85
86#define IRQ_VIC_END 64 86#define IRQ_VIC_END 64
87 87
88/* GPIO pins virtual irqs */
88#define SPEAR_GPIO_INT_BASE IRQ_VIC_END 89#define SPEAR_GPIO_INT_BASE IRQ_VIC_END
89#define SPEAR_GPIO0_INT_BASE SPEAR_GPIO_INT_BASE 90#define SPEAR_GPIO0_INT_BASE SPEAR_GPIO_INT_BASE
90#define SPEAR_GPIO1_INT_BASE (SPEAR_GPIO0_INT_BASE + 8) 91#define SPEAR_GPIO1_INT_BASE (SPEAR_GPIO0_INT_BASE + 8)
diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile
index 6f4ad5e9462e..eb89540aeda9 100644
--- a/arch/arm/plat-spear/Makefile
+++ b/arch/arm/plat-spear/Makefile
@@ -4,3 +4,5 @@
4 4
5# Common support 5# Common support
6obj-y := clock.o padmux.o time.o 6obj-y := clock.o padmux.o time.o
7
8obj-$(CONFIG_ARCH_SPEAR3XX) += shirq.o
diff --git a/arch/arm/plat-spear/include/plat/shirq.h b/arch/arm/plat-spear/include/plat/shirq.h
new file mode 100644
index 000000000000..03ed8b585dcf
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/shirq.h
@@ -0,0 +1,73 @@
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.kumar@st.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_dev_config: shared irq device configuration
22 *
23 * virq: virtual irq number of device
24 * enb_mask: enable mask of device
25 * status_mask: status mask of device
26 * clear_mask: clear mask of device
27 */
28struct shirq_dev_config {
29 u32 virq;
30 u32 enb_mask;
31 u32 status_mask;
32 u32 clear_mask;
33};
34
35/*
36 * struct shirq_regs: shared irq register configuration
37 *
38 * base: base address of shared irq register
39 * enb_reg: enable register offset
40 * reset_to_enb: val 1 indicates, we need to clear bit for enabling interrupt
41 * status_reg: status register offset
42 * status_reg_mask: status register valid mask
43 * clear_reg: clear register offset
44 * reset_to_clear: val 1 indicates, we need to clear bit for clearing interrupt
45 */
46struct shirq_regs {
47 void __iomem *base;
48 u32 enb_reg;
49 u32 reset_to_enb;
50 u32 status_reg;
51 u32 status_reg_mask;
52 u32 clear_reg;
53 u32 reset_to_clear;
54};
55
56/*
57 * struct spear_shirq: shared irq structure
58 *
59 * irq: hardware irq number
60 * dev_config: array of device config structures which are using "irq" line
61 * dev_count: size of dev_config array
62 * regs: register configuration for shared irq block
63 */
64struct spear_shirq {
65 u32 irq;
66 struct shirq_dev_config *dev_config;
67 u32 dev_count;
68 struct shirq_regs regs;
69};
70
71int spear_shirq_register(struct spear_shirq *shirq);
72
73#endif /* __PLAT_SHIRQ_H */
diff --git a/arch/arm/plat-spear/shirq.c b/arch/arm/plat-spear/shirq.c
new file mode 100644
index 000000000000..2172d6946aea
--- /dev/null
+++ b/arch/arm/plat-spear/shirq.c
@@ -0,0 +1,118 @@
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.kumar@st.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#include <linux/err.h>
15#include <linux/io.h>
16#include <linux/irq.h>
17#include <linux/spinlock.h>
18#include <plat/shirq.h>
19
20struct spear_shirq *shirq;
21static DEFINE_SPINLOCK(lock);
22
23static void shirq_irq_mask(unsigned irq)
24{
25 struct spear_shirq *shirq = get_irq_chip_data(irq);
26 u32 val, id = irq - shirq->dev_config[0].virq;
27 unsigned long flags;
28
29 if ((shirq->regs.enb_reg == -1) || shirq->dev_config[id].enb_mask == -1)
30 return;
31
32 spin_lock_irqsave(&lock, flags);
33 val = readl(shirq->regs.base + shirq->regs.enb_reg);
34 if (shirq->regs.reset_to_enb)
35 val |= shirq->dev_config[id].enb_mask;
36 else
37 val &= ~(shirq->dev_config[id].enb_mask);
38 writel(val, shirq->regs.base + shirq->regs.enb_reg);
39 spin_unlock_irqrestore(&lock, flags);
40}
41
42static void shirq_irq_unmask(unsigned irq)
43{
44 struct spear_shirq *shirq = get_irq_chip_data(irq);
45 u32 val, id = irq - shirq->dev_config[0].virq;
46 unsigned long flags;
47
48 if ((shirq->regs.enb_reg == -1) || shirq->dev_config[id].enb_mask == -1)
49 return;
50
51 spin_lock_irqsave(&lock, flags);
52 val = readl(shirq->regs.base + shirq->regs.enb_reg);
53 if (shirq->regs.reset_to_enb)
54 val &= ~(shirq->dev_config[id].enb_mask);
55 else
56 val |= shirq->dev_config[id].enb_mask;
57 writel(val, shirq->regs.base + shirq->regs.enb_reg);
58 spin_unlock_irqrestore(&lock, flags);
59}
60
61static struct irq_chip shirq_chip = {
62 .name = "spear_shirq",
63 .ack = shirq_irq_mask,
64 .mask = shirq_irq_mask,
65 .unmask = shirq_irq_unmask,
66};
67
68static void shirq_handler(unsigned irq, struct irq_desc *desc)
69{
70 u32 i, val, mask;
71 struct spear_shirq *shirq = get_irq_data(irq);
72
73 desc->chip->ack(irq);
74 while ((val = readl(shirq->regs.base + shirq->regs.status_reg) &
75 shirq->regs.status_reg_mask)) {
76 for (i = 0; (i < shirq->dev_count) && val; i++) {
77 if (!(shirq->dev_config[i].status_mask & val))
78 continue;
79
80 generic_handle_irq(shirq->dev_config[i].virq);
81
82 /* clear interrupt */
83 val &= ~shirq->dev_config[i].status_mask;
84 if ((shirq->regs.clear_reg == -1) ||
85 shirq->dev_config[i].clear_mask == -1)
86 continue;
87 mask = readl(shirq->regs.base + shirq->regs.clear_reg);
88 if (shirq->regs.reset_to_clear)
89 mask &= ~shirq->dev_config[i].clear_mask;
90 else
91 mask |= shirq->dev_config[i].clear_mask;
92 writel(mask, shirq->regs.base + shirq->regs.clear_reg);
93 }
94 }
95 desc->chip->unmask(irq);
96}
97
98int spear_shirq_register(struct spear_shirq *shirq)
99{
100 int i;
101
102 if (!shirq || !shirq->dev_config || !shirq->regs.base)
103 return -EFAULT;
104
105 if (!shirq->dev_count)
106 return -EINVAL;
107
108 set_irq_chained_handler(shirq->irq, shirq_handler);
109 for (i = 0; i < shirq->dev_count; i++) {
110 set_irq_chip(shirq->dev_config[i].virq, &shirq_chip);
111 set_irq_handler(shirq->dev_config[i].virq, handle_simple_irq);
112 set_irq_flags(shirq->dev_config[i].virq, IRQF_VALID);
113 set_irq_chip_data(shirq->dev_config[i].virq, shirq);
114 }
115
116 set_irq_data(shirq->irq, shirq);
117 return 0;
118}