aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/wm831x-irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/wm831x-irq.c')
-rw-r--r--drivers/mfd/wm831x-irq.c24
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
512out: 532out:
@@ -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