Blame view

drivers/regulator/mc13892-regulator.c 20.1 KB
0f5683990   Fabio Estevam   regulator: mc1389...
1
2
3
4
5
6
7
  // SPDX-License-Identifier: GPL-2.0
  //
  // Regulator Driver for Freescale MC13892 PMIC
  //
  // Copyright 2010 Yong Shen <yong.shen@linaro.org>
  //
  // Based on draft driver from Arnaud Patard <arnaud.patard@rtp-net.org>
5e428d5ce   Yong Shen   regulator: suppor...
8
9
10
11
12
13
14
15
16
  
  #include <linux/mfd/mc13892.h>
  #include <linux/regulator/machine.h>
  #include <linux/regulator/driver.h>
  #include <linux/platform_device.h>
  #include <linux/kernel.h>
  #include <linux/slab.h>
  #include <linux/init.h>
  #include <linux/err.h>
65602c32e   Paul Gortmaker   regulator: Add mo...
17
  #include <linux/module.h>
5e428d5ce   Yong Shen   regulator: suppor...
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
  #include "mc13xxx.h"
  
  #define MC13892_REVISION			7
  
  #define MC13892_POWERCTL0			13
  #define MC13892_POWERCTL0_USEROFFSPI		3
  #define MC13892_POWERCTL0_VCOINCELLVSEL		20
  #define MC13892_POWERCTL0_VCOINCELLVSEL_M	(7<<20)
  #define MC13892_POWERCTL0_VCOINCELLEN		(1<<23)
  
  #define MC13892_SWITCHERS0_SWxHI		(1<<23)
  
  #define MC13892_SWITCHERS0			24
  #define MC13892_SWITCHERS0_SW1VSEL		0
  #define MC13892_SWITCHERS0_SW1VSEL_M		(0x1f<<0)
  #define MC13892_SWITCHERS0_SW1HI		(1<<23)
  #define MC13892_SWITCHERS0_SW1EN		0
  
  #define MC13892_SWITCHERS1			25
  #define MC13892_SWITCHERS1_SW2VSEL		0
  #define MC13892_SWITCHERS1_SW2VSEL_M		(0x1f<<0)
  #define MC13892_SWITCHERS1_SW2HI		(1<<23)
  #define MC13892_SWITCHERS1_SW2EN		0
  
  #define MC13892_SWITCHERS2			26
  #define MC13892_SWITCHERS2_SW3VSEL		0
  #define MC13892_SWITCHERS2_SW3VSEL_M		(0x1f<<0)
  #define MC13892_SWITCHERS2_SW3HI		(1<<23)
  #define MC13892_SWITCHERS2_SW3EN		0
  
  #define MC13892_SWITCHERS3			27
  #define MC13892_SWITCHERS3_SW4VSEL		0
  #define MC13892_SWITCHERS3_SW4VSEL_M		(0x1f<<0)
  #define MC13892_SWITCHERS3_SW4HI		(1<<23)
  #define MC13892_SWITCHERS3_SW4EN		0
  
  #define MC13892_SWITCHERS4			28
  #define MC13892_SWITCHERS4_SW1MODE		0
  #define MC13892_SWITCHERS4_SW1MODE_AUTO		(8<<0)
  #define MC13892_SWITCHERS4_SW1MODE_M		(0xf<<0)
  #define MC13892_SWITCHERS4_SW2MODE		10
  #define MC13892_SWITCHERS4_SW2MODE_AUTO		(8<<10)
  #define MC13892_SWITCHERS4_SW2MODE_M		(0xf<<10)
  
  #define MC13892_SWITCHERS5			29
  #define MC13892_SWITCHERS5_SW3MODE		0
  #define MC13892_SWITCHERS5_SW3MODE_AUTO		(8<<0)
  #define MC13892_SWITCHERS5_SW3MODE_M		(0xf<<0)
  #define MC13892_SWITCHERS5_SW4MODE		8
  #define MC13892_SWITCHERS5_SW4MODE_AUTO		(8<<8)
  #define MC13892_SWITCHERS5_SW4MODE_M		(0xf<<8)
  #define MC13892_SWITCHERS5_SWBSTEN		(1<<20)
  
  #define MC13892_REGULATORSETTING0		30
  #define MC13892_REGULATORSETTING0_VGEN1VSEL	0
  #define MC13892_REGULATORSETTING0_VDIGVSEL	4
  #define MC13892_REGULATORSETTING0_VGEN2VSEL	6
  #define MC13892_REGULATORSETTING0_VPLLVSEL	9
  #define MC13892_REGULATORSETTING0_VUSB2VSEL	11
  #define MC13892_REGULATORSETTING0_VGEN3VSEL	14
  #define MC13892_REGULATORSETTING0_VCAMVSEL	16
  
  #define MC13892_REGULATORSETTING0_VGEN1VSEL_M	(3<<0)
  #define MC13892_REGULATORSETTING0_VDIGVSEL_M	(3<<4)
  #define MC13892_REGULATORSETTING0_VGEN2VSEL_M	(7<<6)
  #define MC13892_REGULATORSETTING0_VPLLVSEL_M	(3<<9)
  #define MC13892_REGULATORSETTING0_VUSB2VSEL_M	(3<<11)
  #define MC13892_REGULATORSETTING0_VGEN3VSEL_M	(1<<14)
  #define MC13892_REGULATORSETTING0_VCAMVSEL_M	(3<<16)
  
  #define MC13892_REGULATORSETTING1		31
  #define MC13892_REGULATORSETTING1_VVIDEOVSEL	2
  #define MC13892_REGULATORSETTING1_VAUDIOVSEL	4
  #define MC13892_REGULATORSETTING1_VSDVSEL	6
  
  #define MC13892_REGULATORSETTING1_VVIDEOVSEL_M	(3<<2)
  #define MC13892_REGULATORSETTING1_VAUDIOVSEL_M	(3<<4)
  #define MC13892_REGULATORSETTING1_VSDVSEL_M	(7<<6)
  
  #define MC13892_REGULATORMODE0			32
  #define MC13892_REGULATORMODE0_VGEN1EN		(1<<0)
  #define MC13892_REGULATORMODE0_VGEN1STDBY	(1<<1)
  #define MC13892_REGULATORMODE0_VGEN1MODE	(1<<2)
  #define MC13892_REGULATORMODE0_VIOHIEN		(1<<3)
  #define MC13892_REGULATORMODE0_VIOHISTDBY	(1<<4)
  #define MC13892_REGULATORMODE0_VIOHIMODE	(1<<5)
  #define MC13892_REGULATORMODE0_VDIGEN		(1<<9)
  #define MC13892_REGULATORMODE0_VDIGSTDBY	(1<<10)
  #define MC13892_REGULATORMODE0_VDIGMODE		(1<<11)
  #define MC13892_REGULATORMODE0_VGEN2EN		(1<<12)
  #define MC13892_REGULATORMODE0_VGEN2STDBY	(1<<13)
  #define MC13892_REGULATORMODE0_VGEN2MODE	(1<<14)
  #define MC13892_REGULATORMODE0_VPLLEN		(1<<15)
  #define MC13892_REGULATORMODE0_VPLLSTDBY	(1<<16)
  #define MC13892_REGULATORMODE0_VPLLMODE		(1<<17)
  #define MC13892_REGULATORMODE0_VUSB2EN		(1<<18)
  #define MC13892_REGULATORMODE0_VUSB2STDBY	(1<<19)
  #define MC13892_REGULATORMODE0_VUSB2MODE	(1<<20)
  
  #define MC13892_REGULATORMODE1			33
  #define MC13892_REGULATORMODE1_VGEN3EN		(1<<0)
  #define MC13892_REGULATORMODE1_VGEN3STDBY	(1<<1)
  #define MC13892_REGULATORMODE1_VGEN3MODE	(1<<2)
  #define MC13892_REGULATORMODE1_VCAMEN		(1<<6)
  #define MC13892_REGULATORMODE1_VCAMSTDBY	(1<<7)
  #define MC13892_REGULATORMODE1_VCAMMODE		(1<<8)
  #define MC13892_REGULATORMODE1_VCAMCONFIGEN	(1<<9)
  #define MC13892_REGULATORMODE1_VVIDEOEN		(1<<12)
  #define MC13892_REGULATORMODE1_VVIDEOSTDBY	(1<<13)
  #define MC13892_REGULATORMODE1_VVIDEOMODE	(1<<14)
  #define MC13892_REGULATORMODE1_VAUDIOEN		(1<<15)
  #define MC13892_REGULATORMODE1_VAUDIOSTDBY	(1<<16)
  #define MC13892_REGULATORMODE1_VAUDIOMODE	(1<<17)
  #define MC13892_REGULATORMODE1_VSDEN		(1<<18)
  #define MC13892_REGULATORMODE1_VSDSTDBY		(1<<19)
  #define MC13892_REGULATORMODE1_VSDMODE		(1<<20)
  
  #define MC13892_POWERMISC			34
  #define MC13892_POWERMISC_GPO1EN		(1<<6)
  #define MC13892_POWERMISC_GPO2EN		(1<<8)
  #define MC13892_POWERMISC_GPO3EN		(1<<10)
  #define MC13892_POWERMISC_GPO4EN		(1<<12)
  #define MC13892_POWERMISC_PWGT1SPIEN		(1<<15)
  #define MC13892_POWERMISC_PWGT2SPIEN		(1<<16)
  #define MC13892_POWERMISC_GPO4ADINEN		(1<<21)
  
  #define MC13892_POWERMISC_PWGTSPI_M		(3 << 15)
  
  #define MC13892_USB1				50
  #define MC13892_USB1_VUSBEN			(1<<3)
