diff options
Diffstat (limited to 'drivers/mfd/wm831x-irq.c')
-rw-r--r-- | drivers/mfd/wm831x-irq.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c index ada1835a5455..f4747a4a9a93 100644 --- a/drivers/mfd/wm831x-irq.c +++ b/drivers/mfd/wm831x-irq.c | |||
@@ -420,12 +420,19 @@ static int wm831x_irq_set_type(struct irq_data *data, unsigned int type) | |||
420 | switch (type) { | 420 | switch (type) { |
421 | case IRQ_TYPE_EDGE_BOTH: | 421 | case IRQ_TYPE_EDGE_BOTH: |
422 | wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_INT_MODE; | 422 | wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_INT_MODE; |
423 | wm831x->gpio_level[irq] = false; | ||
423 | break; | 424 | break; |
424 | case IRQ_TYPE_EDGE_RISING: | 425 | case IRQ_TYPE_EDGE_RISING: |
425 | wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL; | 426 | wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL; |
427 | wm831x->gpio_level[irq] = false; | ||
426 | break; | 428 | break; |
427 | case IRQ_TYPE_EDGE_FALLING: | 429 | case IRQ_TYPE_EDGE_FALLING: |
428 | wm831x->gpio_update[irq] = 0x10000; | 430 | wm831x->gpio_update[irq] = 0x10000; |
431 | wm831x->gpio_level[irq] = false; | ||
432 | break; | ||
433 | case IRQ_TYPE_LEVEL_HIGH: | ||
434 | wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL; | ||
435 | wm831x->gpio_level[irq] = true; | ||
429 | break; | 436 | break; |
430 | default: | 437 | default: |
431 | return -EINVAL; | 438 | return -EINVAL; |
@@ -449,7 +456,7 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data) | |||
449 | { | 456 | { |
450 | struct wm831x *wm831x = data; | 457 | struct wm831x *wm831x = data; |
451 | unsigned int i; | 458 | unsigned int i; |
452 | int primary, status_addr; | 459 | int primary, status_addr, ret; |
453 | int status_regs[WM831X_NUM_IRQ_REGS] = { 0 }; | 460 | int status_regs[WM831X_NUM_IRQ_REGS] = { 0 }; |
454 | int read[WM831X_NUM_IRQ_REGS] = { 0 }; | 461 | int read[WM831X_NUM_IRQ_REGS] = { 0 }; |
455 | int *status; | 462 | int *status; |
@@ -507,6 +514,19 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data) | |||
507 | 514 | ||
508 | if (*status & wm831x_irqs[i].mask) | 515 | if (*status & wm831x_irqs[i].mask) |
509 | handle_nested_irq(wm831x->irq_base + i); | 516 | handle_nested_irq(wm831x->irq_base + i); |
517 | |||
518 | /* Simulate an edge triggered IRQ by polling the input | ||
519 | * status. This is sucky but improves interoperability. | ||
520 | */ | ||
521 | if (primary == WM831X_GP_INT && | ||
522 | wm831x->gpio_level[i - WM831X_IRQ_GPIO_1]) { | ||
523 | ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL); | ||
524 | while (ret & 1 << (i - WM831X_IRQ_GPIO_1)) { | ||
525 | handle_nested_irq(wm831x->irq_base + i); | ||
526 | ret = wm831x_reg_read(wm831x, | ||
527 | WM831X_GPIO_LEVEL); | ||
528 | } | ||
529 | } | ||
510 | } | 530 | } |
511 | 531 | ||
512 | out: | 532 | out: |
@@ -596,8 +616,6 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) | |||
596 | "No interrupt specified - functionality limited\n"); | 616 | "No interrupt specified - functionality limited\n"); |
597 | } | 617 | } |
598 | 618 | ||
599 | |||
600 | |||
601 | /* Enable top level interrupts, we mask at secondary level */ | 619 | /* Enable top level interrupts, we mask at secondary level */ |
602 | wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0); | 620 | wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0); |
603 | 621 | ||