aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2007-02-04 18:38:48 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2007-02-08 09:48:19 -0500
commit4932e397be71370b95f555f87d3b424d2b5ca57b (patch)
tree29f27c56dfcb45fed7f14efa20bba3b67a692ec4
parentfac105d05e4b410c586de55dfbf34f40a95f6977 (diff)
[ARM] 4122/1: ep93xx: add support for GPIO port F interrupts
Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/mach-ep93xx/core.c90
-rw-r--r--include/asm-arm/arch-ep93xx/ep93xx-regs.h5
-rw-r--r--include/asm-arm/arch-ep93xx/irqs.h8
3 files changed, 73 insertions, 30 deletions
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 5d2739abd960..94bba0b87e36 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -152,22 +152,29 @@ struct sys_timer ep93xx_timer = {
152/************************************************************************* 152/*************************************************************************
153 * GPIO handling for EP93xx 153 * GPIO handling for EP93xx
154 *************************************************************************/ 154 *************************************************************************/
155static unsigned char gpio_int_enable[2]; 155static unsigned char gpio_int_enable[3];
156static unsigned char gpio_int_type1[2]; 156static unsigned char gpio_int_type1[3];
157static unsigned char gpio_int_type2[2]; 157static unsigned char gpio_int_type2[3];
158 158
159static void update_gpio_ab_int_params(int port) 159static void update_gpio_int_params(int abf)
160{ 160{
161 if (port == 0) { 161 if (abf == 0) {
162 __raw_writeb(0, EP93XX_GPIO_A_INT_ENABLE); 162 __raw_writeb(0, EP93XX_GPIO_A_INT_ENABLE);
163 __raw_writeb(gpio_int_type2[0], EP93XX_GPIO_A_INT_TYPE2); 163 __raw_writeb(gpio_int_type2[0], EP93XX_GPIO_A_INT_TYPE2);
164 __raw_writeb(gpio_int_type1[0], EP93XX_GPIO_A_INT_TYPE1); 164 __raw_writeb(gpio_int_type1[0], EP93XX_GPIO_A_INT_TYPE1);
165 __raw_writeb(gpio_int_enable[0], EP93XX_GPIO_A_INT_ENABLE); 165 __raw_writeb(gpio_int_enable[0], EP93XX_GPIO_A_INT_ENABLE);
166 } else if (port == 1) { 166 } else if (abf == 1) {
167 __raw_writeb(0, EP93XX_GPIO_B_INT_ENABLE); 167 __raw_writeb(0, EP93XX_GPIO_B_INT_ENABLE);
168 __raw_writeb(gpio_int_type2[1], EP93XX_GPIO_B_INT_TYPE2); 168 __raw_writeb(gpio_int_type2[1], EP93XX_GPIO_B_INT_TYPE2);
169 __raw_writeb(gpio_int_type1[1], EP93XX_GPIO_B_INT_TYPE1); 169 __raw_writeb(gpio_int_type1[1], EP93XX_GPIO_B_INT_TYPE1);
170 __raw_writeb(gpio_int_enable[1], EP93XX_GPIO_B_INT_ENABLE); 170 __raw_writeb(gpio_int_enable[1], EP93XX_GPIO_B_INT_ENABLE);
171 } else if (abf == 2) {
172 __raw_writeb(0, EP93XX_GPIO_F_INT_ENABLE);
173 __raw_writeb(gpio_int_type2[2], EP93XX_GPIO_F_INT_TYPE2);
174 __raw_writeb(gpio_int_type1[2], EP93XX_GPIO_F_INT_TYPE1);
175 __raw_writeb(gpio_int_enable[2], EP93XX_GPIO_F_INT_ENABLE);
176 } else {
177 BUG();
171 } 178 }
172} 179}
173 180
@@ -192,8 +199,13 @@ void gpio_line_config(int line, int direction)
192 local_irq_save(flags); 199 local_irq_save(flags);
193 if (direction == GPIO_OUT) { 200 if (direction == GPIO_OUT) {
194 if (line >= 0 && line < 16) { 201 if (line >= 0 && line < 16) {
202 /* Port A/B. */
195 gpio_int_enable[line >> 3] &= ~(1 << (line & 7)); 203 gpio_int_enable[line >> 3] &= ~(1 << (line & 7));
196 update_gpio_ab_int_params(line >> 3); 204 update_gpio_int_params(line >> 3);
205 } else if (line >= 40 && line < 48) {
206 /* Port F. */
207 gpio_int_enable[2] &= ~(1 << (line & 7));
208 update_gpio_int_params(2);
197 } 209 }
198 210
199 v = __raw_readb(data_direction_register); 211 v = __raw_readb(data_direction_register);
@@ -244,8 +256,7 @@ EXPORT_SYMBOL(gpio_line_set);
244/************************************************************************* 256/*************************************************************************
245 * EP93xx IRQ handling 257 * EP93xx IRQ handling
246 *************************************************************************/ 258 *************************************************************************/
247static void ep93xx_gpio_ab_irq_handler(unsigned int irq, 259static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
248 struct irq_desc *desc)
249{ 260{
250 unsigned char status; 261 unsigned char status;
251 int i; 262 int i;
@@ -267,37 +278,46 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq,
267 } 278 }
268} 279}
269 280
270static void ep93xx_gpio_ab_irq_mask_ack(unsigned int irq) 281static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
282{
283 int gpio_irq = IRQ_EP93XX_GPIO(16) + (((irq + 1) & 7) ^ 4);
284
285 desc_handle_irq(gpio_irq, irq_desc + gpio_irq);
286}
287
288static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
271{ 289{
272 int line = irq - IRQ_EP93XX_GPIO(0); 290 int line = irq - IRQ_EP93XX_GPIO(0);
273 int port = line >> 3; 291 int port = line >> 3;
274 292
275 gpio_int_enable[port] &= ~(1 << (line & 7)); 293 gpio_int_enable[port] &= ~(1 << (line & 7));
276 update_gpio_ab_int_params(port); 294 update_gpio_int_params(port);
277 295
278 if (line >> 3) { 296 if (port == 0) {
279 __raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK);
280 } else {
281 __raw_writel(1 << (line & 7), EP93XX_GPIO_A_INT_ACK); 297 __raw_writel(1 << (line & 7), EP93XX_GPIO_A_INT_ACK);
298 } else if (port == 1) {
299 __raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK);
300 } else if (port == 2) {
301 __raw_writel(1 << (line & 7), EP93XX_GPIO_F_INT_ACK);
282 } 302 }
283} 303}
284 304
285static void ep93xx_gpio_ab_irq_mask(unsigned int irq) 305static void ep93xx_gpio_irq_mask(unsigned int irq)
286{ 306{
287 int line = irq - IRQ_EP93XX_GPIO(0); 307 int line = irq - IRQ_EP93XX_GPIO(0);
288 int port = line >> 3; 308 int port = line >> 3;
289 309
290 gpio_int_enable[port] &= ~(1 << (line & 7)); 310 gpio_int_enable[port] &= ~(1 << (line & 7));
291 update_gpio_ab_int_params(port); 311 update_gpio_int_params(port);
292} 312}
293 313
294static void ep93xx_gpio_ab_irq_unmask(unsigned int irq) 314static void ep93xx_gpio_irq_unmask(unsigned int irq)
295{ 315{
296 int line = irq - IRQ_EP93XX_GPIO(0); 316 int line = irq - IRQ_EP93XX_GPIO(0);
297 int port = line >> 3; 317 int port = line >> 3;
298 318
299 gpio_int_enable[port] |= 1 << (line & 7); 319 gpio_int_enable[port] |= 1 << (line & 7);
300 update_gpio_ab_int_params(port); 320 update_gpio_int_params(port);
301} 321}
302 322
303 323
@@ -306,13 +326,17 @@ static void ep93xx_gpio_ab_irq_unmask(unsigned int irq)
306 * edge (1) triggered, while gpio_int_type2 controls whether it 326 * edge (1) triggered, while gpio_int_type2 controls whether it
307 * triggers on low/falling (0) or high/rising (1). 327 * triggers on low/falling (0) or high/rising (1).
308 */ 328 */
309static int ep93xx_gpio_ab_irq_type(unsigned int irq, unsigned int type) 329static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
310{ 330{
311 int port; 331 int port;
312 int line; 332 int line;
313 333
314 line = irq - IRQ_EP93XX_GPIO(0); 334 line = irq - IRQ_EP93XX_GPIO(0);
315 gpio_line_config(line, GPIO_IN); 335 if (line >= 0 && line < 16) {
336 gpio_line_config(line, GPIO_IN);
337 } else {
338 gpio_line_config(EP93XX_GPIO_LINE_F(line), GPIO_IN);
339 }
316 340
317 port = line >> 3; 341 port = line >> 3;
318 line &= 7; 342 line &= 7;
@@ -330,16 +354,17 @@ static int ep93xx_gpio_ab_irq_type(unsigned int irq, unsigned int type)
330 gpio_int_type1[port] &= ~(1 << line); 354 gpio_int_type1[port] &= ~(1 << line);
331 gpio_int_type2[port] &= ~(1 << line); 355 gpio_int_type2[port] &= ~(1 << line);
332 } 356 }
333 update_gpio_ab_int_params(port); 357 update_gpio_int_params(port);
334 358
335 return 0; 359 return 0;
336} 360}
337 361
338static struct irq_chip ep93xx_gpio_ab_irq_chip = { 362static struct irq_chip ep93xx_gpio_irq_chip = {
339 .ack = ep93xx_gpio_ab_irq_mask_ack, 363 .name = "GPIO",
340 .mask = ep93xx_gpio_ab_irq_mask, 364 .ack = ep93xx_gpio_irq_mask_ack,
341 .unmask = ep93xx_gpio_ab_irq_unmask, 365 .mask = ep93xx_gpio_irq_mask,
342 .set_type = ep93xx_gpio_ab_irq_type, 366 .unmask = ep93xx_gpio_irq_unmask,
367 .set_type = ep93xx_gpio_irq_type,
343}; 368};
344 369
345 370
@@ -350,12 +375,21 @@ void __init ep93xx_init_irq(void)
350 vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK); 375 vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK);
351 vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK); 376 vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK);
352 377
353 for (irq = IRQ_EP93XX_GPIO(0) ; irq <= IRQ_EP93XX_GPIO(15); irq++) { 378 for (irq = IRQ_EP93XX_GPIO(0); irq <= IRQ_EP93XX_GPIO(23); irq++) {
354 set_irq_chip(irq, &ep93xx_gpio_ab_irq_chip); 379 set_irq_chip(irq, &ep93xx_gpio_irq_chip);
355 set_irq_handler(irq, handle_level_irq); 380 set_irq_handler(irq, handle_level_irq);
356 set_irq_flags(irq, IRQF_VALID); 381 set_irq_flags(irq, IRQF_VALID);
357 } 382 }
383
358 set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler); 384 set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler);
385 set_irq_chained_handler(IRQ_EP93XX_GPIO0MUX, ep93xx_gpio_f_irq_handler);
386 set_irq_chained_handler(IRQ_EP93XX_GPIO1MUX, ep93xx_gpio_f_irq_handler);
387 set_irq_chained_handler(IRQ_EP93XX_GPIO2MUX, ep93xx_gpio_f_irq_handler);
388 set_irq_chained_handler(IRQ_EP93XX_GPIO3MUX, ep93xx_gpio_f_irq_handler);
389 set_irq_chained_handler(IRQ_EP93XX_GPIO4MUX, ep93xx_gpio_f_irq_handler);
390 set_irq_chained_handler(IRQ_EP93XX_GPIO5MUX, ep93xx_gpio_f_irq_handler);
391 set_irq_chained_handler(IRQ_EP93XX_GPIO6MUX, ep93xx_gpio_f_irq_handler);
392 set_irq_chained_handler(IRQ_EP93XX_GPIO7MUX, ep93xx_gpio_f_irq_handler);
359} 393}
360 394
361 395
diff --git a/include/asm-arm/arch-ep93xx/ep93xx-regs.h b/include/asm-arm/arch-ep93xx/ep93xx-regs.h
index 593f562f85c3..625c6f0abc03 100644
--- a/include/asm-arm/arch-ep93xx/ep93xx-regs.h
+++ b/include/asm-arm/arch-ep93xx/ep93xx-regs.h
@@ -73,6 +73,11 @@
73 73
74#define EP93XX_GPIO_BASE (EP93XX_APB_VIRT_BASE + 0x00040000) 74#define EP93XX_GPIO_BASE (EP93XX_APB_VIRT_BASE + 0x00040000)
75#define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x)) 75#define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x))
76#define EP93XX_GPIO_F_INT_TYPE1 EP93XX_GPIO_REG(0x4c)
77#define EP93XX_GPIO_F_INT_TYPE2 EP93XX_GPIO_REG(0x50)
78#define EP93XX_GPIO_F_INT_ACK EP93XX_GPIO_REG(0x54)
79#define EP93XX_GPIO_F_INT_ENABLE EP93XX_GPIO_REG(0x58)
80#define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c)
76#define EP93XX_GPIO_A_INT_TYPE1 EP93XX_GPIO_REG(0x90) 81#define EP93XX_GPIO_A_INT_TYPE1 EP93XX_GPIO_REG(0x90)
77#define EP93XX_GPIO_A_INT_TYPE2 EP93XX_GPIO_REG(0x94) 82#define EP93XX_GPIO_A_INT_TYPE2 EP93XX_GPIO_REG(0x94)
78#define EP93XX_GPIO_A_INT_ACK EP93XX_GPIO_REG(0x98) 83#define EP93XX_GPIO_A_INT_ACK EP93XX_GPIO_REG(0x98)
diff --git a/include/asm-arm/arch-ep93xx/irqs.h b/include/asm-arm/arch-ep93xx/irqs.h
index ae532e304bf1..2a8c63638c5e 100644
--- a/include/asm-arm/arch-ep93xx/irqs.h
+++ b/include/asm-arm/arch-ep93xx/irqs.h
@@ -67,9 +67,13 @@
67#define IRQ_EP93XX_SAI 60 67#define IRQ_EP93XX_SAI 60
68#define EP93XX_VIC2_VALID_IRQ_MASK 0x1fffffff 68#define EP93XX_VIC2_VALID_IRQ_MASK 0x1fffffff
69 69
70#define IRQ_EP93XX_GPIO(x) (64 + (x)) 70/*
71 * Map GPIO A0..A7 to irq 64..71, B0..B7 to 72..79, and
72 * F0..F7 to 80..87.
73 */
74#define IRQ_EP93XX_GPIO(x) (64 + (((x) + (((x) >> 2) & 8)) & 0x1f))
71 75
72#define NR_EP93XX_IRQS IRQ_EP93XX_GPIO(16) 76#define NR_EP93XX_IRQS (64 + 24)
73 77
74#define EP93XX_BOARD_IRQ(x) (NR_EP93XX_IRQS + (x)) 78#define EP93XX_BOARD_IRQ(x) (NR_EP93XX_IRQS + (x))
75#define EP93XX_BOARD_IRQS 32 79#define EP93XX_BOARD_IRQS 32