diff options
| -rw-r--r-- | arch/arm/plat-nomadik/gpio.c | 53 |
1 files changed, 39 insertions, 14 deletions
diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 14466519fcc3..9cb717417ba0 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c | |||
| @@ -301,32 +301,41 @@ static void nmk_gpio_irq_ack(unsigned int irq) | |||
| 301 | writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC); | 301 | writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC); |
| 302 | } | 302 | } |
| 303 | 303 | ||
| 304 | enum nmk_gpio_irq_type { | ||
| 305 | NORMAL, | ||
| 306 | WAKE, | ||
| 307 | }; | ||
| 308 | |||
| 304 | static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip, | 309 | static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip, |
| 305 | int gpio, bool enable) | 310 | int gpio, enum nmk_gpio_irq_type which, |
| 311 | bool enable) | ||
| 306 | { | 312 | { |
| 313 | u32 rimsc = which == WAKE ? NMK_GPIO_RWIMSC : NMK_GPIO_RIMSC; | ||
| 314 | u32 fimsc = which == WAKE ? NMK_GPIO_FWIMSC : NMK_GPIO_FIMSC; | ||
| 307 | u32 bitmask = nmk_gpio_get_bitmask(gpio); | 315 | u32 bitmask = nmk_gpio_get_bitmask(gpio); |
| 308 | u32 reg; | 316 | u32 reg; |
| 309 | 317 | ||
| 310 | /* we must individually set/clear the two edges */ | 318 | /* we must individually set/clear the two edges */ |
| 311 | if (nmk_chip->edge_rising & bitmask) { | 319 | if (nmk_chip->edge_rising & bitmask) { |
| 312 | reg = readl(nmk_chip->addr + NMK_GPIO_RIMSC); | 320 | reg = readl(nmk_chip->addr + rimsc); |
| 313 | if (enable) | 321 | if (enable) |
| 314 | reg |= bitmask; | 322 | reg |= bitmask; |
| 315 | else | 323 | else |
| 316 | reg &= ~bitmask; | 324 | reg &= ~bitmask; |
| 317 | writel(reg, nmk_chip->addr + NMK_GPIO_RIMSC); | 325 | writel(reg, nmk_chip->addr + rimsc); |
| 318 | } | 326 | } |
| 319 | if (nmk_chip->edge_falling & bitmask) { | 327 | if (nmk_chip->edge_falling & bitmask) { |
| 320 | reg = readl(nmk_chip->addr + NMK_GPIO_FIMSC); | 328 | reg = readl(nmk_chip->addr + fimsc); |
| 321 | if (enable) | 329 | if (enable) |
| 322 | reg |= bitmask; | 330 | reg |= bitmask; |
| 323 | else | 331 | else |
| 324 | reg &= ~bitmask; | 332 | reg &= ~bitmask; |
| 325 | writel(reg, nmk_chip->addr + NMK_GPIO_FIMSC); | 333 | writel(reg, nmk_chip->addr + fimsc); |
| 326 | } | 334 | } |
| 327 | } | 335 | } |
| 328 | 336 | ||
| 329 | static void nmk_gpio_irq_modify(unsigned int irq, bool enable) | 337 | static int nmk_gpio_irq_modify(unsigned int irq, enum nmk_gpio_irq_type which, |
| 338 | bool enable) | ||
| 330 | { | 339 | { |
| 331 | int gpio; | 340 | int gpio; |
| 332 | struct nmk_gpio_chip *nmk_chip; | 341 | struct nmk_gpio_chip *nmk_chip; |
| @@ -337,26 +346,35 @@ static void nmk_gpio_irq_modify(unsigned int irq, bool enable) | |||
| 337 | nmk_chip = get_irq_chip_data(irq); | 346 | nmk_chip = get_irq_chip_data(irq); |
| 338 | bitmask = nmk_gpio_get_bitmask(gpio); | 347 | bitmask = nmk_gpio_get_bitmask(gpio); |
| 339 | if (!nmk_chip) | 348 | if (!nmk_chip) |
| 340 | return; | 349 | return -EINVAL; |
| 341 | 350 | ||
| 342 | spin_lock_irqsave(&nmk_chip->lock, flags); | 351 | spin_lock_irqsave(&nmk_chip->lock, flags); |
| 343 | __nmk_gpio_irq_modify(nmk_chip, gpio, enable); | 352 | __nmk_gpio_irq_modify(nmk_chip, gpio, which, enable); |
| 344 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | 353 | spin_unlock_irqrestore(&nmk_chip->lock, flags); |
| 354 | |||
| 355 | return 0; | ||
| 345 | } | 356 | } |
| 346 | 357 | ||
| 347 | static void nmk_gpio_irq_mask(unsigned int irq) | 358 | static void nmk_gpio_irq_mask(unsigned int irq) |
| 348 | { | 359 | { |
| 349 | nmk_gpio_irq_modify(irq, false); | 360 | nmk_gpio_irq_modify(irq, NORMAL, false); |
| 350 | }; | 361 | } |
| 351 | 362 | ||
| 352 | static void nmk_gpio_irq_unmask(unsigned int irq) | 363 | static void nmk_gpio_irq_unmask(unsigned int irq) |
| 353 | { | 364 | { |
| 354 | nmk_gpio_irq_modify(irq, true); | 365 | nmk_gpio_irq_modify(irq, NORMAL, true); |
| 366 | } | ||
| 367 | |||
| 368 | static int nmk_gpio_irq_set_wake(unsigned int irq, unsigned int on) | ||
| 369 | { | ||
| 370 | return nmk_gpio_irq_modify(irq, WAKE, on); | ||
| 355 | } | 371 | } |
| 356 | 372 | ||
| 357 | static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) | 373 | static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) |
| 358 | { | 374 | { |
| 359 | bool enabled = !(irq_to_desc(irq)->status & IRQ_DISABLED); | 375 | struct irq_desc *desc = irq_to_desc(irq); |
| 376 | bool enabled = !(desc->status & IRQ_DISABLED); | ||
| 377 | bool wake = desc->wake_depth; | ||
| 360 | int gpio; | 378 | int gpio; |
| 361 | struct nmk_gpio_chip *nmk_chip; | 379 | struct nmk_gpio_chip *nmk_chip; |
| 362 | unsigned long flags; | 380 | unsigned long flags; |
| @@ -376,7 +394,10 @@ static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) | |||
| 376 | spin_lock_irqsave(&nmk_chip->lock, flags); | 394 | spin_lock_irqsave(&nmk_chip->lock, flags); |
| 377 | 395 | ||
| 378 | if (enabled) | 396 | if (enabled) |
| 379 | __nmk_gpio_irq_modify(nmk_chip, gpio, false); | 397 | __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false); |
| 398 | |||
| 399 | if (wake) | ||
| 400 | __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false); | ||
| 380 | 401 | ||
| 381 | nmk_chip->edge_rising &= ~bitmask; | 402 | nmk_chip->edge_rising &= ~bitmask; |
| 382 | if (type & IRQ_TYPE_EDGE_RISING) | 403 | if (type & IRQ_TYPE_EDGE_RISING) |
| @@ -387,7 +408,10 @@ static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) | |||
| 387 | nmk_chip->edge_falling |= bitmask; | 408 | nmk_chip->edge_falling |= bitmask; |
| 388 | 409 | ||
| 389 | if (enabled) | 410 | if (enabled) |
| 390 | __nmk_gpio_irq_modify(nmk_chip, gpio, true); | 411 | __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true); |
| 412 | |||
| 413 | if (wake) | ||
| 414 | __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true); | ||
| 391 | 415 | ||
| 392 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | 416 | spin_unlock_irqrestore(&nmk_chip->lock, flags); |
| 393 | 417 | ||
| @@ -400,6 +424,7 @@ static struct irq_chip nmk_gpio_irq_chip = { | |||
| 400 | .mask = nmk_gpio_irq_mask, | 424 | .mask = nmk_gpio_irq_mask, |
| 401 | .unmask = nmk_gpio_irq_unmask, | 425 | .unmask = nmk_gpio_irq_unmask, |
| 402 | .set_type = nmk_gpio_irq_set_type, | 426 | .set_type = nmk_gpio_irq_set_type, |
| 427 | .set_wake = nmk_gpio_irq_set_wake, | ||
| 403 | }; | 428 | }; |
| 404 | 429 | ||
| 405 | static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | 430 | static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) |
