diff options
| -rw-r--r-- | arch/arm/mach-ep93xx/core.c | 64 |
1 files changed, 53 insertions, 11 deletions
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 58957d7a5763..2788da06417c 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | * Core routines for Cirrus EP93xx chips. | 3 | * Core routines for Cirrus EP93xx chips. |
| 4 | * | 4 | * |
| 5 | * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> | 5 | * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> |
| 6 | * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org> | ||
| 6 | * | 7 | * |
| 7 | * Thanks go to Michael Burian and Ray Lehtiniemi for their key | 8 | * Thanks go to Michael Burian and Ray Lehtiniemi for their key |
| 8 | * role in the ep93xx linux community. | 9 | * role in the ep93xx linux community. |
| @@ -315,12 +316,29 @@ static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
| 315 | desc_handle_irq(gpio_irq, irq_desc + gpio_irq); | 316 | desc_handle_irq(gpio_irq, irq_desc + gpio_irq); |
| 316 | } | 317 | } |
| 317 | 318 | ||
| 319 | static void ep93xx_gpio_irq_ack(unsigned int irq) | ||
| 320 | { | ||
| 321 | int line = irq_to_gpio(irq); | ||
| 322 | int port = line >> 3; | ||
| 323 | int port_mask = 1 << (line & 7); | ||
| 324 | |||
| 325 | if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) { | ||
| 326 | gpio_int_type2[port] ^= port_mask; /* switch edge direction */ | ||
| 327 | update_gpio_int_params(port); | ||
| 328 | } | ||
| 329 | |||
| 330 | __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port])); | ||
| 331 | } | ||
| 332 | |||
| 318 | static void ep93xx_gpio_irq_mask_ack(unsigned int irq) | 333 | static void ep93xx_gpio_irq_mask_ack(unsigned int irq) |
| 319 | { | 334 | { |
| 320 | int line = irq_to_gpio(irq); | 335 | int line = irq_to_gpio(irq); |
| 321 | int port = line >> 3; | 336 | int port = line >> 3; |
| 322 | int port_mask = 1 << (line & 7); | 337 | int port_mask = 1 << (line & 7); |
| 323 | 338 | ||
| 339 | if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) | ||
| 340 | gpio_int_type2[port] ^= port_mask; /* switch edge direction */ | ||
| 341 | |||
| 324 | gpio_int_unmasked[port] &= ~port_mask; | 342 | gpio_int_unmasked[port] &= ~port_mask; |
| 325 | update_gpio_int_params(port); | 343 | update_gpio_int_params(port); |
| 326 | 344 | ||
| @@ -353,31 +371,54 @@ static void ep93xx_gpio_irq_unmask(unsigned int irq) | |||
| 353 | */ | 371 | */ |
| 354 | static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) | 372 | static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) |
| 355 | { | 373 | { |
| 374 | struct irq_desc *desc = irq_desc + irq; | ||
| 356 | const int gpio = irq_to_gpio(irq); | 375 | const int gpio = irq_to_gpio(irq); |
| 357 | const int port = gpio >> 3; | 376 | const int port = gpio >> 3; |
| 358 | const int port_mask = 1 << (gpio & 7); | 377 | const int port_mask = 1 << (gpio & 7); |
| 359 | 378 | ||
| 360 | ep93xx_gpio_set_direction(gpio, GPIO_IN); | 379 | ep93xx_gpio_set_direction(gpio, GPIO_IN); |
| 361 | 380 | ||
| 362 | if (type & IRQT_RISING) { | 381 | switch (type) { |
| 363 | gpio_int_enabled[port] |= port_mask; | 382 | case IRQT_RISING: |
| 364 | gpio_int_type1[port] |= port_mask; | 383 | gpio_int_type1[port] |= port_mask; |
| 365 | gpio_int_type2[port] |= port_mask; | 384 | gpio_int_type2[port] |= port_mask; |
| 366 | } else if (type & IRQT_FALLING) { | 385 | desc->handle_irq = handle_edge_irq; |
| 367 | gpio_int_enabled[port] |= port_mask; | 386 | break; |
| 387 | case IRQT_FALLING: | ||
| 368 | gpio_int_type1[port] |= port_mask; | 388 | gpio_int_type1[port] |= port_mask; |
| 369 | gpio_int_type2[port] &= ~port_mask; | 389 | gpio_int_type2[port] &= ~port_mask; |
| 370 | } else if (type & IRQT_HIGH) { | 390 | desc->handle_irq = handle_edge_irq; |
| 371 | gpio_int_enabled[port] |= port_mask; | 391 | break; |
| 392 | case IRQT_HIGH: | ||
| 372 | gpio_int_type1[port] &= ~port_mask; | 393 | gpio_int_type1[port] &= ~port_mask; |
| 373 | gpio_int_type2[port] |= port_mask; | 394 | gpio_int_type2[port] |= port_mask; |
| 374 | } else if (type & IRQT_LOW) { | 395 | desc->handle_irq = handle_level_irq; |
| 375 | gpio_int_enabled[port] |= port_mask; | 396 | break; |
| 397 | case IRQT_LOW: | ||
| 376 | gpio_int_type1[port] &= ~port_mask; | 398 | gpio_int_type1[port] &= ~port_mask; |
| 377 | gpio_int_type2[port] &= ~port_mask; | 399 | gpio_int_type2[port] &= ~port_mask; |
| 378 | } else { | 400 | desc->handle_irq = handle_level_irq; |
| 379 | gpio_int_enabled[port] &= ~port_mask; | 401 | break; |
| 402 | case IRQT_BOTHEDGE: | ||
| 403 | gpio_int_type1[port] |= port_mask; | ||
| 404 | /* set initial polarity based on current input level */ | ||
| 405 | if (gpio_get_value(gpio)) | ||
| 406 | gpio_int_type2[port] &= ~port_mask; /* falling */ | ||
| 407 | else | ||
| 408 | gpio_int_type2[port] |= port_mask; /* rising */ | ||
| 409 | desc->handle_irq = handle_edge_irq; | ||
| 410 | break; | ||
| 411 | default: | ||
| 412 | pr_err("ep93xx: failed to set irq type %d for gpio %d\n", | ||
| 413 | type, gpio); | ||
| 414 | return -EINVAL; | ||
| 380 | } | 415 | } |
| 416 | |||
| 417 | gpio_int_enabled[port] |= port_mask; | ||
| 418 | |||
| 419 | desc->status &= ~IRQ_TYPE_SENSE_MASK; | ||
| 420 | desc->status |= type & IRQ_TYPE_SENSE_MASK; | ||
| 421 | |||
| 381 | update_gpio_int_params(port); | 422 | update_gpio_int_params(port); |
| 382 | 423 | ||
| 383 | return 0; | 424 | return 0; |
| @@ -385,7 +426,8 @@ static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) | |||
| 385 | 426 | ||
| 386 | static struct irq_chip ep93xx_gpio_irq_chip = { | 427 | static struct irq_chip ep93xx_gpio_irq_chip = { |
| 387 | .name = "GPIO", | 428 | .name = "GPIO", |
| 388 | .ack = ep93xx_gpio_irq_mask_ack, | 429 | .ack = ep93xx_gpio_irq_ack, |
| 430 | .mask_ack = ep93xx_gpio_irq_mask_ack, | ||
| 389 | .mask = ep93xx_gpio_irq_mask, | 431 | .mask = ep93xx_gpio_irq_mask, |
| 390 | .unmask = ep93xx_gpio_irq_unmask, | 432 | .unmask = ep93xx_gpio_irq_unmask, |
| 391 | .set_type = ep93xx_gpio_irq_type, | 433 | .set_type = ep93xx_gpio_irq_type, |
