xref: /OK3568_Linux_fs/kernel/drivers/regulator/twl-regulator.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * twl-regulator.c -- support regulators in twl4030/twl6030 family chips
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2008 David Brownell
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/module.h>
9*4882a593Smuzhiyun #include <linux/string.h>
10*4882a593Smuzhiyun #include <linux/slab.h>
11*4882a593Smuzhiyun #include <linux/init.h>
12*4882a593Smuzhiyun #include <linux/err.h>
13*4882a593Smuzhiyun #include <linux/platform_device.h>
14*4882a593Smuzhiyun #include <linux/of.h>
15*4882a593Smuzhiyun #include <linux/of_device.h>
16*4882a593Smuzhiyun #include <linux/regulator/driver.h>
17*4882a593Smuzhiyun #include <linux/regulator/machine.h>
18*4882a593Smuzhiyun #include <linux/regulator/of_regulator.h>
19*4882a593Smuzhiyun #include <linux/mfd/twl.h>
20*4882a593Smuzhiyun #include <linux/delay.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun /*
23*4882a593Smuzhiyun  * The TWL4030/TW5030/TPS659x0 family chips include power management, a
24*4882a593Smuzhiyun  * USB OTG transceiver, an RTC, ADC, PWM, and lots more.  Some versions
25*4882a593Smuzhiyun  * include an audio codec, battery charger, and more voltage regulators.
26*4882a593Smuzhiyun  * These chips are often used in OMAP-based systems.
27*4882a593Smuzhiyun  *
28*4882a593Smuzhiyun  * This driver implements software-based resource control for various
29*4882a593Smuzhiyun  * voltage regulators.  This is usually augmented with state machine
30*4882a593Smuzhiyun  * based control.
31*4882a593Smuzhiyun  */
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun struct twlreg_info {
34*4882a593Smuzhiyun 	/* start of regulator's PM_RECEIVER control register bank */
35*4882a593Smuzhiyun 	u8			base;
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun 	/* twl resource ID, for resource control state machine */
38*4882a593Smuzhiyun 	u8			id;
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 	/* voltage in mV = table[VSEL]; table_len must be a power-of-two */
41*4882a593Smuzhiyun 	u8			table_len;
42*4882a593Smuzhiyun 	const u16		*table;
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	/* State REMAP default configuration */
45*4882a593Smuzhiyun 	u8			remap;
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun 	/* used by regulator core */
48*4882a593Smuzhiyun 	struct regulator_desc	desc;
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	/* chip specific features */
51*4882a593Smuzhiyun 	unsigned long		features;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	/* data passed from board for external get/set voltage */
54*4882a593Smuzhiyun 	void			*data;
55*4882a593Smuzhiyun };
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun /* LDO control registers ... offset is from the base of its register bank.
59*4882a593Smuzhiyun  * The first three registers of all power resource banks help hardware to
60*4882a593Smuzhiyun  * manage the various resource groups.
61*4882a593Smuzhiyun  */
62*4882a593Smuzhiyun /* Common offset in TWL4030/6030 */
63*4882a593Smuzhiyun #define VREG_GRP		0
64*4882a593Smuzhiyun /* TWL4030 register offsets */
65*4882a593Smuzhiyun #define VREG_TYPE		1
66*4882a593Smuzhiyun #define VREG_REMAP		2
67*4882a593Smuzhiyun #define VREG_DEDICATED		3	/* LDO control */
68*4882a593Smuzhiyun #define VREG_VOLTAGE_SMPS_4030	9
69*4882a593Smuzhiyun /* TWL6030 register offsets */
70*4882a593Smuzhiyun #define VREG_TRANS		1
71*4882a593Smuzhiyun #define VREG_STATE		2
72*4882a593Smuzhiyun #define VREG_VOLTAGE		3
73*4882a593Smuzhiyun #define VREG_VOLTAGE_SMPS	4
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun static inline int
twlreg_read(struct twlreg_info * info,unsigned slave_subgp,unsigned offset)76*4882a593Smuzhiyun twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun 	u8 value;
79*4882a593Smuzhiyun 	int status;
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	status = twl_i2c_read_u8(slave_subgp,
82*4882a593Smuzhiyun 			&value, info->base + offset);
83*4882a593Smuzhiyun 	return (status < 0) ? status : value;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun static inline int
twlreg_write(struct twlreg_info * info,unsigned slave_subgp,unsigned offset,u8 value)87*4882a593Smuzhiyun twlreg_write(struct twlreg_info *info, unsigned slave_subgp, unsigned offset,
88*4882a593Smuzhiyun 						 u8 value)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun 	return twl_i2c_write_u8(slave_subgp,
91*4882a593Smuzhiyun 			value, info->base + offset);
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun /*----------------------------------------------------------------------*/
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun /* generic power resource operations, which work on all regulators */
97*4882a593Smuzhiyun 
twlreg_grp(struct regulator_dev * rdev)98*4882a593Smuzhiyun static int twlreg_grp(struct regulator_dev *rdev)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun 	return twlreg_read(rdev_get_drvdata(rdev), TWL_MODULE_PM_RECEIVER,
101*4882a593Smuzhiyun 								 VREG_GRP);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun /*
105*4882a593Smuzhiyun  * Enable/disable regulators by joining/leaving the P1 (processor) group.
106*4882a593Smuzhiyun  * We assume nobody else is updating the DEV_GRP registers.
107*4882a593Smuzhiyun  */
108*4882a593Smuzhiyun /* definition for 4030 family */
109*4882a593Smuzhiyun #define P3_GRP_4030	BIT(7)		/* "peripherals" */
110*4882a593Smuzhiyun #define P2_GRP_4030	BIT(6)		/* secondary processor, modem, etc */
111*4882a593Smuzhiyun #define P1_GRP_4030	BIT(5)		/* CPU/Linux */
112*4882a593Smuzhiyun /* definition for 6030 family */
113*4882a593Smuzhiyun #define P3_GRP_6030	BIT(2)		/* secondary processor, modem, etc */
114*4882a593Smuzhiyun #define P2_GRP_6030	BIT(1)		/* "peripherals" */
115*4882a593Smuzhiyun #define P1_GRP_6030	BIT(0)		/* CPU/Linux */
116*4882a593Smuzhiyun 
twl4030reg_is_enabled(struct regulator_dev * rdev)117*4882a593Smuzhiyun static int twl4030reg_is_enabled(struct regulator_dev *rdev)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun 	int	state = twlreg_grp(rdev);
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	if (state < 0)
122*4882a593Smuzhiyun 		return state;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	return state & P1_GRP_4030;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun #define PB_I2C_BUSY	BIT(0)
128*4882a593Smuzhiyun #define PB_I2C_BWEN	BIT(1)
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun /* Wait until buffer empty/ready to send a word on power bus. */
twl4030_wait_pb_ready(void)131*4882a593Smuzhiyun static int twl4030_wait_pb_ready(void)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	int	ret;
135*4882a593Smuzhiyun 	int	timeout = 10;
136*4882a593Smuzhiyun 	u8	val;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	do {
139*4882a593Smuzhiyun 		ret = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val,
140*4882a593Smuzhiyun 				      TWL4030_PM_MASTER_PB_CFG);
141*4882a593Smuzhiyun 		if (ret < 0)
142*4882a593Smuzhiyun 			return ret;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 		if (!(val & PB_I2C_BUSY))
145*4882a593Smuzhiyun 			return 0;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 		mdelay(1);
148*4882a593Smuzhiyun 		timeout--;
149*4882a593Smuzhiyun 	} while (timeout);
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	return -ETIMEDOUT;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun /* Send a word over the powerbus */
twl4030_send_pb_msg(unsigned msg)155*4882a593Smuzhiyun static int twl4030_send_pb_msg(unsigned msg)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun 	u8	val;
158*4882a593Smuzhiyun 	int	ret;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	/* save powerbus configuration */
161*4882a593Smuzhiyun 	ret = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val,
162*4882a593Smuzhiyun 			      TWL4030_PM_MASTER_PB_CFG);
163*4882a593Smuzhiyun 	if (ret < 0)
164*4882a593Smuzhiyun 		return ret;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	/* Enable i2c access to powerbus */
167*4882a593Smuzhiyun 	ret = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, val | PB_I2C_BWEN,
168*4882a593Smuzhiyun 			       TWL4030_PM_MASTER_PB_CFG);
169*4882a593Smuzhiyun 	if (ret < 0)
170*4882a593Smuzhiyun 		return ret;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	ret = twl4030_wait_pb_ready();
173*4882a593Smuzhiyun 	if (ret < 0)
174*4882a593Smuzhiyun 		return ret;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	ret = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, msg >> 8,
177*4882a593Smuzhiyun 			       TWL4030_PM_MASTER_PB_WORD_MSB);
178*4882a593Smuzhiyun 	if (ret < 0)
179*4882a593Smuzhiyun 		return ret;
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	ret = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, msg & 0xff,
182*4882a593Smuzhiyun 			       TWL4030_PM_MASTER_PB_WORD_LSB);
183*4882a593Smuzhiyun 	if (ret < 0)
184*4882a593Smuzhiyun 		return ret;
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	ret = twl4030_wait_pb_ready();
187*4882a593Smuzhiyun 	if (ret < 0)
188*4882a593Smuzhiyun 		return ret;
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	/* Restore powerbus configuration */
191*4882a593Smuzhiyun 	return twl_i2c_write_u8(TWL_MODULE_PM_MASTER, val,
192*4882a593Smuzhiyun 				TWL4030_PM_MASTER_PB_CFG);
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun 
twl4030reg_enable(struct regulator_dev * rdev)195*4882a593Smuzhiyun static int twl4030reg_enable(struct regulator_dev *rdev)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun 	struct twlreg_info	*info = rdev_get_drvdata(rdev);
198*4882a593Smuzhiyun 	int			grp;
199*4882a593Smuzhiyun 	int			ret;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	grp = twlreg_grp(rdev);
202*4882a593Smuzhiyun 	if (grp < 0)
203*4882a593Smuzhiyun 		return grp;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	grp |= P1_GRP_4030;
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp);
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	return ret;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
twl4030reg_disable(struct regulator_dev * rdev)212*4882a593Smuzhiyun static int twl4030reg_disable(struct regulator_dev *rdev)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	struct twlreg_info	*info = rdev_get_drvdata(rdev);
215*4882a593Smuzhiyun 	int			grp;
216*4882a593Smuzhiyun 	int			ret;
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	grp = twlreg_grp(rdev);
219*4882a593Smuzhiyun 	if (grp < 0)
220*4882a593Smuzhiyun 		return grp;
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	grp &= ~(P1_GRP_4030 | P2_GRP_4030 | P3_GRP_4030);
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp);
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	return ret;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun 
twl4030reg_get_status(struct regulator_dev * rdev)229*4882a593Smuzhiyun static int twl4030reg_get_status(struct regulator_dev *rdev)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun 	int	state = twlreg_grp(rdev);
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	if (state < 0)
234*4882a593Smuzhiyun 		return state;
235*4882a593Smuzhiyun 	state &= 0x0f;
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	/* assume state != WARM_RESET; we'd not be running...  */
238*4882a593Smuzhiyun 	if (!state)
239*4882a593Smuzhiyun 		return REGULATOR_STATUS_OFF;
240*4882a593Smuzhiyun 	return (state & BIT(3))
241*4882a593Smuzhiyun 		? REGULATOR_STATUS_NORMAL
242*4882a593Smuzhiyun 		: REGULATOR_STATUS_STANDBY;
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun 
twl4030reg_set_mode(struct regulator_dev * rdev,unsigned mode)245*4882a593Smuzhiyun static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun 	struct twlreg_info	*info = rdev_get_drvdata(rdev);
248*4882a593Smuzhiyun 	unsigned		message;
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	/* We can only set the mode through state machine commands... */
251*4882a593Smuzhiyun 	switch (mode) {
252*4882a593Smuzhiyun 	case REGULATOR_MODE_NORMAL:
253*4882a593Smuzhiyun 		message = MSG_SINGULAR(DEV_GRP_P1, info->id, RES_STATE_ACTIVE);
254*4882a593Smuzhiyun 		break;
255*4882a593Smuzhiyun 	case REGULATOR_MODE_STANDBY:
256*4882a593Smuzhiyun 		message = MSG_SINGULAR(DEV_GRP_P1, info->id, RES_STATE_SLEEP);
257*4882a593Smuzhiyun 		break;
258*4882a593Smuzhiyun 	default:
259*4882a593Smuzhiyun 		return -EINVAL;
260*4882a593Smuzhiyun 	}
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	return twl4030_send_pb_msg(message);
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun 
twl4030reg_map_mode(unsigned int mode)265*4882a593Smuzhiyun static inline unsigned int twl4030reg_map_mode(unsigned int mode)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun 	switch (mode) {
268*4882a593Smuzhiyun 	case RES_STATE_ACTIVE:
269*4882a593Smuzhiyun 		return REGULATOR_MODE_NORMAL;
270*4882a593Smuzhiyun 	case RES_STATE_SLEEP:
271*4882a593Smuzhiyun 		return REGULATOR_MODE_STANDBY;
272*4882a593Smuzhiyun 	default:
273*4882a593Smuzhiyun 		return REGULATOR_MODE_INVALID;
274*4882a593Smuzhiyun 	}
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun /*----------------------------------------------------------------------*/
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun /*
280*4882a593Smuzhiyun  * Support for adjustable-voltage LDOs uses a four bit (or less) voltage
281*4882a593Smuzhiyun  * select field in its control register.   We use tables indexed by VSEL
282*4882a593Smuzhiyun  * to record voltages in milliVolts.  (Accuracy is about three percent.)
283*4882a593Smuzhiyun  *
284*4882a593Smuzhiyun  * Note that VSEL values for VAUX2 changed in twl5030 and newer silicon;
285*4882a593Smuzhiyun  * currently handled by listing two slightly different VAUX2 regulators,
286*4882a593Smuzhiyun  * only one of which will be configured.
287*4882a593Smuzhiyun  *
288*4882a593Smuzhiyun  * VSEL values documented as "TI cannot support these values" are flagged
289*4882a593Smuzhiyun  * in these tables as UNSUP() values; we normally won't assign them.
290*4882a593Smuzhiyun  *
291*4882a593Smuzhiyun  * VAUX3 at 3V is incorrectly listed in some TI manuals as unsupported.
292*4882a593Smuzhiyun  * TI are revising the twl5030/tps659x0 specs to support that 3.0V setting.
293*4882a593Smuzhiyun  */
294*4882a593Smuzhiyun #define UNSUP_MASK	0x8000
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun #define UNSUP(x)	(UNSUP_MASK | (x))
297*4882a593Smuzhiyun #define IS_UNSUP(info, x)			\
298*4882a593Smuzhiyun 	((UNSUP_MASK & (x)) &&			\
299*4882a593Smuzhiyun 	 !((info)->features & TWL4030_ALLOW_UNSUPPORTED))
300*4882a593Smuzhiyun #define LDO_MV(x)	(~UNSUP_MASK & (x))
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun static const u16 VAUX1_VSEL_table[] = {
304*4882a593Smuzhiyun 	UNSUP(1500), UNSUP(1800), 2500, 2800,
305*4882a593Smuzhiyun 	3000, 3000, 3000, 3000,
306*4882a593Smuzhiyun };
307*4882a593Smuzhiyun static const u16 VAUX2_4030_VSEL_table[] = {
308*4882a593Smuzhiyun 	UNSUP(1000), UNSUP(1000), UNSUP(1200), 1300,
309*4882a593Smuzhiyun 	1500, 1800, UNSUP(1850), 2500,
310*4882a593Smuzhiyun 	UNSUP(2600), 2800, UNSUP(2850), UNSUP(3000),
311*4882a593Smuzhiyun 	UNSUP(3150), UNSUP(3150), UNSUP(3150), UNSUP(3150),
312*4882a593Smuzhiyun };
313*4882a593Smuzhiyun static const u16 VAUX2_VSEL_table[] = {
314*4882a593Smuzhiyun 	1700, 1700, 1900, 1300,
315*4882a593Smuzhiyun 	1500, 1800, 2000, 2500,
316*4882a593Smuzhiyun 	2100, 2800, 2200, 2300,
317*4882a593Smuzhiyun 	2400, 2400, 2400, 2400,
318*4882a593Smuzhiyun };
319*4882a593Smuzhiyun static const u16 VAUX3_VSEL_table[] = {
320*4882a593Smuzhiyun 	1500, 1800, 2500, 2800,
321*4882a593Smuzhiyun 	3000, 3000, 3000, 3000,
322*4882a593Smuzhiyun };
323*4882a593Smuzhiyun static const u16 VAUX4_VSEL_table[] = {
324*4882a593Smuzhiyun 	700, 1000, 1200, UNSUP(1300),
325*4882a593Smuzhiyun 	1500, 1800, UNSUP(1850), 2500,
326*4882a593Smuzhiyun 	UNSUP(2600), 2800, UNSUP(2850), UNSUP(3000),
327*4882a593Smuzhiyun 	UNSUP(3150), UNSUP(3150), UNSUP(3150), UNSUP(3150),
328*4882a593Smuzhiyun };
329*4882a593Smuzhiyun static const u16 VMMC1_VSEL_table[] = {
330*4882a593Smuzhiyun 	1850, 2850, 3000, 3150,
331*4882a593Smuzhiyun };
332*4882a593Smuzhiyun static const u16 VMMC2_VSEL_table[] = {
333*4882a593Smuzhiyun 	UNSUP(1000), UNSUP(1000), UNSUP(1200), UNSUP(1300),
334*4882a593Smuzhiyun 	UNSUP(1500), UNSUP(1800), 1850, UNSUP(2500),
335*4882a593Smuzhiyun 	2600, 2800, 2850, 3000,
336*4882a593Smuzhiyun 	3150, 3150, 3150, 3150,
337*4882a593Smuzhiyun };
338*4882a593Smuzhiyun static const u16 VPLL1_VSEL_table[] = {
339*4882a593Smuzhiyun 	1000, 1200, 1300, 1800,
340*4882a593Smuzhiyun 	UNSUP(2800), UNSUP(3000), UNSUP(3000), UNSUP(3000),
341*4882a593Smuzhiyun };
342*4882a593Smuzhiyun static const u16 VPLL2_VSEL_table[] = {
343*4882a593Smuzhiyun 	700, 1000, 1200, 1300,
344*4882a593Smuzhiyun 	UNSUP(1500), 1800, UNSUP(1850), UNSUP(2500),
345*4882a593Smuzhiyun 	UNSUP(2600), UNSUP(2800), UNSUP(2850), UNSUP(3000),
346*4882a593Smuzhiyun 	UNSUP(3150), UNSUP(3150), UNSUP(3150), UNSUP(3150),
347*4882a593Smuzhiyun };
348*4882a593Smuzhiyun static const u16 VSIM_VSEL_table[] = {
349*4882a593Smuzhiyun 	UNSUP(1000), UNSUP(1200), UNSUP(1300), 1800,
350*4882a593Smuzhiyun 	2800, 3000, 3000, 3000,
351*4882a593Smuzhiyun };
352*4882a593Smuzhiyun static const u16 VDAC_VSEL_table[] = {
353*4882a593Smuzhiyun 	1200, 1300, 1800, 1800,
354*4882a593Smuzhiyun };
355*4882a593Smuzhiyun static const u16 VIO_VSEL_table[] = {
356*4882a593Smuzhiyun 	1800, 1850,
357*4882a593Smuzhiyun };
358*4882a593Smuzhiyun static const u16 VINTANA2_VSEL_table[] = {
359*4882a593Smuzhiyun 	2500, 2750,
360*4882a593Smuzhiyun };
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun /* 600mV to 1450mV in 12.5 mV steps */
363*4882a593Smuzhiyun static const struct linear_range VDD1_ranges[] = {
364*4882a593Smuzhiyun 	REGULATOR_LINEAR_RANGE(600000, 0, 68, 12500)
365*4882a593Smuzhiyun };
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun /* 600mV to 1450mV in 12.5 mV steps, everything above = 1500mV */
368*4882a593Smuzhiyun static const struct linear_range VDD2_ranges[] = {
369*4882a593Smuzhiyun 	REGULATOR_LINEAR_RANGE(600000, 0, 68, 12500),
370*4882a593Smuzhiyun 	REGULATOR_LINEAR_RANGE(1500000, 69, 69, 12500)
371*4882a593Smuzhiyun };
372*4882a593Smuzhiyun 
twl4030ldo_list_voltage(struct regulator_dev * rdev,unsigned index)373*4882a593Smuzhiyun static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
374*4882a593Smuzhiyun {
375*4882a593Smuzhiyun 	struct twlreg_info	*info = rdev_get_drvdata(rdev);
376*4882a593Smuzhiyun 	int			mV = info->table[index];
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	return IS_UNSUP(info, mV) ? 0 : (LDO_MV(mV) * 1000);
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun static int
twl4030ldo_set_voltage_sel(struct regulator_dev * rdev,unsigned selector)382*4882a593Smuzhiyun twl4030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
383*4882a593Smuzhiyun {
384*4882a593Smuzhiyun 	struct twlreg_info	*info = rdev_get_drvdata(rdev);
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE,
387*4882a593Smuzhiyun 			    selector);
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun 
twl4030ldo_get_voltage_sel(struct regulator_dev * rdev)390*4882a593Smuzhiyun static int twl4030ldo_get_voltage_sel(struct regulator_dev *rdev)
391*4882a593Smuzhiyun {
392*4882a593Smuzhiyun 	struct twlreg_info	*info = rdev_get_drvdata(rdev);
393*4882a593Smuzhiyun 	int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE);
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun 	if (vsel < 0)
396*4882a593Smuzhiyun 		return vsel;
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	vsel &= info->table_len - 1;
399*4882a593Smuzhiyun 	return vsel;
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun static const struct regulator_ops twl4030ldo_ops = {
403*4882a593Smuzhiyun 	.list_voltage	= twl4030ldo_list_voltage,
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	.set_voltage_sel = twl4030ldo_set_voltage_sel,
406*4882a593Smuzhiyun 	.get_voltage_sel = twl4030ldo_get_voltage_sel,
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun 	.enable		= twl4030reg_enable,
409*4882a593Smuzhiyun 	.disable	= twl4030reg_disable,
410*4882a593Smuzhiyun 	.is_enabled	= twl4030reg_is_enabled,
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 	.set_mode	= twl4030reg_set_mode,
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	.get_status	= twl4030reg_get_status,
415*4882a593Smuzhiyun };
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun static int
twl4030smps_set_voltage(struct regulator_dev * rdev,int min_uV,int max_uV,unsigned * selector)418*4882a593Smuzhiyun twl4030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
419*4882a593Smuzhiyun 			unsigned *selector)
420*4882a593Smuzhiyun {
421*4882a593Smuzhiyun 	struct twlreg_info *info = rdev_get_drvdata(rdev);
422*4882a593Smuzhiyun 	int vsel = DIV_ROUND_UP(min_uV - 600000, 12500);
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS_4030, vsel);
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	return 0;
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun 
twl4030smps_get_voltage(struct regulator_dev * rdev)429*4882a593Smuzhiyun static int twl4030smps_get_voltage(struct regulator_dev *rdev)
430*4882a593Smuzhiyun {
431*4882a593Smuzhiyun 	struct twlreg_info *info = rdev_get_drvdata(rdev);
432*4882a593Smuzhiyun 	int vsel;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 	vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER,
435*4882a593Smuzhiyun 		VREG_VOLTAGE_SMPS_4030);
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	return vsel * 12500 + 600000;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun static const struct regulator_ops twl4030smps_ops = {
441*4882a593Smuzhiyun 	.list_voltage   = regulator_list_voltage_linear_range,
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	.set_voltage	= twl4030smps_set_voltage,
444*4882a593Smuzhiyun 	.get_voltage	= twl4030smps_get_voltage,
445*4882a593Smuzhiyun };
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun /*----------------------------------------------------------------------*/
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun static const struct regulator_ops twl4030fixed_ops = {
450*4882a593Smuzhiyun 	.list_voltage	= regulator_list_voltage_linear,
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	.enable		= twl4030reg_enable,
453*4882a593Smuzhiyun 	.disable	= twl4030reg_disable,
454*4882a593Smuzhiyun 	.is_enabled	= twl4030reg_is_enabled,
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 	.set_mode	= twl4030reg_set_mode,
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun 	.get_status	= twl4030reg_get_status,
459*4882a593Smuzhiyun };
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun /*----------------------------------------------------------------------*/
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun #define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) \
464*4882a593Smuzhiyun static const struct twlreg_info TWL4030_INFO_##label = { \
465*4882a593Smuzhiyun 	.base = offset, \
466*4882a593Smuzhiyun 	.id = num, \
467*4882a593Smuzhiyun 	.table_len = ARRAY_SIZE(label##_VSEL_table), \
468*4882a593Smuzhiyun 	.table = label##_VSEL_table, \
469*4882a593Smuzhiyun 	.remap = remap_conf, \
470*4882a593Smuzhiyun 	.desc = { \
471*4882a593Smuzhiyun 		.name = #label, \
472*4882a593Smuzhiyun 		.id = TWL4030_REG_##label, \
473*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(label##_VSEL_table), \
474*4882a593Smuzhiyun 		.ops = &twl4030ldo_ops, \
475*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE, \
476*4882a593Smuzhiyun 		.owner = THIS_MODULE, \
477*4882a593Smuzhiyun 		.enable_time = turnon_delay, \
478*4882a593Smuzhiyun 		.of_map_mode = twl4030reg_map_mode, \
479*4882a593Smuzhiyun 		}, \
480*4882a593Smuzhiyun 	}
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun #define TWL4030_ADJUSTABLE_SMPS(label, offset, num, turnon_delay, remap_conf, \
483*4882a593Smuzhiyun 		n_volt) \
484*4882a593Smuzhiyun static const struct twlreg_info TWL4030_INFO_##label = { \
485*4882a593Smuzhiyun 	.base = offset, \
486*4882a593Smuzhiyun 	.id = num, \
487*4882a593Smuzhiyun 	.remap = remap_conf, \
488*4882a593Smuzhiyun 	.desc = { \
489*4882a593Smuzhiyun 		.name = #label, \
490*4882a593Smuzhiyun 		.id = TWL4030_REG_##label, \
491*4882a593Smuzhiyun 		.ops = &twl4030smps_ops, \
492*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE, \
493*4882a593Smuzhiyun 		.owner = THIS_MODULE, \
494*4882a593Smuzhiyun 		.enable_time = turnon_delay, \
495*4882a593Smuzhiyun 		.of_map_mode = twl4030reg_map_mode, \
496*4882a593Smuzhiyun 		.n_voltages = n_volt, \
497*4882a593Smuzhiyun 		.n_linear_ranges = ARRAY_SIZE(label ## _ranges), \
498*4882a593Smuzhiyun 		.linear_ranges = label ## _ranges, \
499*4882a593Smuzhiyun 		}, \
500*4882a593Smuzhiyun 	}
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun #define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
503*4882a593Smuzhiyun 			remap_conf) \
504*4882a593Smuzhiyun static const struct twlreg_info TWLFIXED_INFO_##label = { \
505*4882a593Smuzhiyun 	.base = offset, \
506*4882a593Smuzhiyun 	.id = num, \
507*4882a593Smuzhiyun 	.remap = remap_conf, \
508*4882a593Smuzhiyun 	.desc = { \
509*4882a593Smuzhiyun 		.name = #label, \
510*4882a593Smuzhiyun 		.id = TWL4030##_REG_##label, \
511*4882a593Smuzhiyun 		.n_voltages = 1, \
512*4882a593Smuzhiyun 		.ops = &twl4030fixed_ops, \
513*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE, \
514*4882a593Smuzhiyun 		.owner = THIS_MODULE, \
515*4882a593Smuzhiyun 		.min_uV = mVolts * 1000, \
516*4882a593Smuzhiyun 		.enable_time = turnon_delay, \
517*4882a593Smuzhiyun 		.of_map_mode = twl4030reg_map_mode, \
518*4882a593Smuzhiyun 		}, \
519*4882a593Smuzhiyun 	}
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun /*
522*4882a593Smuzhiyun  * We list regulators here if systems need some level of
523*4882a593Smuzhiyun  * software control over them after boot.
524*4882a593Smuzhiyun  */
525*4882a593Smuzhiyun TWL4030_ADJUSTABLE_LDO(VAUX1, 0x17, 1, 100, 0x08);
526*4882a593Smuzhiyun TWL4030_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2, 100, 0x08);
527*4882a593Smuzhiyun TWL4030_ADJUSTABLE_LDO(VAUX2, 0x1b, 2, 100, 0x08);
528*4882a593Smuzhiyun TWL4030_ADJUSTABLE_LDO(VAUX3, 0x1f, 3, 100, 0x08);
529*4882a593Smuzhiyun TWL4030_ADJUSTABLE_LDO(VAUX4, 0x23, 4, 100, 0x08);
530*4882a593Smuzhiyun TWL4030_ADJUSTABLE_LDO(VMMC1, 0x27, 5, 100, 0x08);
531*4882a593Smuzhiyun TWL4030_ADJUSTABLE_LDO(VMMC2, 0x2b, 6, 100, 0x08);
532*4882a593Smuzhiyun TWL4030_ADJUSTABLE_LDO(VPLL1, 0x2f, 7, 100, 0x00);
533*4882a593Smuzhiyun TWL4030_ADJUSTABLE_LDO(VPLL2, 0x33, 8, 100, 0x08);
534*4882a593Smuzhiyun TWL4030_ADJUSTABLE_LDO(VSIM, 0x37, 9, 100, 0x00);
535*4882a593Smuzhiyun TWL4030_ADJUSTABLE_LDO(VDAC, 0x3b, 10, 100, 0x08);
536*4882a593Smuzhiyun TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12, 100, 0x08);
537*4882a593Smuzhiyun TWL4030_ADJUSTABLE_LDO(VIO, 0x4b, 14, 1000, 0x08);
538*4882a593Smuzhiyun TWL4030_ADJUSTABLE_SMPS(VDD1, 0x55, 15, 1000, 0x08, 68);
539*4882a593Smuzhiyun TWL4030_ADJUSTABLE_SMPS(VDD2, 0x63, 16, 1000, 0x08, 69);
540*4882a593Smuzhiyun /* VUSBCP is managed *only* by the USB subchip */
541*4882a593Smuzhiyun TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08);
542*4882a593Smuzhiyun TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08);
543*4882a593Smuzhiyun TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08);
544*4882a593Smuzhiyun TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08);
545*4882a593Smuzhiyun TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19, 150, 0x08);
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun #define TWL_OF_MATCH(comp, family, label) \
548*4882a593Smuzhiyun 	{ \
549*4882a593Smuzhiyun 		.compatible = comp, \
550*4882a593Smuzhiyun 		.data = &family##_INFO_##label, \
551*4882a593Smuzhiyun 	}
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun #define TWL4030_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL4030, label)
554*4882a593Smuzhiyun #define TWL6030_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6030, label)
555*4882a593Smuzhiyun #define TWL6032_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6032, label)
556*4882a593Smuzhiyun #define TWLFIXED_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLFIXED, label)
557*4882a593Smuzhiyun #define TWLSMPS_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLSMPS, label)
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun static const struct of_device_id twl_of_match[] = {
560*4882a593Smuzhiyun 	TWL4030_OF_MATCH("ti,twl4030-vaux1", VAUX1),
561*4882a593Smuzhiyun 	TWL4030_OF_MATCH("ti,twl4030-vaux2", VAUX2_4030),
562*4882a593Smuzhiyun 	TWL4030_OF_MATCH("ti,twl5030-vaux2", VAUX2),
563*4882a593Smuzhiyun 	TWL4030_OF_MATCH("ti,twl4030-vaux3", VAUX3),
564*4882a593Smuzhiyun 	TWL4030_OF_MATCH("ti,twl4030-vaux4", VAUX4),
565*4882a593Smuzhiyun 	TWL4030_OF_MATCH("ti,twl4030-vmmc1", VMMC1),
566*4882a593Smuzhiyun 	TWL4030_OF_MATCH("ti,twl4030-vmmc2", VMMC2),
567*4882a593Smuzhiyun 	TWL4030_OF_MATCH("ti,twl4030-vpll1", VPLL1),
568*4882a593Smuzhiyun 	TWL4030_OF_MATCH("ti,twl4030-vpll2", VPLL2),
569*4882a593Smuzhiyun 	TWL4030_OF_MATCH("ti,twl4030-vsim", VSIM),
570*4882a593Smuzhiyun 	TWL4030_OF_MATCH("ti,twl4030-vdac", VDAC),
571*4882a593Smuzhiyun 	TWL4030_OF_MATCH("ti,twl4030-vintana2", VINTANA2),
572*4882a593Smuzhiyun 	TWL4030_OF_MATCH("ti,twl4030-vio", VIO),
573*4882a593Smuzhiyun 	TWL4030_OF_MATCH("ti,twl4030-vdd1", VDD1),
574*4882a593Smuzhiyun 	TWL4030_OF_MATCH("ti,twl4030-vdd2", VDD2),
575*4882a593Smuzhiyun 	TWLFIXED_OF_MATCH("ti,twl4030-vintana1", VINTANA1),
576*4882a593Smuzhiyun 	TWLFIXED_OF_MATCH("ti,twl4030-vintdig", VINTDIG),
577*4882a593Smuzhiyun 	TWLFIXED_OF_MATCH("ti,twl4030-vusb1v5", VUSB1V5),
578*4882a593Smuzhiyun 	TWLFIXED_OF_MATCH("ti,twl4030-vusb1v8", VUSB1V8),
579*4882a593Smuzhiyun 	TWLFIXED_OF_MATCH("ti,twl4030-vusb3v1", VUSB3V1),
580*4882a593Smuzhiyun 	{},
581*4882a593Smuzhiyun };
582*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, twl_of_match);
583*4882a593Smuzhiyun 
twlreg_probe(struct platform_device * pdev)584*4882a593Smuzhiyun static int twlreg_probe(struct platform_device *pdev)
585*4882a593Smuzhiyun {
586*4882a593Smuzhiyun 	int id;
587*4882a593Smuzhiyun 	struct twlreg_info		*info;
588*4882a593Smuzhiyun 	const struct twlreg_info	*template;
589*4882a593Smuzhiyun 	struct regulator_init_data	*initdata;
590*4882a593Smuzhiyun 	struct regulation_constraints	*c;
591*4882a593Smuzhiyun 	struct regulator_dev		*rdev;
592*4882a593Smuzhiyun 	struct regulator_config		config = { };
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun 	template = of_device_get_match_data(&pdev->dev);
595*4882a593Smuzhiyun 	if (!template)
596*4882a593Smuzhiyun 		return -ENODEV;
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun 	id = template->desc.id;
599*4882a593Smuzhiyun 	initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
600*4882a593Smuzhiyun 						&template->desc);
601*4882a593Smuzhiyun 	if (!initdata)
602*4882a593Smuzhiyun 		return -EINVAL;
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun 	info = devm_kmemdup(&pdev->dev, template, sizeof(*info), GFP_KERNEL);
605*4882a593Smuzhiyun 	if (!info)
606*4882a593Smuzhiyun 		return -ENOMEM;
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun 	/* Constrain board-specific capabilities according to what
609*4882a593Smuzhiyun 	 * this driver and the chip itself can actually do.
610*4882a593Smuzhiyun 	 */
611*4882a593Smuzhiyun 	c = &initdata->constraints;
612*4882a593Smuzhiyun 	c->valid_modes_mask &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY;
613*4882a593Smuzhiyun 	c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE
614*4882a593Smuzhiyun 				| REGULATOR_CHANGE_MODE
615*4882a593Smuzhiyun 				| REGULATOR_CHANGE_STATUS;
616*4882a593Smuzhiyun 	switch (id) {
617*4882a593Smuzhiyun 	case TWL4030_REG_VIO:
618*4882a593Smuzhiyun 	case TWL4030_REG_VDD1:
619*4882a593Smuzhiyun 	case TWL4030_REG_VDD2:
620*4882a593Smuzhiyun 	case TWL4030_REG_VPLL1:
621*4882a593Smuzhiyun 	case TWL4030_REG_VINTANA1:
622*4882a593Smuzhiyun 	case TWL4030_REG_VINTANA2:
623*4882a593Smuzhiyun 	case TWL4030_REG_VINTDIG:
624*4882a593Smuzhiyun 		c->always_on = true;
625*4882a593Smuzhiyun 		break;
626*4882a593Smuzhiyun 	default:
627*4882a593Smuzhiyun 		break;
628*4882a593Smuzhiyun 	}
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun 	config.dev = &pdev->dev;
631*4882a593Smuzhiyun 	config.init_data = initdata;
632*4882a593Smuzhiyun 	config.driver_data = info;
633*4882a593Smuzhiyun 	config.of_node = pdev->dev.of_node;
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun 	rdev = devm_regulator_register(&pdev->dev, &info->desc, &config);
636*4882a593Smuzhiyun 	if (IS_ERR(rdev)) {
637*4882a593Smuzhiyun 		dev_err(&pdev->dev, "can't register %s, %ld\n",
638*4882a593Smuzhiyun 				info->desc.name, PTR_ERR(rdev));
639*4882a593Smuzhiyun 		return PTR_ERR(rdev);
640*4882a593Smuzhiyun 	}
641*4882a593Smuzhiyun 	platform_set_drvdata(pdev, rdev);
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP, info->remap);
644*4882a593Smuzhiyun 
645*4882a593Smuzhiyun 	/* NOTE:  many regulators support short-circuit IRQs (presentable
646*4882a593Smuzhiyun 	 * as REGULATOR_OVER_CURRENT notifications?) configured via:
647*4882a593Smuzhiyun 	 *  - SC_CONFIG
648*4882a593Smuzhiyun 	 *  - SC_DETECT1 (vintana2, vmmc1/2, vaux1/2/3/4)
649*4882a593Smuzhiyun 	 *  - SC_DETECT2 (vusb, vdac, vio, vdd1/2, vpll2)
650*4882a593Smuzhiyun 	 *  - IT_CONFIG
651*4882a593Smuzhiyun 	 */
652*4882a593Smuzhiyun 
653*4882a593Smuzhiyun 	return 0;
654*4882a593Smuzhiyun }
655*4882a593Smuzhiyun 
656*4882a593Smuzhiyun MODULE_ALIAS("platform:twl4030_reg");
657*4882a593Smuzhiyun 
658*4882a593Smuzhiyun static struct platform_driver twlreg_driver = {
659*4882a593Smuzhiyun 	.probe		= twlreg_probe,
660*4882a593Smuzhiyun 	/* NOTE: short name, to work around driver model truncation of
661*4882a593Smuzhiyun 	 * "twl_regulator.12" (and friends) to "twl_regulator.1".
662*4882a593Smuzhiyun 	 */
663*4882a593Smuzhiyun 	.driver  = {
664*4882a593Smuzhiyun 		.name  = "twl4030_reg",
665*4882a593Smuzhiyun 		.of_match_table = of_match_ptr(twl_of_match),
666*4882a593Smuzhiyun 	},
667*4882a593Smuzhiyun };
668*4882a593Smuzhiyun 
twlreg_init(void)669*4882a593Smuzhiyun static int __init twlreg_init(void)
670*4882a593Smuzhiyun {
671*4882a593Smuzhiyun 	return platform_driver_register(&twlreg_driver);
672*4882a593Smuzhiyun }
673*4882a593Smuzhiyun subsys_initcall(twlreg_init);
674*4882a593Smuzhiyun 
twlreg_exit(void)675*4882a593Smuzhiyun static void __exit twlreg_exit(void)
676*4882a593Smuzhiyun {
677*4882a593Smuzhiyun 	platform_driver_unregister(&twlreg_driver);
678*4882a593Smuzhiyun }
679*4882a593Smuzhiyun module_exit(twlreg_exit)
680*4882a593Smuzhiyun 
681*4882a593Smuzhiyun MODULE_DESCRIPTION("TWL4030 regulator driver");
682*4882a593Smuzhiyun MODULE_LICENSE("GPL");
683