2 //#include <linux/config.h>
3 #include <asm/arch/moxa.h>
4 #include <linux/module.h>
5 #include <linux/init.h>
7 //#include <asm/mach/irq.h>
8 #include <asm/hardware.h>
11 #include <asm/system.h>
13 #include <asm/arch/ftpci.h>
16 //#define VICTOR_USE_IRQ_LOCK // add by Victor Yu. 07-31-2007
18 #if 0 // mask by Victtor Yu. 03-15-2007
19 static spinlock_t cpe_int_lock
;
21 static spinlock_t cpe_int_lock
=SPIN_LOCK_UNLOCKED
;
24 #if 0 // add by Victor Yu. 05-17-2005
25 #include <asm/arch/irq.h>
26 #if 0 // mask by Victor Yu, 03-15-2007
27 struct irqchip cpe_irq_chip
= {
28 .ack
= cpe_mask_ack_irq
,
30 .unmask
= cpe_unmask_irq
,
35 inline void cpe_irq_set_mode(unsigned int base_p
,unsigned int irq
,unsigned int edge
)
38 *(volatile unsigned int *)(base_p
+IRQ_MODE_REG
)|=(1<<irq
);
40 *(volatile unsigned int *)(base_p
+IRQ_MODE_REG
)&=~(1<<irq
);
43 inline void cpe_irq_set_level(unsigned int base_p
,unsigned int irq
,unsigned int low
)
46 *(volatile unsigned int *)(base_p
+IRQ_LEVEL_REG
)|=(1<<irq
);
48 *(volatile unsigned int *)(base_p
+IRQ_LEVEL_REG
)&=~(1<<irq
);
52 inline void cpe_fiq_set_mode(unsigned int base_p
,unsigned int fiq
,unsigned int edge
)
55 *(volatile unsigned int *)(base_p
+FIQ_MODE_REG
)|=(1<<fiq
);
57 *(volatile unsigned int *)(base_p
+FIQ_MODE_REG
)&=~(1<<fiq
);
61 inline void cpe_fiq_set_level(unsigned int base_p
,unsigned int fiq
,unsigned int low
)
64 *(volatile unsigned int *)(base_p
+FIQ_LEVEL_REG
)|=(1<<fiq
);
66 *(volatile unsigned int *)(base_p
+FIQ_LEVEL_REG
)&=~(1<<fiq
);
70 void cpe_int_set_irq(unsigned int irq
,int mode
,int level
)
74 spin_lock_irqsave(&cpe_int_lock
, flags
);
75 if ( irq
< 32 ) { //irq
76 cpe_irq_set_mode(CPE_IC_VA_BASE
,irq
,mode
);
77 cpe_irq_set_level(CPE_IC_VA_BASE
,irq
,level
);
78 goto cpe_int_set_irq_exit
;
80 if ( irq
< 64 ) { //fiq
82 cpe_fiq_set_mode(CPE_IC_VA_BASE
,irq
,mode
);
83 cpe_fiq_set_level(CPE_IC_VA_BASE
,irq
,level
);
84 goto cpe_int_set_irq_exit
;
87 #ifdef CONFIG_ARCH_CPE
88 if ( irq
< 96 ) { //a321 irq
90 cpe_irq_set_mode(CPE_A321_IC_VA_BASE
,irq
,mode
);
91 cpe_irq_set_level(CPE_A321_IC_VA_BASE
,irq
,level
);
92 cpe_irq_set_mode(CPE_IC_VA_BASE
,IRQ_EXT_A321
,LEVEL
);
93 cpe_irq_set_level(CPE_IC_VA_BASE
,IRQ_EXT_A321
,H_ACTIVE
);
94 goto cpe_int_set_irq_exit
;
96 if ( irq
< 150 ) { //a321 fiq
98 cpe_fiq_set_mode(CPE_A321_IC_VA_BASE
,irq
,mode
);
99 cpe_fiq_set_level(CPE_A321_IC_VA_BASE
,irq
,level
);
100 cpe_fiq_set_mode(CPE_IC_VA_BASE
,IRQ_EXT_A321
,LEVEL
);
101 cpe_fiq_set_level(CPE_IC_VA_BASE
,IRQ_EXT_A321
,H_ACTIVE
);
102 goto cpe_int_set_irq_exit
;
107 if ( (irq
==VIRQ_PCI_A
)||(irq
==VIRQ_PCI_B
)||(irq
==VIRQ_PCI_C
)||(irq
==VIRQ_PCI_D
) ) {
109 goto cpe_int_set_irq_exit
;
110 cpe_irq_set_mode(CPE_A321_IC_VA_BASE
,IRQ_A321_PCI
,mode
);
111 cpe_irq_set_level(CPE_A321_IC_VA_BASE
,IRQ_A321_PCI
,level
);
112 cpe_irq_set_mode(CPE_IC_VA_BASE
,IRQ_EXT_A321
,LEVEL
);
113 cpe_irq_set_level(CPE_IC_VA_BASE
,IRQ_EXT_A321
,H_ACTIVE
);
114 #if 1 // add by Victor Yu. 10-20-2005
115 goto cpe_int_set_irq_exit
;
119 #endif // CONFIG_ARCH_CPE
121 #ifdef CONFIG_ARCH_IA240
124 if ( (irq
==VIRQ_PCI_A
)||(irq
==VIRQ_PCI_B
)||(irq
==VIRQ_PCI_C
)||(irq
==VIRQ_PCI_D
) ) {
126 goto cpe_int_set_irq_exit
;
127 cpe_irq_set_mode(CPE_IC_VA_BASE
,IRQ_PCI
,LEVEL
);
128 cpe_irq_set_level(CPE_IC_VA_BASE
,IRQ_PCI
,H_ACTIVE
);
129 goto cpe_int_set_irq_exit
;
132 #endif // CONFIG_ARCH_IA240
134 //printk("Not support irq %d\n",irq);
136 cpe_int_set_irq_exit
:
137 spin_unlock_irqrestore(&cpe_int_lock
, flags
);
140 void cpe_int_clear_irq(unsigned int base
,unsigned int irq
)
142 *(volatile unsigned int *)(base
+IRQ_CLEAR_REG
)=1<<irq
;
145 void cpe_int_clear_fiq(unsigned int base
,unsigned int irq
)
147 *(volatile unsigned int *)(base
+FIQ_CLEAR_REG
)=1<<irq
;
150 inline void cpe_int_disable_irq(unsigned int base
,unsigned int irq
)
152 *(volatile unsigned int *)(base
+IRQ_MASK_REG
)&=~(1<<irq
);
155 inline void cpe_int_disable_fiq(unsigned int base
,unsigned int irq
)
157 *(volatile unsigned int *)(base
+FIQ_MASK_REG
)&=~(1<<irq
);
160 /* Turn the interrupt source on. */
161 inline void cpe_int_enable_irq(unsigned int base
,unsigned int irq
)
163 *(volatile unsigned int *)(base
+IRQ_MASK_REG
)|=(1<<irq
);
166 inline void cpe_int_enable_fiq(unsigned int base
,unsigned int irq
)
168 *(volatile unsigned int *)(base
+FIQ_MASK_REG
)|=(1<<irq
);
171 void cpe_unmask_irq(unsigned int irq
)
173 #ifdef VICTOR_USE_IRQ_LOCK // add by Victor Yu. 07-31-2007
176 spin_lock_irqsave(&cpe_int_lock
, flags
);
178 spin_lock(&cpe_int_lock
);
180 if ( irq
< 32 ) { //irq
181 cpe_int_clear_irq(CPE_IC_VA_BASE
,irq
);
182 cpe_int_enable_irq(CPE_IC_VA_BASE
,irq
);
183 goto cpe_unmask_irq_exit
;
185 if ( irq
< 64 ) { //fiq
187 cpe_int_clear_fiq(CPE_IC_VA_BASE
,irq
);
188 cpe_int_enable_fiq(CPE_IC_VA_BASE
,irq
);
189 goto cpe_unmask_irq_exit
;
192 #ifdef CONFIG_ARCH_CPE
193 if ( irq
< 96 ) { //a321 irq
195 cpe_int_clear_irq(CPE_A321_IC_VA_BASE
,irq
);
196 cpe_int_clear_irq(CPE_IC_VA_BASE
,IRQ_EXT_A321
);
197 cpe_int_enable_irq(CPE_A321_IC_VA_BASE
,irq
);
198 cpe_int_enable_irq(CPE_IC_VA_BASE
,IRQ_EXT_A321
);
199 goto cpe_unmask_irq_exit
;
201 if ( irq
< 150 ) { //a321 fiq
203 cpe_int_clear_fiq(CPE_A321_IC_VA_BASE
,irq
);
204 cpe_int_clear_fiq(CPE_IC_VA_BASE
,IRQ_EXT_A321
);
205 cpe_int_enable_fiq(CPE_A321_IC_VA_BASE
,irq
);
206 cpe_int_enable_fiq(CPE_IC_VA_BASE
,IRQ_EXT_A321
);
207 goto cpe_unmask_irq_exit
;
212 if( (irq
==VIRQ_PCI_A
)||(irq
==VIRQ_PCI_B
)||(irq
==VIRQ_PCI_C
)||(irq
==VIRQ_PCI_D
) ) {
214 goto cpe_unmask_irq_exit
;
215 ftpci_clear_irq(irq
-150);
216 cpe_int_clear_irq(CPE_A321_IC_VA_BASE
,IRQ_A321_PCI
);
217 cpe_int_enable_irq(CPE_A321_IC_VA_BASE
,IRQ_A321_PCI
); //always enabled
218 cpe_int_clear_irq(CPE_IC_VA_BASE
,IRQ_EXT_A321
);
219 cpe_int_enable_irq(CPE_IC_VA_BASE
,IRQ_EXT_A321
); //always enabled
220 goto cpe_unmask_irq_exit
;
223 #endif // CONFIG_ARCH_CPE
225 #ifdef CONFIG_ARCH_IA240
228 if( (irq
==VIRQ_PCI_A
)||(irq
==VIRQ_PCI_B
)||(irq
==VIRQ_PCI_C
)||(irq
==VIRQ_PCI_D
) ) {
230 goto cpe_unmask_irq_exit
;
231 ftpci_clear_irq(irq
-64);
232 cpe_int_clear_irq(CPE_IC_VA_BASE
,IRQ_PCI
);
233 cpe_int_enable_irq(CPE_IC_VA_BASE
,IRQ_PCI
); //always enabled
234 goto cpe_unmask_irq_exit
;
237 #endif // CONFIG_ARCH_IA240
240 #ifdef VICTOR_USE_IRQ_LOCK // add by Victor Yu. 07-31-2007
241 spin_unlock_irqrestore(&cpe_int_lock
, flags
);
243 spin_unlock(&cpe_int_lock
);
247 void cpe_mask_ack_irq(unsigned int irq
)
249 #ifdef VICTOR_USE_IRQ_LOCK // add by Victor Yu. 07-31-2007
252 spin_lock_irqsave(&cpe_int_lock
, flags
);
254 spin_lock(&cpe_int_lock
);
256 if ( irq
< 32 ) { //irq
257 cpe_int_disable_irq(CPE_IC_VA_BASE
,irq
);
258 goto cpe_mask_ack_irq_exit
;
261 if ( irq
< 64 ) { //fiq
263 cpe_int_disable_fiq(CPE_IC_VA_BASE
,irq
);
264 goto cpe_mask_ack_irq_exit
;
267 #ifdef CONFIG_ARCH_CPE
268 if ( irq
< 96 ) { //a321 irq
270 cpe_int_disable_irq(CPE_A321_IC_VA_BASE
,irq
);
271 goto cpe_mask_ack_irq_exit
;
273 if ( irq
< 150 ) { //a321 fiq
275 cpe_int_disable_fiq(CPE_A321_IC_VA_BASE
,irq
);
276 goto cpe_mask_ack_irq_exit
;
280 if( (irq
==VIRQ_PCI_A
)||(irq
==VIRQ_PCI_B
)||(irq
==VIRQ_PCI_C
)||(irq
==VIRQ_PCI_D
) ) {
282 goto cpe_mask_ack_irq_exit
;
283 cpe_int_disable_irq(CPE_A321_IC_VA_BASE
,IRQ_A321_PCI
); //always enabled
284 goto cpe_mask_ack_irq_exit
;
287 #endif // CONFIG_ARCH_CPE
289 #ifdef CONFIG_ARCH_IA240
292 if( (irq
==VIRQ_PCI_A
)||(irq
==VIRQ_PCI_B
)||(irq
==VIRQ_PCI_C
)||(irq
==VIRQ_PCI_D
) ) {
294 goto cpe_mask_ack_irq_exit
;
295 cpe_int_disable_irq(CPE_IC_VA_BASE
,IRQ_PCI
);
296 goto cpe_mask_ack_irq_exit
;
299 #endif // CONFIG_ARCH_IA240
301 cpe_mask_ack_irq_exit
:
302 #ifdef VICTOR_USE_IRQ_LOCK // add by Victor Yu. 07-31-2007
303 spin_unlock_irqrestore(&cpe_int_lock
, flags
);
305 spin_unlock(&cpe_int_lock
);
309 void cpe_mask_irq(unsigned int irq
)
311 cpe_mask_ack_irq(irq
);
314 void cpe_int_init(void)
316 spin_lock_init(&cpe_int_lock
);
317 //init interrupt controller
318 outl(0, CPE_IC_VA_BASE
+IRQ_MASK_REG
);
319 outl(0, CPE_IC_VA_BASE
+FIQ_MASK_REG
);
320 outl(0xffffffff, CPE_IC_VA_BASE
+IRQ_CLEAR_REG
);
321 outl(0xffffffff, CPE_IC_VA_BASE
+FIQ_CLEAR_REG
);
323 #ifdef CONFIG_ARCH_CPE
324 //init a321 interrupt controller
325 outl(0, CPE_A321_IC_VA_BASE
+IRQ_MASK_REG
);
326 outl(0, CPE_A321_IC_VA_BASE
+FIQ_MASK_REG
);
327 outl(0xffffffff, CPE_A321_IC_VA_BASE
+IRQ_CLEAR_REG
);
328 outl(0xffffffff, CPE_A321_IC_VA_BASE
+FIQ_CLEAR_REG
);
329 cpe_int_set_irq(IRQ_EXT_A321
, LEVEL
, H_ACTIVE
);
330 cpe_int_enable_irq(CPE_IC_VA_BASE
,IRQ_EXT_A321
);
331 #endif // CONFIG_ARCH_CPE
334 EXPORT_SYMBOL(cpe_int_set_irq
);
335 EXPORT_SYMBOL(cpe_int_clear_irq
);