diff options
author | Benoit Cousson <b-cousson@ti.com> | 2011-08-29 16:20:23 +0200 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-01-09 00:37:40 +0100 |
commit | aeb5032b3f8b9ab69daa545777433fa94b3494c4 (patch) | |
tree | 70a5ec2e43e0ae6c4e7d5793bf79da61c1ac7bf9 /drivers/mfd | |
parent | 5391b5c645a86d4657c2175acbf21c6461d34849 (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/Kconfig | 2 | ||||
-rw-r--r-- | drivers/mfd/twl-core.c | 51 |
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); |