aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManuel Lauss <mano@roarinelk.homelinux.net>2008-12-21 03:26:18 -0500
committerRalf Baechle <ralf@linux-mips.org>2009-01-11 04:57:26 -0500
commit197b0d31eb3e82f598bf13da6ee777d906c611f3 (patch)
tree663ecf85c0096a695f425bb602012ea7ca9e57de
parent785e3268e2951d4c0c21417c8e5d8004b2ab2480 (diff)
MIPS: Alchemy: pb1200: update CPLD cascade irq handler.
Tested on Db1200. Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/alchemy/devboards/pb1200/irqmap.c87
1 files changed, 30 insertions, 57 deletions
diff --git a/arch/mips/alchemy/devboards/pb1200/irqmap.c b/arch/mips/alchemy/devboards/pb1200/irqmap.c
index 1f92fec24a33..fe47498da280 100644
--- a/arch/mips/alchemy/devboards/pb1200/irqmap.c
+++ b/arch/mips/alchemy/devboards/pb1200/irqmap.c
@@ -47,77 +47,50 @@ struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
47/* 47/*
48 * Support for External interrupts on the Pb1200 Development platform. 48 * Support for External interrupts on the Pb1200 Development platform.
49 */ 49 */
50static volatile int pb1200_cascade_en;
51 50
52irqreturn_t pb1200_cascade_handler(int irq, void *dev_id) 51static void pb1200_cascade_handler(unsigned int irq, struct irq_desc *d)
53{ 52{
54 unsigned short bisr = bcsr->int_status; 53 unsigned short bisr = bcsr->int_status;
55 int extirq_nr = 0;
56
57 /* Clear all the edge interrupts. This has no effect on level. */
58 bcsr->int_status = bisr;
59 for ( ; bisr; bisr &= bisr - 1) {
60 extirq_nr = PB1200_INT_BEGIN + __ffs(bisr);
61 /* Ack and dispatch IRQ */
62 do_IRQ(extirq_nr);
63 }
64
65 return IRQ_RETVAL(1);
66}
67 54
68inline void pb1200_enable_irq(unsigned int irq_nr) 55 for ( ; bisr; bisr &= bisr - 1)
69{ 56 generic_handle_irq(PB1200_INT_BEGIN + __ffs(bisr));
70 bcsr->intset_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
71 bcsr->intset = 1 << (irq_nr - PB1200_INT_BEGIN);
72} 57}
73 58
74inline void pb1200_disable_irq(unsigned int irq_nr) 59/* NOTE: both the enable and mask bits must be cleared, otherwise the
60 * CPLD generates tons of spurious interrupts (at least on the DB1200).
61 */
62static void pb1200_mask_irq(unsigned int irq_nr)
75{ 63{
76 bcsr->intclr_mask = 1 << (irq_nr - PB1200_INT_BEGIN); 64 bcsr->intclr_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
77 bcsr->intclr = 1 << (irq_nr - PB1200_INT_BEGIN); 65 bcsr->intclr = 1 << (irq_nr - PB1200_INT_BEGIN);
66 au_sync();
78} 67}
79 68
80static unsigned int pb1200_setup_cascade(void) 69static void pb1200_maskack_irq(unsigned int irq_nr)
81{
82 return request_irq(AU1000_GPIO_7, &pb1200_cascade_handler,
83 0, "Pb1200 Cascade", &pb1200_cascade_handler);
84}
85
86static unsigned int pb1200_startup_irq(unsigned int irq)
87{ 70{
88 if (++pb1200_cascade_en == 1) { 71 bcsr->intclr_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
89 int res; 72 bcsr->intclr = 1 << (irq_nr - PB1200_INT_BEGIN);
90 73 bcsr->int_status = 1 << (irq_nr - PB1200_INT_BEGIN); /* ack */
91 res = pb1200_setup_cascade(); 74 au_sync();
92 if (res)
93 return res;
94 }
95
96 pb1200_enable_irq(irq);
97
98 return 0;
99} 75}
100 76
101static void pb1200_shutdown_irq(unsigned int irq) 77static void pb1200_unmask_irq(unsigned int irq_nr)
102{ 78{
103 pb1200_disable_irq(irq); 79 bcsr->intset = 1 << (irq_nr - PB1200_INT_BEGIN);
104 if (--pb1200_cascade_en == 0) 80 bcsr->intset_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
105 free_irq(AU1000_GPIO_7, &pb1200_cascade_handler); 81 au_sync();
106} 82}
107 83
108static struct irq_chip external_irq_type = { 84static struct irq_chip pb1200_cpld_irq_type = {
109#ifdef CONFIG_MIPS_PB1200 85#ifdef CONFIG_MIPS_PB1200
110 .name = "Pb1200 Ext", 86 .name = "Pb1200 Ext",
111#endif 87#endif
112#ifdef CONFIG_MIPS_DB1200 88#ifdef CONFIG_MIPS_DB1200
113 .name = "Db1200 Ext", 89 .name = "Db1200 Ext",
114#endif 90#endif
115 .startup = pb1200_startup_irq, 91 .mask = pb1200_mask_irq,
116 .shutdown = pb1200_shutdown_irq, 92 .mask_ack = pb1200_maskack_irq,
117 .ack = pb1200_disable_irq, 93 .unmask = pb1200_unmask_irq,
118 .mask = pb1200_disable_irq,
119 .mask_ack = pb1200_disable_irq,
120 .unmask = pb1200_enable_irq,
121}; 94};
122 95
123void __init board_init_irq(void) 96void __init board_init_irq(void)
@@ -147,15 +120,15 @@ void __init board_init_irq(void)
147 panic("Game over. Your score is 0."); 120 panic("Game over. Your score is 0.");
148 } 121 }
149#endif 122#endif
123 /* mask & disable & ack all */
124 bcsr->intclr_mask = 0xffff;
125 bcsr->intclr = 0xffff;
126 bcsr->int_status = 0xffff;
127 au_sync();
150 128
151 for (irq = PB1200_INT_BEGIN; irq <= PB1200_INT_END; irq++) { 129 for (irq = PB1200_INT_BEGIN; irq <= PB1200_INT_END; irq++)
152 set_irq_chip_and_handler(irq, &external_irq_type, 130 set_irq_chip_and_handler_name(irq, &pb1200_cpld_irq_type,
153 handle_level_irq); 131 handle_level_irq, "level");
154 pb1200_disable_irq(irq);
155 }
156 132
157 /* 133 set_irq_chained_handler(AU1000_GPIO_7, pb1200_cascade_handler);
158 * GPIO_7 can not be hooked here, so it is hooked upon first
159 * request of any source attached to the cascade.
160 */
161} 134}