aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@ti.com>2012-05-16 07:11:58 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-05-20 11:27:12 -0400
commit37e13cecaa141eccce705843f5d2f7509e29bd3a (patch)
tree6f0b138f14c86ac5851b97fc3acd59c7a736ca5e
parent1f01d60e4c0cae3416071680635f227df0020dd8 (diff)
mfd: Add support for Device Tree to twl6040
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>
-rw-r--r--Documentation/devicetree/bindings/mfd/twl6040.txt62
-rw-r--r--drivers/mfd/twl6040-core.c27
-rw-r--r--drivers/mfd/twl6040-irq.c6
3 files changed, 87 insertions, 8 deletions
diff --git a/Documentation/devicetree/bindings/mfd/twl6040.txt b/Documentation/devicetree/bindings/mfd/twl6040.txt
new file mode 100644
index 000000000000..bc67c6f424aa
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/twl6040.txt
@@ -0,0 +1,62 @@
1Texas Instruments TWL6040 family
2
3The TWL6040s are 8-channel high quality low-power audio codecs providing audio
4and vibra functionality on OMAP4+ platforms.
5They are connected ot the host processor via i2c for commands, McPDM for audio
6data and commands.
7
8Required properties:
9- compatible : Must be "ti,twl6040";
10- reg: must be 0x4b for i2c address
11- interrupts: twl6040 has one interrupt line connecteded to the main SoC
12- interrupt-parent: The parent interrupt controller
13- twl6040,audpwron-gpio: Power on GPIO line for the twl6040
14
15- vio-supply: Regulator for the twl6040 VIO supply
16- v2v1-supply: Regulator for the twl6040 V2V1 supply
17
18Optional properties, nodes:
19- enable-active-high: To power on the twl6040 during boot.
20
21Vibra functionality
22Required properties:
23- vddvibl-supply: Regulator for the left vibra motor
24- vddvibr-supply: Regulator for the right vibra motor
25- vibra { }: Configuration section for vibra parameters containing the following
26 properties:
27- ti,vibldrv-res: Resistance parameter for left driver
28- ti,vibrdrv-res: Resistance parameter for right driver
29- ti,viblmotor-res: Resistance parameter for left motor
30- ti,viblmotor-res: Resistance parameter for right motor
31
32Optional properties within vibra { } section:
33- vddvibl_uV: If the vddvibl default voltage need to be changed
34- vddvibr_uV: If the vddvibr default voltage need to be changed
35
36Example:
37&i2c1 {
38 twl6040: twl@4b {
39 compatible = "ti,twl6040";
40 reg = <0x4b>;
41
42 interrupts = <0 119 4>;
43 interrupt-parent = <&gic>;
44 twl6040,audpwron-gpio = <&gpio4 31 0>;
45
46 vio-supply = <&v1v8>;
47 v2v1-supply = <&v2v1>;
48 enable-active-high;
49
50 /* regulators for vibra motor */
51 vddvibl-supply = <&vbat>;
52 vddvibr-supply = <&vbat>;
53
54 vibra {
55 /* Vibra driver, motor resistance parameters */
56 ti,vibldrv-res = <8>;
57 ti,vibrdrv-res = <3>;
58 ti,viblmotor-res = <10>;
59 ti,vibrmotor-res = <10>;
60 };
61 };
62};
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c
index 9765dc2b0ca3..450a28fe8fc2 100644
--- a/drivers/mfd/twl6040-core.c
+++ b/drivers/mfd/twl6040-core.c
@@ -29,6 +29,10 @@
29#include <linux/kernel.h> 29#include <linux/kernel.h>
30#include <linux/err.h> 30#include <linux/err.h>
31#include <linux/platform_device.h> 31#include <linux/platform_device.h>
32#include <linux/of.h>
33#include <linux/of_irq.h>
34#include <linux/of_gpio.h>
35#include <linux/of_platform.h>
32#include <linux/gpio.h> 36#include <linux/gpio.h>
33#include <linux/delay.h> 37#include <linux/delay.h>
34#include <linux/i2c.h> 38#include <linux/i2c.h>
@@ -505,11 +509,12 @@ static int __devinit twl6040_probe(struct i2c_client *client,
505 const struct i2c_device_id *id) 509 const struct i2c_device_id *id)
506{ 510{
507 struct twl6040_platform_data *pdata = client->dev.platform_data; 511 struct twl6040_platform_data *pdata = client->dev.platform_data;
512 struct device_node *node = client->dev.of_node;
508 struct twl6040 *twl6040; 513 struct twl6040 *twl6040;
509 struct mfd_cell *cell = NULL; 514 struct mfd_cell *cell = NULL;
510 int irq, ret, children = 0; 515 int irq, ret, children = 0;
511 516
512 if (!pdata) { 517 if (!pdata && !node) {
513 dev_err(&client->dev, "Platform data is missing\n"); 518 dev_err(&client->dev, "Platform data is missing\n");
514 return -EINVAL; 519 return -EINVAL;
515 } 520 }
@@ -560,9 +565,13 @@ static int __devinit twl6040_probe(struct i2c_client *client,
560 twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV); 565 twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV);
561 566
562 /* ERRATA: Automatic power-up is not possible in ES1.0 */ 567 /* ERRATA: Automatic power-up is not possible in ES1.0 */
563 if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0) 568 if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0) {
564 twl6040->audpwron = pdata->audpwron_gpio; 569 if (pdata)
565 else 570 twl6040->audpwron = pdata->audpwron_gpio;
571 else
572 twl6040->audpwron = of_get_named_gpio(node,
573 "ti,audpwron-gpio", 0);
574 } else
566 twl6040->audpwron = -EINVAL; 575 twl6040->audpwron = -EINVAL;
567 576
568 if (gpio_is_valid(twl6040->audpwron)) { 577 if (gpio_is_valid(twl6040->audpwron)) {
@@ -602,13 +611,13 @@ static int __devinit twl6040_probe(struct i2c_client *client,
602 twl6040_codec_rsrc[0].end = irq; 611 twl6040_codec_rsrc[0].end = irq;
603 cell->resources = twl6040_codec_rsrc; 612 cell->resources = twl6040_codec_rsrc;
604 cell->num_resources = ARRAY_SIZE(twl6040_codec_rsrc); 613 cell->num_resources = ARRAY_SIZE(twl6040_codec_rsrc);
605 if (pdata->codec) { 614 if (pdata && pdata->codec) {
606 cell->platform_data = pdata->codec; 615 cell->platform_data = pdata->codec;
607 cell->pdata_size = sizeof(*pdata->codec); 616 cell->pdata_size = sizeof(*pdata->codec);
608 } 617 }
609 children++; 618 children++;
610 619
611 if (pdata->vibra) { 620 if ((pdata && pdata->vibra) || of_find_node_by_name(node, "vibra")) {
612 irq = twl6040->irq_base + TWL6040_IRQ_VIB; 621 irq = twl6040->irq_base + TWL6040_IRQ_VIB;
613 622
614 cell = &twl6040->cells[children]; 623 cell = &twl6040->cells[children];
@@ -618,8 +627,10 @@ static int __devinit twl6040_probe(struct i2c_client *client,
618 cell->resources = twl6040_vibra_rsrc; 627 cell->resources = twl6040_vibra_rsrc;
619 cell->num_resources = ARRAY_SIZE(twl6040_vibra_rsrc); 628 cell->num_resources = ARRAY_SIZE(twl6040_vibra_rsrc);
620 629
621 cell->platform_data = pdata->vibra; 630 if (pdata && pdata->vibra) {
622 cell->pdata_size = sizeof(*pdata->vibra); 631 cell->platform_data = pdata->vibra;
632 cell->pdata_size = sizeof(*pdata->vibra);
633 }
623 children++; 634 children++;
624 } 635 }
625 636
diff --git a/drivers/mfd/twl6040-irq.c b/drivers/mfd/twl6040-irq.c
index 914978e1b62e..4b42543da228 100644
--- a/drivers/mfd/twl6040-irq.c
+++ b/drivers/mfd/twl6040-irq.c
@@ -25,6 +25,8 @@
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/err.h> 26#include <linux/err.h>
27#include <linux/irq.h> 27#include <linux/irq.h>
28#include <linux/of.h>
29#include <linux/irqdomain.h>
28#include <linux/interrupt.h> 30#include <linux/interrupt.h>
29#include <linux/mfd/core.h> 31#include <linux/mfd/core.h>
30#include <linux/mfd/twl6040.h> 32#include <linux/mfd/twl6040.h>
@@ -139,6 +141,7 @@ static irqreturn_t twl6040_irq_thread(int irq, void *data)
139 141
140int twl6040_irq_init(struct twl6040 *twl6040) 142int twl6040_irq_init(struct twl6040 *twl6040)
141{ 143{
144 struct device_node *node = twl6040->dev->of_node;
142 int i, nr_irqs, irq_base, ret; 145 int i, nr_irqs, irq_base, ret;
143 u8 val; 146 u8 val;
144 147
@@ -158,6 +161,9 @@ int twl6040_irq_init(struct twl6040 *twl6040)
158 } 161 }
159 twl6040->irq_base = irq_base; 162 twl6040->irq_base = irq_base;
160 163
164 irq_domain_add_legacy(node, ARRAY_SIZE(twl6040_irqs), irq_base, 0,
165 &irq_domain_simple_ops, NULL);
166
161 /* Register them with genirq */ 167 /* Register them with genirq */
162 for (i = irq_base; i < irq_base + nr_irqs; i++) { 168 for (i = irq_base; i < irq_base + nr_irqs; i++) {
163 irq_set_chip_data(i, twl6040); 169 irq_set_chip_data(i, twl6040);