xref: /openbmc/linux/drivers/mfd/twl-core.c (revision da059ecf)
1b07682b6SSantosh Shilimkar /*
2fc7b92fcSBalaji T K  * twl_core.c - driver for TWL4030/TWL5030/TWL60X0/TPS659x0 PM
3fc7b92fcSBalaji T K  * and audio CODEC devices
4b07682b6SSantosh Shilimkar  *
5b07682b6SSantosh Shilimkar  * Copyright (C) 2005-2006 Texas Instruments, Inc.
6b07682b6SSantosh Shilimkar  *
7b07682b6SSantosh Shilimkar  * Modifications to defer interrupt handling to a kernel thread:
8b07682b6SSantosh Shilimkar  * Copyright (C) 2006 MontaVista Software, Inc.
9b07682b6SSantosh Shilimkar  *
10b07682b6SSantosh Shilimkar  * Based on tlv320aic23.c:
11b07682b6SSantosh Shilimkar  * Copyright (c) by Kai Svahn <kai.svahn@nokia.com>
12b07682b6SSantosh Shilimkar  *
13b07682b6SSantosh Shilimkar  * Code cleanup and modifications to IRQ handler.
14b07682b6SSantosh Shilimkar  * by syed khasim <x0khasim@ti.com>
15b07682b6SSantosh Shilimkar  *
16b07682b6SSantosh Shilimkar  * This program is free software; you can redistribute it and/or modify
17b07682b6SSantosh Shilimkar  * it under the terms of the GNU General Public License as published by
18b07682b6SSantosh Shilimkar  * the Free Software Foundation; either version 2 of the License, or
19b07682b6SSantosh Shilimkar  * (at your option) any later version.
20b07682b6SSantosh Shilimkar  *
21b07682b6SSantosh Shilimkar  * This program is distributed in the hope that it will be useful,
22b07682b6SSantosh Shilimkar  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23b07682b6SSantosh Shilimkar  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24b07682b6SSantosh Shilimkar  * GNU General Public License for more details.
25b07682b6SSantosh Shilimkar  *
26b07682b6SSantosh Shilimkar  * You should have received a copy of the GNU General Public License
27b07682b6SSantosh Shilimkar  * along with this program; if not, write to the Free Software
28b07682b6SSantosh Shilimkar  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
29b07682b6SSantosh Shilimkar  */
30b07682b6SSantosh Shilimkar 
31b07682b6SSantosh Shilimkar #include <linux/init.h>
32b07682b6SSantosh Shilimkar #include <linux/mutex.h>
334e36dd33SPaul Gortmaker #include <linux/module.h>
34b07682b6SSantosh Shilimkar #include <linux/platform_device.h>
352473d25aSPeter Ujfalusi #include <linux/regmap.h>
36b07682b6SSantosh Shilimkar #include <linux/clk.h>
37b07682b6SSantosh Shilimkar #include <linux/err.h>
38aeb5032bSBenoit Cousson #include <linux/device.h>
39aeb5032bSBenoit Cousson #include <linux/of.h>
40aeb5032bSBenoit Cousson #include <linux/of_irq.h>
41aeb5032bSBenoit Cousson #include <linux/of_platform.h>
42e7cc3acaSGrant Likely #include <linux/irq.h>
43aeb5032bSBenoit Cousson #include <linux/irqdomain.h>
44b07682b6SSantosh Shilimkar 
45b07682b6SSantosh Shilimkar #include <linux/regulator/machine.h>
46b07682b6SSantosh Shilimkar 
47b07682b6SSantosh Shilimkar #include <linux/i2c.h>
48b07682b6SSantosh Shilimkar #include <linux/i2c/twl.h>
49b07682b6SSantosh Shilimkar 
501b8f333fSBenoit Cousson #include "twl-core.h"
51b07682b6SSantosh Shilimkar 
52b07682b6SSantosh Shilimkar /*
53b07682b6SSantosh Shilimkar  * The TWL4030 "Triton 2" is one of a family of a multi-function "Power
54b07682b6SSantosh Shilimkar  * Management and System Companion Device" chips originally designed for
55b07682b6SSantosh Shilimkar  * use in OMAP2 and OMAP 3 based systems.  Its control interfaces use I2C,
56b07682b6SSantosh Shilimkar  * often at around 3 Mbit/sec, including for interrupt handling.
57b07682b6SSantosh Shilimkar  *
58b07682b6SSantosh Shilimkar  * This driver core provides genirq support for the interrupts emitted,
59b07682b6SSantosh Shilimkar  * by the various modules, and exports register access primitives.
60b07682b6SSantosh Shilimkar  *
61b07682b6SSantosh Shilimkar  * FIXME this driver currently requires use of the first interrupt line
62b07682b6SSantosh Shilimkar  * (and associated registers).
63b07682b6SSantosh Shilimkar  */
64b07682b6SSantosh Shilimkar 
65fc7b92fcSBalaji T K #define DRIVER_NAME			"twl"
66b07682b6SSantosh Shilimkar 
67b07682b6SSantosh Shilimkar /* Triton Core internal information (BEGIN) */
68b07682b6SSantosh Shilimkar 
69fc7b92fcSBalaji T K #define TWL_NUM_SLAVES		4
70b07682b6SSantosh Shilimkar 
71fc7b92fcSBalaji T K #define SUB_CHIP_ID0 0
72fc7b92fcSBalaji T K #define SUB_CHIP_ID1 1
73fc7b92fcSBalaji T K #define SUB_CHIP_ID2 2
74fc7b92fcSBalaji T K #define SUB_CHIP_ID3 3
75364cedb2SPeter Ujfalusi #define SUB_CHIP_ID_INVAL 0xff
76fc7b92fcSBalaji T K 
77fc7b92fcSBalaji T K #define TWL_MODULE_LAST TWL4030_MODULE_LAST
78fc7b92fcSBalaji T K 
79b07682b6SSantosh Shilimkar /* Base Address defns for twl4030_map[] */
80b07682b6SSantosh Shilimkar 
81b07682b6SSantosh Shilimkar /* subchip/slave 0 - USB ID */
82b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_USB		0x0000
83b07682b6SSantosh Shilimkar 
84b07682b6SSantosh Shilimkar /* subchip/slave 1 - AUD ID */
85b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_AUDIO_VOICE	0x0000
86b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_GPIO		0x0098
87b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_INTBR		0x0085
88b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_PIH		0x0080
89b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_TEST		0x004C
90b07682b6SSantosh Shilimkar 
91b07682b6SSantosh Shilimkar /* subchip/slave 2 - AUX ID */
92b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_INTERRUPTS	0x00B9
93b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_LED		0x00EE
94b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_MADC		0x0000
95b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_MAIN_CHARGE	0x0074
96b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_PRECHARGE	0x00AA
97b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_PWM0		0x00F8
98b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_PWM1		0x00FB
99b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_PWMA		0x00EF
100b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_PWMB		0x00F1
101b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_KEYPAD		0x00D2
102b07682b6SSantosh Shilimkar 
103b07682b6SSantosh Shilimkar #define TWL5031_BASEADD_ACCESSORY	0x0074 /* Replaces Main Charge */
104b07682b6SSantosh Shilimkar #define TWL5031_BASEADD_INTERRUPTS	0x00B9 /* Different than TWL4030's
105b07682b6SSantosh Shilimkar 						  one */
106b07682b6SSantosh Shilimkar 
107b07682b6SSantosh Shilimkar /* subchip/slave 3 - POWER ID */
108b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_BACKUP		0x0014
109b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_INT		0x002E
110b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_PM_MASTER	0x0036
111b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_PM_RECEIVER	0x005B
112b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_RTC		0x001C
113b07682b6SSantosh Shilimkar #define TWL4030_BASEADD_SECURED_REG	0x0000
114b07682b6SSantosh Shilimkar 
115b07682b6SSantosh Shilimkar /* Triton Core internal information (END) */
116b07682b6SSantosh Shilimkar 
117b07682b6SSantosh Shilimkar 
118e8deb28cSBalaji T K /* subchip/slave 0 0x48 - POWER */
119e8deb28cSBalaji T K #define TWL6030_BASEADD_RTC		0x0000
120e8deb28cSBalaji T K #define TWL6030_BASEADD_MEM		0x0017
121e8deb28cSBalaji T K #define TWL6030_BASEADD_PM_MASTER	0x001F
122e8deb28cSBalaji T K #define TWL6030_BASEADD_PM_SLAVE_MISC	0x0030 /* PM_RECEIVER */
123e8deb28cSBalaji T K #define TWL6030_BASEADD_PM_MISC		0x00E2
124e8deb28cSBalaji T K #define TWL6030_BASEADD_PM_PUPD		0x00F0
125e8deb28cSBalaji T K 
126e8deb28cSBalaji T K /* subchip/slave 1 0x49 - FEATURE */
127e8deb28cSBalaji T K #define TWL6030_BASEADD_USB		0x0000
128e8deb28cSBalaji T K #define TWL6030_BASEADD_GPADC_CTRL	0x002E
129e8deb28cSBalaji T K #define TWL6030_BASEADD_AUX		0x0090
130e8deb28cSBalaji T K #define TWL6030_BASEADD_PWM		0x00BA
131e8deb28cSBalaji T K #define TWL6030_BASEADD_GASGAUGE	0x00C0
132e8deb28cSBalaji T K #define TWL6030_BASEADD_PIH		0x00D0
133e8deb28cSBalaji T K #define TWL6030_BASEADD_CHARGER		0x00E0
134521d8ec3SGraeme Gregory #define TWL6025_BASEADD_CHARGER		0x00DA
135e8deb28cSBalaji T K 
136e8deb28cSBalaji T K /* subchip/slave 2 0x4A - DFT */
137e8deb28cSBalaji T K #define TWL6030_BASEADD_DIEID		0x00C0
138e8deb28cSBalaji T K 
139e8deb28cSBalaji T K /* subchip/slave 3 0x4B - AUDIO */
140e8deb28cSBalaji T K #define TWL6030_BASEADD_AUDIO		0x0000
141e8deb28cSBalaji T K #define TWL6030_BASEADD_RSV		0x0000
142fa0d9762SBalaji T K #define TWL6030_BASEADD_ZERO		0x0000
143e8deb28cSBalaji T K 
144b07682b6SSantosh Shilimkar /* Few power values */
145b07682b6SSantosh Shilimkar #define R_CFG_BOOT			0x05
146b07682b6SSantosh Shilimkar 
147b07682b6SSantosh Shilimkar /* some fields in R_CFG_BOOT */
148b07682b6SSantosh Shilimkar #define HFCLK_FREQ_19p2_MHZ		(1 << 0)
149b07682b6SSantosh Shilimkar #define HFCLK_FREQ_26_MHZ		(2 << 0)
150b07682b6SSantosh Shilimkar #define HFCLK_FREQ_38p4_MHZ		(3 << 0)
151b07682b6SSantosh Shilimkar #define HIGH_PERF_SQ			(1 << 3)
152b07682b6SSantosh Shilimkar #define CK32K_LOWPWR_EN			(1 << 7)
153b07682b6SSantosh Shilimkar 
154b07682b6SSantosh Shilimkar /*----------------------------------------------------------------------*/
155b07682b6SSantosh Shilimkar 
156b07682b6SSantosh Shilimkar /* is driver active, bound to a chip? */
157b07682b6SSantosh Shilimkar static bool inuse;
158b07682b6SSantosh Shilimkar 
159ca972d13SLesly A M /* TWL IDCODE Register value */
160ca972d13SLesly A M static u32 twl_idcode;
161ca972d13SLesly A M 
162e8deb28cSBalaji T K static unsigned int twl_id;
163e8deb28cSBalaji T K unsigned int twl_rev(void)
164e8deb28cSBalaji T K {
165e8deb28cSBalaji T K 	return twl_id;
166e8deb28cSBalaji T K }
167e8deb28cSBalaji T K EXPORT_SYMBOL(twl_rev);
168e8deb28cSBalaji T K 
169e8deb28cSBalaji T K /* Structure for each TWL4030/TWL6030 Slave */
170fc7b92fcSBalaji T K struct twl_client {
171b07682b6SSantosh Shilimkar 	struct i2c_client *client;
1722473d25aSPeter Ujfalusi 	struct regmap *regmap;
173b07682b6SSantosh Shilimkar };
174b07682b6SSantosh Shilimkar 
175fc7b92fcSBalaji T K static struct twl_client twl_modules[TWL_NUM_SLAVES];
176b07682b6SSantosh Shilimkar 
177b07682b6SSantosh Shilimkar /* mapping the module id to slave id and base address */
178fc7b92fcSBalaji T K struct twl_mapping {
179b07682b6SSantosh Shilimkar 	unsigned char sid;	/* Slave ID */
180b07682b6SSantosh Shilimkar 	unsigned char base;	/* base address */
181b07682b6SSantosh Shilimkar };
1822cfcce18SG, Manjunath Kondaiah static struct twl_mapping *twl_map;
183b07682b6SSantosh Shilimkar 
184da059ecfSPeter Ujfalusi static struct twl_mapping twl4030_map[] = {
185b07682b6SSantosh Shilimkar 	/*
186b07682b6SSantosh Shilimkar 	 * NOTE:  don't change this table without updating the
187e8deb28cSBalaji T K 	 * <linux/i2c/twl.h> defines for TWL4030_MODULE_*
188b07682b6SSantosh Shilimkar 	 * so they continue to match the order in this table.
189b07682b6SSantosh Shilimkar 	 */
190b07682b6SSantosh Shilimkar 
191b07682b6SSantosh Shilimkar 	{ 0, TWL4030_BASEADD_USB },
192b07682b6SSantosh Shilimkar 
193b07682b6SSantosh Shilimkar 	{ 1, TWL4030_BASEADD_AUDIO_VOICE },
194b07682b6SSantosh Shilimkar 	{ 1, TWL4030_BASEADD_GPIO },
195b07682b6SSantosh Shilimkar 	{ 1, TWL4030_BASEADD_INTBR },
196b07682b6SSantosh Shilimkar 	{ 1, TWL4030_BASEADD_PIH },
197b07682b6SSantosh Shilimkar 	{ 1, TWL4030_BASEADD_TEST },
198b07682b6SSantosh Shilimkar 
199b07682b6SSantosh Shilimkar 	{ 2, TWL4030_BASEADD_KEYPAD },
200b07682b6SSantosh Shilimkar 	{ 2, TWL4030_BASEADD_MADC },
201b07682b6SSantosh Shilimkar 	{ 2, TWL4030_BASEADD_INTERRUPTS },
202b07682b6SSantosh Shilimkar 	{ 2, TWL4030_BASEADD_LED },
203b07682b6SSantosh Shilimkar 	{ 2, TWL4030_BASEADD_MAIN_CHARGE },
204b07682b6SSantosh Shilimkar 	{ 2, TWL4030_BASEADD_PRECHARGE },
205b07682b6SSantosh Shilimkar 	{ 2, TWL4030_BASEADD_PWM0 },
206b07682b6SSantosh Shilimkar 	{ 2, TWL4030_BASEADD_PWM1 },
207b07682b6SSantosh Shilimkar 	{ 2, TWL4030_BASEADD_PWMA },
208b07682b6SSantosh Shilimkar 	{ 2, TWL4030_BASEADD_PWMB },
209b07682b6SSantosh Shilimkar 	{ 2, TWL5031_BASEADD_ACCESSORY },
210b07682b6SSantosh Shilimkar 	{ 2, TWL5031_BASEADD_INTERRUPTS },
211b07682b6SSantosh Shilimkar 
212b07682b6SSantosh Shilimkar 	{ 3, TWL4030_BASEADD_BACKUP },
213b07682b6SSantosh Shilimkar 	{ 3, TWL4030_BASEADD_INT },
214b07682b6SSantosh Shilimkar 	{ 3, TWL4030_BASEADD_PM_MASTER },
215b07682b6SSantosh Shilimkar 	{ 3, TWL4030_BASEADD_PM_RECEIVER },
216b07682b6SSantosh Shilimkar 	{ 3, TWL4030_BASEADD_RTC },
217b07682b6SSantosh Shilimkar 	{ 3, TWL4030_BASEADD_SECURED_REG },
218b07682b6SSantosh Shilimkar };
219b07682b6SSantosh Shilimkar 
2202473d25aSPeter Ujfalusi static struct regmap_config twl4030_regmap_config[4] = {
2212473d25aSPeter Ujfalusi 	{
2222473d25aSPeter Ujfalusi 		/* Address 0x48 */
2232473d25aSPeter Ujfalusi 		.reg_bits = 8,
2242473d25aSPeter Ujfalusi 		.val_bits = 8,
2252473d25aSPeter Ujfalusi 		.max_register = 0xff,
2262473d25aSPeter Ujfalusi 	},
2272473d25aSPeter Ujfalusi 	{
2282473d25aSPeter Ujfalusi 		/* Address 0x49 */
2292473d25aSPeter Ujfalusi 		.reg_bits = 8,
2302473d25aSPeter Ujfalusi 		.val_bits = 8,
2312473d25aSPeter Ujfalusi 		.max_register = 0xff,
2322473d25aSPeter Ujfalusi 	},
2332473d25aSPeter Ujfalusi 	{
2342473d25aSPeter Ujfalusi 		/* Address 0x4a */
2352473d25aSPeter Ujfalusi 		.reg_bits = 8,
2362473d25aSPeter Ujfalusi 		.val_bits = 8,
2372473d25aSPeter Ujfalusi 		.max_register = 0xff,
2382473d25aSPeter Ujfalusi 	},
2392473d25aSPeter Ujfalusi 	{
2402473d25aSPeter Ujfalusi 		/* Address 0x4b */
2412473d25aSPeter Ujfalusi 		.reg_bits = 8,
2422473d25aSPeter Ujfalusi 		.val_bits = 8,
2432473d25aSPeter Ujfalusi 		.max_register = 0xff,
2442473d25aSPeter Ujfalusi 	},
2452473d25aSPeter Ujfalusi };
2462473d25aSPeter Ujfalusi 
247e8deb28cSBalaji T K static struct twl_mapping twl6030_map[] = {
248e8deb28cSBalaji T K 	/*
249e8deb28cSBalaji T K 	 * NOTE:  don't change this table without updating the
250e8deb28cSBalaji T K 	 * <linux/i2c/twl.h> defines for TWL4030_MODULE_*
251e8deb28cSBalaji T K 	 * so they continue to match the order in this table.
252e8deb28cSBalaji T K 	 */
253e8deb28cSBalaji T K 	{ SUB_CHIP_ID1, TWL6030_BASEADD_USB },
254364cedb2SPeter Ujfalusi 	{ SUB_CHIP_ID_INVAL, TWL6030_BASEADD_AUDIO },
255e8deb28cSBalaji T K 	{ SUB_CHIP_ID2, TWL6030_BASEADD_DIEID },
256e8deb28cSBalaji T K 	{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
257e8deb28cSBalaji T K 	{ SUB_CHIP_ID1, TWL6030_BASEADD_PIH },
258e8deb28cSBalaji T K 
259e8deb28cSBalaji T K 	{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
260e8deb28cSBalaji T K 	{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
261e8deb28cSBalaji T K 	{ SUB_CHIP_ID1, TWL6030_BASEADD_GPADC_CTRL },
262e8deb28cSBalaji T K 	{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
263e8deb28cSBalaji T K 	{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
264e8deb28cSBalaji T K 
265e8deb28cSBalaji T K 	{ SUB_CHIP_ID1, TWL6030_BASEADD_CHARGER },
266e8deb28cSBalaji T K 	{ SUB_CHIP_ID1, TWL6030_BASEADD_GASGAUGE },
267e8deb28cSBalaji T K 	{ SUB_CHIP_ID1, TWL6030_BASEADD_PWM },
268fa0d9762SBalaji T K 	{ SUB_CHIP_ID0, TWL6030_BASEADD_ZERO },
269fa0d9762SBalaji T K 	{ SUB_CHIP_ID1, TWL6030_BASEADD_ZERO },
270e8deb28cSBalaji T K 
271fa0d9762SBalaji T K 	{ SUB_CHIP_ID2, TWL6030_BASEADD_ZERO },
272fa0d9762SBalaji T K 	{ SUB_CHIP_ID2, TWL6030_BASEADD_ZERO },
273e8deb28cSBalaji T K 	{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
274e8deb28cSBalaji T K 	{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
275e8deb28cSBalaji T K 	{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
276e8deb28cSBalaji T K 	{ SUB_CHIP_ID0, TWL6030_BASEADD_PM_MASTER },
277e8deb28cSBalaji T K 	{ SUB_CHIP_ID0, TWL6030_BASEADD_PM_SLAVE_MISC },
278e8deb28cSBalaji T K 
279e8deb28cSBalaji T K 	{ SUB_CHIP_ID0, TWL6030_BASEADD_RTC },
280e8deb28cSBalaji T K 	{ SUB_CHIP_ID0, TWL6030_BASEADD_MEM },
281521d8ec3SGraeme Gregory 	{ SUB_CHIP_ID1, TWL6025_BASEADD_CHARGER },
282e8deb28cSBalaji T K };
283e8deb28cSBalaji T K 
2842473d25aSPeter Ujfalusi static struct regmap_config twl6030_regmap_config[3] = {
2852473d25aSPeter Ujfalusi 	{
2862473d25aSPeter Ujfalusi 		/* Address 0x48 */
2872473d25aSPeter Ujfalusi 		.reg_bits = 8,
2882473d25aSPeter Ujfalusi 		.val_bits = 8,
2892473d25aSPeter Ujfalusi 		.max_register = 0xff,
2902473d25aSPeter Ujfalusi 	},
2912473d25aSPeter Ujfalusi 	{
2922473d25aSPeter Ujfalusi 		/* Address 0x49 */
2932473d25aSPeter Ujfalusi 		.reg_bits = 8,
2942473d25aSPeter Ujfalusi 		.val_bits = 8,
2952473d25aSPeter Ujfalusi 		.max_register = 0xff,
2962473d25aSPeter Ujfalusi 	},
2972473d25aSPeter Ujfalusi 	{
2982473d25aSPeter Ujfalusi 		/* Address 0x4a */
2992473d25aSPeter Ujfalusi 		.reg_bits = 8,
3002473d25aSPeter Ujfalusi 		.val_bits = 8,
3012473d25aSPeter Ujfalusi 		.max_register = 0xff,
3022473d25aSPeter Ujfalusi 	},
3032473d25aSPeter Ujfalusi };
3042473d25aSPeter Ujfalusi 
305b07682b6SSantosh Shilimkar /*----------------------------------------------------------------------*/
306b07682b6SSantosh Shilimkar 
307b07682b6SSantosh Shilimkar /* Exported Functions */
308b07682b6SSantosh Shilimkar 
309b07682b6SSantosh Shilimkar /**
310fc7b92fcSBalaji T K  * twl_i2c_write - Writes a n bit register in TWL4030/TWL5030/TWL60X0
311b07682b6SSantosh Shilimkar  * @mod_no: module number
312b07682b6SSantosh Shilimkar  * @value: an array of num_bytes+1 containing data to write
313b07682b6SSantosh Shilimkar  * @reg: register address (just offset will do)
314b07682b6SSantosh Shilimkar  * @num_bytes: number of bytes to transfer
315b07682b6SSantosh Shilimkar  *
316b07682b6SSantosh Shilimkar  * IMPORTANT: for 'value' parameter: Allocate value num_bytes+1 and
317b07682b6SSantosh Shilimkar  * valid data starts at Offset 1.
318b07682b6SSantosh Shilimkar  *
319b07682b6SSantosh Shilimkar  * Returns the result of operation - 0 is success
320b07682b6SSantosh Shilimkar  */
321fc7b92fcSBalaji T K int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
322b07682b6SSantosh Shilimkar {
323b07682b6SSantosh Shilimkar 	int ret;
324b07682b6SSantosh Shilimkar 	int sid;
325fc7b92fcSBalaji T K 	struct twl_client *twl;
326b07682b6SSantosh Shilimkar 
327da059ecfSPeter Ujfalusi 	if (unlikely(mod_no >= TWL_MODULE_LAST)) {
328b07682b6SSantosh Shilimkar 		pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
329b07682b6SSantosh Shilimkar 		return -EPERM;
330b07682b6SSantosh Shilimkar 	}
3318653be1aSIlya Yanok 	if (unlikely(!inuse)) {
3328653be1aSIlya Yanok 		pr_err("%s: not initialized\n", DRIVER_NAME);
3338653be1aSIlya Yanok 		return -EPERM;
3348653be1aSIlya Yanok 	}
335e8deb28cSBalaji T K 	sid = twl_map[mod_no].sid;
336364cedb2SPeter Ujfalusi 	if (unlikely(sid == SUB_CHIP_ID_INVAL)) {
337364cedb2SPeter Ujfalusi 		pr_err("%s: module %d is not part of the pmic\n",
338364cedb2SPeter Ujfalusi 		       DRIVER_NAME, mod_no);
339364cedb2SPeter Ujfalusi 		return -EINVAL;
340364cedb2SPeter Ujfalusi 	}
341fc7b92fcSBalaji T K 	twl = &twl_modules[sid];
342b07682b6SSantosh Shilimkar 
3432473d25aSPeter Ujfalusi 	ret = regmap_bulk_write(twl->regmap, twl_map[mod_no].base + reg,
34414591d88SPeter Ujfalusi 				value, num_bytes);
345b07682b6SSantosh Shilimkar 
3462473d25aSPeter Ujfalusi 	if (ret)
3472473d25aSPeter Ujfalusi 		pr_err("%s: Write failed (mod %d, reg 0x%02x count %d)\n",
3482473d25aSPeter Ujfalusi 		       DRIVER_NAME, mod_no, reg, num_bytes);
3492473d25aSPeter Ujfalusi 
350b07682b6SSantosh Shilimkar 	return ret;
351b07682b6SSantosh Shilimkar }
352fc7b92fcSBalaji T K EXPORT_SYMBOL(twl_i2c_write);
353b07682b6SSantosh Shilimkar 
354b07682b6SSantosh Shilimkar /**
355fc7b92fcSBalaji T K  * twl_i2c_read - Reads a n bit register in TWL4030/TWL5030/TWL60X0
356b07682b6SSantosh Shilimkar  * @mod_no: module number
357b07682b6SSantosh Shilimkar  * @value: an array of num_bytes containing data to be read
358b07682b6SSantosh Shilimkar  * @reg: register address (just offset will do)
359b07682b6SSantosh Shilimkar  * @num_bytes: number of bytes to transfer
360b07682b6SSantosh Shilimkar  *
361b07682b6SSantosh Shilimkar  * Returns result of operation - num_bytes is success else failure.
362b07682b6SSantosh Shilimkar  */
363fc7b92fcSBalaji T K int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
364b07682b6SSantosh Shilimkar {
365b07682b6SSantosh Shilimkar 	int ret;
366b07682b6SSantosh Shilimkar 	int sid;
367fc7b92fcSBalaji T K 	struct twl_client *twl;
368b07682b6SSantosh Shilimkar 
369da059ecfSPeter Ujfalusi 	if (unlikely(mod_no >= TWL_MODULE_LAST)) {
370b07682b6SSantosh Shilimkar 		pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
371b07682b6SSantosh Shilimkar 		return -EPERM;
372b07682b6SSantosh Shilimkar 	}
3738653be1aSIlya Yanok 	if (unlikely(!inuse)) {
3748653be1aSIlya Yanok 		pr_err("%s: not initialized\n", DRIVER_NAME);
3758653be1aSIlya Yanok 		return -EPERM;
3768653be1aSIlya Yanok 	}
377e8deb28cSBalaji T K 	sid = twl_map[mod_no].sid;
378364cedb2SPeter Ujfalusi 	if (unlikely(sid == SUB_CHIP_ID_INVAL)) {
379364cedb2SPeter Ujfalusi 		pr_err("%s: module %d is not part of the pmic\n",
380364cedb2SPeter Ujfalusi 		       DRIVER_NAME, mod_no);
381364cedb2SPeter Ujfalusi 		return -EINVAL;
382364cedb2SPeter Ujfalusi 	}
383fc7b92fcSBalaji T K 	twl = &twl_modules[sid];
384b07682b6SSantosh Shilimkar 
3852473d25aSPeter Ujfalusi 	ret = regmap_bulk_read(twl->regmap, twl_map[mod_no].base + reg,
3862473d25aSPeter Ujfalusi 			       value, num_bytes);
387b07682b6SSantosh Shilimkar 
3882473d25aSPeter Ujfalusi 	if (ret)
3892473d25aSPeter Ujfalusi 		pr_err("%s: Read failed (mod %d, reg 0x%02x count %d)\n",
3902473d25aSPeter Ujfalusi 		       DRIVER_NAME, mod_no, reg, num_bytes);
3912473d25aSPeter Ujfalusi 
392b07682b6SSantosh Shilimkar 	return ret;
393b07682b6SSantosh Shilimkar }
394fc7b92fcSBalaji T K EXPORT_SYMBOL(twl_i2c_read);
395b07682b6SSantosh Shilimkar 
396b07682b6SSantosh Shilimkar /**
397fc7b92fcSBalaji T K  * twl_i2c_write_u8 - Writes a 8 bit register in TWL4030/TWL5030/TWL60X0
398b07682b6SSantosh Shilimkar  * @mod_no: module number
399b07682b6SSantosh Shilimkar  * @value: the value to be written 8 bit
400b07682b6SSantosh Shilimkar  * @reg: register address (just offset will do)
401b07682b6SSantosh Shilimkar  *
402b07682b6SSantosh Shilimkar  * Returns result of operation - 0 is success
403b07682b6SSantosh Shilimkar  */
404fc7b92fcSBalaji T K int twl_i2c_write_u8(u8 mod_no, u8 value, u8 reg)
405b07682b6SSantosh Shilimkar {
40614591d88SPeter Ujfalusi 	return twl_i2c_write(mod_no, &value, reg, 1);
407b07682b6SSantosh Shilimkar }
408fc7b92fcSBalaji T K EXPORT_SYMBOL(twl_i2c_write_u8);
409b07682b6SSantosh Shilimkar 
410b07682b6SSantosh Shilimkar /**
411fc7b92fcSBalaji T K  * twl_i2c_read_u8 - Reads a 8 bit register from TWL4030/TWL5030/TWL60X0
412b07682b6SSantosh Shilimkar  * @mod_no: module number
413b07682b6SSantosh Shilimkar  * @value: the value read 8 bit
414b07682b6SSantosh Shilimkar  * @reg: register address (just offset will do)
415b07682b6SSantosh Shilimkar  *
416b07682b6SSantosh Shilimkar  * Returns result of operation - 0 is success
417b07682b6SSantosh Shilimkar  */
418fc7b92fcSBalaji T K int twl_i2c_read_u8(u8 mod_no, u8 *value, u8 reg)
419b07682b6SSantosh Shilimkar {
420fc7b92fcSBalaji T K 	return twl_i2c_read(mod_no, value, reg, 1);
421b07682b6SSantosh Shilimkar }
422fc7b92fcSBalaji T K EXPORT_SYMBOL(twl_i2c_read_u8);
423b07682b6SSantosh Shilimkar 
424b07682b6SSantosh Shilimkar /*----------------------------------------------------------------------*/
425b07682b6SSantosh Shilimkar 
426ca972d13SLesly A M /**
427ca972d13SLesly A M  * twl_read_idcode_register - API to read the IDCODE register.
428ca972d13SLesly A M  *
429ca972d13SLesly A M  * Unlocks the IDCODE register and read the 32 bit value.
430ca972d13SLesly A M  */
431ca972d13SLesly A M static int twl_read_idcode_register(void)
432ca972d13SLesly A M {
433ca972d13SLesly A M 	int err;
434ca972d13SLesly A M 
435ca972d13SLesly A M 	err = twl_i2c_write_u8(TWL4030_MODULE_INTBR, TWL_EEPROM_R_UNLOCK,
436ca972d13SLesly A M 						REG_UNLOCK_TEST_REG);
437ca972d13SLesly A M 	if (err) {
438ca972d13SLesly A M 		pr_err("TWL4030 Unable to unlock IDCODE registers -%d\n", err);
439ca972d13SLesly A M 		goto fail;
440ca972d13SLesly A M 	}
441ca972d13SLesly A M 
442ca972d13SLesly A M 	err = twl_i2c_read(TWL4030_MODULE_INTBR, (u8 *)(&twl_idcode),
443ca972d13SLesly A M 						REG_IDCODE_7_0, 4);
444ca972d13SLesly A M 	if (err) {
445ca972d13SLesly A M 		pr_err("TWL4030: unable to read IDCODE -%d\n", err);
446ca972d13SLesly A M 		goto fail;
447ca972d13SLesly A M 	}
448ca972d13SLesly A M 
449ca972d13SLesly A M 	err = twl_i2c_write_u8(TWL4030_MODULE_INTBR, 0x0, REG_UNLOCK_TEST_REG);
450ca972d13SLesly A M 	if (err)
451ca972d13SLesly A M 		pr_err("TWL4030 Unable to relock IDCODE registers -%d\n", err);
452ca972d13SLesly A M fail:
453ca972d13SLesly A M 	return err;
454ca972d13SLesly A M }
455ca972d13SLesly A M 
456ca972d13SLesly A M /**
457ca972d13SLesly A M  * twl_get_type - API to get TWL Si type.
458ca972d13SLesly A M  *
459ca972d13SLesly A M  * Api to get the TWL Si type from IDCODE value.
460ca972d13SLesly A M  */
461ca972d13SLesly A M int twl_get_type(void)
462ca972d13SLesly A M {
463ca972d13SLesly A M 	return TWL_SIL_TYPE(twl_idcode);
464ca972d13SLesly A M }
465ca972d13SLesly A M EXPORT_SYMBOL_GPL(twl_get_type);
466ca972d13SLesly A M 
467ca972d13SLesly A M /**
468ca972d13SLesly A M  * twl_get_version - API to get TWL Si version.
469ca972d13SLesly A M  *
470ca972d13SLesly A M  * Api to get the TWL Si version from IDCODE value.
471ca972d13SLesly A M  */
472ca972d13SLesly A M int twl_get_version(void)
473ca972d13SLesly A M {
474ca972d13SLesly A M 	return TWL_SIL_REV(twl_idcode);
475ca972d13SLesly A M }
476ca972d13SLesly A M EXPORT_SYMBOL_GPL(twl_get_version);
477ca972d13SLesly A M 
4782275c544SPeter Ujfalusi /**
4792275c544SPeter Ujfalusi  * twl_get_hfclk_rate - API to get TWL external HFCLK clock rate.
4802275c544SPeter Ujfalusi  *
4812275c544SPeter Ujfalusi  * Api to get the TWL HFCLK rate based on BOOT_CFG register.
4822275c544SPeter Ujfalusi  */
4832275c544SPeter Ujfalusi int twl_get_hfclk_rate(void)
4842275c544SPeter Ujfalusi {
4852275c544SPeter Ujfalusi 	u8 ctrl;
4862275c544SPeter Ujfalusi 	int rate;
4872275c544SPeter Ujfalusi 
4882275c544SPeter Ujfalusi 	twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &ctrl, R_CFG_BOOT);
4892275c544SPeter Ujfalusi 
4902275c544SPeter Ujfalusi 	switch (ctrl & 0x3) {
4912275c544SPeter Ujfalusi 	case HFCLK_FREQ_19p2_MHZ:
4922275c544SPeter Ujfalusi 		rate = 19200000;
4932275c544SPeter Ujfalusi 		break;
4942275c544SPeter Ujfalusi 	case HFCLK_FREQ_26_MHZ:
4952275c544SPeter Ujfalusi 		rate = 26000000;
4962275c544SPeter Ujfalusi 		break;
4972275c544SPeter Ujfalusi 	case HFCLK_FREQ_38p4_MHZ:
4982275c544SPeter Ujfalusi 		rate = 38400000;
4992275c544SPeter Ujfalusi 		break;
5002275c544SPeter Ujfalusi 	default:
5012275c544SPeter Ujfalusi 		pr_err("TWL4030: HFCLK is not configured\n");
5022275c544SPeter Ujfalusi 		rate = -EINVAL;
5032275c544SPeter Ujfalusi 		break;
5042275c544SPeter Ujfalusi 	}
5052275c544SPeter Ujfalusi 
5062275c544SPeter Ujfalusi 	return rate;
5072275c544SPeter Ujfalusi }
5082275c544SPeter Ujfalusi EXPORT_SYMBOL_GPL(twl_get_hfclk_rate);
5092275c544SPeter Ujfalusi 
510b07682b6SSantosh Shilimkar static struct device *
511b07682b6SSantosh Shilimkar add_numbered_child(unsigned chip, const char *name, int num,
512b07682b6SSantosh Shilimkar 		void *pdata, unsigned pdata_len,
513b07682b6SSantosh Shilimkar 		bool can_wakeup, int irq0, int irq1)
514b07682b6SSantosh Shilimkar {
515b07682b6SSantosh Shilimkar 	struct platform_device	*pdev;
516fc7b92fcSBalaji T K 	struct twl_client	*twl = &twl_modules[chip];
517b07682b6SSantosh Shilimkar 	int			status;
518b07682b6SSantosh Shilimkar 
519b07682b6SSantosh Shilimkar 	pdev = platform_device_alloc(name, num);
520b07682b6SSantosh Shilimkar 	if (!pdev) {
521b07682b6SSantosh Shilimkar 		dev_dbg(&twl->client->dev, "can't alloc dev\n");
522b07682b6SSantosh Shilimkar 		status = -ENOMEM;
523b07682b6SSantosh Shilimkar 		goto err;
524b07682b6SSantosh Shilimkar 	}
525b07682b6SSantosh Shilimkar 
526b07682b6SSantosh Shilimkar 	pdev->dev.parent = &twl->client->dev;
527b07682b6SSantosh Shilimkar 
528b07682b6SSantosh Shilimkar 	if (pdata) {
529b07682b6SSantosh Shilimkar 		status = platform_device_add_data(pdev, pdata, pdata_len);
530b07682b6SSantosh Shilimkar 		if (status < 0) {
531b07682b6SSantosh Shilimkar 			dev_dbg(&pdev->dev, "can't add platform_data\n");
532b07682b6SSantosh Shilimkar 			goto err;
533b07682b6SSantosh Shilimkar 		}
534b07682b6SSantosh Shilimkar 	}
535b07682b6SSantosh Shilimkar 
536b07682b6SSantosh Shilimkar 	if (irq0) {
537b07682b6SSantosh Shilimkar 		struct resource r[2] = {
538b07682b6SSantosh Shilimkar 			{ .start = irq0, .flags = IORESOURCE_IRQ, },
539b07682b6SSantosh Shilimkar 			{ .start = irq1, .flags = IORESOURCE_IRQ, },
540b07682b6SSantosh Shilimkar 		};
541b07682b6SSantosh Shilimkar 
542b07682b6SSantosh Shilimkar 		status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1);
543b07682b6SSantosh Shilimkar 		if (status < 0) {
544b07682b6SSantosh Shilimkar 			dev_dbg(&pdev->dev, "can't add irqs\n");
545b07682b6SSantosh Shilimkar 			goto err;
546b07682b6SSantosh Shilimkar 		}
547b07682b6SSantosh Shilimkar 	}
548b07682b6SSantosh Shilimkar 
549b07682b6SSantosh Shilimkar 	status = platform_device_add(pdev);
55017ffba6aSNeilBrown 	if (status == 0)
55117ffba6aSNeilBrown 		device_init_wakeup(&pdev->dev, can_wakeup);
552b07682b6SSantosh Shilimkar 
553b07682b6SSantosh Shilimkar err:
554b07682b6SSantosh Shilimkar 	if (status < 0) {
555b07682b6SSantosh Shilimkar 		platform_device_put(pdev);
556b07682b6SSantosh Shilimkar 		dev_err(&twl->client->dev, "can't add %s dev\n", name);
557b07682b6SSantosh Shilimkar 		return ERR_PTR(status);
558b07682b6SSantosh Shilimkar 	}
559b07682b6SSantosh Shilimkar 	return &pdev->dev;
560b07682b6SSantosh Shilimkar }
561b07682b6SSantosh Shilimkar 
562b07682b6SSantosh Shilimkar static inline struct device *add_child(unsigned chip, const char *name,
563b07682b6SSantosh Shilimkar 		void *pdata, unsigned pdata_len,
564b07682b6SSantosh Shilimkar 		bool can_wakeup, int irq0, int irq1)
565b07682b6SSantosh Shilimkar {
566b07682b6SSantosh Shilimkar 	return add_numbered_child(chip, name, -1, pdata, pdata_len,
567b07682b6SSantosh Shilimkar 		can_wakeup, irq0, irq1);
568b07682b6SSantosh Shilimkar }
569b07682b6SSantosh Shilimkar 
570b07682b6SSantosh Shilimkar static struct device *
571b07682b6SSantosh Shilimkar add_regulator_linked(int num, struct regulator_init_data *pdata,
572b07682b6SSantosh Shilimkar 		struct regulator_consumer_supply *consumers,
573521d8ec3SGraeme Gregory 		unsigned num_consumers, unsigned long features)
574b07682b6SSantosh Shilimkar {
575e8deb28cSBalaji T K 	unsigned sub_chip_id;
57663bfff4eSTero Kristo 	struct twl_regulator_driver_data drv_data;
57763bfff4eSTero Kristo 
578b07682b6SSantosh Shilimkar 	/* regulator framework demands init_data ... */
579b07682b6SSantosh Shilimkar 	if (!pdata)
580b07682b6SSantosh Shilimkar 		return NULL;
581b07682b6SSantosh Shilimkar 
582b07682b6SSantosh Shilimkar 	if (consumers) {
583b07682b6SSantosh Shilimkar 		pdata->consumer_supplies = consumers;
584b07682b6SSantosh Shilimkar 		pdata->num_consumer_supplies = num_consumers;
585b07682b6SSantosh Shilimkar 	}
586b07682b6SSantosh Shilimkar 
58763bfff4eSTero Kristo 	if (pdata->driver_data) {
58863bfff4eSTero Kristo 		/* If we have existing drv_data, just add the flags */
58963bfff4eSTero Kristo 		struct twl_regulator_driver_data *tmp;
59063bfff4eSTero Kristo 		tmp = pdata->driver_data;
59163bfff4eSTero Kristo 		tmp->features |= features;
59263bfff4eSTero Kristo 	} else {
59363bfff4eSTero Kristo 		/* add new driver data struct, used only during init */
59463bfff4eSTero Kristo 		drv_data.features = features;
59563bfff4eSTero Kristo 		drv_data.set_voltage = NULL;
59663bfff4eSTero Kristo 		drv_data.get_voltage = NULL;
59763bfff4eSTero Kristo 		drv_data.data = NULL;
59863bfff4eSTero Kristo 		pdata->driver_data = &drv_data;
59963bfff4eSTero Kristo 	}
600521d8ec3SGraeme Gregory 
601b07682b6SSantosh Shilimkar 	/* NOTE:  we currently ignore regulator IRQs, e.g. for short circuits */
602e8deb28cSBalaji T K 	sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid;
603e8deb28cSBalaji T K 	return add_numbered_child(sub_chip_id, "twl_reg", num,
604b07682b6SSantosh Shilimkar 		pdata, sizeof(*pdata), false, 0, 0);
605b07682b6SSantosh Shilimkar }
606b07682b6SSantosh Shilimkar 
607b07682b6SSantosh Shilimkar static struct device *
608521d8ec3SGraeme Gregory add_regulator(int num, struct regulator_init_data *pdata,
609521d8ec3SGraeme Gregory 		unsigned long features)
610b07682b6SSantosh Shilimkar {
611521d8ec3SGraeme Gregory 	return add_regulator_linked(num, pdata, NULL, 0, features);
612b07682b6SSantosh Shilimkar }
613b07682b6SSantosh Shilimkar 
614b07682b6SSantosh Shilimkar /*
615b07682b6SSantosh Shilimkar  * NOTE:  We know the first 8 IRQs after pdata->base_irq are
616b07682b6SSantosh Shilimkar  * for the PIH, and the next are for the PWR_INT SIH, since
617b07682b6SSantosh Shilimkar  * that's how twl_init_irq() sets things up.
618b07682b6SSantosh Shilimkar  */
619b07682b6SSantosh Shilimkar 
620b07682b6SSantosh Shilimkar static int
6219e178620SFelipe Balbi add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
6229e178620SFelipe Balbi 		unsigned long features)
623b07682b6SSantosh Shilimkar {
624b07682b6SSantosh Shilimkar 	struct device	*child;
625e8deb28cSBalaji T K 	unsigned sub_chip_id;
626b07682b6SSantosh Shilimkar 
627f78959cfSThierry Reding 	if (IS_ENABLED(CONFIG_GPIO_TWL4030) && pdata->gpio) {
628fc7b92fcSBalaji T K 		child = add_child(SUB_CHIP_ID1, "twl4030_gpio",
629b07682b6SSantosh Shilimkar 				pdata->gpio, sizeof(*pdata->gpio),
6309e178620SFelipe Balbi 				false, irq_base + GPIO_INTR_OFFSET, 0);
631b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
632b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
633b07682b6SSantosh Shilimkar 	}
634b07682b6SSantosh Shilimkar 
635f78959cfSThierry Reding 	if (IS_ENABLED(CONFIG_KEYBOARD_TWL4030) && pdata->keypad) {
636fc7b92fcSBalaji T K 		child = add_child(SUB_CHIP_ID2, "twl4030_keypad",
637b07682b6SSantosh Shilimkar 				pdata->keypad, sizeof(*pdata->keypad),
6389e178620SFelipe Balbi 				true, irq_base + KEYPAD_INTR_OFFSET, 0);
639b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
640b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
641b07682b6SSantosh Shilimkar 	}
642b07682b6SSantosh Shilimkar 
64324ae36f5SPeter Ujfalusi 	if (IS_ENABLED(CONFIG_TWL4030_MADC) && pdata->madc &&
64424ae36f5SPeter Ujfalusi 	    twl_class_is_4030()) {
6452d86ad37SPeter Ujfalusi 		child = add_child(SUB_CHIP_ID2, "twl4030_madc",
646b07682b6SSantosh Shilimkar 				pdata->madc, sizeof(*pdata->madc),
6479e178620SFelipe Balbi 				true, irq_base + MADC_INTR_OFFSET, 0);
648b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
649b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
650b07682b6SSantosh Shilimkar 	}
651b07682b6SSantosh Shilimkar 
652f78959cfSThierry Reding 	if (IS_ENABLED(CONFIG_RTC_DRV_TWL4030)) {
653b07682b6SSantosh Shilimkar 		/*
654b07682b6SSantosh Shilimkar 		 * REVISIT platform_data here currently might expose the
655b07682b6SSantosh Shilimkar 		 * "msecure" line ... but for now we just expect board
656b07682b6SSantosh Shilimkar 		 * setup to tell the chip "it's always ok to SET_TIME".
657b07682b6SSantosh Shilimkar 		 * Eventually, Linux might become more aware of such
658b07682b6SSantosh Shilimkar 		 * HW security concerns, and "least privilege".
659b07682b6SSantosh Shilimkar 		 */
660e8deb28cSBalaji T K 		sub_chip_id = twl_map[TWL_MODULE_RTC].sid;
6612d86ad37SPeter Ujfalusi 		child = add_child(sub_chip_id, "twl_rtc", NULL, 0,
6629e178620SFelipe Balbi 				true, irq_base + RTC_INTR_OFFSET, 0);
663b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
664b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
665b07682b6SSantosh Shilimkar 	}
666b07682b6SSantosh Shilimkar 
667afc45898SPeter Ujfalusi 	if (IS_ENABLED(CONFIG_PWM_TWL)) {
668afc45898SPeter Ujfalusi 		child = add_child(SUB_CHIP_ID1, "twl-pwm", NULL, 0,
669afc45898SPeter Ujfalusi 				  false, 0, 0);
670afc45898SPeter Ujfalusi 		if (IS_ERR(child))
671afc45898SPeter Ujfalusi 			return PTR_ERR(child);
672afc45898SPeter Ujfalusi 	}
673afc45898SPeter Ujfalusi 
674afc45898SPeter Ujfalusi 	if (IS_ENABLED(CONFIG_PWM_TWL_LED)) {
675afc45898SPeter Ujfalusi 		child = add_child(SUB_CHIP_ID1, "twl-pwmled", NULL, 0,
67648a364b7SThierry Reding 				  false, 0, 0);
67748a364b7SThierry Reding 		if (IS_ERR(child))
67848a364b7SThierry Reding 			return PTR_ERR(child);
67948a364b7SThierry Reding 	}
68048a364b7SThierry Reding 
681f78959cfSThierry Reding 	if (IS_ENABLED(CONFIG_TWL4030_USB) && pdata->usb &&
682f78959cfSThierry Reding 	    twl_class_is_4030()) {
683b07682b6SSantosh Shilimkar 
684b07682b6SSantosh Shilimkar 		static struct regulator_consumer_supply usb1v5 = {
685b07682b6SSantosh Shilimkar 			.supply =	"usb1v5",
686b07682b6SSantosh Shilimkar 		};
687b07682b6SSantosh Shilimkar 		static struct regulator_consumer_supply usb1v8 = {
688b07682b6SSantosh Shilimkar 			.supply =	"usb1v8",
689b07682b6SSantosh Shilimkar 		};
690ab37813fSNeilBrown 		static struct regulator_consumer_supply usb3v1[] = {
691ab37813fSNeilBrown 			{ .supply =	"usb3v1" },
692ab37813fSNeilBrown 			{ .supply =	"bci3v1" },
693b07682b6SSantosh Shilimkar 		};
694b07682b6SSantosh Shilimkar 
695b07682b6SSantosh Shilimkar 	/* First add the regulators so that they can be used by transceiver */
696f78959cfSThierry Reding 		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030)) {
697b07682b6SSantosh Shilimkar 			/* this is a template that gets copied */
698b07682b6SSantosh Shilimkar 			struct regulator_init_data usb_fixed = {
699b07682b6SSantosh Shilimkar 				.constraints.valid_modes_mask =
700b07682b6SSantosh Shilimkar 					REGULATOR_MODE_NORMAL
701b07682b6SSantosh Shilimkar 					| REGULATOR_MODE_STANDBY,
702b07682b6SSantosh Shilimkar 				.constraints.valid_ops_mask =
703b07682b6SSantosh Shilimkar 					REGULATOR_CHANGE_MODE
704b07682b6SSantosh Shilimkar 					| REGULATOR_CHANGE_STATUS,
705b07682b6SSantosh Shilimkar 			};
706b07682b6SSantosh Shilimkar 
707b07682b6SSantosh Shilimkar 			child = add_regulator_linked(TWL4030_REG_VUSB1V5,
708521d8ec3SGraeme Gregory 						      &usb_fixed, &usb1v5, 1,
709521d8ec3SGraeme Gregory 						      features);
710b07682b6SSantosh Shilimkar 			if (IS_ERR(child))
711b07682b6SSantosh Shilimkar 				return PTR_ERR(child);
712b07682b6SSantosh Shilimkar 
713b07682b6SSantosh Shilimkar 			child = add_regulator_linked(TWL4030_REG_VUSB1V8,
714521d8ec3SGraeme Gregory 						      &usb_fixed, &usb1v8, 1,
715521d8ec3SGraeme Gregory 						      features);
716b07682b6SSantosh Shilimkar 			if (IS_ERR(child))
717b07682b6SSantosh Shilimkar 				return PTR_ERR(child);
718b07682b6SSantosh Shilimkar 
719b07682b6SSantosh Shilimkar 			child = add_regulator_linked(TWL4030_REG_VUSB3V1,
720ab37813fSNeilBrown 						      &usb_fixed, usb3v1, 2,
721521d8ec3SGraeme Gregory 						      features);
722b07682b6SSantosh Shilimkar 			if (IS_ERR(child))
723b07682b6SSantosh Shilimkar 				return PTR_ERR(child);
724b07682b6SSantosh Shilimkar 
725b07682b6SSantosh Shilimkar 		}
726b07682b6SSantosh Shilimkar 
7272d86ad37SPeter Ujfalusi 		child = add_child(SUB_CHIP_ID0, "twl4030_usb",
7282d86ad37SPeter Ujfalusi 				pdata->usb, sizeof(*pdata->usb), true,
729b07682b6SSantosh Shilimkar 				/* irq0 = USB_PRES, irq1 = USB */
7309e178620SFelipe Balbi 				irq_base + USB_PRES_INTR_OFFSET,
7319e178620SFelipe Balbi 				irq_base + USB_INTR_OFFSET);
732b07682b6SSantosh Shilimkar 
733b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
734b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
735b07682b6SSantosh Shilimkar 
736b07682b6SSantosh Shilimkar 		/* we need to connect regulators to this transceiver */
737f78959cfSThierry Reding 		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child) {
7381b65fa84SMark Brown 			usb1v5.dev_name = dev_name(child);
7391b65fa84SMark Brown 			usb1v8.dev_name = dev_name(child);
740ab37813fSNeilBrown 			usb3v1[0].dev_name = dev_name(child);
741b07682b6SSantosh Shilimkar 		}
742b07682b6SSantosh Shilimkar 	}
743f78959cfSThierry Reding 	if (IS_ENABLED(CONFIG_TWL6030_USB) && pdata->usb &&
744f78959cfSThierry Reding 	    twl_class_is_6030()) {
745e70357e3SHema HK 
746521d8ec3SGraeme Gregory 		static struct regulator_consumer_supply usb3v3;
747521d8ec3SGraeme Gregory 		int regulator;
748e70357e3SHema HK 
749f78959cfSThierry Reding 		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030)) {
750e70357e3SHema HK 			/* this is a template that gets copied */
751e70357e3SHema HK 			struct regulator_init_data usb_fixed = {
752e70357e3SHema HK 				.constraints.valid_modes_mask =
753e70357e3SHema HK 					REGULATOR_MODE_NORMAL
754e70357e3SHema HK 					| REGULATOR_MODE_STANDBY,
755e70357e3SHema HK 				.constraints.valid_ops_mask =
756e70357e3SHema HK 					REGULATOR_CHANGE_MODE
757e70357e3SHema HK 					| REGULATOR_CHANGE_STATUS,
758e70357e3SHema HK 			};
759e70357e3SHema HK 
760521d8ec3SGraeme Gregory 			if (features & TWL6025_SUBCLASS) {
761521d8ec3SGraeme Gregory 				usb3v3.supply =	"ldousb";
762521d8ec3SGraeme Gregory 				regulator = TWL6025_REG_LDOUSB;
763521d8ec3SGraeme Gregory 			} else {
764521d8ec3SGraeme Gregory 				usb3v3.supply = "vusb";
765521d8ec3SGraeme Gregory 				regulator = TWL6030_REG_VUSB;
766521d8ec3SGraeme Gregory 			}
767521d8ec3SGraeme Gregory 			child = add_regulator_linked(regulator, &usb_fixed,
768521d8ec3SGraeme Gregory 							&usb3v3, 1,
769521d8ec3SGraeme Gregory 							features);
770e70357e3SHema HK 			if (IS_ERR(child))
771e70357e3SHema HK 				return PTR_ERR(child);
772e70357e3SHema HK 		}
773e70357e3SHema HK 
774521d8ec3SGraeme Gregory 		pdata->usb->features = features;
775521d8ec3SGraeme Gregory 
7762d86ad37SPeter Ujfalusi 		child = add_child(SUB_CHIP_ID0, "twl6030_usb",
7772d86ad37SPeter Ujfalusi 			pdata->usb, sizeof(*pdata->usb), true,
778e70357e3SHema HK 			/* irq1 = VBUS_PRES, irq0 = USB ID */
7799e178620SFelipe Balbi 			irq_base + USBOTG_INTR_OFFSET,
7809e178620SFelipe Balbi 			irq_base + USB_PRES_INTR_OFFSET);
781e70357e3SHema HK 
782e70357e3SHema HK 		if (IS_ERR(child))
783e70357e3SHema HK 			return PTR_ERR(child);
784e70357e3SHema HK 		/* we need to connect regulators to this transceiver */
785f78959cfSThierry Reding 		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child)
7861b65fa84SMark Brown 			usb3v3.dev_name = dev_name(child);
787f78959cfSThierry Reding 	} else if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) &&
788f78959cfSThierry Reding 		   twl_class_is_6030()) {
789521d8ec3SGraeme Gregory 		if (features & TWL6025_SUBCLASS)
790521d8ec3SGraeme Gregory 			child = add_regulator(TWL6025_REG_LDOUSB,
791521d8ec3SGraeme Gregory 						pdata->ldousb, features);
792521d8ec3SGraeme Gregory 		else
793521d8ec3SGraeme Gregory 			child = add_regulator(TWL6030_REG_VUSB,
794521d8ec3SGraeme Gregory 						pdata->vusb, features);
795e70357e3SHema HK 
796521d8ec3SGraeme Gregory 			if (IS_ERR(child))
797521d8ec3SGraeme Gregory 					return PTR_ERR(child);
798e70357e3SHema HK 	}
799b07682b6SSantosh Shilimkar 
800f78959cfSThierry Reding 	if (IS_ENABLED(CONFIG_TWL4030_WATCHDOG) && twl_class_is_4030()) {
8012d86ad37SPeter Ujfalusi 		child = add_child(SUB_CHIP_ID3, "twl4030_wdt", NULL, 0,
8022d86ad37SPeter Ujfalusi 				  false, 0, 0);
803b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
804b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
805b07682b6SSantosh Shilimkar 	}
806b07682b6SSantosh Shilimkar 
807f78959cfSThierry Reding 	if (IS_ENABLED(CONFIG_INPUT_TWL4030_PWRBUTTON) && twl_class_is_4030()) {
8082d86ad37SPeter Ujfalusi 		child = add_child(SUB_CHIP_ID3, "twl4030_pwrbutton", NULL, 0,
8092d86ad37SPeter Ujfalusi 				  true, irq_base + 8 + 0, 0);
810b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
811b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
812b07682b6SSantosh Shilimkar 	}
813b07682b6SSantosh Shilimkar 
814f78959cfSThierry Reding 	if (IS_ENABLED(CONFIG_MFD_TWL4030_AUDIO) && pdata->audio &&
815f78959cfSThierry Reding 	    twl_class_is_4030()) {
8162d86ad37SPeter Ujfalusi 		child = add_child(SUB_CHIP_ID1, "twl4030-audio",
8174ae6df5eSPeter Ujfalusi 				pdata->audio, sizeof(*pdata->audio),
818d62abe56SMisael Lopez Cruz 				false, 0, 0);
819d62abe56SMisael Lopez Cruz 		if (IS_ERR(child))
820d62abe56SMisael Lopez Cruz 			return PTR_ERR(child);
821d62abe56SMisael Lopez Cruz 	}
822d62abe56SMisael Lopez Cruz 
8239da66539SRajendra Nayak 	/* twl4030 regulators */
824f78959cfSThierry Reding 	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_4030()) {
825521d8ec3SGraeme Gregory 		child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1,
826521d8ec3SGraeme Gregory 					features);
827b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
828b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
829b07682b6SSantosh Shilimkar 
830521d8ec3SGraeme Gregory 		child = add_regulator(TWL4030_REG_VIO, pdata->vio,
831521d8ec3SGraeme Gregory 					features);
832b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
833b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
834b07682b6SSantosh Shilimkar 
835521d8ec3SGraeme Gregory 		child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1,
836521d8ec3SGraeme Gregory 					features);
837b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
838b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
839b07682b6SSantosh Shilimkar 
840521d8ec3SGraeme Gregory 		child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2,
841521d8ec3SGraeme Gregory 					features);
842b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
843b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
844b07682b6SSantosh Shilimkar 
845521d8ec3SGraeme Gregory 		child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1,
846521d8ec3SGraeme Gregory 					features);
847b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
848b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
849b07682b6SSantosh Shilimkar 
850521d8ec3SGraeme Gregory 		child = add_regulator(TWL4030_REG_VDAC, pdata->vdac,
851521d8ec3SGraeme Gregory 					features);
852b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
853b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
854b07682b6SSantosh Shilimkar 
855b07682b6SSantosh Shilimkar 		child = add_regulator((features & TWL4030_VAUX2)
856b07682b6SSantosh Shilimkar 					? TWL4030_REG_VAUX2_4030
857b07682b6SSantosh Shilimkar 					: TWL4030_REG_VAUX2,
858521d8ec3SGraeme Gregory 				pdata->vaux2, features);
859b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
860b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
861b07682b6SSantosh Shilimkar 
862521d8ec3SGraeme Gregory 		child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1,
863521d8ec3SGraeme Gregory 					features);
864b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
865b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
866b07682b6SSantosh Shilimkar 
867521d8ec3SGraeme Gregory 		child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2,
868521d8ec3SGraeme Gregory 					features);
869b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
870b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
871b07682b6SSantosh Shilimkar 
872521d8ec3SGraeme Gregory 		child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig,
873521d8ec3SGraeme Gregory 					features);
874b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
875b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
876b07682b6SSantosh Shilimkar 	}
877b07682b6SSantosh Shilimkar 
878b07682b6SSantosh Shilimkar 	/* maybe add LDOs that are omitted on cost-reduced parts */
879f78959cfSThierry Reding 	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && !(features & TPS_SUBSET)
8809da66539SRajendra Nayak 	  && twl_class_is_4030()) {
881521d8ec3SGraeme Gregory 		child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2,
882521d8ec3SGraeme Gregory 					features);
883b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
884b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
885b07682b6SSantosh Shilimkar 
886521d8ec3SGraeme Gregory 		child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2,
887521d8ec3SGraeme Gregory 					features);
888b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
889b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
890b07682b6SSantosh Shilimkar 
891521d8ec3SGraeme Gregory 		child = add_regulator(TWL4030_REG_VSIM, pdata->vsim,
892521d8ec3SGraeme Gregory 					features);
893b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
894b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
895b07682b6SSantosh Shilimkar 
896521d8ec3SGraeme Gregory 		child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1,
897521d8ec3SGraeme Gregory 					features);
898b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
899b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
900b07682b6SSantosh Shilimkar 
901521d8ec3SGraeme Gregory 		child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3,
902521d8ec3SGraeme Gregory 					features);
903b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
904b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
905b07682b6SSantosh Shilimkar 
906521d8ec3SGraeme Gregory 		child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4,
907521d8ec3SGraeme Gregory 					features);
908b07682b6SSantosh Shilimkar 		if (IS_ERR(child))
909b07682b6SSantosh Shilimkar 			return PTR_ERR(child);
910b07682b6SSantosh Shilimkar 	}
911b07682b6SSantosh Shilimkar 
9129da66539SRajendra Nayak 	/* twl6030 regulators */
913f78959cfSThierry Reding 	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() &&
914521d8ec3SGraeme Gregory 			!(features & TWL6025_SUBCLASS)) {
91534a38440STero Kristo 		child = add_regulator(TWL6030_REG_VDD1, pdata->vdd1,
91634a38440STero Kristo 					features);
91734a38440STero Kristo 		if (IS_ERR(child))
91834a38440STero Kristo 			return PTR_ERR(child);
91934a38440STero Kristo 
92034a38440STero Kristo 		child = add_regulator(TWL6030_REG_VDD2, pdata->vdd2,
92134a38440STero Kristo 					features);
92234a38440STero Kristo 		if (IS_ERR(child))
92334a38440STero Kristo 			return PTR_ERR(child);
92434a38440STero Kristo 
92534a38440STero Kristo 		child = add_regulator(TWL6030_REG_VDD3, pdata->vdd3,
92634a38440STero Kristo 					features);
92734a38440STero Kristo 		if (IS_ERR(child))
92834a38440STero Kristo 			return PTR_ERR(child);
92934a38440STero Kristo 
93046eda3e9SPeter Ujfalusi 		child = add_regulator(TWL6030_REG_V1V8, pdata->v1v8,
93146eda3e9SPeter Ujfalusi 					features);
93246eda3e9SPeter Ujfalusi 		if (IS_ERR(child))
93346eda3e9SPeter Ujfalusi 			return PTR_ERR(child);
93446eda3e9SPeter Ujfalusi 
93546eda3e9SPeter Ujfalusi 		child = add_regulator(TWL6030_REG_V2V1, pdata->v2v1,
93646eda3e9SPeter Ujfalusi 					features);
93746eda3e9SPeter Ujfalusi 		if (IS_ERR(child))
93846eda3e9SPeter Ujfalusi 			return PTR_ERR(child);
93946eda3e9SPeter Ujfalusi 
940521d8ec3SGraeme Gregory 		child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc,
941521d8ec3SGraeme Gregory 					features);
942521d8ec3SGraeme Gregory 		if (IS_ERR(child))
943521d8ec3SGraeme Gregory 			return PTR_ERR(child);
944521d8ec3SGraeme Gregory 
945521d8ec3SGraeme Gregory 		child = add_regulator(TWL6030_REG_VPP, pdata->vpp,
946521d8ec3SGraeme Gregory 					features);
947521d8ec3SGraeme Gregory 		if (IS_ERR(child))
948521d8ec3SGraeme Gregory 			return PTR_ERR(child);
949521d8ec3SGraeme Gregory 
950521d8ec3SGraeme Gregory 		child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim,
951521d8ec3SGraeme Gregory 					features);
952521d8ec3SGraeme Gregory 		if (IS_ERR(child))
953521d8ec3SGraeme Gregory 			return PTR_ERR(child);
954521d8ec3SGraeme Gregory 
955521d8ec3SGraeme Gregory 		child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio,
956521d8ec3SGraeme Gregory 					features);
957521d8ec3SGraeme Gregory 		if (IS_ERR(child))
958521d8ec3SGraeme Gregory 			return PTR_ERR(child);
959521d8ec3SGraeme Gregory 
960521d8ec3SGraeme Gregory 		child = add_regulator(TWL6030_REG_VDAC, pdata->vdac,
961521d8ec3SGraeme Gregory 					features);
962521d8ec3SGraeme Gregory 		if (IS_ERR(child))
963521d8ec3SGraeme Gregory 			return PTR_ERR(child);
964521d8ec3SGraeme Gregory 
965521d8ec3SGraeme Gregory 		child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1,
966521d8ec3SGraeme Gregory 					features);
967521d8ec3SGraeme Gregory 		if (IS_ERR(child))
968521d8ec3SGraeme Gregory 			return PTR_ERR(child);
969521d8ec3SGraeme Gregory 
970521d8ec3SGraeme Gregory 		child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2,
971521d8ec3SGraeme Gregory 					features);
972521d8ec3SGraeme Gregory 		if (IS_ERR(child))
973521d8ec3SGraeme Gregory 			return PTR_ERR(child);
974521d8ec3SGraeme Gregory 
975521d8ec3SGraeme Gregory 		child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3,
976521d8ec3SGraeme Gregory 					features);
977521d8ec3SGraeme Gregory 		if (IS_ERR(child))
978521d8ec3SGraeme Gregory 			return PTR_ERR(child);
979521d8ec3SGraeme Gregory 
980521d8ec3SGraeme Gregory 		child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg,
981521d8ec3SGraeme Gregory 					features);
982521d8ec3SGraeme Gregory 		if (IS_ERR(child))
983521d8ec3SGraeme Gregory 			return PTR_ERR(child);
984521d8ec3SGraeme Gregory 	}
985521d8ec3SGraeme Gregory 
986521d8ec3SGraeme Gregory 	/* 6030 and 6025 share this regulator */
987f78959cfSThierry Reding 	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030()) {
988521d8ec3SGraeme Gregory 		child = add_regulator(TWL6030_REG_VANA, pdata->vana,
989521d8ec3SGraeme Gregory 					features);
990521d8ec3SGraeme Gregory 		if (IS_ERR(child))
991521d8ec3SGraeme Gregory 			return PTR_ERR(child);
992521d8ec3SGraeme Gregory 	}
993521d8ec3SGraeme Gregory 
994521d8ec3SGraeme Gregory 	/* twl6025 regulators */
995f78959cfSThierry Reding 	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() &&
996521d8ec3SGraeme Gregory 			(features & TWL6025_SUBCLASS)) {
997521d8ec3SGraeme Gregory 		child = add_regulator(TWL6025_REG_LDO5, pdata->ldo5,
998521d8ec3SGraeme Gregory 					features);
9999da66539SRajendra Nayak 		if (IS_ERR(child))
10009da66539SRajendra Nayak 			return PTR_ERR(child);
10019da66539SRajendra Nayak 
1002521d8ec3SGraeme Gregory 		child = add_regulator(TWL6025_REG_LDO1, pdata->ldo1,
1003521d8ec3SGraeme Gregory 					features);
10049da66539SRajendra Nayak 		if (IS_ERR(child))
10059da66539SRajendra Nayak 			return PTR_ERR(child);
10069da66539SRajendra Nayak 
1007521d8ec3SGraeme Gregory 		child = add_regulator(TWL6025_REG_LDO7, pdata->ldo7,
1008521d8ec3SGraeme Gregory 					features);
10099da66539SRajendra Nayak 		if (IS_ERR(child))
10109da66539SRajendra Nayak 			return PTR_ERR(child);
10119da66539SRajendra Nayak 
1012521d8ec3SGraeme Gregory 		child = add_regulator(TWL6025_REG_LDO6, pdata->ldo6,
1013521d8ec3SGraeme Gregory 					features);
10149da66539SRajendra Nayak 		if (IS_ERR(child))
10159da66539SRajendra Nayak 			return PTR_ERR(child);
10169da66539SRajendra Nayak 
1017521d8ec3SGraeme Gregory 		child = add_regulator(TWL6025_REG_LDOLN, pdata->ldoln,
1018521d8ec3SGraeme Gregory 					features);
10199da66539SRajendra Nayak 		if (IS_ERR(child))
10209da66539SRajendra Nayak 			return PTR_ERR(child);
10219da66539SRajendra Nayak 
1022521d8ec3SGraeme Gregory 		child = add_regulator(TWL6025_REG_LDO2, pdata->ldo2,
1023521d8ec3SGraeme Gregory 					features);
10249da66539SRajendra Nayak 		if (IS_ERR(child))
10259da66539SRajendra Nayak 			return PTR_ERR(child);
10269da66539SRajendra Nayak 
1027521d8ec3SGraeme Gregory 		child = add_regulator(TWL6025_REG_LDO4, pdata->ldo4,
1028521d8ec3SGraeme Gregory 					features);
10299da66539SRajendra Nayak 		if (IS_ERR(child))
10309da66539SRajendra Nayak 			return PTR_ERR(child);
10319da66539SRajendra Nayak 
1032521d8ec3SGraeme Gregory 		child = add_regulator(TWL6025_REG_LDO3, pdata->ldo3,
1033521d8ec3SGraeme Gregory 					features);
10349da66539SRajendra Nayak 		if (IS_ERR(child))
10359da66539SRajendra Nayak 			return PTR_ERR(child);
10369da66539SRajendra Nayak 
1037521d8ec3SGraeme Gregory 		child = add_regulator(TWL6025_REG_SMPS3, pdata->smps3,
1038521d8ec3SGraeme Gregory 					features);
10399da66539SRajendra Nayak 		if (IS_ERR(child))
10409da66539SRajendra Nayak 			return PTR_ERR(child);
10418e6de4a3SBalaji T K 
1042521d8ec3SGraeme Gregory 		child = add_regulator(TWL6025_REG_SMPS4, pdata->smps4,
1043521d8ec3SGraeme Gregory 					features);
10448e6de4a3SBalaji T K 		if (IS_ERR(child))
10458e6de4a3SBalaji T K 			return PTR_ERR(child);
1046521d8ec3SGraeme Gregory 
1047521d8ec3SGraeme Gregory 		child = add_regulator(TWL6025_REG_VIO, pdata->vio6025,
1048521d8ec3SGraeme Gregory 					features);
1049521d8ec3SGraeme Gregory 		if (IS_ERR(child))
1050521d8ec3SGraeme Gregory 			return PTR_ERR(child);
1051521d8ec3SGraeme Gregory 
10529da66539SRajendra Nayak 	}
10539da66539SRajendra Nayak 
1054f78959cfSThierry Reding 	if (IS_ENABLED(CONFIG_CHARGER_TWL4030) && pdata->bci &&
105511c39c4bSGrazvydas Ignotas 			!(features & (TPS_SUBSET | TWL5031))) {
10562d86ad37SPeter Ujfalusi 		child = add_child(SUB_CHIP_ID3, "twl4030_bci",
105711c39c4bSGrazvydas Ignotas 				pdata->bci, sizeof(*pdata->bci), false,
105811c39c4bSGrazvydas Ignotas 				/* irq0 = CHG_PRES, irq1 = BCI */
10599e178620SFelipe Balbi 				irq_base + BCI_PRES_INTR_OFFSET,
10609e178620SFelipe Balbi 				irq_base + BCI_INTR_OFFSET);
106111c39c4bSGrazvydas Ignotas 		if (IS_ERR(child))
106211c39c4bSGrazvydas Ignotas 			return PTR_ERR(child);
106311c39c4bSGrazvydas Ignotas 	}
106411c39c4bSGrazvydas Ignotas 
1065b07682b6SSantosh Shilimkar 	return 0;
1066b07682b6SSantosh Shilimkar }
1067b07682b6SSantosh Shilimkar 
1068b07682b6SSantosh Shilimkar /*----------------------------------------------------------------------*/
1069b07682b6SSantosh Shilimkar 
1070b07682b6SSantosh Shilimkar /*
1071b07682b6SSantosh Shilimkar  * These three functions initialize the on-chip clock framework,
1072b07682b6SSantosh Shilimkar  * letting it generate the right frequencies for USB, MADC, and
1073b07682b6SSantosh Shilimkar  * other purposes.
1074b07682b6SSantosh Shilimkar  */
1075b07682b6SSantosh Shilimkar static inline int __init protect_pm_master(void)
1076b07682b6SSantosh Shilimkar {
1077b07682b6SSantosh Shilimkar 	int e = 0;
1078b07682b6SSantosh Shilimkar 
107949e6f87eSFelipe Balbi 	e = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0,
108049e6f87eSFelipe Balbi 			TWL4030_PM_MASTER_PROTECT_KEY);
1081b07682b6SSantosh Shilimkar 	return e;
1082b07682b6SSantosh Shilimkar }
1083b07682b6SSantosh Shilimkar 
1084b07682b6SSantosh Shilimkar static inline int __init unprotect_pm_master(void)
1085b07682b6SSantosh Shilimkar {
1086b07682b6SSantosh Shilimkar 	int e = 0;
1087b07682b6SSantosh Shilimkar 
108849e6f87eSFelipe Balbi 	e |= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
108949e6f87eSFelipe Balbi 			TWL4030_PM_MASTER_KEY_CFG1,
109049e6f87eSFelipe Balbi 			TWL4030_PM_MASTER_PROTECT_KEY);
109149e6f87eSFelipe Balbi 	e |= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
109249e6f87eSFelipe Balbi 			TWL4030_PM_MASTER_KEY_CFG2,
109349e6f87eSFelipe Balbi 			TWL4030_PM_MASTER_PROTECT_KEY);
109449e6f87eSFelipe Balbi 
1095b07682b6SSantosh Shilimkar 	return e;
1096b07682b6SSantosh Shilimkar }
1097b07682b6SSantosh Shilimkar 
1098b07682b6SSantosh Shilimkar static void clocks_init(struct device *dev,
1099b07682b6SSantosh Shilimkar 			struct twl4030_clock_init_data *clock)
1100b07682b6SSantosh Shilimkar {
1101b07682b6SSantosh Shilimkar 	int e = 0;
1102b07682b6SSantosh Shilimkar 	struct clk *osc;
1103b07682b6SSantosh Shilimkar 	u32 rate;
1104b07682b6SSantosh Shilimkar 	u8 ctrl = HFCLK_FREQ_26_MHZ;
1105b07682b6SSantosh Shilimkar 
1106defa6be1STony Lindgren 	osc = clk_get(dev, "fck");
1107b07682b6SSantosh Shilimkar 	if (IS_ERR(osc)) {
1108fc7b92fcSBalaji T K 		printk(KERN_WARNING "Skipping twl internal clock init and "
1109b07682b6SSantosh Shilimkar 				"using bootloader value (unknown osc rate)\n");
1110b07682b6SSantosh Shilimkar 		return;
1111b07682b6SSantosh Shilimkar 	}
1112b07682b6SSantosh Shilimkar 
1113b07682b6SSantosh Shilimkar 	rate = clk_get_rate(osc);
1114b07682b6SSantosh Shilimkar 	clk_put(osc);
1115b07682b6SSantosh Shilimkar 
1116b07682b6SSantosh Shilimkar 	switch (rate) {
1117b07682b6SSantosh Shilimkar 	case 19200000:
1118b07682b6SSantosh Shilimkar 		ctrl = HFCLK_FREQ_19p2_MHZ;
1119b07682b6SSantosh Shilimkar 		break;
1120b07682b6SSantosh Shilimkar 	case 26000000:
1121b07682b6SSantosh Shilimkar 		ctrl = HFCLK_FREQ_26_MHZ;
1122b07682b6SSantosh Shilimkar 		break;
1123b07682b6SSantosh Shilimkar 	case 38400000:
1124b07682b6SSantosh Shilimkar 		ctrl = HFCLK_FREQ_38p4_MHZ;
1125b07682b6SSantosh Shilimkar 		break;
1126b07682b6SSantosh Shilimkar 	}
1127b07682b6SSantosh Shilimkar 
1128b07682b6SSantosh Shilimkar 	ctrl |= HIGH_PERF_SQ;
1129b07682b6SSantosh Shilimkar 	if (clock && clock->ck32k_lowpwr_enable)
1130b07682b6SSantosh Shilimkar 		ctrl |= CK32K_LOWPWR_EN;
1131b07682b6SSantosh Shilimkar 
1132b07682b6SSantosh Shilimkar 	e |= unprotect_pm_master();
1133b07682b6SSantosh Shilimkar 	/* effect->MADC+USB ck en */
1134fc7b92fcSBalaji T K 	e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, ctrl, R_CFG_BOOT);
1135b07682b6SSantosh Shilimkar 	e |= protect_pm_master();
1136b07682b6SSantosh Shilimkar 
1137b07682b6SSantosh Shilimkar 	if (e < 0)
1138b07682b6SSantosh Shilimkar 		pr_err("%s: clock init err [%d]\n", DRIVER_NAME, e);
1139b07682b6SSantosh Shilimkar }
1140b07682b6SSantosh Shilimkar 
1141b07682b6SSantosh Shilimkar /*----------------------------------------------------------------------*/
1142b07682b6SSantosh Shilimkar 
1143b07682b6SSantosh Shilimkar 
1144fc7b92fcSBalaji T K static int twl_remove(struct i2c_client *client)
1145b07682b6SSantosh Shilimkar {
1146364cedb2SPeter Ujfalusi 	unsigned i, num_slaves;
1147b07682b6SSantosh Shilimkar 	int status;
1148b07682b6SSantosh Shilimkar 
1149364cedb2SPeter Ujfalusi 	if (twl_class_is_4030()) {
1150e8deb28cSBalaji T K 		status = twl4030_exit_irq();
1151364cedb2SPeter Ujfalusi 		num_slaves = TWL_NUM_SLAVES;
1152364cedb2SPeter Ujfalusi 	} else {
1153e8deb28cSBalaji T K 		status = twl6030_exit_irq();
1154364cedb2SPeter Ujfalusi 		num_slaves = TWL_NUM_SLAVES - 1;
1155364cedb2SPeter Ujfalusi 	}
1156e8deb28cSBalaji T K 
1157b07682b6SSantosh Shilimkar 	if (status < 0)
1158b07682b6SSantosh Shilimkar 		return status;
1159b07682b6SSantosh Shilimkar 
1160364cedb2SPeter Ujfalusi 	for (i = 0; i < num_slaves; i++) {
1161fc7b92fcSBalaji T K 		struct twl_client	*twl = &twl_modules[i];
1162b07682b6SSantosh Shilimkar 
1163b07682b6SSantosh Shilimkar 		if (twl->client && twl->client != client)
1164b07682b6SSantosh Shilimkar 			i2c_unregister_device(twl->client);
1165fc7b92fcSBalaji T K 		twl_modules[i].client = NULL;
1166b07682b6SSantosh Shilimkar 	}
1167b07682b6SSantosh Shilimkar 	inuse = false;
1168b07682b6SSantosh Shilimkar 	return 0;
1169b07682b6SSantosh Shilimkar }
1170b07682b6SSantosh Shilimkar 
1171ec1a07b3SBenoit Cousson /* NOTE: This driver only handles a single twl4030/tps659x0 chip */
11725b9cecd6SBryan Wu static int __devinit
1173fc7b92fcSBalaji T K twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
1174b07682b6SSantosh Shilimkar {
1175b07682b6SSantosh Shilimkar 	struct twl4030_platform_data	*pdata = client->dev.platform_data;
1176aeb5032bSBenoit Cousson 	struct device_node		*node = client->dev.of_node;
1177defa6be1STony Lindgren 	struct platform_device		*pdev;
11782473d25aSPeter Ujfalusi 	struct regmap_config		*twl_regmap_config;
1179ec1a07b3SBenoit Cousson 	int				irq_base = 0;
1180ec1a07b3SBenoit Cousson 	int				status;
1181364cedb2SPeter Ujfalusi 	unsigned			i, num_slaves;
1182aeb5032bSBenoit Cousson 
1183defa6be1STony Lindgren 	pdev = platform_device_alloc(DRIVER_NAME, -1);
1184defa6be1STony Lindgren 	if (!pdev) {
1185defa6be1STony Lindgren 		dev_err(&client->dev, "can't alloc pdev\n");
1186defa6be1STony Lindgren 		return -ENOMEM;
1187defa6be1STony Lindgren 	}
1188defa6be1STony Lindgren 
1189defa6be1STony Lindgren 	status = platform_device_add(pdev);
1190defa6be1STony Lindgren 	if (status) {
1191defa6be1STony Lindgren 		platform_device_put(pdev);
1192defa6be1STony Lindgren 		return status;
1193defa6be1STony Lindgren 	}
1194defa6be1STony Lindgren 
1195aeb5032bSBenoit Cousson 	if (node && !pdata) {
1196aeb5032bSBenoit Cousson 		/*
1197aeb5032bSBenoit Cousson 		 * XXX: Temporary pdata until the information is correctly
1198aeb5032bSBenoit Cousson 		 * retrieved by every TWL modules from DT.
1199aeb5032bSBenoit Cousson 		 */
1200aeb5032bSBenoit Cousson 		pdata = devm_kzalloc(&client->dev,
1201aeb5032bSBenoit Cousson 				     sizeof(struct twl4030_platform_data),
1202aeb5032bSBenoit Cousson 				     GFP_KERNEL);
1203defa6be1STony Lindgren 		if (!pdata) {
1204defa6be1STony Lindgren 			status = -ENOMEM;
1205defa6be1STony Lindgren 			goto free;
1206defa6be1STony Lindgren 		}
1207aeb5032bSBenoit Cousson 	}
1208b07682b6SSantosh Shilimkar 
1209b07682b6SSantosh Shilimkar 	if (!pdata) {
1210b07682b6SSantosh Shilimkar 		dev_dbg(&client->dev, "no platform data?\n");
1211defa6be1STony Lindgren 		status = -EINVAL;
1212defa6be1STony Lindgren 		goto free;
1213b07682b6SSantosh Shilimkar 	}
1214b07682b6SSantosh Shilimkar 
1215defa6be1STony Lindgren 	platform_set_drvdata(pdev, pdata);
1216defa6be1STony Lindgren 
1217b07682b6SSantosh Shilimkar 	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
1218b07682b6SSantosh Shilimkar 		dev_dbg(&client->dev, "can't talk I2C?\n");
1219defa6be1STony Lindgren 		status = -EIO;
1220defa6be1STony Lindgren 		goto free;
1221b07682b6SSantosh Shilimkar 	}
1222b07682b6SSantosh Shilimkar 
1223b07682b6SSantosh Shilimkar 	if (inuse) {
1224b07682b6SSantosh Shilimkar 		dev_dbg(&client->dev, "driver is already in use\n");
1225defa6be1STony Lindgren 		status = -EBUSY;
1226defa6be1STony Lindgren 		goto free;
1227b07682b6SSantosh Shilimkar 	}
1228b07682b6SSantosh Shilimkar 
1229364cedb2SPeter Ujfalusi 	if ((id->driver_data) & TWL6030_CLASS) {
1230364cedb2SPeter Ujfalusi 		twl_id = TWL6030_CLASS_ID;
1231364cedb2SPeter Ujfalusi 		twl_map = &twl6030_map[0];
12322473d25aSPeter Ujfalusi 		twl_regmap_config = twl6030_regmap_config;
1233364cedb2SPeter Ujfalusi 		num_slaves = TWL_NUM_SLAVES - 1;
1234364cedb2SPeter Ujfalusi 	} else {
1235364cedb2SPeter Ujfalusi 		twl_id = TWL4030_CLASS_ID;
1236364cedb2SPeter Ujfalusi 		twl_map = &twl4030_map[0];
12372473d25aSPeter Ujfalusi 		twl_regmap_config = twl4030_regmap_config;
1238364cedb2SPeter Ujfalusi 		num_slaves = TWL_NUM_SLAVES;
1239364cedb2SPeter Ujfalusi 	}
1240364cedb2SPeter Ujfalusi 
1241364cedb2SPeter Ujfalusi 	for (i = 0; i < num_slaves; i++) {
1242fc7b92fcSBalaji T K 		struct twl_client *twl = &twl_modules[i];
1243b07682b6SSantosh Shilimkar 
1244ec1a07b3SBenoit Cousson 		if (i == 0) {
1245b07682b6SSantosh Shilimkar 			twl->client = client;
1246ec1a07b3SBenoit Cousson 		} else {
1247b07682b6SSantosh Shilimkar 			twl->client = i2c_new_dummy(client->adapter,
12482473d25aSPeter Ujfalusi 						    client->addr + i);
1249b07682b6SSantosh Shilimkar 			if (!twl->client) {
1250b07682b6SSantosh Shilimkar 				dev_err(&client->dev,
1251b07682b6SSantosh Shilimkar 					"can't attach client %d\n", i);
1252b07682b6SSantosh Shilimkar 				status = -ENOMEM;
1253b07682b6SSantosh Shilimkar 				goto fail;
1254b07682b6SSantosh Shilimkar 			}
1255b07682b6SSantosh Shilimkar 		}
12562473d25aSPeter Ujfalusi 
12572473d25aSPeter Ujfalusi 		twl->regmap = devm_regmap_init_i2c(twl->client,
12582473d25aSPeter Ujfalusi 						   &twl_regmap_config[i]);
12592473d25aSPeter Ujfalusi 		if (IS_ERR(twl->regmap)) {
12602473d25aSPeter Ujfalusi 			status = PTR_ERR(twl->regmap);
12612473d25aSPeter Ujfalusi 			dev_err(&client->dev,
12622473d25aSPeter Ujfalusi 				"Failed to allocate regmap %d, err: %d\n", i,
12632473d25aSPeter Ujfalusi 				status);
12642473d25aSPeter Ujfalusi 			goto fail;
12652473d25aSPeter Ujfalusi 		}
1266b07682b6SSantosh Shilimkar 	}
1267ec1a07b3SBenoit Cousson 
1268b07682b6SSantosh Shilimkar 	inuse = true;
1269b07682b6SSantosh Shilimkar 
1270b07682b6SSantosh Shilimkar 	/* setup clock framework */
1271defa6be1STony Lindgren 	clocks_init(&pdev->dev, pdata->clock);
1272b07682b6SSantosh Shilimkar 
1273ca972d13SLesly A M 	/* read TWL IDCODE Register */
1274ca972d13SLesly A M 	if (twl_id == TWL4030_CLASS_ID) {
1275ec1a07b3SBenoit Cousson 		status = twl_read_idcode_register();
1276ec1a07b3SBenoit Cousson 		WARN(status < 0, "Error: reading twl_idcode register value\n");
1277ca972d13SLesly A M 	}
1278ca972d13SLesly A M 
1279b07682b6SSantosh Shilimkar 	/* load power event scripts */
1280f78959cfSThierry Reding 	if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata->power)
1281b07682b6SSantosh Shilimkar 		twl4030_power_init(pdata->power);
1282b07682b6SSantosh Shilimkar 
1283b07682b6SSantosh Shilimkar 	/* Maybe init the T2 Interrupt subsystem */
12849e178620SFelipe Balbi 	if (client->irq) {
1285e8deb28cSBalaji T K 		if (twl_class_is_4030()) {
1286e8deb28cSBalaji T K 			twl4030_init_chip_irq(id->name);
128778518ffaSBenoit Cousson 			irq_base = twl4030_init_irq(&client->dev, client->irq);
1288e8deb28cSBalaji T K 		} else {
128978518ffaSBenoit Cousson 			irq_base = twl6030_init_irq(&client->dev, client->irq);
1290e8deb28cSBalaji T K 		}
1291e8deb28cSBalaji T K 
129278518ffaSBenoit Cousson 		if (irq_base < 0) {
129378518ffaSBenoit Cousson 			status = irq_base;
1294b07682b6SSantosh Shilimkar 			goto fail;
1295b07682b6SSantosh Shilimkar 		}
129678518ffaSBenoit Cousson 	}
1297b07682b6SSantosh Shilimkar 
1298ec1a07b3SBenoit Cousson 	/*
1299ec1a07b3SBenoit Cousson 	 * Disable TWL4030/TWL5030 I2C Pull-up on I2C1 and I2C4(SR) interface.
1300a29aaf55SMoiz Sonasath 	 * Program I2C_SCL_CTRL_PU(bit 0)=0, I2C_SDA_CTRL_PU (bit 2)=0,
1301a29aaf55SMoiz Sonasath 	 * SR_I2C_SCL_CTRL_PU(bit 4)=0 and SR_I2C_SDA_CTRL_PU(bit 6)=0.
1302a29aaf55SMoiz Sonasath 	 */
1303a29aaf55SMoiz Sonasath 	if (twl_class_is_4030()) {
1304ec1a07b3SBenoit Cousson 		u8 temp;
1305ec1a07b3SBenoit Cousson 
1306a29aaf55SMoiz Sonasath 		twl_i2c_read_u8(TWL4030_MODULE_INTBR, &temp, REG_GPPUPDCTR1);
1307a29aaf55SMoiz Sonasath 		temp &= ~(SR_I2C_SDA_CTRL_PU | SR_I2C_SCL_CTRL_PU | \
1308a29aaf55SMoiz Sonasath 			I2C_SDA_CTRL_PU | I2C_SCL_CTRL_PU);
1309a29aaf55SMoiz Sonasath 		twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
1310a29aaf55SMoiz Sonasath 	}
1311a29aaf55SMoiz Sonasath 
1312964dba28SGrant Likely 	status = -ENODEV;
1313aeb5032bSBenoit Cousson 	if (node)
1314aeb5032bSBenoit Cousson 		status = of_platform_populate(node, NULL, NULL, &client->dev);
1315964dba28SGrant Likely 	if (status)
13169e178620SFelipe Balbi 		status = add_children(pdata, irq_base, id->driver_data);
1317aeb5032bSBenoit Cousson 
1318b07682b6SSantosh Shilimkar fail:
1319b07682b6SSantosh Shilimkar 	if (status < 0)
1320fc7b92fcSBalaji T K 		twl_remove(client);
1321defa6be1STony Lindgren free:
1322defa6be1STony Lindgren 	if (status < 0)
1323defa6be1STony Lindgren 		platform_device_unregister(pdev);
1324ec1a07b3SBenoit Cousson 
1325b07682b6SSantosh Shilimkar 	return status;
1326b07682b6SSantosh Shilimkar }
1327b07682b6SSantosh Shilimkar 
1328fc7b92fcSBalaji T K static const struct i2c_device_id twl_ids[] = {
1329b07682b6SSantosh Shilimkar 	{ "twl4030", TWL4030_VAUX2 },	/* "Triton 2" */
1330b07682b6SSantosh Shilimkar 	{ "twl5030", 0 },		/* T2 updated */
1331b07682b6SSantosh Shilimkar 	{ "twl5031", TWL5031 },		/* TWL5030 updated */
1332b07682b6SSantosh Shilimkar 	{ "tps65950", 0 },		/* catalog version of twl5030 */
1333b07682b6SSantosh Shilimkar 	{ "tps65930", TPS_SUBSET },	/* fewer LDOs and DACs; no charger */
1334b07682b6SSantosh Shilimkar 	{ "tps65920", TPS_SUBSET },	/* fewer LDOs; no codec or charger */
133559dead5aSOleg Drokin 	{ "tps65921", TPS_SUBSET },	/* fewer LDOs; no codec, no LED
133659dead5aSOleg Drokin 					   and vibrator. Charger in USB module*/
1337e8deb28cSBalaji T K 	{ "twl6030", TWL6030_CLASS },	/* "Phoenix power chip" */
1338521d8ec3SGraeme Gregory 	{ "twl6025", TWL6030_CLASS | TWL6025_SUBCLASS }, /* "Phoenix lite" */
1339b07682b6SSantosh Shilimkar 	{ /* end of list */ },
1340b07682b6SSantosh Shilimkar };
1341fc7b92fcSBalaji T K MODULE_DEVICE_TABLE(i2c, twl_ids);
1342b07682b6SSantosh Shilimkar 
1343b07682b6SSantosh Shilimkar /* One Client Driver , 4 Clients */
1344fc7b92fcSBalaji T K static struct i2c_driver twl_driver = {
1345b07682b6SSantosh Shilimkar 	.driver.name	= DRIVER_NAME,
1346fc7b92fcSBalaji T K 	.id_table	= twl_ids,
1347fc7b92fcSBalaji T K 	.probe		= twl_probe,
1348fc7b92fcSBalaji T K 	.remove		= twl_remove,
1349b07682b6SSantosh Shilimkar };
1350b07682b6SSantosh Shilimkar 
1351fc7b92fcSBalaji T K static int __init twl_init(void)
1352b07682b6SSantosh Shilimkar {
1353fc7b92fcSBalaji T K 	return i2c_add_driver(&twl_driver);
1354b07682b6SSantosh Shilimkar }
1355fc7b92fcSBalaji T K subsys_initcall(twl_init);
1356b07682b6SSantosh Shilimkar 
1357fc7b92fcSBalaji T K static void __exit twl_exit(void)
1358b07682b6SSantosh Shilimkar {
1359fc7b92fcSBalaji T K 	i2c_del_driver(&twl_driver);
1360b07682b6SSantosh Shilimkar }
1361fc7b92fcSBalaji T K module_exit(twl_exit);
1362b07682b6SSantosh Shilimkar 
1363b07682b6SSantosh Shilimkar MODULE_AUTHOR("Texas Instruments, Inc.");
1364fc7b92fcSBalaji T K MODULE_DESCRIPTION("I2C Core interface for TWL");
1365b07682b6SSantosh Shilimkar MODULE_LICENSE("GPL");
1366