34e74f39f   Axel Lin   regulator: mc13xx...
148
  static const unsigned int mc13892_vcoincell[] = {
5e428d5ce   Yong Shen   regulator: suppor...
149
150
151
  	2500000, 2700000, 2800000, 2900000, 3000000, 3100000,
  	3200000, 3300000,
  };
34e74f39f   Axel Lin   regulator: mc13xx...
152
  static const unsigned int mc13892_sw1[] = {
5e428d5ce   Yong Shen   regulator: suppor...
153
154
155
156
157
158
159
  	600000,   625000,  650000,  675000,  700000,  725000,
  	750000,   775000,  800000,  825000,  850000,  875000,
  	900000,   925000,  950000,  975000, 1000000, 1025000,
  	1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
  	1200000, 1225000, 1250000, 1275000, 1300000, 1325000,
  	1350000, 1375000
  };
ccf3ed782   Matt Sealey   regulator: mc1389...
160
161
162
163
164
165
166
  /*
   * Note: this table is used to derive SWxVSEL by index into
   * the array. Offset the values by the index of 1100000uV
   * to get the actual register value for that voltage selector
   * if the HI bit is to be set as well.
   */
  #define MC13892_SWxHI_SEL_OFFSET		20
34e74f39f   Axel Lin   regulator: mc13xx...
167
  static const unsigned int mc13892_sw[] = {
5e428d5ce   Yong Shen   regulator: suppor...
168
169
170
171
172
173
174
175
176
177
  	600000,   625000,  650000,  675000,  700000,  725000,
  	750000,   775000,  800000,  825000,  850000,  875000,
  	900000,   925000,  950000,  975000, 1000000, 1025000,
  	1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
  	1200000, 1225000, 1250000, 1275000, 1300000, 1325000,
  	1350000, 1375000, 1400000, 1425000, 1450000, 1475000,
  	1500000, 1525000, 1550000, 1575000, 1600000, 1625000,
  	1650000, 1675000, 1700000, 1725000, 1750000, 1775000,
  	1800000, 1825000, 1850000, 1875000
  };
