diff options
| author | Lennert Buytenhek <buytenh@wantstofly.org> | 2007-02-04 18:38:48 -0500 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2007-02-08 09:48:19 -0500 |
| commit | 4932e397be71370b95f555f87d3b424d2b5ca57b (patch) | |
| tree | 29f27c56dfcb45fed7f14efa20bba3b67a692ec4 | |
| parent | fac105d05e4b410c586de55dfbf34f40a95f6977 (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.c | 90 | ||||
| -rw-r--r-- | include/asm-arm/arch-ep93xx/ep93xx-regs.h | 5 | ||||
| -rw-r--r-- | include/asm-arm/arch-ep93xx/irqs.h | 8 |
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 | *************************************************************************/ |
| 155 | static unsigned char gpio_int_enable[2]; | 155 | static unsigned char gpio_int_enable[3]; |
| 156 | static unsigned char gpio_int_type1[2]; | 156 | static unsigned char gpio_int_type1[3]; |
| 157 | static unsigned char gpio_int_type2[2]; | 157 | static unsigned char gpio_int_type2[3]; |
| 158 | 158 | ||
| 159 | static void update_gpio_ab_int_params(int port) | 159 | static 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 | *************************************************************************/ |
| 247 | static void ep93xx_gpio_ab_irq_handler(unsigned int irq, | 259 | static 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 | ||
| 270 | static void ep93xx_gpio_ab_irq_mask_ack(unsigned int irq) | 281 | static 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 | |||
| 288 | static 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 | ||
| 285 | static void ep93xx_gpio_ab_irq_mask(unsigned int irq) | 305 | static 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 | ||
| 294 | static void ep93xx_gpio_ab_irq_unmask(unsigned int irq) | 314 | static 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 | */ |
| 309 | static int ep93xx_gpio_ab_irq_type(unsigned int irq, unsigned int type) | 329 | static 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 | ||
| 338 | static struct irq_chip ep93xx_gpio_ab_irq_chip = { | 362 | static 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 |
