Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Mark Brown and committed by
Samuel Ortiz
1fe17a24 c48bf153

+21 -6
+19 -5
drivers/mfd/wm831x-irq.c
··· 413 413 * do the update here as we can be called with the bus lock 414 414 * held. 415 415 */ 416 + wm831x->gpio_level_low[irq] = false; 417 + wm831x->gpio_level_high[irq] = false; 416 418 switch (type) { 417 419 case IRQ_TYPE_EDGE_BOTH: 418 420 wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_INT_MODE; 419 - wm831x->gpio_level[irq] = false; 420 421 break; 421 422 case IRQ_TYPE_EDGE_RISING: 422 423 wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL; 423 - wm831x->gpio_level[irq] = false; 424 424 break; 425 425 case IRQ_TYPE_EDGE_FALLING: 426 426 wm831x->gpio_update[irq] = 0x10000; 427 - wm831x->gpio_level[irq] = false; 428 427 break; 429 428 case IRQ_TYPE_LEVEL_HIGH: 430 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 435 break; 433 436 default: 434 437 return -EINVAL; ··· 520 517 * status. This is sucky but improves interoperability. 521 518 */ 522 519 if (primary == WM831X_GP_INT && 523 - wm831x->gpio_level[i - WM831X_IRQ_GPIO_1]) { 520 + wm831x->gpio_level_high[i - WM831X_IRQ_GPIO_1]) { 524 521 ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL); 525 522 while (ret & 1 << (i - WM831X_IRQ_GPIO_1)) { 523 + handle_nested_irq(irq_find_mapping(wm831x->irq_domain, 524 + i)); 525 + ret = wm831x_reg_read(wm831x, 526 + WM831X_GPIO_LEVEL); 527 + } 528 + } 529 + 530 + if (primary == WM831X_GP_INT && 531 + wm831x->gpio_level_low[i - WM831X_IRQ_GPIO_1]) { 532 + ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL); 533 + while (!(ret & 1 << (i - WM831X_IRQ_GPIO_1))) { 526 534 handle_nested_irq(irq_find_mapping(wm831x->irq_domain, 527 535 i)); 528 536 ret = wm831x_reg_read(wm831x,
+2 -1
include/linux/mfd/wm831x/core.h
··· 384 384 385 385 /* Used by the interrupt controller code to post writes */ 386 386 int gpio_update[WM831X_NUM_GPIO_REGS]; 387 - bool gpio_level[WM831X_NUM_GPIO_REGS]; 387 + bool gpio_level_high[WM831X_NUM_GPIO_REGS]; 388 + bool gpio_level_low[WM831X_NUM_GPIO_REGS]; 388 389 389 390 struct mutex auxadc_lock; 390 391 struct list_head auxadc_pending;