summaryrefslogtreecommitdiff
path: root/drivers/mfd
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-05-18 16:02:02 (GMT)
committerSamuel Ortiz <sameo@linux.intel.com>2012-05-20 15:27:14 (GMT)
commit1fe17a24e2fe0a9554d19a4249eb2d80050ecb8c (patch)
tree9368a59bbdf4a0ba33a8bed514076acd2c31ec86 /drivers/mfd
parentc48bf153f293894d232ee44f5bff99c523a06585 (diff)
downloadlinux-fsl-qoriq-1fe17a24e2fe0a9554d19a4249eb2d80050ecb8c.tar.xz
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/mfd')
-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 ecc9d6d..804e56e 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)
* do the update here as we can be called with the bus lock
* held.
*/
+ wm831x->gpio_level_low[irq] = false;
+ wm831x->gpio_level_high[irq] = false;
switch (type) {
case IRQ_TYPE_EDGE_BOTH:
wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_INT_MODE;
- wm831x->gpio_level[irq] = false;
break;
case IRQ_TYPE_EDGE_RISING:
wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL;
- wm831x->gpio_level[irq] = false;
break;
case IRQ_TYPE_EDGE_FALLING:
wm831x->gpio_update[irq] = 0x10000;
- wm831x->gpio_level[irq] = false;
break;
case IRQ_TYPE_LEVEL_HIGH:
wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL;
- wm831x->gpio_level[irq] = true;
+ wm831x->gpio_level_high[irq] = true;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ wm831x->gpio_update[irq] = 0x10000;
+ wm831x->gpio_level_low[irq] = true;
break;
default:
return -EINVAL;
@@ -517,7 +520,7 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
* status. This is sucky but improves interoperability.
*/
if (primary == WM831X_GP_INT &&
- wm831x->gpio_level[i - WM831X_IRQ_GPIO_1]) {
+ wm831x->gpio_level_high[i - WM831X_IRQ_GPIO_1]) {
ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL);
while (ret & 1 << (i - WM831X_IRQ_GPIO_1)) {
handle_nested_irq(irq_find_mapping(wm831x->irq_domain,
@@ -526,6 +529,17 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
WM831X_GPIO_LEVEL);
}
}
+
+ if (primary == WM831X_GP_INT &&
+ wm831x->gpio_level_low[i - WM831X_IRQ_GPIO_1]) {
+ ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL);
+ while (!(ret & 1 << (i - WM831X_IRQ_GPIO_1))) {
+ handle_nested_irq(irq_find_mapping(wm831x->irq_domain,
+ i));
+ ret = wm831x_reg_read(wm831x,
+ WM831X_GPIO_LEVEL);
+ }
+ }
}
out: