mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-16 08:44:21 +08:00
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>
This commit is contained in:
parent
5391b5c645
commit
aeb5032b3f
47
Documentation/devicetree/bindings/mfd/twl-familly.txt
Normal file
47
Documentation/devicetree/bindings/mfd/twl-familly.txt
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
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
|
|||||||
|
|
||||||
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 @@
|
|||||||
#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 @@
|
|||||||
|
|
||||||
#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 {
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user