diff options
author | Peter Ujfalusi <peter.ujfalusi@ti.com> | 2012-05-16 07:11:58 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-05-20 11:27:12 -0400 |
commit | 37e13cecaa141eccce705843f5d2f7509e29bd3a (patch) | |
tree | 6f0b138f14c86ac5851b97fc3acd59c7a736ca5e | |
parent | 1f01d60e4c0cae3416071680635f227df0020dd8 (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.txt | 62 | ||||
-rw-r--r-- | drivers/mfd/twl6040-core.c | 27 | ||||
-rw-r--r-- | drivers/mfd/twl6040-irq.c | 6 |
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 @@ | |||
1 | Texas Instruments TWL6040 family | ||
2 | |||
3 | The TWL6040s are 8-channel high quality low-power audio codecs providing audio | ||
4 | and vibra functionality on OMAP4+ platforms. | ||
5 | They are connected ot the host processor via i2c for commands, McPDM for audio | ||
6 | data and commands. | ||
7 | |||
8 | Required 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 | |||
18 | Optional properties, nodes: | ||
19 | - enable-active-high: To power on the twl6040 during boot. | ||
20 | |||
21 | Vibra functionality | ||
22 | Required 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 | |||
32 | Optional 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 | |||
36 | Example: | ||
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 | ||
140 | int twl6040_irq_init(struct twl6040 *twl6040) | 142 | int 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); |