aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-05-18 12:02:02 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-05-20 11:27:14 -0400
commit1fe17a24e2fe0a9554d19a4249eb2d80050ecb8c (patch)
tree9368a59bbdf4a0ba33a8bed514076acd2c31ec86 /drivers
parentc48bf153f293894d232ee44f5bff99c523a06585 (diff)
mfd: Emulate active low IRQs as well as active high IRQs for wm831x
As with the existing emulation this should not be used in production systems but is useful for test purposes. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mfd/wm831x-irq.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c
index ecc9d6d62fa..804e56ec99e 100644
--- a/drivers/mfd/wm831x-irq.c
+++ b/drivers/mfd/wm831x-irq.c
@@ -413,22 +413,25 @@ static int wm831x_irq_set_type(struct irq_data *data, unsigned int type)
413 * do the update here as we can be called with the bus lock 413 * do the update here as we can be called with the bus lock
414 * held. 414 * held.
415 */ 415 */
416 wm831x->gpio_level_low[irq] = false;
417 wm831x->gpio_level_high[irq] = false;
416 switch (type) { 418 switch (type) {
417 case IRQ_TYPE_EDGE_BOTH: 419 case IRQ_TYPE_EDGE_BOTH:
418 wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_INT_MODE; 420 wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_INT_MODE;
419 wm831x->gpio_level[irq] = false;
420 break; 421 break;
421 case IRQ_TYPE_EDGE_RISING: 422 case IRQ_TYPE_EDGE_RISING:
422 wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL; 423 wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL;
423 wm831x->gpio_level[irq] = false;
424 break; 424 break;
425 case IRQ_TYPE_EDGE_FALLING: 425 case IRQ_TYPE_EDGE_FALLING:
426 wm831x->gpio_update[irq] = 0x10000; 426 wm831x->gpio_update[irq] = 0x10000;
427 wm831x->gpio_level[irq] = false;
428 break; 427 break;
429 case IRQ_TYPE_LEVEL_HIGH: 428 case IRQ_TYPE_LEVEL_HIGH:
430 wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL; 429 wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL;
431 wm831x->gpio_level[irq] = true; 430 wm831x->gpio_level_high[irq] = true;
431 break;
432 case IRQ_TYPE_LEVEL_LOW:
433 wm831x->gpio_update[irq] = 0x10000;
434 wm831x->gpio_level_low[irq] = true;
432 break; 435 break;
433 default: 436 default:
434 return -EINVAL; 437 return -EINVAL;
@@ -517,7 +520,7 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
517 * status. This is sucky but improves interoperability. 520 * status. This is sucky but improves interoperability.
518 */ 521 */
519 if (primary == WM831X_GP_INT && 522 if (primary == WM831X_GP_INT &&
520 wm831x->gpio_level[i - WM831X_IRQ_GPIO_1]) { 523 wm831x->gpio_level_high[i - WM831X_IRQ_GPIO_1]) {
521 ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL); 524 ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL);
522 while (ret & 1 << (i - WM831X_IRQ_GPIO_1)) { 525 while (ret & 1 << (i - WM831X_IRQ_GPIO_1)) {
523 handle_nested_irq(irq_find_mapping(wm831x->irq_domain, 526 handle_nested_irq(irq_find_mapping(wm831x->irq_domain,
@@ -526,6 +529,17 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
526 WM831X_GPIO_LEVEL); 529 WM831X_GPIO_LEVEL);
527 } 530 }
528 } 531 }
532
533 if (primary == WM831X_GP_INT &&
534 wm831x->gpio_level_low[i - WM831X_IRQ_GPIO_1]) {
535 ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL);
536 while (!(ret & 1 << (i - WM831X_IRQ_GPIO_1))) {
537 handle_nested_irq(irq_find_mapping(wm831x->irq_domain,
538 i));
539 ret = wm831x_reg_read(wm831x,
540 WM831X_GPIO_LEVEL);
541 }
542 }
529 } 543 }
530 544
531out: 545out: