Skip to content

Commit

Permalink
Merge tag 'mfd/wm5102' of git://git.kernel.org/pub/scm/linux/kernel/g…
Browse files Browse the repository at this point in the history
…it/broonie/misc into for-next

mfd: Initial support for Wolfson Arizona platform and WM5102 devices

The Wolfson Arizona platform is used to provide common register
interface to a series of low power audio hub CODECs, starting with the
WM5102. Since the features of these devices work over a range of
subsystems an MFD core driver is provided to instantiate the subdevices
and arbitrate access between them.

As the new regmap wake IRQ functionality is used as part of the driver
it is incorporated as a dependency.
  • Loading branch information
Samuel Ortiz committed Jul 8, 2012
2 parents 3a8e39c + 3afbac9 commit 0620de5
Show file tree
Hide file tree
Showing 13 changed files with 9,938 additions and 0 deletions.
51 changes: 51 additions & 0 deletions drivers/base/regmap/regmap-irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,13 @@ struct regmap_irq_chip_data {
int irq_base;
struct irq_domain *domain;

int irq;
int wake_count;

unsigned int *status_buf;
unsigned int *mask_buf;
unsigned int *mask_buf_def;
unsigned int *wake_buf;

unsigned int irq_reg_stride;
};
Expand Down Expand Up @@ -71,6 +75,16 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
d->chip->mask_base + (i * map->reg_stride));
}

/* If we've changed our wakeup count propagate it to the parent */
if (d->wake_count < 0)
for (i = d->wake_count; i < 0; i++)
irq_set_irq_wake(d->irq, 0);
else if (d->wake_count > 0)
for (i = 0; i < d->wake_count; i++)
irq_set_irq_wake(d->irq, 1);

d->wake_count = 0;

mutex_unlock(&d->lock);
}

Expand All @@ -92,12 +106,35 @@ static void regmap_irq_disable(struct irq_data *data)
d->mask_buf[irq_data->reg_offset / map->reg_stride] |= irq_data->mask;
}

static int regmap_irq_set_wake(struct irq_data *data, unsigned int on)
{
struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
struct regmap *map = d->map;
const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq);

if (!d->chip->wake_base)
return -EINVAL;

if (on) {
d->wake_buf[irq_data->reg_offset / map->reg_stride]
&= ~irq_data->mask;
d->wake_count++;
} else {
d->wake_buf[irq_data->reg_offset / map->reg_stride]
|= irq_data->mask;
d->wake_count--;
}

return 0;
}

static struct irq_chip regmap_irq_chip = {
.name = "regmap",
.irq_bus_lock = regmap_irq_lock,
.irq_bus_sync_unlock = regmap_irq_sync_unlock,
.irq_disable = regmap_irq_disable,
.irq_enable = regmap_irq_enable,
.irq_set_wake = regmap_irq_set_wake,
};

static irqreturn_t regmap_irq_thread(int irq, void *d)
Expand Down Expand Up @@ -240,6 +277,14 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
if (!d->mask_buf_def)
goto err_alloc;

if (chip->wake_base) {
d->wake_buf = kzalloc(sizeof(unsigned int) * chip->num_regs,
GFP_KERNEL);
if (!d->wake_buf)
goto err_alloc;
}

d->irq = irq;
d->map = map;
d->chip = chip;
d->irq_base = irq_base;
Expand Down Expand Up @@ -294,6 +339,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
err_domain:
/* Should really dispose of the domain but... */
err_alloc:
kfree(d->wake_buf);
kfree(d->mask_buf_def);
kfree(d->mask_buf);
kfree(d->status_buf);
Expand All @@ -315,6 +361,7 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)

free_irq(irq, d);
/* We should unmap the domain but... */
kfree(d->wake_buf);
kfree(d->mask_buf_def);
kfree(d->mask_buf);
kfree(d->status_buf);
Expand Down Expand Up @@ -346,6 +393,10 @@ EXPORT_SYMBOL_GPL(regmap_irq_chip_get_base);
*/
int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq)
{
/* Handle holes in the IRQ list */
if (!data->chip->irqs[irq].mask)
return -EINVAL;

return irq_create_mapping(data->domain, irq);
}
EXPORT_SYMBOL_GPL(regmap_irq_get_virq);
29 changes: 29 additions & 0 deletions drivers/mfd/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,35 @@ config MFD_S5M_CORE
additional drivers must be enabled in order to use the functionality
of the device

config MFD_ARIZONA
tristate

config MFD_ARIZONA_I2C
tristate "Support Wolfson Microelectronics Arizona platform with I2C"
select MFD_ARIZONA
select MFD_CORE
select REGMAP_I2C
depends on I2C
help
Support for the Wolfson Microelectronics Arizona platform audio SoC
core functionality controlled via I2C.

config MFD_ARIZONA_SPI
tristate "Support Wolfson Microelectronics Arizona platform with SPI"
select MFD_ARIZONA
select MFD_CORE
select REGMAP_SPI
depends on SPI_MASTER
help
Support for the Wolfson Microelectronics Arizona platform audio SoC
core functionality controlled via I2C.

config MFD_WM5102
bool "Support Wolfson Microelectronics WM5102"
depends on MFD_ARIZONA
help
Support for Wolfson Microelectronics WM5102 low power audio SoC

config MFD_WM8400
bool "Support Wolfson Microelectronics WM8400"
select MFD_CORE
Expand Down
7 changes: 7 additions & 0 deletions drivers/mfd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o
obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o
obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o

obj-$(CONFIG_MFD_ARIZONA) += arizona-core.o
obj-$(CONFIG_MFD_ARIZONA) += arizona-irq.o
obj-$(CONFIG_MFD_ARIZONA_I2C) += arizona-i2c.o
obj-$(CONFIG_MFD_ARIZONA_SPI) += arizona-spi.o
ifneq ($(CONFIG_MFD_WM5102),n)
obj-$(CONFIG_MFD_ARIZONA) += wm5102-tables.o
endif
obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o
wm831x-objs += wm831x-auxadc.o
Expand Down
Loading

0 comments on commit 0620de5

Please sign in to comment.