Skip to content

Commit

Permalink
mfd: Add WM8994 interrupt controller support
Browse files Browse the repository at this point in the history
The WM8994 has an interrupt controller which supports interrupts for
both CODEC and GPIO portions of the chip. Support this using genirq,
while allowing for systems that do not have an interrupt hooked up.

Wrapper functions are provided for the IRQ request and free to simplify
the code in consumer drivers when handling cases where IRQs are not
set up.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Samuel Ortiz <sameo@linux.intel.com>
  • Loading branch information
Mark Brown committed Apr 5, 2010
1 parent 8c0d8fa commit c9fbf7e
Show file tree
Hide file tree
Showing 6 changed files with 406 additions and 7 deletions.
4 changes: 2 additions & 2 deletions drivers/mfd/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -301,9 +301,9 @@ config MFD_WM8350_I2C
selected to enable support for the functionality of the chip.

config MFD_WM8994
tristate "Support Wolfson Microelectronics WM8994"
bool "Support Wolfson Microelectronics WM8994"
select MFD_CORE
depends on I2C
depends on I2C=y && GENERIC_HARDIRQS
help
The WM8994 is a highly integrated hi-fi CODEC designed for
smartphone applicatiosn. As well as audio functionality it
Expand Down
2 changes: 1 addition & 1 deletion drivers/mfd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
wm8350-objs += wm8350-irq.o
obj-$(CONFIG_MFD_WM8350) += wm8350.o
obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
obj-$(CONFIG_MFD_WM8994) += wm8994-core.o
obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o

obj-$(CONFIG_TPS65010) += tps65010.o
obj-$(CONFIG_MENELAUS) += menelaus.o
Expand Down
43 changes: 40 additions & 3 deletions drivers/mfd/wm8994-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,34 @@ static struct mfd_cell wm8994_regulator_devs[] = {
{ .name = "wm8994-ldo", .id = 2 },
};

static struct resource wm8994_codec_resources[] = {
{
.start = WM8994_IRQ_TEMP_SHUT,
.end = WM8994_IRQ_TEMP_WARN,
.flags = IORESOURCE_IRQ,
},
};

static struct resource wm8994_gpio_resources[] = {
{
.start = WM8994_IRQ_GPIO(1),
.end = WM8994_IRQ_GPIO(11),
.flags = IORESOURCE_IRQ,
},
};

static struct mfd_cell wm8994_devs[] = {
{ .name = "wm8994-codec" },
{ .name = "wm8994-gpio" },
{
.name = "wm8994-codec",
.num_resources = ARRAY_SIZE(wm8994_codec_resources),
.resources = wm8994_codec_resources,
},

{
.name = "wm8994-gpio",
.num_resources = ARRAY_SIZE(wm8994_gpio_resources),
.resources = wm8994_gpio_resources,
},
};

/*
Expand Down Expand Up @@ -235,6 +260,11 @@ static int wm8994_device_resume(struct device *dev)
return ret;
}

ret = wm8994_write(wm8994, WM8994_INTERRUPT_STATUS_1_MASK,
WM8994_NUM_IRQ_REGS * 2, &wm8994->irq_masks_cur);
if (ret < 0)
dev_err(dev, "Failed to restore interrupt masks: %d\n", ret);

ret = wm8994_write(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
&wm8994->ldo_regs);
if (ret < 0)
Expand Down Expand Up @@ -347,6 +377,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq)


if (pdata) {
wm8994->irq_base = pdata->irq_base;
wm8994->gpio_base = pdata->gpio_base;

/* GPIO configuration is only applied if it's non-zero */
Expand Down Expand Up @@ -374,16 +405,20 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq)
WM8994_LDO1_DISCH, 0);
}

wm8994_irq_init(wm8994);

ret = mfd_add_devices(wm8994->dev, -1,
wm8994_devs, ARRAY_SIZE(wm8994_devs),
NULL, 0);
if (ret != 0) {
dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
goto err_enable;
goto err_irq;
}

return 0;

err_irq:
wm8994_irq_exit(wm8994);
err_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
wm8994->supplies);
Expand All @@ -400,6 +435,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq)
static void wm8994_device_exit(struct wm8994 *wm8994)
{
mfd_remove_devices(wm8994->dev);
wm8994_irq_exit(wm8994);
regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
wm8994->supplies);
regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies);
Expand Down Expand Up @@ -468,6 +504,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
wm8994->control_data = i2c;
wm8994->read_dev = wm8994_i2c_read_device;
wm8994->write_dev = wm8994_i2c_write_device;
wm8994->irq = i2c->irq;

return wm8994_device_init(wm8994, id->driver_data, i2c->irq);
}
Expand Down
Loading

0 comments on commit c9fbf7e

Please sign in to comment.