34e74f39f   Axel Lin   regulator: mc13xx...
178
  static const unsigned int mc13892_swbst[] = {
5e428d5ce   Yong Shen   regulator: suppor...
179
180
  	5000000,
  };
34e74f39f   Axel Lin   regulator: mc13xx...
181
  static const unsigned int mc13892_viohi[] = {
5e428d5ce   Yong Shen   regulator: suppor...
182
183
  	2775000,
  };
34e74f39f   Axel Lin   regulator: mc13xx...
184
  static const unsigned int mc13892_vpll[] = {
5e428d5ce   Yong Shen   regulator: suppor...
185
186
  	1050000, 1250000, 1650000, 1800000,
  };
34e74f39f   Axel Lin   regulator: mc13xx...
187
  static const unsigned int mc13892_vdig[] = {
5e428d5ce   Yong Shen   regulator: suppor...
188
189
  	1050000, 1250000, 1650000, 1800000,
  };
34e74f39f   Axel Lin   regulator: mc13xx...
190
  static const unsigned int mc13892_vsd[] = {
5e428d5ce   Yong Shen   regulator: suppor...
191
192
193
  	1800000, 2000000, 2600000, 2700000,
  	2800000, 2900000, 3000000, 3150000,
  };
34e74f39f   Axel Lin   regulator: mc13xx...
194
  static const unsigned int mc13892_vusb2[] = {
5e428d5ce   Yong Shen   regulator: suppor...
195
196
  	2400000, 2600000, 2700000, 2775000,
  };
34e74f39f   Axel Lin   regulator: mc13xx...
197
  static const unsigned int mc13892_vvideo[] = {
5e428d5ce   Yong Shen   regulator: suppor...
198
199
  	2700000, 2775000, 2500000, 2600000,
  };
34e74f39f   Axel Lin   regulator: mc13xx...
200
  static const unsigned int mc13892_vaudio[] = {
5e428d5ce   Yong Shen   regulator: suppor...
201
202
  	2300000, 2500000, 2775000, 3000000,
  };
34e74f39f   Axel Lin   regulator: mc13xx...
203
  static const unsigned int mc13892_vcam[] = {
5e428d5ce   Yong Shen   regulator: suppor...
204
205
  	2500000, 2600000, 2750000, 3000000,
  };
34e74f39f   Axel Lin   regulator: mc13xx...
206
  static const unsigned int mc13892_vgen1[] = {
5e428d5ce   Yong Shen   regulator: suppor...
207
208
  	1200000, 1500000, 2775000, 3150000,
  };
34e74f39f   Axel Lin   regulator: mc13xx...
209
  static const unsigned int mc13892_vgen2[] = {
5e428d5ce   Yong Shen   regulator: suppor...
210
211
212
  	1200000, 1500000, 1600000, 1800000,
  	2700000, 2800000, 3000000, 3150000,
  };
34e74f39f   Axel Lin   regulator: mc13xx...
213
  static const unsigned int mc13892_vgen3[] = {
5e428d5ce   Yong Shen   regulator: suppor...
214
215
  	1800000, 2900000,
  };
34e74f39f   Axel Lin   regulator: mc13xx...
216
  static const unsigned int mc13892_vusb[] = {
5e428d5ce   Yong Shen   regulator: suppor...
217
218
  	3300000,
  };
34e74f39f   Axel Lin   regulator: mc13xx...
219
  static const unsigned int mc13892_gpo[] = {
5e428d5ce   Yong Shen   regulator: suppor...
220
221
  	2750000,
  };
34e74f39f   Axel Lin   regulator: mc13xx...
222
  static const unsigned int mc13892_pwgtdrv[] = {
5e428d5ce   Yong Shen   regulator: suppor...
223
224
  	5000000,
  };
e5680c4de   Axel Lin   regulator: mc13xx...
225
226
  static const struct regulator_ops mc13892_gpo_regulator_ops;
  static const struct regulator_ops mc13892_sw_regulator_ops;
5e428d5ce   Yong Shen   regulator: suppor...
227

ec520911e   Rob Herring   regulator: mc13xx...
228
229
  #define MC13892_FIXED_DEFINE(name, node, reg, voltages)			\
  	MC13xxx_FIXED_DEFINE(MC13892_, name, node, reg, voltages,	\
5e428d5ce   Yong Shen   regulator: suppor...
230
  			mc13xxx_fixed_regulator_ops)
ec520911e   Rob Herring   regulator: mc13xx...
231
232
  #define MC13892_GPO_DEFINE(name, node, reg, voltages)			\
  	MC13xxx_GPO_DEFINE(MC13892_, name, node, reg, voltages,		\
5e428d5ce   Yong Shen   regulator: suppor...
233
  			mc13892_gpo_regulator_ops)
ec520911e   Rob Herring   regulator: mc13xx...
234
235
  #define MC13892_SW_DEFINE(name, node, reg, vsel_reg, voltages)		\
  	MC13xxx_DEFINE(MC13892_, name, node, reg, vsel_reg, voltages,	\
5e428d5ce   Yong Shen   regulator: suppor...
236
  			mc13892_sw_regulator_ops)
ec520911e   Rob Herring   regulator: mc13xx...
237
238
  #define MC13892_DEFINE_REGU(name, node, reg, vsel_reg, voltages)	\
  	MC13xxx_DEFINE(MC13892_, name, node, reg, vsel_reg, voltages, \
5e428d5ce   Yong Shen   regulator: suppor...
239
240
241
  			mc13xxx_regulator_ops)
  
  static struct mc13xxx_regulator mc13892_regulators[] = {
ec520911e   Rob Herring   regulator: mc13xx...
242
243
244
245
246
247
248
249
  	MC13892_DEFINE_REGU(VCOINCELL, vcoincell, POWERCTL0, POWERCTL0, mc13892_vcoincell),
  	MC13892_SW_DEFINE(SW1, sw1, SWITCHERS0, SWITCHERS0, mc13892_sw1),
  	MC13892_SW_DEFINE(SW2, sw2, SWITCHERS1, SWITCHERS1, mc13892_sw),
  	MC13892_SW_DEFINE(SW3, sw3, SWITCHERS2, SWITCHERS2, mc13892_sw),
  	MC13892_SW_DEFINE(SW4, sw4, SWITCHERS3, SWITCHERS3, mc13892_sw),
  	MC13892_FIXED_DEFINE(SWBST, swbst, SWITCHERS5, mc13892_swbst),
  	MC13892_FIXED_DEFINE(VIOHI, viohi, REGULATORMODE0, mc13892_viohi),
  	MC13892_DEFINE_REGU(VPLL, vpll, REGULATORMODE0, REGULATORSETTING0,
5e428d5ce   Yong Shen   regulator: suppor...
250
  		mc13892_vpll),
ec520911e   Rob Herring   regulator: mc13xx...
251
  	MC13892_DEFINE_REGU(VDIG, vdig, REGULATORMODE0, REGULATORSETTING0,
5e428d5ce   Yong Shen   regulator: suppor...
252
  		mc13892_vdig),
ec520911e   Rob Herring   regulator: mc13xx...
253
  	MC13892_DEFINE_REGU(VSD, vsd, REGULATORMODE1, REGULATORSETTING1,
5e428d5ce   Yong Shen   regulator: suppor...
254
  		mc13892_vsd),
ec520911e   Rob Herring   regulator: mc13xx...
255
  	MC13892_DEFINE_REGU(VUSB2, vusb2, REGULATORMODE0, REGULATORSETTING0,
5e428d5ce   Yong Shen   regulator: suppor...
256
  		mc13892_vusb2),
ec520911e   Rob Herring   regulator: mc13xx...
257
  	MC13892_DEFINE_REGU(VVIDEO, vvideo, REGULATORMODE1, REGULATORSETTING1,
5e428d5ce   Yong Shen   regulator: suppor...
258
  		mc13892_vvideo),
ec520911e   Rob Herring   regulator: mc13xx...
259
  	MC13892_DEFINE_REGU(VAUDIO, vaudio, REGULATORMODE1, REGULATORSETTING1,
5e428d5ce   Yong Shen   regulator: suppor...
260
  		mc13892_vaudio),
ec520911e   Rob Herring   regulator: mc13xx...
261
  	MC13892_DEFINE_REGU(VCAM, vcam, REGULATORMODE1, REGULATORSETTING0,
5e428d5ce   Yong Shen   regulator: suppor...
262
  		mc13892_vcam),
ec520911e   Rob Herring   regulator: mc13xx...
263
  	MC13892_DEFINE_REGU(VGEN1, vgen1, REGULATORMODE0, REGULATORSETTING0,
5e428d5ce   Yong Shen   regulator: suppor...
264
  		mc13892_vgen1),
ec520911e   Rob Herring   regulator: mc13xx...
265
  	MC13892_DEFINE_REGU(VGEN2, vgen2, REGULATORMODE0, REGULATORSETTING0,
5e428d5ce   Yong Shen   regulator: suppor...
266
  		mc13892_vgen2),
ec520911e   Rob Herring   regulator: mc13xx...
267
  	MC13892_DEFINE_REGU(VGEN3, vgen3, REGULATORMODE1, REGULATORSETTING0,
5e428d5ce   Yong Shen   regulator: suppor...
268
  		mc13892_vgen3),
ec520911e   Rob Herring   regulator: mc13xx...
269
270
271
272
273
274
275
  	MC13892_FIXED_DEFINE(VUSB, vusb, USB1, mc13892_vusb),
  	MC13892_GPO_DEFINE(GPO1, gpo1, POWERMISC, mc13892_gpo),
  	MC13892_GPO_DEFINE(GPO2, gpo2, POWERMISC, mc13892_gpo),
  	MC13892_GPO_DEFINE(GPO3, gpo3, POWERMISC, mc13892_gpo),
  	MC13892_GPO_DEFINE(GPO4, gpo4, POWERMISC, mc13892_gpo),
  	MC13892_GPO_DEFINE(PWGT1SPI, pwgt1spi, POWERMISC, mc13892_pwgtdrv),
  	MC13892_GPO_DEFINE(PWGT2SPI, pwgt2spi, POWERMISC, mc13892_pwgtdrv),
5e428d5ce   Yong Shen   regulator: suppor...
276
  };
