Skip to content

Commit

Permalink
mfd: Add support for Device Tree to twl6040
Browse files Browse the repository at this point in the history
Device tree based probing support for the core twl6040 driver. Child
devices will be created as MFD devices:
- ASoC codec is always created
- Vibra child is only created if the vibra section present in the DT blob.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
  • Loading branch information
Peter Ujfalusi authored and Samuel Ortiz committed May 20, 2012
1 parent 1f01d60 commit 37e13ce
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 8 deletions.
62 changes: 62 additions & 0 deletions Documentation/devicetree/bindings/mfd/twl6040.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
Texas Instruments TWL6040 family

The TWL6040s are 8-channel high quality low-power audio codecs providing audio
and vibra functionality on OMAP4+ platforms.
They are connected ot the host processor via i2c for commands, McPDM for audio
data and commands.

Required properties:
- compatible : Must be "ti,twl6040";
- reg: must be 0x4b for i2c address
- interrupts: twl6040 has one interrupt line connecteded to the main SoC
- interrupt-parent: The parent interrupt controller
- twl6040,audpwron-gpio: Power on GPIO line for the twl6040

- vio-supply: Regulator for the twl6040 VIO supply
- v2v1-supply: Regulator for the twl6040 V2V1 supply

Optional properties, nodes:
- enable-active-high: To power on the twl6040 during boot.

Vibra functionality
Required properties:
- vddvibl-supply: Regulator for the left vibra motor
- vddvibr-supply: Regulator for the right vibra motor
- vibra { }: Configuration section for vibra parameters containing the following
properties:
- ti,vibldrv-res: Resistance parameter for left driver
- ti,vibrdrv-res: Resistance parameter for right driver
- ti,viblmotor-res: Resistance parameter for left motor
- ti,viblmotor-res: Resistance parameter for right motor

Optional properties within vibra { } section:
- vddvibl_uV: If the vddvibl default voltage need to be changed
- vddvibr_uV: If the vddvibr default voltage need to be changed

Example:
&i2c1 {
twl6040: twl@4b {
compatible = "ti,twl6040";
reg = <0x4b>;

interrupts = <0 119 4>;
interrupt-parent = <&gic>;
twl6040,audpwron-gpio = <&gpio4 31 0>;

vio-supply = <&v1v8>;
v2v1-supply = <&v2v1>;
enable-active-high;

/* regulators for vibra motor */
vddvibl-supply = <&vbat>;
vddvibr-supply = <&vbat>;

vibra {
/* Vibra driver, motor resistance parameters */
ti,vibldrv-res = <8>;
ti,vibrdrv-res = <3>;
ti,viblmotor-res = <10>;
ti,vibrmotor-res = <10>;
};
};
};
27 changes: 19 additions & 8 deletions drivers/mfd/twl6040-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/i2c.h>
Expand Down Expand Up @@ -505,11 +509,12 @@ static int __devinit twl6040_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct twl6040_platform_data *pdata = client->dev.platform_data;
struct device_node *node = client->dev.of_node;
struct twl6040 *twl6040;
struct mfd_cell *cell = NULL;
int irq, ret, children = 0;

if (!pdata) {
if (!pdata && !node) {
dev_err(&client->dev, "Platform data is missing\n");
return -EINVAL;
}
Expand Down Expand Up @@ -560,9 +565,13 @@ static int __devinit twl6040_probe(struct i2c_client *client,
twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV);

/* ERRATA: Automatic power-up is not possible in ES1.0 */
if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0)
twl6040->audpwron = pdata->audpwron_gpio;
else
if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0) {
if (pdata)
twl6040->audpwron = pdata->audpwron_gpio;
else
twl6040->audpwron = of_get_named_gpio(node,
"ti,audpwron-gpio", 0);
} else
twl6040->audpwron = -EINVAL;

if (gpio_is_valid(twl6040->audpwron)) {
Expand Down Expand Up @@ -602,13 +611,13 @@ static int __devinit twl6040_probe(struct i2c_client *client,
twl6040_codec_rsrc[0].end = irq;
cell->resources = twl6040_codec_rsrc;
cell->num_resources = ARRAY_SIZE(twl6040_codec_rsrc);
if (pdata->codec) {
if (pdata && pdata->codec) {
cell->platform_data = pdata->codec;
cell->pdata_size = sizeof(*pdata->codec);
}
children++;

if (pdata->vibra) {
if ((pdata && pdata->vibra) || of_find_node_by_name(node, "vibra")) {
irq = twl6040->irq_base + TWL6040_IRQ_VIB;

cell = &twl6040->cells[children];
Expand All @@ -618,8 +627,10 @@ static int __devinit twl6040_probe(struct i2c_client *client,
cell->resources = twl6040_vibra_rsrc;
cell->num_resources = ARRAY_SIZE(twl6040_vibra_rsrc);

cell->platform_data = pdata->vibra;
cell->pdata_size = sizeof(*pdata->vibra);
if (pdata && pdata->vibra) {
cell->platform_data = pdata->vibra;
cell->pdata_size = sizeof(*pdata->vibra);
}
children++;
}

Expand Down
6 changes: 6 additions & 0 deletions drivers/mfd/twl6040-irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <linux/module.h>
#include <linux/err.h>
#include <linux/irq.h>
#include <linux/of.h>
#include <linux/irqdomain.h>
#include <linux/interrupt.h>
#include <linux/mfd/core.h>
#include <linux/mfd/twl6040.h>
Expand Down Expand Up @@ -139,6 +141,7 @@ static irqreturn_t twl6040_irq_thread(int irq, void *data)

int twl6040_irq_init(struct twl6040 *twl6040)
{
struct device_node *node = twl6040->dev->of_node;
int i, nr_irqs, irq_base, ret;
u8 val;

Expand All @@ -158,6 +161,9 @@ int twl6040_irq_init(struct twl6040 *twl6040)
}
twl6040->irq_base = irq_base;

irq_domain_add_legacy(node, ARRAY_SIZE(twl6040_irqs), irq_base, 0,
&irq_domain_simple_ops, NULL);

/* Register them with genirq */
for (i = irq_base; i < irq_base + nr_irqs; i++) {
irq_set_chip_data(i, twl6040);
Expand Down

0 comments on commit 37e13ce

Please sign in to comment.