Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Benoit Cousson and committed by
Samuel Ortiz
aeb5032b 5391b5c6

+98 -2
+47
Documentation/devicetree/bindings/mfd/twl-familly.txt
··· 1 + Texas Instruments TWL family 2 + 3 + The TWLs are Integrated Power Management Chips. 4 + Some version might contain much more analog function like 5 + USB transceiver or Audio amplifier. 6 + These chips are connected to an i2c bus. 7 + 8 + 9 + Required properties: 10 + - compatible : Must be "ti,twl4030"; 11 + For Integrated power-management/audio CODEC device used in OMAP3 12 + based boards 13 + - compatible : Must be "ti,twl6030"; 14 + For Integrated power-management used in OMAP4 based boards 15 + - interrupts : This i2c device has an IRQ line connected to the main SoC 16 + - interrupt-controller : Since the twl support several interrupts internally, 17 + it is considered as an interrupt controller cascaded to the SoC one. 18 + - #interrupt-cells = <1>; 19 + - interrupt-parent : The parent interrupt controller. 20 + 21 + Optional node: 22 + - Child nodes contain in the twl. The twl family is made of several variants 23 + that support a different number of features. 24 + The children nodes will thus depend of the capability of the variant. 25 + 26 + 27 + Example: 28 + /* 29 + * Integrated Power Management Chip 30 + * http://www.ti.com/lit/ds/symlink/twl6030.pdf 31 + */ 32 + twl@48 { 33 + compatible = "ti,twl6030"; 34 + reg = <0x48>; 35 + interrupts = <39>; /* IRQ_SYS_1N cascaded to gic */ 36 + interrupt-controller; 37 + #interrupt-cells = <1>; 38 + interrupt-parent = <&gic>; 39 + #address-cells = <1>; 40 + #size-cells = <0>; 41 + 42 + twl_rtc { 43 + compatible = "ti,twl_rtc"; 44 + interrupts = <11>; 45 + reg = <0>; 46 + }; 47 + };
+1 -1
drivers/mfd/Kconfig
··· 200 200 201 201 config TWL4030_CORE 202 202 bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support" 203 - depends on I2C=y && GENERIC_HARDIRQS 203 + depends on I2C=y && GENERIC_HARDIRQS && IRQ_DOMAIN 204 204 help 205 205 Say yes here if you have TWL4030 / TWL6030 family chip on your board. 206 206 This core driver provides register access and IRQ handling
+50 -1
drivers/mfd/twl-core.c
··· 34 34 #include <linux/platform_device.h> 35 35 #include <linux/clk.h> 36 36 #include <linux/err.h> 37 + #include <linux/device.h> 38 + #include <linux/of.h> 39 + #include <linux/of_irq.h> 40 + #include <linux/of_platform.h> 41 + #include <linux/irqdomain.h> 37 42 38 43 #include <linux/regulator/machine.h> 39 44 ··· 148 143 #define SUB_CHIP_ID3 3 149 144 150 145 #define TWL_MODULE_LAST TWL4030_MODULE_LAST 146 + 147 + #define TWL4030_NR_IRQS 8 148 + #define TWL6030_NR_IRQS 20 151 149 152 150 /* Base Address defns for twl4030_map[] */ 153 151 ··· 263 255 264 256 static struct twl_client twl_modules[TWL_NUM_SLAVES]; 265 257 258 + static struct irq_domain domain; 266 259 267 260 /* mapping the module id to slave id and base address */ 268 261 struct twl_mapping { ··· 1192 1183 int status; 1193 1184 unsigned i; 1194 1185 struct twl4030_platform_data *pdata = client->dev.platform_data; 1186 + struct device_node *node = client->dev.of_node; 1195 1187 u8 temp; 1196 1188 int ret = 0; 1189 + int nr_irqs = TWL4030_NR_IRQS; 1190 + 1191 + if ((id->driver_data) & TWL6030_CLASS) 1192 + nr_irqs = TWL6030_NR_IRQS; 1193 + 1194 + if (node && !pdata) { 1195 + /* 1196 + * XXX: Temporary pdata until the information is correctly 1197 + * retrieved by every TWL modules from DT. 1198 + */ 1199 + pdata = devm_kzalloc(&client->dev, 1200 + sizeof(struct twl4030_platform_data), 1201 + GFP_KERNEL); 1202 + if (!pdata) 1203 + return -ENOMEM; 1204 + } 1197 1205 1198 1206 if (!pdata) { 1199 1207 dev_dbg(&client->dev, "no platform data?\n"); 1200 1208 return -EINVAL; 1201 1209 } 1210 + 1211 + status = irq_alloc_descs(-1, pdata->irq_base, nr_irqs, 0); 1212 + if (IS_ERR_VALUE(status)) { 1213 + dev_err(&client->dev, "Fail to allocate IRQ descs\n"); 1214 + return status; 1215 + } 1216 + 1217 + pdata->irq_base = status; 1218 + pdata->irq_end = pdata->irq_base + nr_irqs; 1219 + 1220 + domain.irq_base = pdata->irq_base; 1221 + domain.nr_irq = nr_irqs; 1222 + #ifdef CONFIG_OF_IRQ 1223 + domain.of_node = of_node_get(node); 1224 + domain.ops = &irq_domain_simple_ops; 1225 + #endif 1226 + irq_domain_add(&domain); 1202 1227 1203 1228 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) { 1204 1229 dev_dbg(&client->dev, "can't talk I2C?\n"); ··· 1313 1270 twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1); 1314 1271 } 1315 1272 1316 - status = add_children(pdata, id->driver_data); 1273 + #ifdef CONFIG_OF_DEVICE 1274 + if (node) 1275 + status = of_platform_populate(node, NULL, NULL, &client->dev); 1276 + else 1277 + #endif 1278 + status = add_children(pdata, id->driver_data); 1279 + 1317 1280 fail: 1318 1281 if (status < 0) 1319 1282 twl_remove(client);