summaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorBenoit Cousson <b-cousson@ti.com>2011-08-29 16:20:23 +0200
committerSamuel Ortiz <sameo@linux.intel.com>2012-01-09 00:37:40 +0100
commitaeb5032b3f8b9ab69daa545777433fa94b3494c4 (patch)
tree70a5ec2e43e0ae6c4e7d5793bf79da61c1ac7bf9 /drivers/mfd
parent5391b5c645a86d4657c2175acbf21c6461d34849 (diff)
mfd: twl-core: Add initial DT support for twl4030/twl6030
Add initial device-tree support for twl familly chips. The current version is missing the regulator entries due to the lack of DT regulator bindings for the moment. Only the simple sub-modules that do not depend on platform_data information can be initialized properly. Add irqdomain support. Add documentation for the Texas Instruments TWL Integrated Chip. Signed-off-by: Benoit Cousson <b-cousson@ti.com> Cc: Balaji T K <balajitk@ti.com> Cc: Graeme Gregory <gg@slimlogic.co.uk> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> Acked-by: Rob Herring <rob.herring@calxeda.com> [grant.likely@secretlab.ca: Fix IRQ_DOMAIN dependency in kconfig] Cc: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/Kconfig2
-rw-r--r--drivers/mfd/twl-core.c51
2 files changed, 51 insertions, 2 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 0f6db32240f..08a3e087bce 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -200,7 +200,7 @@ config MENELAUS
config TWL4030_CORE
bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support"
- depends on I2C=y && GENERIC_HARDIRQS
+ depends on I2C=y && GENERIC_HARDIRQS && IRQ_DOMAIN
help
Say yes here if you have TWL4030 / TWL6030 family chip on your board.
This core driver provides register access and IRQ handling
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 61e70cfaa77..e04e04ddc15 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -34,6 +34,11 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/irqdomain.h>
#include <linux/regulator/machine.h>
@@ -144,6 +149,9 @@
#define TWL_MODULE_LAST TWL4030_MODULE_LAST
+#define TWL4030_NR_IRQS 8
+#define TWL6030_NR_IRQS 20
+
/* Base Address defns for twl4030_map[] */
/* subchip/slave 0 - USB ID */
@@ -255,6 +263,7 @@ struct twl_client {
static struct twl_client twl_modules[TWL_NUM_SLAVES];
+static struct irq_domain domain;
/* mapping the module id to slave id and base address */
struct twl_mapping {
@@ -1183,14 +1192,48 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
int status;
unsigned i;
struct twl4030_platform_data *pdata = client->dev.platform_data;
+ struct device_node *node = client->dev.of_node;
u8 temp;
int ret = 0;
+ int nr_irqs = TWL4030_NR_IRQS;
+
+ if ((id->driver_data) & TWL6030_CLASS)
+ nr_irqs = TWL6030_NR_IRQS;
+
+ if (node && !pdata) {
+ /*
+ * XXX: Temporary pdata until the information is correctly
+ * retrieved by every TWL modules from DT.
+ */
+ pdata = devm_kzalloc(&client->dev,
+ sizeof(struct twl4030_platform_data),
+ GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+ }
if (!pdata) {
dev_dbg(&client->dev, "no platform data?\n");
return -EINVAL;
}
+ status = irq_alloc_descs(-1, pdata->irq_base, nr_irqs, 0);
+ if (IS_ERR_VALUE(status)) {
+ dev_err(&client->dev, "Fail to allocate IRQ descs\n");
+ return status;
+ }
+
+ pdata->irq_base = status;
+ pdata->irq_end = pdata->irq_base + nr_irqs;
+
+ domain.irq_base = pdata->irq_base;
+ domain.nr_irq = nr_irqs;
+#ifdef CONFIG_OF_IRQ
+ domain.of_node = of_node_get(node);
+ domain.ops = &irq_domain_simple_ops;
+#endif
+ irq_domain_add(&domain);
+
if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
dev_dbg(&client->dev, "can't talk I2C?\n");
return -EIO;
@@ -1270,7 +1313,13 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
}
- status = add_children(pdata, id->driver_data);
+#ifdef CONFIG_OF_DEVICE
+ if (node)
+ status = of_platform_populate(node, NULL, NULL, &client->dev);
+ else
+#endif
+ status = add_children(pdata, id->driver_data);
+
fail:
if (status < 0)
twl_remove(client);