27315cf61   Mark Brown   regulator: Static...
277
278
  static int mc13892_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask,
  				 u32 val)
5e428d5ce   Yong Shen   regulator: suppor...
279
280
281
282
283
284
  {
  	struct mc13xxx *mc13892 = priv->mc13xxx;
  	int ret;
  	u32 valread;
  
  	BUG_ON(val & ~mask);
825d10591   Axel Lin   regulator: mc1389...
285
  	mc13xxx_lock(priv->mc13xxx);
5e428d5ce   Yong Shen   regulator: suppor...
286
287
  	ret = mc13xxx_reg_read(mc13892, MC13892_POWERMISC, &valread);
  	if (ret)
825d10591   Axel Lin   regulator: mc1389...
288
  		goto out;
5e428d5ce   Yong Shen   regulator: suppor...
289
290
291
292
293
294
295
296
297
298
299
  
  	/* Update the stored state for Power Gates. */
  	priv->powermisc_pwgt_state =
  		(priv->powermisc_pwgt_state & ~mask) | val;
  	priv->powermisc_pwgt_state &= MC13892_POWERMISC_PWGTSPI_M;
  
  	/* Construct the new register value */
  	valread = (valread & ~mask) | val;
  	/* Overwrite the PWGTxEN with the stored version */
  	valread = (valread & ~MC13892_POWERMISC_PWGTSPI_M) |
  		priv->powermisc_pwgt_state;
825d10591   Axel Lin   regulator: mc1389...
300
301
302
303
  	ret = mc13xxx_reg_write(mc13892, MC13892_POWERMISC, valread);
  out:
  	mc13xxx_unlock(priv->mc13xxx);
  	return ret;
5e428d5ce   Yong Shen   regulator: suppor...
304
305
306
307
308
309
  }
  
  static int mc13892_gpo_regulator_enable(struct regulator_dev *rdev)
  {
  	struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
  	int id = rdev_get_id(rdev);
5e428d5ce   Yong Shen   regulator: suppor...
310
311
312
313
314
315
316
317
318
319
320
321
  	u32 en_val = mc13892_regulators[id].enable_bit;
  	u32 mask = mc13892_regulators[id].enable_bit;
  
  	dev_dbg(rdev_get_dev(rdev), "%s id: %d
  ", __func__, id);
  
  	/* Power Gate enable value is 0 */
  	if (id == MC13892_PWGT1SPI || id == MC13892_PWGT2SPI)
  		en_val = 0;
  
  	if (id == MC13892_GPO4)
  		mask |= MC13892_POWERMISC_GPO4ADINEN;
825d10591   Axel Lin   regulator: mc1389...
322
  	return mc13892_powermisc_rmw(priv, mask, en_val);
5e428d5ce   Yong Shen   regulator: suppor...
323
324
325
326
327
328
  }
  
  static int mc13892_gpo_regulator_disable(struct regulator_dev *rdev)
  {
  	struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
  	int id = rdev_get_id(rdev);
5e428d5ce   Yong Shen   regulator: suppor...
329
330
331
332
333
334
335
336
  	u32 dis_val = 0;
  
  	dev_dbg(rdev_get_dev(rdev), "%s id: %d
  ", __func__, id);
  
  	/* Power Gate disable value is 1 */
  	if (id == MC13892_PWGT1SPI || id == MC13892_PWGT2SPI)
  		dis_val = mc13892_regulators[id].enable_bit;
825d10591   Axel Lin   regulator: mc1389...
337
  	return mc13892_powermisc_rmw(priv, mc13892_regulators[id].enable_bit,
5e428d5ce   Yong Shen   regulator: suppor...
338
  		dis_val);
5e428d5ce   Yong Shen   regulator: suppor...
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
  }
  
  static int mc13892_gpo_regulator_is_enabled(struct regulator_dev *rdev)
  {
  	struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
  	int ret, id = rdev_get_id(rdev);
  	unsigned int val;
  
  	mc13xxx_lock(priv->mc13xxx);
  	ret = mc13xxx_reg_read(priv->mc13xxx, mc13892_regulators[id].reg, &val);
  	mc13xxx_unlock(priv->mc13xxx);
  
  	if (ret)
  		return ret;
  
  	/* Power Gates state is stored in powermisc_pwgt_state
  	 * where the meaning of bits is negated */
  	val = (val & ~MC13892_POWERMISC_PWGTSPI_M) |
  		(priv->powermisc_pwgt_state ^ MC13892_POWERMISC_PWGTSPI_M);
  
  	return (val & mc13892_regulators[id].enable_bit) != 0;
  }
e5680c4de   Axel Lin   regulator: mc13xx...
361
  static const struct regulator_ops mc13892_gpo_regulator_ops = {
5e428d5ce   Yong Shen   regulator: suppor...
362
363
364
  	.enable = mc13892_gpo_regulator_enable,
  	.disable = mc13892_gpo_regulator_disable,
  	.is_enabled = mc13892_gpo_regulator_is_enabled,
34e74f39f   Axel Lin   regulator: mc13xx...
365
  	.list_voltage = regulator_list_voltage_table,
5e428d5ce   Yong Shen   regulator: suppor...
366
  	.set_voltage = mc13xxx_fixed_regulator_set_voltage,
5e428d5ce   Yong Shen   regulator: suppor...
367
  };
f1dcf9e4e   Axel Lin   regulator: mc1389...
368
  static int mc13892_sw_regulator_get_voltage_sel(struct regulator_dev *rdev)
5e428d5ce   Yong Shen   regulator: suppor...
369
370
371
  {
  	struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
  	int ret, id = rdev_get_id(rdev);
ccf3ed782   Matt Sealey   regulator: mc1389...
372
  	unsigned int val, selector;
5e428d5ce   Yong Shen   regulator: suppor...
373
374
375
376
377
378
379
380
381
382
  
  	dev_dbg(rdev_get_dev(rdev), "%s id: %d
  ", __func__, id);
  
  	mc13xxx_lock(priv->mc13xxx);
  	ret = mc13xxx_reg_read(priv->mc13xxx,
  		mc13892_regulators[id].vsel_reg, &val);
  	mc13xxx_unlock(priv->mc13xxx);
  	if (ret)
  		return ret;
ccf3ed782   Matt Sealey   regulator: mc1389...
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
  	/*
  	 * Figure out if the HI bit is set inside the switcher mode register
  	 * since this means the selector value we return is at a different
  	 * offset into the selector table.
  	 *
  	 * According to the MC13892 documentation note 59 (Table 47) the SW1
  	 * buck switcher does not support output range programming therefore
  	 * the HI bit must always remain 0. So do not do anything strange if
  	 * our register is MC13892_SWITCHERS0.
  	 */
  
  	selector = val & mc13892_regulators[id].vsel_mask;
  
  	if ((mc13892_regulators[id].vsel_reg != MC13892_SWITCHERS0) &&
  	    (val & MC13892_SWITCHERS0_SWxHI)) {
  		selector += MC13892_SWxHI_SEL_OFFSET;
  	}
5e428d5ce   Yong Shen   regulator: suppor...
400

ccf3ed782   Matt Sealey   regulator: mc1389...
401
402
403
  	dev_dbg(rdev_get_dev(rdev), "%s id: %d val: 0x%08x selector: %d
  ",
  			__func__, id, val, selector);
5e428d5ce   Yong Shen   regulator: suppor...
404

ccf3ed782   Matt Sealey   regulator: mc1389...
405
  	return selector;
5e428d5ce   Yong Shen   regulator: suppor...
406
  }
939b62d89   Axel Lin   regulator: Conver...
407
408
  static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev,
  						unsigned selector)
5e428d5ce   Yong Shen   regulator: suppor...
409
410
  {
  	struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
8db98440f   Axel Lin   regulator: mc1389...
411
412
  	int volt, mask, id = rdev_get_id(rdev);
  	u32 reg_value;
5e428d5ce   Yong Shen   regulator: suppor...
413
  	int ret;
8db98440f   Axel Lin   regulator: mc1389...
414
415
  	volt = rdev->desc->volt_table[selector];
  	mask = mc13892_regulators[id].vsel_mask;
ccf3ed782   Matt Sealey   regulator: mc1389...
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
  	reg_value = selector;
  
  	/*
  	 * Don't mess with the HI bit or support HI voltage offsets for SW1.
  	 *
  	 * Since the get_voltage_sel callback has given a fudged value for
  	 * the selector offset, we need to back out that offset if HI is
  	 * to be set so we write the correct value to the register.
  	 *
  	 * The HI bit addition and selector offset handling COULD be more
  	 * complicated by shifting and masking off the voltage selector part
  	 * of the register then logical OR it back in, but since the selector
  	 * is at bits 4:0 there is very little point. This makes the whole
  	 * thing more readable and we do far less work.
  	 */
  
  	if (mc13892_regulators[id].vsel_reg != MC13892_SWITCHERS0) {
78040b630   Axel Lin   regulator: mc1389...
433
  		mask |= MC13892_SWITCHERS0_SWxHI;
ccf3ed782   Matt Sealey   regulator: mc1389...
434
435
436
  		if (volt > 1375000) {
  			reg_value -= MC13892_SWxHI_SEL_OFFSET;
  			reg_value |= MC13892_SWITCHERS0_SWxHI;
78040b630   Axel Lin   regulator: mc1389...
437
  		} else {
ccf3ed782   Matt Sealey   regulator: mc1389...
438
  			reg_value &= ~MC13892_SWITCHERS0_SWxHI;
ccf3ed782   Matt Sealey   regulator: mc1389...
439
  		}
8db98440f   Axel Lin   regulator: mc1389...
440
  	}
5e428d5ce   Yong Shen   regulator: suppor...
441

8db98440f   Axel Lin   regulator: mc1389...
442
  	mc13xxx_lock(priv->mc13xxx);
c6a21f246   Jingoo Han   regulator: mc1389...
443
444
  	ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].vsel_reg,
  			      mask, reg_value);
5e428d5ce   Yong Shen   regulator: suppor...
445
446
447
448
  	mc13xxx_unlock(priv->mc13xxx);
  
  	return ret;
  }
