xref: /OK3568_Linux_fs/kernel/drivers/regulator/tps6524x-regulator.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Regulator driver for TPS6524x PMIC
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2010 Texas Instruments
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * This program is free software; you can redistribute it and/or
7*4882a593Smuzhiyun  * modify it under the terms of the GNU General Public License as
8*4882a593Smuzhiyun  * published by the Free Software Foundation version 2.
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
11*4882a593Smuzhiyun  * whether express or implied; without even the implied warranty of
12*4882a593Smuzhiyun  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13*4882a593Smuzhiyun  * General Public License for more details.
14*4882a593Smuzhiyun  */
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include <linux/kernel.h>
17*4882a593Smuzhiyun #include <linux/module.h>
18*4882a593Smuzhiyun #include <linux/err.h>
19*4882a593Smuzhiyun #include <linux/errno.h>
20*4882a593Smuzhiyun #include <linux/slab.h>
21*4882a593Smuzhiyun #include <linux/spi/spi.h>
22*4882a593Smuzhiyun #include <linux/regulator/driver.h>
23*4882a593Smuzhiyun #include <linux/regulator/machine.h>
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define REG_LDO_SET		0x0
26*4882a593Smuzhiyun #define LDO_ILIM_MASK		1	/* 0 = 400-800, 1 = 900-1500 */
27*4882a593Smuzhiyun #define LDO_VSEL_MASK		0x0f
28*4882a593Smuzhiyun #define LDO2_ILIM_SHIFT		12
29*4882a593Smuzhiyun #define LDO2_VSEL_SHIFT		4
30*4882a593Smuzhiyun #define LDO1_ILIM_SHIFT		8
31*4882a593Smuzhiyun #define LDO1_VSEL_SHIFT		0
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #define REG_BLOCK_EN		0x1
34*4882a593Smuzhiyun #define BLOCK_MASK		1
35*4882a593Smuzhiyun #define BLOCK_LDO1_SHIFT	0
36*4882a593Smuzhiyun #define BLOCK_LDO2_SHIFT	1
37*4882a593Smuzhiyun #define BLOCK_LCD_SHIFT		2
38*4882a593Smuzhiyun #define BLOCK_USB_SHIFT		3
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun #define REG_DCDC_SET		0x2
41*4882a593Smuzhiyun #define DCDC_VDCDC_MASK		0x1f
42*4882a593Smuzhiyun #define DCDC_VDCDC1_SHIFT	0
43*4882a593Smuzhiyun #define DCDC_VDCDC2_SHIFT	5
44*4882a593Smuzhiyun #define DCDC_VDCDC3_SHIFT	10
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun #define REG_DCDC_EN		0x3
47*4882a593Smuzhiyun #define DCDCDCDC_EN_MASK	0x1
48*4882a593Smuzhiyun #define DCDCDCDC1_EN_SHIFT	0
49*4882a593Smuzhiyun #define DCDCDCDC1_PG_MSK	BIT(1)
50*4882a593Smuzhiyun #define DCDCDCDC2_EN_SHIFT	2
51*4882a593Smuzhiyun #define DCDCDCDC2_PG_MSK	BIT(3)
52*4882a593Smuzhiyun #define DCDCDCDC3_EN_SHIFT	4
53*4882a593Smuzhiyun #define DCDCDCDC3_PG_MSK	BIT(5)
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun #define REG_USB			0x4
56*4882a593Smuzhiyun #define USB_ILIM_SHIFT		0
57*4882a593Smuzhiyun #define USB_ILIM_MASK		0x3
58*4882a593Smuzhiyun #define USB_TSD_SHIFT		2
59*4882a593Smuzhiyun #define USB_TSD_MASK		0x3
60*4882a593Smuzhiyun #define USB_TWARN_SHIFT		4
61*4882a593Smuzhiyun #define USB_TWARN_MASK		0x3
62*4882a593Smuzhiyun #define USB_IWARN_SD		BIT(6)
63*4882a593Smuzhiyun #define USB_FAST_LOOP		BIT(7)
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun #define REG_ALARM		0x5
66*4882a593Smuzhiyun #define ALARM_LDO1		BIT(0)
67*4882a593Smuzhiyun #define ALARM_DCDC1		BIT(1)
68*4882a593Smuzhiyun #define ALARM_DCDC2		BIT(2)
69*4882a593Smuzhiyun #define ALARM_DCDC3		BIT(3)
70*4882a593Smuzhiyun #define ALARM_LDO2		BIT(4)
71*4882a593Smuzhiyun #define ALARM_USB_WARN		BIT(5)
72*4882a593Smuzhiyun #define ALARM_USB_ALARM		BIT(6)
73*4882a593Smuzhiyun #define ALARM_LCD		BIT(9)
74*4882a593Smuzhiyun #define ALARM_TEMP_WARM		BIT(10)
75*4882a593Smuzhiyun #define ALARM_TEMP_HOT		BIT(11)
76*4882a593Smuzhiyun #define ALARM_NRST		BIT(14)
77*4882a593Smuzhiyun #define ALARM_POWERUP		BIT(15)
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun #define REG_INT_ENABLE		0x6
80*4882a593Smuzhiyun #define INT_LDO1		BIT(0)
81*4882a593Smuzhiyun #define INT_DCDC1		BIT(1)
82*4882a593Smuzhiyun #define INT_DCDC2		BIT(2)
83*4882a593Smuzhiyun #define INT_DCDC3		BIT(3)
84*4882a593Smuzhiyun #define INT_LDO2		BIT(4)
85*4882a593Smuzhiyun #define INT_USB_WARN		BIT(5)
86*4882a593Smuzhiyun #define INT_USB_ALARM		BIT(6)
87*4882a593Smuzhiyun #define INT_LCD			BIT(9)
88*4882a593Smuzhiyun #define INT_TEMP_WARM		BIT(10)
89*4882a593Smuzhiyun #define INT_TEMP_HOT		BIT(11)
90*4882a593Smuzhiyun #define INT_GLOBAL_EN		BIT(15)
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun #define REG_INT_STATUS		0x7
93*4882a593Smuzhiyun #define STATUS_LDO1		BIT(0)
94*4882a593Smuzhiyun #define STATUS_DCDC1		BIT(1)
95*4882a593Smuzhiyun #define STATUS_DCDC2		BIT(2)
96*4882a593Smuzhiyun #define STATUS_DCDC3		BIT(3)
97*4882a593Smuzhiyun #define STATUS_LDO2		BIT(4)
98*4882a593Smuzhiyun #define STATUS_USB_WARN		BIT(5)
99*4882a593Smuzhiyun #define STATUS_USB_ALARM	BIT(6)
100*4882a593Smuzhiyun #define STATUS_LCD		BIT(9)
101*4882a593Smuzhiyun #define STATUS_TEMP_WARM	BIT(10)
102*4882a593Smuzhiyun #define STATUS_TEMP_HOT		BIT(11)
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun #define REG_SOFTWARE_RESET	0xb
105*4882a593Smuzhiyun #define REG_WRITE_ENABLE	0xd
106*4882a593Smuzhiyun #define REG_REV_ID		0xf
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun #define N_DCDC			3
109*4882a593Smuzhiyun #define N_LDO			2
110*4882a593Smuzhiyun #define N_SWITCH		2
111*4882a593Smuzhiyun #define N_REGULATORS		(N_DCDC + N_LDO + N_SWITCH)
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun #define CMD_READ(reg)		((reg) << 6)
114*4882a593Smuzhiyun #define CMD_WRITE(reg)		(BIT(5) | (reg) << 6)
115*4882a593Smuzhiyun #define STAT_CLK		BIT(3)
116*4882a593Smuzhiyun #define STAT_WRITE		BIT(2)
117*4882a593Smuzhiyun #define STAT_INVALID		BIT(1)
118*4882a593Smuzhiyun #define STAT_WP			BIT(0)
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun struct field {
121*4882a593Smuzhiyun 	int		reg;
122*4882a593Smuzhiyun 	int		shift;
123*4882a593Smuzhiyun 	int		mask;
124*4882a593Smuzhiyun };
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun struct supply_info {
127*4882a593Smuzhiyun 	const char	*name;
128*4882a593Smuzhiyun 	int		n_voltages;
129*4882a593Smuzhiyun 	const unsigned int *voltages;
130*4882a593Smuzhiyun 	int		n_ilimsels;
131*4882a593Smuzhiyun 	const unsigned int *ilimsels;
132*4882a593Smuzhiyun 	struct field	enable, voltage, ilimsel;
133*4882a593Smuzhiyun };
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun struct tps6524x {
136*4882a593Smuzhiyun 	struct device		*dev;
137*4882a593Smuzhiyun 	struct spi_device	*spi;
138*4882a593Smuzhiyun 	struct mutex		lock;
139*4882a593Smuzhiyun 	struct regulator_desc	desc[N_REGULATORS];
140*4882a593Smuzhiyun };
141*4882a593Smuzhiyun 
__read_reg(struct tps6524x * hw,int reg)142*4882a593Smuzhiyun static int __read_reg(struct tps6524x *hw, int reg)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun 	int error = 0;
145*4882a593Smuzhiyun 	u16 cmd = CMD_READ(reg), in;
146*4882a593Smuzhiyun 	u8 status;
147*4882a593Smuzhiyun 	struct spi_message m;
148*4882a593Smuzhiyun 	struct spi_transfer t[3];
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	spi_message_init(&m);
151*4882a593Smuzhiyun 	memset(t, 0, sizeof(t));
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	t[0].tx_buf = &cmd;
154*4882a593Smuzhiyun 	t[0].len = 2;
155*4882a593Smuzhiyun 	t[0].bits_per_word = 12;
156*4882a593Smuzhiyun 	spi_message_add_tail(&t[0], &m);
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	t[1].rx_buf = &in;
159*4882a593Smuzhiyun 	t[1].len = 2;
160*4882a593Smuzhiyun 	t[1].bits_per_word = 16;
161*4882a593Smuzhiyun 	spi_message_add_tail(&t[1], &m);
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	t[2].rx_buf = &status;
164*4882a593Smuzhiyun 	t[2].len = 1;
165*4882a593Smuzhiyun 	t[2].bits_per_word = 4;
166*4882a593Smuzhiyun 	spi_message_add_tail(&t[2], &m);
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	error = spi_sync(hw->spi, &m);
169*4882a593Smuzhiyun 	if (error < 0)
170*4882a593Smuzhiyun 		return error;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	dev_dbg(hw->dev, "read reg %d, data %x, status %x\n",
173*4882a593Smuzhiyun 		reg, in, status);
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	if (!(status & STAT_CLK) || (status & STAT_WRITE))
176*4882a593Smuzhiyun 		return -EIO;
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	if (status & STAT_INVALID)
179*4882a593Smuzhiyun 		return -EINVAL;
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	return in;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun 
read_reg(struct tps6524x * hw,int reg)184*4882a593Smuzhiyun static int read_reg(struct tps6524x *hw, int reg)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun 	int ret;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	mutex_lock(&hw->lock);
189*4882a593Smuzhiyun 	ret = __read_reg(hw, reg);
190*4882a593Smuzhiyun 	mutex_unlock(&hw->lock);
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	return ret;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun 
__write_reg(struct tps6524x * hw,int reg,int val)195*4882a593Smuzhiyun static int __write_reg(struct tps6524x *hw, int reg, int val)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun 	int error = 0;
198*4882a593Smuzhiyun 	u16 cmd = CMD_WRITE(reg), out = val;
199*4882a593Smuzhiyun 	u8 status;
200*4882a593Smuzhiyun 	struct spi_message m;
201*4882a593Smuzhiyun 	struct spi_transfer t[3];
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	spi_message_init(&m);
204*4882a593Smuzhiyun 	memset(t, 0, sizeof(t));
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	t[0].tx_buf = &cmd;
207*4882a593Smuzhiyun 	t[0].len = 2;
208*4882a593Smuzhiyun 	t[0].bits_per_word = 12;
209*4882a593Smuzhiyun 	spi_message_add_tail(&t[0], &m);
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	t[1].tx_buf = &out;
212*4882a593Smuzhiyun 	t[1].len = 2;
213*4882a593Smuzhiyun 	t[1].bits_per_word = 16;
214*4882a593Smuzhiyun 	spi_message_add_tail(&t[1], &m);
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	t[2].rx_buf = &status;
217*4882a593Smuzhiyun 	t[2].len = 1;
218*4882a593Smuzhiyun 	t[2].bits_per_word = 4;
219*4882a593Smuzhiyun 	spi_message_add_tail(&t[2], &m);
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	error = spi_sync(hw->spi, &m);
222*4882a593Smuzhiyun 	if (error < 0)
223*4882a593Smuzhiyun 		return error;
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	dev_dbg(hw->dev, "wrote reg %d, data %x, status %x\n",
226*4882a593Smuzhiyun 		reg, out, status);
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	if (!(status & STAT_CLK) || !(status & STAT_WRITE))
229*4882a593Smuzhiyun 		return -EIO;
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	if (status & (STAT_INVALID | STAT_WP))
232*4882a593Smuzhiyun 		return -EINVAL;
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	return error;
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun 
__rmw_reg(struct tps6524x * hw,int reg,int mask,int val)237*4882a593Smuzhiyun static int __rmw_reg(struct tps6524x *hw, int reg, int mask, int val)
238*4882a593Smuzhiyun {
239*4882a593Smuzhiyun 	int ret;
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	ret = __read_reg(hw, reg);
242*4882a593Smuzhiyun 	if (ret < 0)
243*4882a593Smuzhiyun 		return ret;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	ret &= ~mask;
246*4882a593Smuzhiyun 	ret |= val;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	ret = __write_reg(hw, reg, ret);
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	return (ret < 0) ? ret : 0;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
rmw_protect(struct tps6524x * hw,int reg,int mask,int val)253*4882a593Smuzhiyun static int rmw_protect(struct tps6524x *hw, int reg, int mask, int val)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun 	int ret;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	mutex_lock(&hw->lock);
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	ret = __write_reg(hw, REG_WRITE_ENABLE, 1);
260*4882a593Smuzhiyun 	if (ret) {
261*4882a593Smuzhiyun 		dev_err(hw->dev, "failed to set write enable\n");
262*4882a593Smuzhiyun 		goto error;
263*4882a593Smuzhiyun 	}
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	ret = __rmw_reg(hw, reg, mask, val);
266*4882a593Smuzhiyun 	if (ret)
267*4882a593Smuzhiyun 		dev_err(hw->dev, "failed to rmw register %d\n", reg);
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	ret = __write_reg(hw, REG_WRITE_ENABLE, 0);
270*4882a593Smuzhiyun 	if (ret) {
271*4882a593Smuzhiyun 		dev_err(hw->dev, "failed to clear write enable\n");
272*4882a593Smuzhiyun 		goto error;
273*4882a593Smuzhiyun 	}
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun error:
276*4882a593Smuzhiyun 	mutex_unlock(&hw->lock);
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	return ret;
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun 
read_field(struct tps6524x * hw,const struct field * field)281*4882a593Smuzhiyun static int read_field(struct tps6524x *hw, const struct field *field)
282*4882a593Smuzhiyun {
283*4882a593Smuzhiyun 	int tmp;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	tmp = read_reg(hw, field->reg);
286*4882a593Smuzhiyun 	if (tmp < 0)
287*4882a593Smuzhiyun 		return tmp;
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	return (tmp >> field->shift) & field->mask;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun 
write_field(struct tps6524x * hw,const struct field * field,int val)292*4882a593Smuzhiyun static int write_field(struct tps6524x *hw, const struct field *field,
293*4882a593Smuzhiyun 		       int val)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun 	if (val & ~field->mask)
296*4882a593Smuzhiyun 		return -EOVERFLOW;
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	return rmw_protect(hw, field->reg,
299*4882a593Smuzhiyun 				    field->mask << field->shift,
300*4882a593Smuzhiyun 				    val << field->shift);
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun static const unsigned int dcdc1_voltages[] = {
304*4882a593Smuzhiyun 	 800000,  825000,  850000,  875000,
305*4882a593Smuzhiyun 	 900000,  925000,  950000,  975000,
306*4882a593Smuzhiyun 	1000000, 1025000, 1050000, 1075000,
307*4882a593Smuzhiyun 	1100000, 1125000, 1150000, 1175000,
308*4882a593Smuzhiyun 	1200000, 1225000, 1250000, 1275000,
309*4882a593Smuzhiyun 	1300000, 1325000, 1350000, 1375000,
310*4882a593Smuzhiyun 	1400000, 1425000, 1450000, 1475000,
311*4882a593Smuzhiyun 	1500000, 1525000, 1550000, 1575000,
312*4882a593Smuzhiyun };
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun static const unsigned int dcdc2_voltages[] = {
315*4882a593Smuzhiyun 	1400000, 1450000, 1500000, 1550000,
316*4882a593Smuzhiyun 	1600000, 1650000, 1700000, 1750000,
317*4882a593Smuzhiyun 	1800000, 1850000, 1900000, 1950000,
318*4882a593Smuzhiyun 	2000000, 2050000, 2100000, 2150000,
319*4882a593Smuzhiyun 	2200000, 2250000, 2300000, 2350000,
320*4882a593Smuzhiyun 	2400000, 2450000, 2500000, 2550000,
321*4882a593Smuzhiyun 	2600000, 2650000, 2700000, 2750000,
322*4882a593Smuzhiyun 	2800000, 2850000, 2900000, 2950000,
323*4882a593Smuzhiyun };
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun static const unsigned int dcdc3_voltages[] = {
326*4882a593Smuzhiyun 	2400000, 2450000, 2500000, 2550000, 2600000,
327*4882a593Smuzhiyun 	2650000, 2700000, 2750000, 2800000, 2850000,
328*4882a593Smuzhiyun 	2900000, 2950000, 3000000, 3050000, 3100000,
329*4882a593Smuzhiyun 	3150000, 3200000, 3250000, 3300000, 3350000,
330*4882a593Smuzhiyun 	3400000, 3450000, 3500000, 3550000, 3600000,
331*4882a593Smuzhiyun };
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun static const unsigned int ldo1_voltages[] = {
334*4882a593Smuzhiyun 	4300000, 4350000, 4400000, 4450000,
335*4882a593Smuzhiyun 	4500000, 4550000, 4600000, 4650000,
336*4882a593Smuzhiyun 	4700000, 4750000, 4800000, 4850000,
337*4882a593Smuzhiyun 	4900000, 4950000, 5000000, 5050000,
338*4882a593Smuzhiyun };
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun static const unsigned int ldo2_voltages[] = {
341*4882a593Smuzhiyun 	1100000, 1150000, 1200000, 1250000,
342*4882a593Smuzhiyun 	1300000, 1700000, 1750000, 1800000,
343*4882a593Smuzhiyun 	1850000, 1900000, 3150000, 3200000,
344*4882a593Smuzhiyun 	3250000, 3300000, 3350000, 3400000,
345*4882a593Smuzhiyun };
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun static const unsigned int fixed_5000000_voltage[] = {
348*4882a593Smuzhiyun 	5000000
349*4882a593Smuzhiyun };
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun static const unsigned int ldo_ilimsel[] = {
352*4882a593Smuzhiyun 	400000, 1500000
353*4882a593Smuzhiyun };
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun static const unsigned int usb_ilimsel[] = {
356*4882a593Smuzhiyun 	200000, 400000, 800000, 1000000
357*4882a593Smuzhiyun };
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun static const unsigned int fixed_2400000_ilimsel[] = {
360*4882a593Smuzhiyun 	2400000
361*4882a593Smuzhiyun };
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun static const unsigned int fixed_1200000_ilimsel[] = {
364*4882a593Smuzhiyun 	1200000
365*4882a593Smuzhiyun };
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun static const unsigned int fixed_400000_ilimsel[] = {
368*4882a593Smuzhiyun 	400000
369*4882a593Smuzhiyun };
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun #define __MK_FIELD(_reg, _mask, _shift) \
372*4882a593Smuzhiyun 	{ .reg = (_reg), .mask = (_mask), .shift = (_shift), }
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun static const struct supply_info supply_info[N_REGULATORS] = {
375*4882a593Smuzhiyun 	{
376*4882a593Smuzhiyun 		.name		= "DCDC1",
377*4882a593Smuzhiyun 		.n_voltages	= ARRAY_SIZE(dcdc1_voltages),
378*4882a593Smuzhiyun 		.voltages	= dcdc1_voltages,
379*4882a593Smuzhiyun 		.n_ilimsels	= ARRAY_SIZE(fixed_2400000_ilimsel),
380*4882a593Smuzhiyun 		.ilimsels	= fixed_2400000_ilimsel,
381*4882a593Smuzhiyun 		.enable		= __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
382*4882a593Smuzhiyun 					     DCDCDCDC1_EN_SHIFT),
383*4882a593Smuzhiyun 		.voltage	= __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
384*4882a593Smuzhiyun 					     DCDC_VDCDC1_SHIFT),
385*4882a593Smuzhiyun 	},
386*4882a593Smuzhiyun 	{
387*4882a593Smuzhiyun 		.name		= "DCDC2",
388*4882a593Smuzhiyun 		.n_voltages	= ARRAY_SIZE(dcdc2_voltages),
389*4882a593Smuzhiyun 		.voltages	= dcdc2_voltages,
390*4882a593Smuzhiyun 		.n_ilimsels	= ARRAY_SIZE(fixed_1200000_ilimsel),
391*4882a593Smuzhiyun 		.ilimsels	= fixed_1200000_ilimsel,
392*4882a593Smuzhiyun 		.enable		= __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
393*4882a593Smuzhiyun 					     DCDCDCDC2_EN_SHIFT),
394*4882a593Smuzhiyun 		.voltage	= __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
395*4882a593Smuzhiyun 					     DCDC_VDCDC2_SHIFT),
396*4882a593Smuzhiyun 	},
397*4882a593Smuzhiyun 	{
398*4882a593Smuzhiyun 		.name		= "DCDC3",
399*4882a593Smuzhiyun 		.n_voltages	= ARRAY_SIZE(dcdc3_voltages),
400*4882a593Smuzhiyun 		.voltages	= dcdc3_voltages,
401*4882a593Smuzhiyun 		.n_ilimsels	= ARRAY_SIZE(fixed_1200000_ilimsel),
402*4882a593Smuzhiyun 		.ilimsels	= fixed_1200000_ilimsel,
403*4882a593Smuzhiyun 		.enable		= __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
404*4882a593Smuzhiyun 					DCDCDCDC3_EN_SHIFT),
405*4882a593Smuzhiyun 		.voltage	= __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
406*4882a593Smuzhiyun 					     DCDC_VDCDC3_SHIFT),
407*4882a593Smuzhiyun 	},
408*4882a593Smuzhiyun 	{
409*4882a593Smuzhiyun 		.name		= "LDO1",
410*4882a593Smuzhiyun 		.n_voltages	= ARRAY_SIZE(ldo1_voltages),
411*4882a593Smuzhiyun 		.voltages	= ldo1_voltages,
412*4882a593Smuzhiyun 		.n_ilimsels	= ARRAY_SIZE(ldo_ilimsel),
413*4882a593Smuzhiyun 		.ilimsels	= ldo_ilimsel,
414*4882a593Smuzhiyun 		.enable		= __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
415*4882a593Smuzhiyun 					     BLOCK_LDO1_SHIFT),
416*4882a593Smuzhiyun 		.voltage	= __MK_FIELD(REG_LDO_SET, LDO_VSEL_MASK,
417*4882a593Smuzhiyun 					     LDO1_VSEL_SHIFT),
418*4882a593Smuzhiyun 		.ilimsel	= __MK_FIELD(REG_LDO_SET, LDO_ILIM_MASK,
419*4882a593Smuzhiyun 					     LDO1_ILIM_SHIFT),
420*4882a593Smuzhiyun 	},
421*4882a593Smuzhiyun 	{
422*4882a593Smuzhiyun 		.name		= "LDO2",
423*4882a593Smuzhiyun 		.n_voltages	= ARRAY_SIZE(ldo2_voltages),
424*4882a593Smuzhiyun 		.voltages	= ldo2_voltages,
425*4882a593Smuzhiyun 		.n_ilimsels	= ARRAY_SIZE(ldo_ilimsel),
426*4882a593Smuzhiyun 		.ilimsels	= ldo_ilimsel,
427*4882a593Smuzhiyun 		.enable		= __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
428*4882a593Smuzhiyun 					     BLOCK_LDO2_SHIFT),
429*4882a593Smuzhiyun 		.voltage	= __MK_FIELD(REG_LDO_SET, LDO_VSEL_MASK,
430*4882a593Smuzhiyun 					     LDO2_VSEL_SHIFT),
431*4882a593Smuzhiyun 		.ilimsel	= __MK_FIELD(REG_LDO_SET, LDO_ILIM_MASK,
432*4882a593Smuzhiyun 					     LDO2_ILIM_SHIFT),
433*4882a593Smuzhiyun 	},
434*4882a593Smuzhiyun 	{
435*4882a593Smuzhiyun 		.name		= "USB",
436*4882a593Smuzhiyun 		.n_voltages	= ARRAY_SIZE(fixed_5000000_voltage),
437*4882a593Smuzhiyun 		.voltages	= fixed_5000000_voltage,
438*4882a593Smuzhiyun 		.n_ilimsels	= ARRAY_SIZE(usb_ilimsel),
439*4882a593Smuzhiyun 		.ilimsels	= usb_ilimsel,
440*4882a593Smuzhiyun 		.enable		= __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
441*4882a593Smuzhiyun 					     BLOCK_USB_SHIFT),
442*4882a593Smuzhiyun 		.ilimsel	= __MK_FIELD(REG_USB, USB_ILIM_MASK,
443*4882a593Smuzhiyun 					     USB_ILIM_SHIFT),
444*4882a593Smuzhiyun 	},
445*4882a593Smuzhiyun 	{
446*4882a593Smuzhiyun 		.name		= "LCD",
447*4882a593Smuzhiyun 		.n_voltages	= ARRAY_SIZE(fixed_5000000_voltage),
448*4882a593Smuzhiyun 		.voltages	= fixed_5000000_voltage,
449*4882a593Smuzhiyun 		.n_ilimsels	= ARRAY_SIZE(fixed_400000_ilimsel),
450*4882a593Smuzhiyun 		.ilimsels	= fixed_400000_ilimsel,
451*4882a593Smuzhiyun 		.enable		= __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
452*4882a593Smuzhiyun 					     BLOCK_LCD_SHIFT),
453*4882a593Smuzhiyun 	},
454*4882a593Smuzhiyun };
455*4882a593Smuzhiyun 
set_voltage_sel(struct regulator_dev * rdev,unsigned selector)456*4882a593Smuzhiyun static int set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun 	const struct supply_info *info;
459*4882a593Smuzhiyun 	struct tps6524x *hw;
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	hw	= rdev_get_drvdata(rdev);
462*4882a593Smuzhiyun 	info	= &supply_info[rdev_get_id(rdev)];
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	if (rdev->desc->n_voltages == 1)
465*4882a593Smuzhiyun 		return -EINVAL;
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	return write_field(hw, &info->voltage, selector);
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun 
get_voltage_sel(struct regulator_dev * rdev)470*4882a593Smuzhiyun static int get_voltage_sel(struct regulator_dev *rdev)
471*4882a593Smuzhiyun {
472*4882a593Smuzhiyun 	const struct supply_info *info;
473*4882a593Smuzhiyun 	struct tps6524x *hw;
474*4882a593Smuzhiyun 	int ret;
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	hw	= rdev_get_drvdata(rdev);
477*4882a593Smuzhiyun 	info	= &supply_info[rdev_get_id(rdev)];
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	if (rdev->desc->n_voltages == 1)
480*4882a593Smuzhiyun 		return 0;
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	ret = read_field(hw, &info->voltage);
483*4882a593Smuzhiyun 	if (ret < 0)
484*4882a593Smuzhiyun 		return ret;
485*4882a593Smuzhiyun 	if (WARN_ON(ret >= info->n_voltages))
486*4882a593Smuzhiyun 		return -EIO;
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	return ret;
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun 
set_current_limit(struct regulator_dev * rdev,int min_uA,int max_uA)491*4882a593Smuzhiyun static int set_current_limit(struct regulator_dev *rdev, int min_uA,
492*4882a593Smuzhiyun 			     int max_uA)
493*4882a593Smuzhiyun {
494*4882a593Smuzhiyun 	const struct supply_info *info;
495*4882a593Smuzhiyun 	struct tps6524x *hw;
496*4882a593Smuzhiyun 	int i;
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	hw	= rdev_get_drvdata(rdev);
499*4882a593Smuzhiyun 	info	= &supply_info[rdev_get_id(rdev)];
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 	if (info->n_ilimsels == 1)
502*4882a593Smuzhiyun 		return -EINVAL;
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun 	for (i = info->n_ilimsels - 1; i >= 0; i--) {
505*4882a593Smuzhiyun 		if (min_uA <= info->ilimsels[i] &&
506*4882a593Smuzhiyun 		    max_uA >= info->ilimsels[i])
507*4882a593Smuzhiyun 			return write_field(hw, &info->ilimsel, i);
508*4882a593Smuzhiyun 	}
509*4882a593Smuzhiyun 
510*4882a593Smuzhiyun 	return -EINVAL;
511*4882a593Smuzhiyun }
512*4882a593Smuzhiyun 
get_current_limit(struct regulator_dev * rdev)513*4882a593Smuzhiyun static int get_current_limit(struct regulator_dev *rdev)
514*4882a593Smuzhiyun {
515*4882a593Smuzhiyun 	const struct supply_info *info;
516*4882a593Smuzhiyun 	struct tps6524x *hw;
517*4882a593Smuzhiyun 	int ret;
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun 	hw	= rdev_get_drvdata(rdev);
520*4882a593Smuzhiyun 	info	= &supply_info[rdev_get_id(rdev)];
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun 	if (info->n_ilimsels == 1)
523*4882a593Smuzhiyun 		return info->ilimsels[0];
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	ret = read_field(hw, &info->ilimsel);
526*4882a593Smuzhiyun 	if (ret < 0)
527*4882a593Smuzhiyun 		return ret;
528*4882a593Smuzhiyun 	if (WARN_ON(ret >= info->n_ilimsels))
529*4882a593Smuzhiyun 		return -EIO;
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 	return info->ilimsels[ret];
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun 
enable_supply(struct regulator_dev * rdev)534*4882a593Smuzhiyun static int enable_supply(struct regulator_dev *rdev)
535*4882a593Smuzhiyun {
536*4882a593Smuzhiyun 	const struct supply_info *info;
537*4882a593Smuzhiyun 	struct tps6524x *hw;
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 	hw	= rdev_get_drvdata(rdev);
540*4882a593Smuzhiyun 	info	= &supply_info[rdev_get_id(rdev)];
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 	return write_field(hw, &info->enable, 1);
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun 
disable_supply(struct regulator_dev * rdev)545*4882a593Smuzhiyun static int disable_supply(struct regulator_dev *rdev)
546*4882a593Smuzhiyun {
547*4882a593Smuzhiyun 	const struct supply_info *info;
548*4882a593Smuzhiyun 	struct tps6524x *hw;
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun 	hw	= rdev_get_drvdata(rdev);
551*4882a593Smuzhiyun 	info	= &supply_info[rdev_get_id(rdev)];
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	return write_field(hw, &info->enable, 0);
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun 
is_supply_enabled(struct regulator_dev * rdev)556*4882a593Smuzhiyun static int is_supply_enabled(struct regulator_dev *rdev)
557*4882a593Smuzhiyun {
558*4882a593Smuzhiyun 	const struct supply_info *info;
559*4882a593Smuzhiyun 	struct tps6524x *hw;
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun 	hw	= rdev_get_drvdata(rdev);
562*4882a593Smuzhiyun 	info	= &supply_info[rdev_get_id(rdev)];
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	return read_field(hw, &info->enable);
565*4882a593Smuzhiyun }
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun static const struct regulator_ops regulator_ops = {
568*4882a593Smuzhiyun 	.is_enabled		= is_supply_enabled,
569*4882a593Smuzhiyun 	.enable			= enable_supply,
570*4882a593Smuzhiyun 	.disable		= disable_supply,
571*4882a593Smuzhiyun 	.get_voltage_sel	= get_voltage_sel,
572*4882a593Smuzhiyun 	.set_voltage_sel	= set_voltage_sel,
573*4882a593Smuzhiyun 	.list_voltage		= regulator_list_voltage_table,
574*4882a593Smuzhiyun 	.map_voltage		= regulator_map_voltage_ascend,
575*4882a593Smuzhiyun 	.set_current_limit	= set_current_limit,
576*4882a593Smuzhiyun 	.get_current_limit	= get_current_limit,
577*4882a593Smuzhiyun };
578*4882a593Smuzhiyun 
pmic_probe(struct spi_device * spi)579*4882a593Smuzhiyun static int pmic_probe(struct spi_device *spi)
580*4882a593Smuzhiyun {
581*4882a593Smuzhiyun 	struct tps6524x *hw;
582*4882a593Smuzhiyun 	struct device *dev = &spi->dev;
583*4882a593Smuzhiyun 	const struct supply_info *info = supply_info;
584*4882a593Smuzhiyun 	struct regulator_init_data *init_data;
585*4882a593Smuzhiyun 	struct regulator_config config = { };
586*4882a593Smuzhiyun 	struct regulator_dev *rdev;
587*4882a593Smuzhiyun 	int i;
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	init_data = dev_get_platdata(dev);
590*4882a593Smuzhiyun 	if (!init_data) {
591*4882a593Smuzhiyun 		dev_err(dev, "could not find regulator platform data\n");
592*4882a593Smuzhiyun 		return -EINVAL;
593*4882a593Smuzhiyun 	}
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun 	hw = devm_kzalloc(&spi->dev, sizeof(struct tps6524x), GFP_KERNEL);
596*4882a593Smuzhiyun 	if (!hw)
597*4882a593Smuzhiyun 		return -ENOMEM;
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun 	spi_set_drvdata(spi, hw);
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 	memset(hw, 0, sizeof(struct tps6524x));
602*4882a593Smuzhiyun 	hw->dev = dev;
603*4882a593Smuzhiyun 	hw->spi = spi;
604*4882a593Smuzhiyun 	mutex_init(&hw->lock);
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	for (i = 0; i < N_REGULATORS; i++, info++, init_data++) {
607*4882a593Smuzhiyun 		hw->desc[i].name	= info->name;
608*4882a593Smuzhiyun 		hw->desc[i].id		= i;
609*4882a593Smuzhiyun 		hw->desc[i].n_voltages	= info->n_voltages;
610*4882a593Smuzhiyun 		hw->desc[i].volt_table	= info->voltages;
611*4882a593Smuzhiyun 		hw->desc[i].ops		= &regulator_ops;
612*4882a593Smuzhiyun 		hw->desc[i].type	= REGULATOR_VOLTAGE;
613*4882a593Smuzhiyun 		hw->desc[i].owner	= THIS_MODULE;
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun 		config.dev = dev;
616*4882a593Smuzhiyun 		config.init_data = init_data;
617*4882a593Smuzhiyun 		config.driver_data = hw;
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 		rdev = devm_regulator_register(dev, &hw->desc[i], &config);
620*4882a593Smuzhiyun 		if (IS_ERR(rdev))
621*4882a593Smuzhiyun 			return PTR_ERR(rdev);
622*4882a593Smuzhiyun 	}
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun 	return 0;
625*4882a593Smuzhiyun }
626*4882a593Smuzhiyun 
627*4882a593Smuzhiyun static struct spi_driver pmic_driver = {
628*4882a593Smuzhiyun 	.probe		= pmic_probe,
629*4882a593Smuzhiyun 	.driver		= {
630*4882a593Smuzhiyun 		.name	= "tps6524x",
631*4882a593Smuzhiyun 	},
632*4882a593Smuzhiyun };
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun module_spi_driver(pmic_driver);
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun MODULE_DESCRIPTION("TPS6524X PMIC Driver");
637*4882a593Smuzhiyun MODULE_AUTHOR("Cyril Chemparathy");
638*4882a593Smuzhiyun MODULE_LICENSE("GPL");
639*4882a593Smuzhiyun MODULE_ALIAS("spi:tps6524x");
640