Skip to content

Commit

Permalink
mfd: Emulate active low IRQs as well as active high IRQs for wm831x
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Mark Brown authored and Samuel Ortiz committed May 20, 2012
1 parent c48bf15 commit 1fe17a2
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
24 changes: 19 additions & 5 deletions drivers/mfd/wm831x-irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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:
Expand Down
3 changes: 2 additions & 1 deletion include/linux/mfd/wm831x/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,8 @@ struct wm831x {

/* Used by the interrupt controller code to post writes */
int gpio_update[WM831X_NUM_GPIO_REGS];
bool gpio_level[WM831X_NUM_GPIO_REGS];
bool gpio_level_high[WM831X_NUM_GPIO_REGS];
bool gpio_level_low[WM831X_NUM_GPIO_REGS];

struct mutex auxadc_lock;
struct list_head auxadc_pending;
Expand Down

0 comments on commit 1fe17a2

Please sign in to comment.