e5680c4de   Axel Lin   regulator: mc13xx...
449
  static const struct regulator_ops mc13892_sw_regulator_ops = {
34e74f39f   Axel Lin   regulator: mc13xx...
450
  	.list_voltage = regulator_list_voltage_table,
3bdf59928   Axel Lin   regulator: mc1389...
451
  	.map_voltage = regulator_map_voltage_ascend,
939b62d89   Axel Lin   regulator: Conver...
452
  	.set_voltage_sel = mc13892_sw_regulator_set_voltage_sel,
f1dcf9e4e   Axel Lin   regulator: mc1389...
453
  	.get_voltage_sel = mc13892_sw_regulator_get_voltage_sel,
5e428d5ce   Yong Shen   regulator: suppor...
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
  };
  
  static int mc13892_vcam_set_mode(struct regulator_dev *rdev, unsigned int mode)
  {
  	unsigned int en_val = 0;
  	struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
  	int ret, id = rdev_get_id(rdev);
  
  	if (mode == REGULATOR_MODE_FAST)
  		en_val = MC13892_REGULATORMODE1_VCAMCONFIGEN;
  
  	mc13xxx_lock(priv->mc13xxx);
  	ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].reg,
  		MC13892_REGULATORMODE1_VCAMCONFIGEN, en_val);
  	mc13xxx_unlock(priv->mc13xxx);
  
  	return ret;
  }
