Commit 7d4d0a3e authored by Mark Brown's avatar Mark Brown Committed by Samuel Ortiz

mfd: Add WM831x interrupt support

The WM831x includes an interrupt controller managing interrupts for
the various functions on the chip. This patch adds support for the
core interrupt block on the device.

Ideally this would be supported by genirq, particularly for the
GPIOs, but currently genirq is unable to cope with controllers on
interrupt driven buses so we cut'n'paste the generic interface.
Once genirq is able to cope chips like this it should be a case
of filing the prefixes off the code and redoing wm831x-irq.c to
move over.
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent d2bedfe7
......@@ -19,6 +19,7 @@
#include <linux/mfd/wm831x/core.h>
#include <linux/mfd/wm831x/pdata.h>
#include <linux/mfd/wm831x/irq.h>
enum wm831x_parent {
WM8310 = 0,
......@@ -1189,6 +1190,10 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
}
}
ret = wm831x_irq_init(wm831x, irq);
if (ret != 0)
goto err;
/* The core device is up, instantiate the subdevices. */
switch (parent) {
case WM8310:
......@@ -1216,19 +1221,21 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
if (ret != 0) {
dev_err(wm831x->dev, "Failed to add children\n");
goto err;
goto err_irq;
}
if (pdata && pdata->post_init) {
ret = pdata->post_init(wm831x);
if (ret != 0) {
dev_err(wm831x->dev, "post_init() failed: %d\n", ret);
goto err;
goto err_irq;
}
}
return 0;
err_irq:
wm831x_irq_exit(wm831x);
err:
mfd_remove_devices(wm831x->dev);
kfree(wm831x);
......@@ -1238,6 +1245,7 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
static void wm831x_device_exit(struct wm831x *wm831x)
{
mfd_remove_devices(wm831x->dev);
wm831x_irq_exit(wm831x);
kfree(wm831x);
}
......
This diff is collapsed.
......@@ -15,6 +15,9 @@
#ifndef __MFD_WM831X_CORE_H__
#define __MFD_WM831X_CORE_H__
#include <linux/interrupt.h>
#include <linux/workqueue.h>
/*
* Register values.
*/
......@@ -224,6 +227,13 @@ struct wm831x {
void *control_data;
int irq; /* Our chip IRQ */
struct mutex irq_lock;
struct workqueue_struct *irq_wq;
struct work_struct irq_work;
unsigned int irq_base;
int irq_masks[5];
/* The WM831x has a security key blocking access to certain
* registers. The mutex is taken by the accessors for locking
* and unlocking the security key, locked is used to fail
......@@ -244,4 +254,15 @@ int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg,
int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg,
int count, u16 *buf);
int wm831x_irq_init(struct wm831x *wm831x, int irq);
void wm831x_irq_exit(struct wm831x *wm831x);
int __must_check wm831x_request_irq(struct wm831x *wm831x,
unsigned int irq, irq_handler_t handler,
unsigned long flags, const char *name,
void *dev);
void wm831x_free_irq(struct wm831x *wm831x, unsigned int, void *);
void wm831x_disable_irq(struct wm831x *wm831x, int irq);
void wm831x_enable_irq(struct wm831x *wm831x, int irq);
#endif
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment