1 #include <linux/kernel.h>
2 #include <linux/device.h>
3 #include <linux/platform_device.h>
4 #include <linux/module.h>
5 #include <linux/interrupt.h>
6 #include <mach/mt_cirq.h>
7 #include <mach/mt_reg_base.h>
8 #include <asm/system.h>
9 #include <linux/module.h>
10 #include <linux/uaccess.h>
11 #include <linux/slab.h>
12 #include <linux/cpu.h>
13 #include <linux/smp.h>
14 #include <linux/types.h>
15 #include <mach/mt_sleep.h>
16 #include "mach/sync_write.h"
17 #include "mach/irqs.h"
18 #include <asm/mach/irq.h>
20 #include <linux/version.h>
21 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
22 #include <asm/hardware/gic.h>
24 #include <linux/irqchip/arm-gic.h>
28 #define INT_POL_CTL0 (MCUSYS_CFGREG_BASE + 0x100)
30 int mt_cirq_test(void);
31 void mt_cirq_dump_reg(void);
33 #define CIRQ_LOG_LEVEL KERN_DEBUG
38 #define dbgmsg dbg_print
41 #define print_func() do { \
42 printk("in %s\n",__func__); \
47 #define print_func() do { }while(0)
51 #define cirq_num_validate(x) do{\
52 if (x > (MT_NR_CIRQ) || x < 0){\
53 dbgmsg(CIRQ_LOG_LEVEL "Error in %s [CIRQ] wrong cirq, num %d is larger then 155 or less then 0\n",__func__,x); \
59 struct mt_cirq_driver
{
60 struct device_driver driver
;
61 const struct platform_device_id
*id_table
;
64 static struct mt_cirq_driver mt_cirq_drv
= {
67 .bus
= &platform_bus_type
,
73 /* 1: this cirq is masked
74 * 0: this cirq is umasked
75 * -1:cirq num is out of range
77 static unsigned int mt_cirq_get_mask(unsigned int cirq_num
)
80 unsigned int bit
= 1 << (cirq_num
% 32);
81 volatile unsigned int val
;
83 cirq_num_validate(cirq_num
);
84 base
= (cirq_num
/ 32) * 4 + CIRQ_MASK0
;
85 val
= readl(IOMEM(base
));
92 void mt_cirq_mask_all(void)
96 for(i
= 0; i
< 5; i
++)
97 mt65xx_reg_sync_writel(0xFFFFFFFF, CIRQ_MASK_SET0
+ i
* 4);
100 void mt_cirq_unmask_all(void)
104 for(i
= 0; i
< 5; i
++)
105 mt65xx_reg_sync_writel(0xFFFFFFFF, CIRQ_MASK_CLR0
+ i
* 4);
108 void mt_cirq_ack_all(void)
112 for(i
= 0; i
< 5; i
++)
113 mt65xx_reg_sync_writel(0xFFFFFFFF, CIRQ_ACK0
+ i
* 4);
118 * -1:cirq num is out of range
120 static int mt_cirq_mask(unsigned int cirq_num
)
123 unsigned int bit
= 1 << (cirq_num
% 32);
126 cirq_num_validate(cirq_num
);
127 base
= (cirq_num
/ 32) * 4 + CIRQ_ACK0
;
128 mt65xx_reg_sync_writel(bit
, base
);
130 base
= (cirq_num
/ 32) * 4 + CIRQ_MASK_SET0
;
131 mt65xx_reg_sync_writel(bit
, base
);
133 dbgmsg(CIRQ_LOG_LEVEL
"[CIRQ] mask addr:%x = %x, after set:0x%x\n", base
, bit
,readl(IOMEM((cirq_num
/ 32) * 4 + CIRQ_MASK0
)));
140 * -1:cirq num is out of range
142 static int mt_cirq_unmask(unsigned int cirq_num
)
145 unsigned int bit
= 1 << (cirq_num
% 32);
149 cirq_num_validate(cirq_num
);
150 base
= (cirq_num
/ 32) * 4 + CIRQ_ACK0
;
151 mt65xx_reg_sync_writel(bit
, base
);
152 dbgmsg(CIRQ_LOG_LEVEL
"[CIRQ] ack :%x, bit: %x\n", base
, bit
);
154 base
= (cirq_num
/ 32) * 4 + CIRQ_MASK_CLR0
;
155 mt65xx_reg_sync_writel(bit
, base
);
157 dbgmsg(CIRQ_LOG_LEVEL
"[CIRQ] unmask addr:%x = %x, after set:0x%x\n", base
, bit
,readl(IOMEM((cirq_num
/ 32) * 4 + CIRQ_MASK0
)));
164 * -1:cirq num is out of range
166 static int mt_cirq_set_pol(unsigned int cirq_num
, unsigned int pol
)
169 unsigned int bit
= 1 << (cirq_num
% 32);
173 cirq_num_validate(cirq_num
);
174 if (pol
== MT_CIRQ_POL_NEG
) {
175 base
= (cirq_num
/ 32) * 4 + CIRQ_POL_CLR0
;
176 } else if (pol
== MT_CIRQ_POL_POS
){
177 base
= (cirq_num
/ 32) * 4 + CIRQ_POL_SET0
;
179 dbgmsg(KERN_CRIT
"%s invalid polarity value\n", __func__
);
182 mt65xx_reg_sync_writel(bit
, base
);
183 dbgmsg(CIRQ_LOG_LEVEL
"[CIRQ] set pol:%d :%x, bit: %x, after set:0x%x\n",pol
, base
, bit
,readl(IOMEM((cirq_num
/ 32) * 4 + CIRQ_POL0
)));
189 * 0: set sens success
190 * -1:cirq num is out of range
192 static int mt_cirq_set_sens(unsigned int cirq_num
, unsigned int sens
)
195 unsigned int bit
= 1 << (cirq_num
% 32);
198 cirq_num_validate(cirq_num
);
199 if (sens
== MT_EDGE_SENSITIVE
) {
200 base
= (cirq_num
/ 32) * 4 + CIRQ_SENS_CLR0
;
201 } else if (sens
== MT_LEVEL_SENSITIVE
) {
202 base
= (cirq_num
/ 32) * 4 + CIRQ_SENS_SET0
;
204 dbgmsg(KERN_CRIT
"%s invalid sensitivity value\n", __func__
);
207 mt65xx_reg_sync_writel(bit
, base
);
208 dbgmsg(CIRQ_LOG_LEVEL
"[CIRQ] %s,sens:%d :%x, bit: %x, after set:0x%x\n", __func__
,sens
, base
, bit
,readl(IOMEM((cirq_num
/ 32) * 4 + CIRQ_SENS0
)));
212 /* 1: this cirq is MT_LEVEL_SENSITIVE
213 * 0: this cirq is MT_EDGE_SENSITIVE
214 * -1:cirq num is out of range
216 static unsigned int mt_cirq_get_sens(unsigned int cirq_num
)
220 unsigned int bit
= 1 << (cirq_num
% 32);
221 volatile unsigned int val
;
223 cirq_num_validate(cirq_num
);
224 base
= (cirq_num
/ 32) * 4 + CIRQ_SENS0
;
225 val
= readl(IOMEM(base
));
228 return MT_LEVEL_SENSITIVE
;
232 return MT_EDGE_SENSITIVE
;
237 /* 1: this cirq is MT_CIRQ_POL_POS
238 * 0: this cirq is MT_CIRQ_POL_NEG
239 * -1:cirq num is out of range
241 static unsigned int mt_cirq_get_pol(unsigned int cirq_num
)
244 unsigned int bit
= 1 << (cirq_num
% 32);
245 volatile unsigned int val
;
247 cirq_num_validate(cirq_num
);
248 base
= (cirq_num
/ 32) * 4 + CIRQ_POL0
;
249 val
= readl(IOMEM(base
));
252 return MT_CIRQ_POL_POS
;
256 return MT_CIRQ_POL_NEG
;
262 * -1:cirq num is out of range
264 static unsigned int mt_cirq_ack(unsigned int cirq_num
)
267 unsigned int bit
= 1 << (cirq_num
% 32);
270 cirq_num_validate(cirq_num
);
271 base
= (cirq_num
/ 32) * 4 + CIRQ_ACK0
;
272 mt65xx_reg_sync_writel(bit
, base
);
275 dbgmsg(CIRQ_LOG_LEVEL
"[CIRQ] ack addr:%x = %x\n", base
, bit
);
283 * -1:cirq num is out of range
285 unsigned int mt_cirq_read_status(unsigned int cirq_num
)
289 unsigned int bit
= 1 << (cirq_num
% 32);
290 volatile unsigned int val
;
292 cirq_num_validate(cirq_num
);
294 base
= (cirq_num
/ 32) * 4 + CIRQ_STA0
;
295 val
= readl(IOMEM(base
));
301 void mt_cirq_enable(void){
302 unsigned int base
=CIRQ_CON
;
303 volatile unsigned int val
;
304 val
= readl(IOMEM(CIRQ_CON
));
305 val
|= (0x3); //enable edge only mode
306 mt65xx_reg_sync_writel(val
,base
);
308 void mt_cirq_disable(void){
309 unsigned int base
=CIRQ_CON
;
310 volatile unsigned int val
;
311 val
= readl(IOMEM(CIRQ_CON
));
313 mt65xx_reg_sync_writel(val
,base
);
315 void mt_cirq_flush(void){
318 volatile unsigned int val
;
321 /*make edge interrupt shows in the STA*/
322 mt_cirq_unmask_all();
323 for (irq
= 64; irq
< (NR_MT_IRQ_LINE
); irq
+=32)
325 val
= readl(IOMEM(((irq
-64) / 32) * 4 + CIRQ_STA0
));
326 //printk("irq:%d,pending bit:%x\n",irq,val);
328 mt65xx_reg_sync_writel(val
,(GIC_DIST_BASE
+ GIC_DIST_PENDING_SET
+ irq
/ 32 * 4));
330 //printk("irq:%d,pending bit:%x,%x\n",irq,val,readl(GIC_DIST_BASE + GIC_DIST_PENDING_SET + irq / 32 * 4));
335 static void mt_cirq_clone_pol(void)
337 unsigned int irq
,irq_offset
;
338 volatile unsigned int value
;
339 volatile unsigned int value_cirq
;
342 for (irq
= 64; irq
< (NR_MT_IRQ_LINE
); irq
+=32)
344 value
= readl(IOMEM(INT_POL_CTL0
+ ((irq
-GIC_PRIVATE_SIGNALS
) / 32 * 4)));
345 irq_offset
= (irq
-64) / 32;
346 dbgmsg(CIRQ_LOG_LEVEL
"irq:%d,gic_pol_address:0x%8x,gic_pol_value:0x%08x\n",irq
,INT_POL_CTL0
+ ((irq
-GIC_PRIVATE_SIGNALS
) / 32 * 4),value
);
347 for (ix
= 0; ix
< 32; ix
++)
349 if (value
& (0x1)) //high trigger
350 mt_cirq_set_pol(irq
+ix
-64,MT_CIRQ_POL_NEG
);
352 mt_cirq_set_pol(irq
+ix
-64,MT_CIRQ_POL_POS
);
356 value_cirq
= readl(IOMEM(CIRQ_POL0
+ irq_offset
*4));
357 dbgmsg(CIRQ_LOG_LEVEL
"irq:%d,cirq_value:0x%08x\n",irq
,value_cirq
);
361 static void mt_cirq_clone_sens(void)
363 unsigned int irq
,irq_offset
;
364 volatile unsigned int value
;
365 volatile unsigned int value_cirq
;
368 for (irq
= 64; irq
< (NR_MT_IRQ_LINE
); irq
+=16)
370 value
= readl(IOMEM(GIC_DIST_BASE
+ GIC_DIST_CONFIG
+ (irq
/ 16) * 4));
371 dbgmsg(CIRQ_LOG_LEVEL
"irq:%d,sens:%08x,value:0x%08x\n",irq
,GIC_DIST_BASE
+ GIC_DIST_CONFIG
+ (irq
/ 16) * 4,value
);
372 irq_offset
= (irq
-64) / 32;
373 for (ix
= 0; ix
< 16; ix
++)
375 if (value
& (0x2)) //edge trigger
376 mt_cirq_set_sens(irq
-64+ix
,MT_EDGE_SENSITIVE
);
378 mt_cirq_set_sens(irq
-64+ix
,MT_LEVEL_SENSITIVE
);
381 value_cirq
= readl(IOMEM(CIRQ_SENS0
+ irq_offset
*4));
382 dbgmsg(CIRQ_LOG_LEVEL
"irq:%d,cirq_value:0x%08x\n",irq
,value_cirq
);
386 static void mt_cirq_clone_mask(void)
388 unsigned int irq
,irq_offset
;
389 volatile unsigned int value
;
390 volatile unsigned int value_cirq
;
393 for (irq
= 64; irq
< (NR_MT_IRQ_LINE
); irq
+=32)
395 value
= readl(IOMEM(GIC_DIST_BASE
+ GIC_DIST_ENABLE_SET
+ irq
/ 32 * 4));
396 dbgmsg(CIRQ_LOG_LEVEL
"irq:%d,mask:%08x,value:0x%08x\n",irq
,(GIC_DIST_BASE
+ GIC_DIST_ENABLE_SET
+ irq
/ 32 * 4) ,value
);
397 irq_offset
= (irq
-64) / 32;
398 for (ix
= 0; ix
< 32; ix
++)
400 if (value
& (0x1)) //enable
401 mt_cirq_unmask(irq
+ix
-64);
403 mt_cirq_mask(irq
+ix
-64);
407 value_cirq
= readl(IOMEM(CIRQ_MASK0
+ irq_offset
*4));
408 dbgmsg(CIRQ_LOG_LEVEL
"irq:%d,cirq_value:0x%08x\n",irq
,value_cirq
);
411 void mt_cirq_clone_gic(void)
414 mt_cirq_clone_sens();
415 mt_cirq_clone_mask();
421 * cirq_dvt_show: To show usage.
423 static ssize_t
cirq_dvt_show(struct device_driver
*driver
, char *buf
)
425 return snprintf(buf
, PAGE_SIZE
, "CIRQ dvt test\n");
429 * mci_dvt_store: To select mci test case.
431 static ssize_t
cirq_dvt_store(struct device_driver
*driver
, const char *buf
,
434 char *p
= (char *)buf
;
437 num
= simple_strtoul(p
, &p
, 10);
455 DRIVER_ATTR(cirq_dvt
, 0664, cirq_dvt_show
, cirq_dvt_store
);
459 * CIRQ interrupt service routine.
461 static irqreturn_t
cirq_irq_handler(int irq
, void *dev_id
)
463 printk("CIRQ_Handler\n");
471 static int __init
mt_cirq_init(void){
473 printk("CIRQ init...\n");
474 if (request_irq(MT_CIRQ_IRQ_ID
, cirq_irq_handler
, IRQF_TRIGGER_LOW
, "CIRQ", NULL
)) {
475 printk(KERN_ERR
"CIRQ IRQ LINE NOT AVAILABLE!!\n");
478 printk("CIRQ handler init success.");
480 ret
= driver_register(&mt_cirq_drv
.driver
);
482 ret
= driver_create_file(&mt_cirq_drv
.driver
, &driver_attr_cirq_dvt
);
485 printk("CIRQ init done...\n");
491 #define __CHECK_IRQ_TYPE
492 #if defined(__CHECK_IRQ_TYPE)
493 #define X_DEFINE_IRQ(__name, __num, __polarity, __sensitivity) \
494 { .num = __num, .polarity = __polarity, .sensitivity = __sensitivity, },
497 #define EDGE MT_EDGE_SENSITIVE
498 #define LEVEL MT_LEVEL_SENSITIVE
499 struct __check_irq_type
505 struct __check_irq_type __check_irq_type
[] =
507 #include <mach/x_define_irq.h>
517 void mt_cirq_dump_reg(void)
523 printk("IRQ:\tPOL\tSENS\tMASK\n");
524 for (cirq_num
= 0; cirq_num
< MT_NR_CIRQ
; cirq_num
++)
526 pol
= mt_cirq_get_pol(cirq_num
);
527 sens
= mt_cirq_get_sens(cirq_num
);
528 mask
= mt_cirq_get_mask(cirq_num
);
529 #if defined(__CHECK_IRQ_TYPE)
530 //only check unmask irq
533 while (__check_irq_type
[irq_iter
].num
>= 0) {
534 if (__check_irq_type
[irq_iter
].num
== (cirq_num
+64)){
535 if(__check_irq_type
[irq_iter
].sensitivity
!= sens
){
536 printk("[CIRQ] Error sens in irq:%d\n",cirq_num
+64);
538 if(__check_irq_type
[irq_iter
].polarity
!= (pol
)){
539 printk("[CIRQ] Error polarity in irq:%d\n",cirq_num
+64);
547 printk("IRQ:%d\t%d\t%d\t%d\n",cirq_num
+64,pol
,sens
,mask
);
551 int mt_cirq_test(void)
557 mt_cirq_set_pol(cirq_num
,MT_CIRQ_POL_NEG
);
558 if ( MT_CIRQ_POL_NEG
!= mt_cirq_get_pol(cirq_num
))
559 printk("mt_cirq_set_pol test failed!!\n");
560 mt_cirq_set_pol(cirq_num
,MT_CIRQ_POL_POS
);
561 if ( MT_CIRQ_POL_POS
!= mt_cirq_get_pol(cirq_num
))
562 printk("mt_cirq_set_pol test failed!!\n");
565 mt_cirq_set_sens(cirq_num
,MT_EDGE_SENSITIVE
);
566 if ( MT_EDGE_SENSITIVE
!= mt_cirq_get_sens(cirq_num
))
567 printk("mt_cirq_set_sens test failed!!\n");
568 mt_cirq_set_sens(cirq_num
,MT_LEVEL_SENSITIVE
);
569 if ( MT_LEVEL_SENSITIVE
!= mt_cirq_get_sens(cirq_num
))
570 printk("mt_cirq_set_sens test failed!!\n");
573 mt_cirq_mask(cirq_num
);
574 if ( 1 != mt_cirq_get_mask(cirq_num
))
575 printk("mt_cirq_mask test failed!!\n");
576 mt_cirq_unmask(cirq_num
);
577 mt_cirq_set_sens(cirq_num
,MT_LEVEL_SENSITIVE
);
578 if ( 0 != mt_cirq_get_mask(cirq_num
))
579 printk("mt_cirq_unmask test failed!!\n");
588 arch_initcall(mt_cirq_init
);
589 EXPORT_SYMBOL(mt_cirq_enable
);
590 EXPORT_SYMBOL(mt_cirq_disable
);
591 EXPORT_SYMBOL(mt_cirq_clone_gic
);
592 EXPORT_SYMBOL(mt_cirq_flush
);