27315cf61   Mark Brown   regulator: Static...
472
  static unsigned int mc13892_vcam_get_mode(struct regulator_dev *rdev)
5e428d5ce   Yong Shen   regulator: suppor...
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
  {
  	struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
  	int ret, id = rdev_get_id(rdev);
  	unsigned int val;
  
  	mc13xxx_lock(priv->mc13xxx);
  	ret = mc13xxx_reg_read(priv->mc13xxx, mc13892_regulators[id].reg, &val);
  	mc13xxx_unlock(priv->mc13xxx);
  
  	if (ret)
  		return ret;
  
  	if (val & MC13892_REGULATORMODE1_VCAMCONFIGEN)
  		return REGULATOR_MODE_FAST;
  
  	return REGULATOR_MODE_NORMAL;
  }
39f5460d7   Guodong Xu   regulator: core: ...
490
  static struct regulator_ops mc13892_vcam_ops;
5e428d5ce   Yong Shen   regulator: suppor...
491

a5023574d   Bill Pemberton   regulator: remove...
492
  static int mc13892_regulator_probe(struct platform_device *pdev)
5e428d5ce   Yong Shen   regulator: suppor...
493
494
495
  {
  	struct mc13xxx_regulator_priv *priv;
  	struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent);
c8a03c96b   Samuel Ortiz   mfd: Use mfd cell...
496
497
  	struct mc13xxx_regulator_platform_data *pdata =
  		dev_get_platdata(&pdev->dev);
93bcb23b3   Shawn Guo   regulator: mc1389...
498
  	struct mc13xxx_regulator_init_data *mc13xxx_data;
a9d580104   Axel Lin   regulator: Fix bu...
499
  	struct regulator_config config = { };
5e428d5ce   Yong Shen   regulator: suppor...
500
  	int i, ret;
eb0d8e7a1   Alexander Shiyan   regulator: mc13xx...
501
  	int num_regulators = 0;
5e428d5ce   Yong Shen   regulator: suppor...
502
  	u32 val;
93bcb23b3   Shawn Guo   regulator: mc1389...
503
  	num_regulators = mc13xxx_get_num_regulators_dt(pdev);
2c8a5dcaa   Matt Sealey   regulator: mc1389...
504

93bcb23b3   Shawn Guo   regulator: mc1389...
505
506
507
508
  	if (num_regulators <= 0 && pdata)
  		num_regulators = pdata->num_regulators;
  	if (num_regulators <= 0)
  		return -EINVAL;
0ed2dd03b   Kees Cook   treewide: Use str...
509
510
511
  	priv = devm_kzalloc(&pdev->dev,
  			    struct_size(priv, regulators, num_regulators),
  			    GFP_KERNEL);
5e428d5ce   Yong Shen   regulator: suppor...
512
513
  	if (!priv)
  		return -ENOMEM;
93bcb23b3   Shawn Guo   regulator: mc1389...
514
  	priv->num_regulators = num_regulators;
5e428d5ce   Yong Shen   regulator: suppor...
515
516
  	priv->mc13xxx_regulators = mc13892_regulators;
  	priv->mc13xxx = mc13892;
93bcb23b3   Shawn Guo   regulator: mc1389...
517
  	platform_set_drvdata(pdev, priv);
5e428d5ce   Yong Shen   regulator: suppor...
518
519
520
521
  
  	mc13xxx_lock(mc13892);
  	ret = mc13xxx_reg_read(mc13892, MC13892_REVISION, &val);
  	if (ret)
5777d9b34   Axel Lin   regulator: Fix un...
522
  		goto err_unlock;
5e428d5ce   Yong Shen   regulator: suppor...
523

ccf3ed782   Matt Sealey   regulator: mc1389...
524
  	/* enable switch auto mode (on 2.0A silicon only) */
