* [PATCH v2 1/3] MFD: twl6040: Code cleanup in interrupt initialization part
2012-05-08 11:33 [PATCH v2 0/3] MFD: twl6040: Device tree support Peter Ujfalusi
@ 2012-05-08 11:33 ` Peter Ujfalusi
2012-05-08 11:33 ` [PATCH v2 2/3] MFD: twl6040: Allocate IRQ numbers dynamically Peter Ujfalusi
2012-05-08 11:33 ` [PATCH v2 3/3] MFD: twl6040: Support for DT Peter Ujfalusi
2 siblings, 0 replies; 6+ messages in thread
From: Peter Ujfalusi @ 2012-05-08 11:33 UTC (permalink / raw)
To: Samuel Ortiz
Cc: linux-kernel, Misael Lopez Cruz, Benoit Cousson,
devicetree-discuss, Liam Girdwood, Mark Brown, peter.ujfalusi
No functional change, just to make the code a bit more uniform and
remove wrapped lines.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
---
drivers/mfd/twl6040-irq.c | 17 ++++++++---------
1 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/drivers/mfd/twl6040-irq.c b/drivers/mfd/twl6040-irq.c
index b3f8dda..008022c 100644
--- a/drivers/mfd/twl6040-irq.c
+++ b/drivers/mfd/twl6040-irq.c
@@ -138,7 +138,7 @@ static irqreturn_t twl6040_irq_thread(int irq, void *data)
int twl6040_irq_init(struct twl6040 *twl6040)
{
- int cur_irq, ret;
+ int i, nr_irqs, ret;
u8 val;
mutex_init(&twl6040->irq_mutex);
@@ -148,21 +148,20 @@ int twl6040_irq_init(struct twl6040 *twl6040)
twl6040->irq_masks_cache = TWL6040_ALLINT_MSK;
twl6040_reg_write(twl6040, TWL6040_REG_INTMR, TWL6040_ALLINT_MSK);
+ nr_irqs = ARRAY_SIZE(twl6040_irqs);
/* Register them with genirq */
- for (cur_irq = twl6040->irq_base;
- cur_irq < twl6040->irq_base + ARRAY_SIZE(twl6040_irqs);
- cur_irq++) {
- irq_set_chip_data(cur_irq, twl6040);
- irq_set_chip_and_handler(cur_irq, &twl6040_irq_chip,
+ for (i = twl6040->irq_base; i < twl6040->irq_base + nr_irqs; i++) {
+ irq_set_chip_data(i, twl6040);
+ irq_set_chip_and_handler(i, &twl6040_irq_chip,
handle_level_irq);
- irq_set_nested_thread(cur_irq, 1);
+ irq_set_nested_thread(i, 1);
/* ARM needs us to explicitly flag the IRQ as valid
* and will set them noprobe when we do so. */
#ifdef CONFIG_ARM
- set_irq_flags(cur_irq, IRQF_VALID);
+ set_irq_flags(i, IRQF_VALID);
#else
- irq_set_noprobe(cur_irq);
+ irq_set_noprobe(i);
#endif
}
--
1.7.8.6
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 2/3] MFD: twl6040: Allocate IRQ numbers dynamically
2012-05-08 11:33 [PATCH v2 0/3] MFD: twl6040: Device tree support Peter Ujfalusi
2012-05-08 11:33 ` [PATCH v2 1/3] MFD: twl6040: Code cleanup in interrupt initialization part Peter Ujfalusi
@ 2012-05-08 11:33 ` Peter Ujfalusi
2012-05-08 11:40 ` Mark Brown
2012-05-08 11:33 ` [PATCH v2 3/3] MFD: twl6040: Support for DT Peter Ujfalusi
2 siblings, 1 reply; 6+ messages in thread
From: Peter Ujfalusi @ 2012-05-08 11:33 UTC (permalink / raw)
To: Samuel Ortiz
Cc: linux-kernel, Misael Lopez Cruz, Benoit Cousson,
devicetree-discuss, Liam Girdwood, Mark Brown, peter.ujfalusi
Use irq_alloc_descs() to get the IRQ number range dynamically instead of
the hardwired use if pdata->irq_base.
The twl6040 only provides interrupts for it's internal components which
means that it is not working as an IRQ expander type of device.
The client drivers will receive their interrupt numbers via pdata which
is configured based on the received IRQ range we got from irq_alloc_descs()
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
---
drivers/mfd/twl6040-core.c | 3 +--
drivers/mfd/twl6040-irq.c | 13 +++++++++++--
2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c
index 7a92d95..c50fba7 100644
--- a/drivers/mfd/twl6040-core.c
+++ b/drivers/mfd/twl6040-core.c
@@ -515,7 +515,7 @@ static int __devinit twl6040_probe(struct i2c_client *client,
}
/* In order to operate correctly we need valid interrupt config */
- if (!client->irq || !pdata->irq_base) {
+ if (!client->irq) {
dev_err(&client->dev, "Invalid IRQ configuration\n");
return -EINVAL;
}
@@ -552,7 +552,6 @@ static int __devinit twl6040_probe(struct i2c_client *client,
twl6040->dev = &client->dev;
twl6040->irq = client->irq;
- twl6040->irq_base = pdata->irq_base;
mutex_init(&twl6040->mutex);
mutex_init(&twl6040->io_mutex);
diff --git a/drivers/mfd/twl6040-irq.c b/drivers/mfd/twl6040-irq.c
index 008022c..914978e 100644
--- a/drivers/mfd/twl6040-irq.c
+++ b/drivers/mfd/twl6040-irq.c
@@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/err.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/mfd/core.h>
@@ -138,7 +139,7 @@ static irqreturn_t twl6040_irq_thread(int irq, void *data)
int twl6040_irq_init(struct twl6040 *twl6040)
{
- int i, nr_irqs, ret;
+ int i, nr_irqs, irq_base, ret;
u8 val;
mutex_init(&twl6040->irq_mutex);
@@ -149,8 +150,16 @@ int twl6040_irq_init(struct twl6040 *twl6040)
twl6040_reg_write(twl6040, TWL6040_REG_INTMR, TWL6040_ALLINT_MSK);
nr_irqs = ARRAY_SIZE(twl6040_irqs);
+
+ irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0);
+ if (IS_ERR_VALUE(irq_base)) {
+ dev_err(twl6040->dev, "Fail to allocate IRQ descs\n");
+ return irq_base;
+ }
+ twl6040->irq_base = irq_base;
+
/* Register them with genirq */
- for (i = twl6040->irq_base; i < twl6040->irq_base + nr_irqs; i++) {
+ for (i = irq_base; i < irq_base + nr_irqs; i++) {
irq_set_chip_data(i, twl6040);
irq_set_chip_and_handler(i, &twl6040_irq_chip,
handle_level_irq);
--
1.7.8.6
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 3/3] MFD: twl6040: Support for DT
2012-05-08 11:33 [PATCH v2 0/3] MFD: twl6040: Device tree support Peter Ujfalusi
2012-05-08 11:33 ` [PATCH v2 1/3] MFD: twl6040: Code cleanup in interrupt initialization part Peter Ujfalusi
2012-05-08 11:33 ` [PATCH v2 2/3] MFD: twl6040: Allocate IRQ numbers dynamically Peter Ujfalusi
@ 2012-05-08 11:33 ` Peter Ujfalusi
2 siblings, 0 replies; 6+ messages in thread
From: Peter Ujfalusi @ 2012-05-08 11:33 UTC (permalink / raw)
To: Samuel Ortiz
Cc: linux-kernel, Misael Lopez Cruz, Benoit Cousson,
devicetree-discuss, Liam Girdwood, Mark Brown, peter.ujfalusi
Add support for DT based probing of twl6040 core.
Example of dts section for twl6040:
twl6040: twl6040@4b {
compatible = "ti,twl6040";
reg = <0x4b>;
interrupts = <0 119 4>; /* IRQ_SYS_2N cascaded to gic */
interrupt-parent = <&gic>;
twl6040,audpwron_gpio = <&gpio4 31 0>; /* gpio line 127 */
enable-active-high;
interrupt-controller;
#interrupt-cells = <1>;
vio-supply = <&v1v8>;
v2v1-supply = <&v2v1>;
twl6040_codec: twl6040@0 {
compatible = "ti,twl6040-codec";
interrupts = <1>;
};
};
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
---
Documentation/devicetree/bindings/mfd/twl6040.txt | 51 +++++++++++++++++++++
drivers/mfd/twl6040-core.c | 23 +++++++---
drivers/mfd/twl6040-irq.c | 6 +++
3 files changed, 74 insertions(+), 6 deletions(-)
create mode 100644 Documentation/devicetree/bindings/mfd/twl6040.txt
diff --git a/Documentation/devicetree/bindings/mfd/twl6040.txt b/Documentation/devicetree/bindings/mfd/twl6040.txt
new file mode 100644
index 0000000..6d2399c7
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/twl6040.txt
@@ -0,0 +1,51 @@
+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
+- interrupt-controller: twl6040 support several interrupts internally, it is
+ considered as an interupt controller cascaded to the SoC core.
+#interrupt-cells = <1>;
+- 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.
+- Child nodes for audio functionality and for the vibra driver
+ For details on the child nodes see:
+ Documentation/devicetree/bindings/input/twl6040-vibra.txt - Vibra driver
+ Documentation/devicetree/bindings/sound/twl6040.txt - ASoC codec driver
+
+Example:
+/*
+ * 8-channel high quality low-power audio codec
+ * http://www.ti.com/lit/ds/symlink/twl6040.pdf
+ */
+twl6040: twl6040@4b {
+ compatible = "ti,twl6040";
+ reg = <0x4b>;
+ interrupts = <0 119 4>; /* IRQ_SYS_2N cascaded to gic */
+ interrupt-parent = <&gic>;
+ twl6040,audpwron_gpio = <&gpio4 31 0>; /* gpio line 127 */
+ enable-active-high;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ vio-supply = <&v1v8>;
+ v2v1-supply = <&v2v1>;
+
+ twl6040_codec: twl6040@0 {
+ compatible = "ti,twl6040-codec";
+ interrupts = <1>;
+ };
+};
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c
index c50fba7..23b9771 100644
--- a/drivers/mfd/twl6040-core.c
+++ b/drivers/mfd/twl6040-core.c
@@ -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>
@@ -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 ret, children = 0;
- if (!pdata) {
+ if (!pdata && !node) {
dev_err(&client->dev, "Platform data is missing\n");
return -EINVAL;
}
@@ -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,
+ "twl6040,audpwron_gpio", 0);
+ } else
twl6040->audpwron = -EINVAL;
if (gpio_is_valid(twl6040->audpwron)) {
@@ -589,7 +598,7 @@ static int __devinit twl6040_probe(struct i2c_client *client,
/* dual-access registers controlled by I2C only */
twl6040_set_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_I2CSEL);
- if (pdata->codec) {
+ if (pdata && pdata->codec) {
int irq = twl6040->irq_base + TWL6040_IRQ_PLUG;
cell = &twl6040->cells[children];
@@ -603,7 +612,7 @@ static int __devinit twl6040_probe(struct i2c_client *client,
children++;
}
- if (pdata->vibra) {
+ if (pdata && pdata->vibra) {
int irq = twl6040->irq_base + TWL6040_IRQ_VIB;
cell = &twl6040->cells[children];
@@ -623,6 +632,8 @@ static int __devinit twl6040_probe(struct i2c_client *client,
children, NULL, 0);
if (ret)
goto mfd_err;
+ } else if (node) {
+ ret = of_platform_populate(node, NULL, NULL, &client->dev);
} else {
dev_err(&client->dev, "No platform data found for children\n");
ret = -ENODEV;
diff --git a/drivers/mfd/twl6040-irq.c b/drivers/mfd/twl6040-irq.c
index 914978e..4b42543 100644
--- a/drivers/mfd/twl6040-irq.c
+++ b/drivers/mfd/twl6040-irq.c
@@ -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>
@@ -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;
@@ -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);
--
1.7.8.6
^ permalink raw reply related [flat|nested] 6+ messages in thread