Skip to content

Commit

Permalink
mfd: Simulate active high IRQs with wm831x
Browse files Browse the repository at this point in the history
In order to ease system integration provide a simulation of active high
IRQs on the GPIOs by polling the GPIO status when an IRQ is generated.

This isn't ideal on several fronts and will miss initially active IRQs in
the current implementation but it should work well for most cases.

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 Oct 24, 2011
1 parent 1f08c11 commit 7583a21
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 1 deletion.
22 changes: 21 additions & 1 deletion drivers/mfd/wm831x-irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,12 +420,19 @@ static int wm831x_irq_set_type(struct irq_data *data, unsigned int type)
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;
break;
default:
return -EINVAL;
Expand All @@ -449,7 +456,7 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
{
struct wm831x *wm831x = data;
unsigned int i;
int primary, status_addr;
int primary, status_addr, ret;
int status_regs[WM831X_NUM_IRQ_REGS] = { 0 };
int read[WM831X_NUM_IRQ_REGS] = { 0 };
int *status;
Expand Down Expand Up @@ -507,6 +514,19 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)

if (*status & wm831x_irqs[i].mask)
handle_nested_irq(wm831x->irq_base + i);

/* Simulate an edge triggered IRQ by polling the input
* status. This is sucky but improves interoperability.
*/
if (primary == WM831X_GP_INT &&
wm831x->gpio_level[i - WM831X_IRQ_GPIO_1]) {
ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL);
while (ret & 1 << (i - WM831X_IRQ_GPIO_1)) {
handle_nested_irq(wm831x->irq_base + i);
ret = wm831x_reg_read(wm831x,
WM831X_GPIO_LEVEL);
}
}
}

out:
Expand Down
1 change: 1 addition & 0 deletions include/linux/mfd/wm831x/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ 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];

struct mutex auxadc_lock;
struct list_head auxadc_pending;
Expand Down

0 comments on commit 7583a21

Please sign in to comment.