5e428d5ce   Yong Shen   regulator: suppor...
525
526
527
528
529
530
531
  	if ((val & 0x0000FFFF) == 0x45d0) {
  		ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS4,
  			MC13892_SWITCHERS4_SW1MODE_M |
  			MC13892_SWITCHERS4_SW2MODE_M,
  			MC13892_SWITCHERS4_SW1MODE_AUTO |
  			MC13892_SWITCHERS4_SW2MODE_AUTO);
  		if (ret)
5777d9b34   Axel Lin   regulator: Fix un...
532
  			goto err_unlock;
5e428d5ce   Yong Shen   regulator: suppor...
533

923430cfe   Axel Lin   regulator: Assign...
534
  		ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS5,
5e428d5ce   Yong Shen   regulator: suppor...
535
536
537
538
539
  			MC13892_SWITCHERS5_SW3MODE_M |
  			MC13892_SWITCHERS5_SW4MODE_M,
  			MC13892_SWITCHERS5_SW3MODE_AUTO |
  			MC13892_SWITCHERS5_SW4MODE_AUTO);
  		if (ret)
5777d9b34   Axel Lin   regulator: Fix un...
540
  			goto err_unlock;
5e428d5ce   Yong Shen   regulator: suppor...
541
542
  	}
  	mc13xxx_unlock(mc13892);
39f5460d7   Guodong Xu   regulator: core: ...
543
544
545
546
547
548
  	/* update mc13892_vcam ops */
  	memcpy(&mc13892_vcam_ops, mc13892_regulators[MC13892_VCAM].desc.ops,
  						sizeof(struct regulator_ops));
  	mc13892_vcam_ops.set_mode = mc13892_vcam_set_mode,
  	mc13892_vcam_ops.get_mode = mc13892_vcam_get_mode,
  	mc13892_regulators[MC13892_VCAM].desc.ops = &mc13892_vcam_ops;
93bcb23b3   Shawn Guo   regulator: mc1389...
549
550
  
  	mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13892_regulators,
eb0d8e7a1   Alexander Shiyan   regulator: mc13xx...
551
  					ARRAY_SIZE(mc13892_regulators));
2c8a5dcaa   Matt Sealey   regulator: mc1389...
552

eb0d8e7a1   Alexander Shiyan   regulator: mc13xx...
553
  	for (i = 0; i < priv->num_regulators; i++) {
93bcb23b3   Shawn Guo   regulator: mc1389...
554
555
556
557
558
559
560
561
562
563
564
565
566
567
  		struct regulator_init_data *init_data;
  		struct regulator_desc *desc;
  		struct device_node *node = NULL;
  		int id;
  
  		if (mc13xxx_data) {
  			id = mc13xxx_data[i].id;
  			init_data = mc13xxx_data[i].init_data;
  			node = mc13xxx_data[i].node;
  		} else {
  			id = pdata->regulators[i].id;
  			init_data = pdata->regulators[i].init_data;
  		}
  		desc = &mc13892_regulators[id].desc;
a9d580104   Axel Lin   regulator: Fix bu...
568
569
570
571
  		config.dev = &pdev->dev;
  		config.init_data = init_data;
  		config.driver_data = priv;
  		config.of_node = node;
5e428d5ce   Yong Shen   regulator: suppor...
572

8c0b4ab50   Sachin Kamat   regulator: mc1389...
573
574
  		priv->regulators[i] = devm_regulator_register(&pdev->dev, desc,
  							      &config);
5e428d5ce   Yong Shen   regulator: suppor...
575
576
577
578
  		if (IS_ERR(priv->regulators[i])) {
  			dev_err(&pdev->dev, "failed to register regulator %s
  ",
  				mc13892_regulators[i].desc.name);
8c0b4ab50   Sachin Kamat   regulator: mc1389...
579
  			return PTR_ERR(priv->regulators[i]);
5e428d5ce   Yong Shen   regulator: suppor...
580
581
  		}
  	}
5e428d5ce   Yong Shen   regulator: suppor...
582
  	return 0;
5e428d5ce   Yong Shen   regulator: suppor...
583

5777d9b34   Axel Lin   regulator: Fix un...
584
  err_unlock:
5e428d5ce   Yong Shen   regulator: suppor...
585
  	mc13xxx_unlock(mc13892);
5e428d5ce   Yong Shen   regulator: suppor...
586
587
  	return ret;
  }
5e428d5ce   Yong Shen   regulator: suppor...
588
589
590
  static struct platform_driver mc13892_regulator_driver = {
  	.driver	= {
  		.name	= "mc13892-regulator",
5e428d5ce   Yong Shen   regulator: suppor...
591
  	},
5e428d5ce   Yong Shen   regulator: suppor...
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
  	.probe	= mc13892_regulator_probe,
  };
  
  static int __init mc13892_regulator_init(void)
  {
  	return platform_driver_register(&mc13892_regulator_driver);
  }
  subsys_initcall(mc13892_regulator_init);
  
  static void __exit mc13892_regulator_exit(void)
  {
  	platform_driver_unregister(&mc13892_regulator_driver);
  }
  module_exit(mc13892_regulator_exit);
  
  MODULE_LICENSE("GPL v2");
  MODULE_AUTHOR("Yong Shen <yong.shen@linaro.org>");
  MODULE_DESCRIPTION("Regulator Driver for Freescale MC13892 PMIC");
  MODULE_ALIAS("platform:mc13892-regulator");