Commit aeb5032b authored by Benoit Cousson's avatar Benoit Cousson Committed by Samuel Ortiz

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: default avatarBenoit Cousson <b-cousson@ti.com>
Cc: Balaji T K <balajitk@ti.com>
Cc: Graeme Gregory <gg@slimlogic.co.uk>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
Acked-by: default avatarRob Herring <rob.herring@calxeda.com>
[grant.likely@secretlab.ca: Fix IRQ_DOMAIN dependency in kconfig]
Cc: Grant Likely <grant.likely@secretlab.ca>
parent 5391b5c6
Texas Instruments TWL family
The TWLs are Integrated Power Management Chips.
Some version might contain much more analog function like
USB transceiver or Audio amplifier.
These chips are connected to an i2c bus.
Required properties:
- compatible : Must be "ti,twl4030";
For Integrated power-management/audio CODEC device used in OMAP3
based boards
- compatible : Must be "ti,twl6030";
For Integrated power-management used in OMAP4 based boards
- interrupts : This i2c device has an IRQ line connected to the main SoC
- interrupt-controller : Since the twl support several interrupts internally,
it is considered as an interrupt controller cascaded to the SoC one.
- #interrupt-cells = <1>;
- interrupt-parent : The parent interrupt controller.
Optional node:
- Child nodes contain in the twl. The twl family is made of several variants
that support a different number of features.
The children nodes will thus depend of the capability of the variant.
Example:
/*
* Integrated Power Management Chip
* http://www.ti.com/lit/ds/symlink/twl6030.pdf
*/
twl@48 {
compatible = "ti,twl6030";
reg = <0x48>;
interrupts = <39>; /* IRQ_SYS_1N cascaded to gic */
interrupt-controller;
#interrupt-cells = <1>;
interrupt-parent = <&gic>;
#address-cells = <1>;
#size-cells = <0>;
twl_rtc {
compatible = "ti,twl_rtc";
interrupts = <11>;
reg = <0>;
};
};
...@@ -200,7 +200,7 @@ config MENELAUS ...@@ -200,7 +200,7 @@ config MENELAUS
config TWL4030_CORE config TWL4030_CORE
bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support" bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support"
depends on I2C=y && GENERIC_HARDIRQS depends on I2C=y && GENERIC_HARDIRQS && IRQ_DOMAIN
help help
Say yes here if you have TWL4030 / TWL6030 family chip on your board. Say yes here if you have TWL4030 / TWL6030 family chip on your board.
This core driver provides register access and IRQ handling This core driver provides register access and IRQ handling
......
...@@ -34,6 +34,11 @@ ...@@ -34,6 +34,11 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/err.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> #include <linux/regulator/machine.h>
...@@ -144,6 +149,9 @@ ...@@ -144,6 +149,9 @@
#define TWL_MODULE_LAST TWL4030_MODULE_LAST #define TWL_MODULE_LAST TWL4030_MODULE_LAST
#define TWL4030_NR_IRQS 8
#define TWL6030_NR_IRQS 20
/* Base Address defns for twl4030_map[] */ /* Base Address defns for twl4030_map[] */
/* subchip/slave 0 - USB ID */ /* subchip/slave 0 - USB ID */
...@@ -255,6 +263,7 @@ struct twl_client { ...@@ -255,6 +263,7 @@ struct twl_client {
static struct twl_client twl_modules[TWL_NUM_SLAVES]; static struct twl_client twl_modules[TWL_NUM_SLAVES];
static struct irq_domain domain;
/* mapping the module id to slave id and base address */ /* mapping the module id to slave id and base address */
struct twl_mapping { struct twl_mapping {
...@@ -1183,14 +1192,48 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -1183,14 +1192,48 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
int status; int status;
unsigned i; unsigned i;
struct twl4030_platform_data *pdata = client->dev.platform_data; struct twl4030_platform_data *pdata = client->dev.platform_data;
struct device_node *node = client->dev.of_node;
u8 temp; u8 temp;
int ret = 0; 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) { if (!pdata) {
dev_dbg(&client->dev, "no platform data?\n"); dev_dbg(&client->dev, "no platform data?\n");
return -EINVAL; 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) { if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
dev_dbg(&client->dev, "can't talk I2C?\n"); dev_dbg(&client->dev, "can't talk I2C?\n");
return -EIO; return -EIO;
...@@ -1270,7 +1313,13 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -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); twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
} }
#ifdef CONFIG_OF_DEVICE
if (node)
status = of_platform_populate(node, NULL, NULL, &client->dev);
else
#endif
status = add_children(pdata, id->driver_data); status = add_children(pdata, id->driver_data);
fail: fail:
if (status < 0) if (status < 0)
twl_remove(client); twl_remove(client);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment