Commit | Line | Data |
---|---|---|
295c08bc SH |
1 | /* |
2 | * Regulator Driver for Freescale MC13783 PMIC | |
3 | * | |
4 | * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> | |
1bd588fd | 5 | * Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> |
295c08bc SH |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License version 2 as | |
9 | * published by the Free Software Foundation. | |
10 | */ | |
11 | ||
a10099bc | 12 | #include <linux/mfd/mc13783.h> |
295c08bc SH |
13 | #include <linux/regulator/machine.h> |
14 | #include <linux/regulator/driver.h> | |
15 | #include <linux/platform_device.h> | |
295c08bc SH |
16 | #include <linux/kernel.h> |
17 | #include <linux/init.h> | |
18 | #include <linux/err.h> | |
19 | ||
a10099bc UKK |
20 | #define MC13783_REG_SWITCHERS5 29 |
21 | #define MC13783_REG_SWITCHERS5_SW3EN (1 << 20) | |
1bd588fd AP |
22 | #define MC13783_REG_SWITCHERS5_SW3VSEL 18 |
23 | #define MC13783_REG_SWITCHERS5_SW3VSEL_M (3 << 18) | |
24 | ||
25 | #define MC13783_REG_REGULATORSETTING0 30 | |
26 | #define MC13783_REG_REGULATORSETTING0_VIOLOVSEL 2 | |
27 | #define MC13783_REG_REGULATORSETTING0_VDIGVSEL 4 | |
28 | #define MC13783_REG_REGULATORSETTING0_VGENVSEL 6 | |
29 | #define MC13783_REG_REGULATORSETTING0_VRFDIGVSEL 9 | |
30 | #define MC13783_REG_REGULATORSETTING0_VRFREFVSEL 11 | |
31 | #define MC13783_REG_REGULATORSETTING0_VRFCPVSEL 13 | |
32 | #define MC13783_REG_REGULATORSETTING0_VSIMVSEL 14 | |
33 | #define MC13783_REG_REGULATORSETTING0_VESIMVSEL 15 | |
34 | #define MC13783_REG_REGULATORSETTING0_VCAMVSEL 16 | |
35 | ||
36 | #define MC13783_REG_REGULATORSETTING0_VIOLOVSEL_M (3 << 2) | |
37 | #define MC13783_REG_REGULATORSETTING0_VDIGVSEL_M (3 << 4) | |
38 | #define MC13783_REG_REGULATORSETTING0_VGENVSEL_M (7 << 6) | |
39 | #define MC13783_REG_REGULATORSETTING0_VRFDIGVSEL_M (3 << 9) | |
40 | #define MC13783_REG_REGULATORSETTING0_VRFREFVSEL_M (3 << 11) | |
41 | #define MC13783_REG_REGULATORSETTING0_VRFCPVSEL_M (1 << 13) | |
42 | #define MC13783_REG_REGULATORSETTING0_VSIMVSEL_M (1 << 14) | |
43 | #define MC13783_REG_REGULATORSETTING0_VESIMVSEL_M (1 << 15) | |
44 | #define MC13783_REG_REGULATORSETTING0_VCAMVSEL_M (7 << 16) | |
45 | ||
46 | #define MC13783_REG_REGULATORSETTING1 31 | |
47 | #define MC13783_REG_REGULATORSETTING1_VVIBVSEL 0 | |
48 | #define MC13783_REG_REGULATORSETTING1_VRF1VSEL 2 | |
49 | #define MC13783_REG_REGULATORSETTING1_VRF2VSEL 4 | |
50 | #define MC13783_REG_REGULATORSETTING1_VMMC1VSEL 6 | |
51 | #define MC13783_REG_REGULATORSETTING1_VMMC2VSEL 9 | |
52 | ||
53 | #define MC13783_REG_REGULATORSETTING1_VVIBVSEL_M (3 << 0) | |
54 | #define MC13783_REG_REGULATORSETTING1_VRF1VSEL_M (3 << 2) | |
55 | #define MC13783_REG_REGULATORSETTING1_VRF2VSEL_M (3 << 4) | |
56 | #define MC13783_REG_REGULATORSETTING1_VMMC1VSEL_M (7 << 6) | |
57 | #define MC13783_REG_REGULATORSETTING1_VMMC2VSEL_M (7 << 9) | |
a10099bc UKK |
58 | |
59 | #define MC13783_REG_REGULATORMODE0 32 | |
60 | #define MC13783_REG_REGULATORMODE0_VAUDIOEN (1 << 0) | |
61 | #define MC13783_REG_REGULATORMODE0_VIOHIEN (1 << 3) | |
62 | #define MC13783_REG_REGULATORMODE0_VIOLOEN (1 << 6) | |
63 | #define MC13783_REG_REGULATORMODE0_VDIGEN (1 << 9) | |
64 | #define MC13783_REG_REGULATORMODE0_VGENEN (1 << 12) | |
65 | #define MC13783_REG_REGULATORMODE0_VRFDIGEN (1 << 15) | |
66 | #define MC13783_REG_REGULATORMODE0_VRFREFEN (1 << 18) | |
67 | #define MC13783_REG_REGULATORMODE0_VRFCPEN (1 << 21) | |
68 | ||
69 | #define MC13783_REG_REGULATORMODE1 33 | |
70 | #define MC13783_REG_REGULATORMODE1_VSIMEN (1 << 0) | |
71 | #define MC13783_REG_REGULATORMODE1_VESIMEN (1 << 3) | |
72 | #define MC13783_REG_REGULATORMODE1_VCAMEN (1 << 6) | |
73 | #define MC13783_REG_REGULATORMODE1_VRFBGEN (1 << 9) | |
74 | #define MC13783_REG_REGULATORMODE1_VVIBEN (1 << 11) | |
75 | #define MC13783_REG_REGULATORMODE1_VRF1EN (1 << 12) | |
76 | #define MC13783_REG_REGULATORMODE1_VRF2EN (1 << 15) | |
77 | #define MC13783_REG_REGULATORMODE1_VMMC1EN (1 << 18) | |
78 | #define MC13783_REG_REGULATORMODE1_VMMC2EN (1 << 21) | |
79 | ||
80 | #define MC13783_REG_POWERMISC 34 | |
81 | #define MC13783_REG_POWERMISC_GPO1EN (1 << 6) | |
82 | #define MC13783_REG_POWERMISC_GPO2EN (1 << 8) | |
83 | #define MC13783_REG_POWERMISC_GPO3EN (1 << 10) | |
84 | #define MC13783_REG_POWERMISC_GPO4EN (1 << 12) | |
f4b97b36 AP |
85 | #define MC13783_REG_POWERMISC_PWGT1SPIEN (1 << 15) |
86 | #define MC13783_REG_POWERMISC_PWGT2SPIEN (1 << 16) | |
87 | ||
88 | #define MC13783_REG_POWERMISC_PWGTSPI_M (3 << 15) | |
89 | ||
a10099bc | 90 | |
295c08bc SH |
91 | struct mc13783_regulator { |
92 | struct regulator_desc desc; | |
93 | int reg; | |
94 | int enable_bit; | |
1bd588fd AP |
95 | int vsel_reg; |
96 | int vsel_shift; | |
97 | int vsel_mask; | |
98 | int const *voltages; | |
99 | }; | |
100 | ||
101 | /* Voltage Values */ | |
102 | static const int const mc13783_sw3_val[] = { | |
103 | 5000000, 5000000, 5000000, 5500000, | |
104 | }; | |
105 | ||
106 | static const int const mc13783_vaudio_val[] = { | |
107 | 2775000, | |
108 | }; | |
109 | ||
110 | static const int const mc13783_viohi_val[] = { | |
111 | 2775000, | |
112 | }; | |
113 | ||
114 | static const int const mc13783_violo_val[] = { | |
115 | 1200000, 1300000, 1500000, 1800000, | |
116 | }; | |
117 | ||
118 | static const int const mc13783_vdig_val[] = { | |
119 | 1200000, 1300000, 1500000, 1800000, | |
120 | }; | |
121 | ||
122 | static const int const mc13783_vgen_val[] = { | |
123 | 1200000, 1300000, 1500000, 1800000, | |
124 | 1100000, 2000000, 2775000, 2400000, | |
125 | }; | |
126 | ||
127 | static const int const mc13783_vrfdig_val[] = { | |
128 | 1200000, 1500000, 1800000, 1875000, | |
129 | }; | |
130 | ||
131 | static const int const mc13783_vrfref_val[] = { | |
132 | 2475000, 2600000, 2700000, 2775000, | |
133 | }; | |
134 | ||
135 | static const int const mc13783_vrfcp_val[] = { | |
136 | 2700000, 2775000, | |
137 | }; | |
138 | ||
139 | static const int const mc13783_vsim_val[] = { | |
140 | 1800000, 2900000, 3000000, | |
141 | }; | |
142 | ||
143 | static const int const mc13783_vesim_val[] = { | |
144 | 1800000, 2900000, | |
145 | }; | |
146 | ||
147 | static const int const mc13783_vcam_val[] = { | |
148 | 1500000, 1800000, 2500000, 2550000, | |
149 | 2600000, 2750000, 2800000, 3000000, | |
150 | }; | |
151 | ||
152 | static const int const mc13783_vrfbg_val[] = { | |
153 | 1250000, | |
154 | }; | |
155 | ||
156 | static const int const mc13783_vvib_val[] = { | |
157 | 1300000, 1800000, 2000000, 3000000, | |
158 | }; | |
159 | ||
160 | static const int const mc13783_vmmc_val[] = { | |
161 | 1600000, 1800000, 2000000, 2600000, | |
162 | 2700000, 2800000, 2900000, 3000000, | |
163 | }; | |
164 | ||
165 | static const int const mc13783_vrf_val[] = { | |
166 | 1500000, 1875000, 2700000, 2775000, | |
295c08bc SH |
167 | }; |
168 | ||
f4b97b36 AP |
169 | static const int const mc13783_gpo_val[] = { |
170 | 3100000, | |
171 | }; | |
172 | ||
173 | static const int const mc13783_pwgtdrv_val[] = { | |
174 | 5500000, | |
175 | }; | |
176 | ||
295c08bc | 177 | static struct regulator_ops mc13783_regulator_ops; |
1bd588fd | 178 | static struct regulator_ops mc13783_fixed_regulator_ops; |
f4b97b36 | 179 | static struct regulator_ops mc13783_gpo_regulator_ops; |
1bd588fd AP |
180 | |
181 | #define MC13783_DEFINE(prefix, _name, _reg, _vsel_reg, _voltages) \ | |
182 | [MC13783_ ## prefix ## _ ## _name] = { \ | |
183 | .desc = { \ | |
184 | .name = #prefix "_" #_name, \ | |
185 | .n_voltages = ARRAY_SIZE(_voltages), \ | |
186 | .ops = &mc13783_regulator_ops, \ | |
187 | .type = REGULATOR_VOLTAGE, \ | |
188 | .id = MC13783_ ## prefix ## _ ## _name, \ | |
189 | .owner = THIS_MODULE, \ | |
190 | }, \ | |
191 | .reg = MC13783_REG_ ## _reg, \ | |
192 | .enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN, \ | |
193 | .vsel_reg = MC13783_REG_ ## _vsel_reg, \ | |
194 | .vsel_shift = MC13783_REG_ ## _vsel_reg ## _ ## _name ## VSEL,\ | |
195 | .vsel_mask = MC13783_REG_ ## _vsel_reg ## _ ## _name ## VSEL_M,\ | |
196 | .voltages = _voltages, \ | |
197 | } | |
295c08bc | 198 | |
1bd588fd AP |
199 | #define MC13783_FIXED_DEFINE(prefix, _name, _reg, _voltages) \ |
200 | [MC13783_ ## prefix ## _ ## _name] = { \ | |
201 | .desc = { \ | |
202 | .name = #prefix "_" #_name, \ | |
203 | .n_voltages = ARRAY_SIZE(_voltages), \ | |
204 | .ops = &mc13783_fixed_regulator_ops, \ | |
205 | .type = REGULATOR_VOLTAGE, \ | |
206 | .id = MC13783_ ## prefix ## _ ## _name, \ | |
207 | .owner = THIS_MODULE, \ | |
208 | }, \ | |
209 | .reg = MC13783_REG_ ## _reg, \ | |
210 | .enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN, \ | |
211 | .voltages = _voltages, \ | |
212 | } | |
213 | ||
f4b97b36 | 214 | #define MC13783_GPO_DEFINE(prefix, _name, _reg, _voltages) \ |
a10099bc UKK |
215 | [MC13783_ ## prefix ## _ ## _name] = { \ |
216 | .desc = { \ | |
217 | .name = #prefix "_" #_name, \ | |
f4b97b36 AP |
218 | .n_voltages = ARRAY_SIZE(_voltages), \ |
219 | .ops = &mc13783_gpo_regulator_ops, \ | |
a10099bc UKK |
220 | .type = REGULATOR_VOLTAGE, \ |
221 | .id = MC13783_ ## prefix ## _ ## _name, \ | |
222 | .owner = THIS_MODULE, \ | |
223 | }, \ | |
224 | .reg = MC13783_REG_ ## _reg, \ | |
225 | .enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN, \ | |
f4b97b36 | 226 | .voltages = _voltages, \ |
a10099bc UKK |
227 | } |
228 | ||
1bd588fd AP |
229 | #define MC13783_DEFINE_SW(_name, _reg, _vsel_reg, _voltages) \ |
230 | MC13783_DEFINE(SW, _name, _reg, _vsel_reg, _voltages) | |
231 | #define MC13783_DEFINE_REGU(_name, _reg, _vsel_reg, _voltages) \ | |
232 | MC13783_DEFINE(REGU, _name, _reg, _vsel_reg, _voltages) | |
a10099bc | 233 | |
295c08bc | 234 | static struct mc13783_regulator mc13783_regulators[] = { |
1bd588fd AP |
235 | MC13783_DEFINE_SW(SW3, SWITCHERS5, SWITCHERS5, mc13783_sw3_val), |
236 | ||
237 | MC13783_FIXED_DEFINE(REGU, VAUDIO, REGULATORMODE0, mc13783_vaudio_val), | |
238 | MC13783_FIXED_DEFINE(REGU, VIOHI, REGULATORMODE0, mc13783_viohi_val), | |
239 | MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0, REGULATORSETTING0, \ | |
240 | mc13783_violo_val), | |
241 | MC13783_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0, \ | |
242 | mc13783_vdig_val), | |
243 | MC13783_DEFINE_REGU(VGEN, REGULATORMODE0, REGULATORSETTING0, \ | |
244 | mc13783_vgen_val), | |
245 | MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0, REGULATORSETTING0, \ | |
246 | mc13783_vrfdig_val), | |
247 | MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0, REGULATORSETTING0, \ | |
248 | mc13783_vrfref_val), | |
249 | MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0, REGULATORSETTING0, \ | |
250 | mc13783_vrfcp_val), | |
251 | MC13783_DEFINE_REGU(VSIM, REGULATORMODE1, REGULATORSETTING0, \ | |
252 | mc13783_vsim_val), | |
253 | MC13783_DEFINE_REGU(VESIM, REGULATORMODE1, REGULATORSETTING0, \ | |
254 | mc13783_vesim_val), | |
255 | MC13783_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0, \ | |
256 | mc13783_vcam_val), | |
257 | MC13783_FIXED_DEFINE(REGU, VRFBG, REGULATORMODE1, mc13783_vrfbg_val), | |
258 | MC13783_DEFINE_REGU(VVIB, REGULATORMODE1, REGULATORSETTING1, \ | |
259 | mc13783_vvib_val), | |
260 | MC13783_DEFINE_REGU(VRF1, REGULATORMODE1, REGULATORSETTING1, \ | |
261 | mc13783_vrf_val), | |
262 | MC13783_DEFINE_REGU(VRF2, REGULATORMODE1, REGULATORSETTING1, \ | |
263 | mc13783_vrf_val), | |
264 | MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1, REGULATORSETTING1, \ | |
265 | mc13783_vmmc_val), | |
266 | MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1, REGULATORSETTING1, \ | |
267 | mc13783_vmmc_val), | |
f4b97b36 AP |
268 | MC13783_GPO_DEFINE(REGU, GPO1, POWERMISC, mc13783_gpo_val), |
269 | MC13783_GPO_DEFINE(REGU, GPO2, POWERMISC, mc13783_gpo_val), | |
270 | MC13783_GPO_DEFINE(REGU, GPO3, POWERMISC, mc13783_gpo_val), | |
271 | MC13783_GPO_DEFINE(REGU, GPO4, POWERMISC, mc13783_gpo_val), | |
272 | MC13783_GPO_DEFINE(REGU, PWGT1SPI, POWERMISC, mc13783_pwgtdrv_val), | |
273 | MC13783_GPO_DEFINE(REGU, PWGT2SPI, POWERMISC, mc13783_pwgtdrv_val), | |
295c08bc SH |
274 | }; |
275 | ||
a10099bc | 276 | struct mc13783_regulator_priv { |
295c08bc | 277 | struct mc13783 *mc13783; |
f4b97b36 | 278 | u32 powermisc_pwgt_state; |
a10099bc | 279 | struct regulator_dev *regulators[]; |
295c08bc SH |
280 | }; |
281 | ||
a10099bc | 282 | static int mc13783_regulator_enable(struct regulator_dev *rdev) |
295c08bc | 283 | { |
a10099bc | 284 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); |
295c08bc | 285 | int id = rdev_get_id(rdev); |
a10099bc | 286 | int ret; |
295c08bc SH |
287 | |
288 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | |
289 | ||
a10099bc UKK |
290 | mc13783_lock(priv->mc13783); |
291 | ret = mc13783_reg_rmw(priv->mc13783, mc13783_regulators[id].reg, | |
295c08bc SH |
292 | mc13783_regulators[id].enable_bit, |
293 | mc13783_regulators[id].enable_bit); | |
a10099bc UKK |
294 | mc13783_unlock(priv->mc13783); |
295 | ||
296 | return ret; | |
295c08bc SH |
297 | } |
298 | ||
a10099bc | 299 | static int mc13783_regulator_disable(struct regulator_dev *rdev) |
295c08bc | 300 | { |
a10099bc | 301 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); |
295c08bc | 302 | int id = rdev_get_id(rdev); |
a10099bc | 303 | int ret; |
295c08bc SH |
304 | |
305 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | |
306 | ||
a10099bc UKK |
307 | mc13783_lock(priv->mc13783); |
308 | ret = mc13783_reg_rmw(priv->mc13783, mc13783_regulators[id].reg, | |
295c08bc | 309 | mc13783_regulators[id].enable_bit, 0); |
a10099bc UKK |
310 | mc13783_unlock(priv->mc13783); |
311 | ||
312 | return ret; | |
295c08bc SH |
313 | } |
314 | ||
a10099bc | 315 | static int mc13783_regulator_is_enabled(struct regulator_dev *rdev) |
295c08bc | 316 | { |
a10099bc | 317 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); |
295c08bc SH |
318 | int ret, id = rdev_get_id(rdev); |
319 | unsigned int val; | |
320 | ||
a10099bc | 321 | mc13783_lock(priv->mc13783); |
295c08bc | 322 | ret = mc13783_reg_read(priv->mc13783, mc13783_regulators[id].reg, &val); |
a10099bc UKK |
323 | mc13783_unlock(priv->mc13783); |
324 | ||
295c08bc SH |
325 | if (ret) |
326 | return ret; | |
327 | ||
328 | return (val & mc13783_regulators[id].enable_bit) != 0; | |
329 | } | |
330 | ||
1bd588fd AP |
331 | static int mc13783_regulator_list_voltage(struct regulator_dev *rdev, |
332 | unsigned selector) | |
333 | { | |
334 | int id = rdev_get_id(rdev); | |
335 | ||
336 | if (selector >= mc13783_regulators[id].desc.n_voltages) | |
337 | return -EINVAL; | |
338 | ||
339 | return mc13783_regulators[id].voltages[selector]; | |
340 | } | |
341 | ||
342 | static int mc13783_get_best_voltage_index(struct regulator_dev *rdev, | |
343 | int min_uV, int max_uV) | |
344 | { | |
345 | int reg_id = rdev_get_id(rdev); | |
346 | int i; | |
347 | int bestmatch; | |
348 | int bestindex; | |
349 | ||
350 | /* | |
351 | * Locate the minimum voltage fitting the criteria on | |
352 | * this regulator. The switchable voltages are not | |
353 | * in strict falling order so we need to check them | |
354 | * all for the best match. | |
355 | */ | |
356 | bestmatch = INT_MAX; | |
357 | bestindex = -1; | |
358 | for (i = 0; i < mc13783_regulators[reg_id].desc.n_voltages; i++) { | |
359 | if (mc13783_regulators[reg_id].voltages[i] >= min_uV && | |
360 | mc13783_regulators[reg_id].voltages[i] < bestmatch) { | |
361 | bestmatch = mc13783_regulators[reg_id].voltages[i]; | |
362 | bestindex = i; | |
363 | } | |
364 | } | |
365 | ||
366 | if (bestindex < 0 || bestmatch > max_uV) { | |
367 | dev_warn(&rdev->dev, "no possible value for %d<=x<=%d uV\n", | |
368 | min_uV, max_uV); | |
369 | return -EINVAL; | |
370 | } | |
371 | return bestindex; | |
372 | } | |
373 | ||
374 | static int mc13783_regulator_set_voltage(struct regulator_dev *rdev, | |
375 | int min_uV, int max_uV) | |
376 | { | |
377 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); | |
378 | int value, id = rdev_get_id(rdev); | |
379 | int ret; | |
380 | ||
381 | dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", | |
382 | __func__, id, min_uV, max_uV); | |
383 | ||
384 | /* Find the best index */ | |
385 | value = mc13783_get_best_voltage_index(rdev, min_uV, max_uV); | |
386 | dev_dbg(rdev_get_dev(rdev), "%s best value: %d \n", __func__, value); | |
387 | if (value < 0) | |
388 | return value; | |
389 | ||
390 | mc13783_lock(priv->mc13783); | |
391 | ret = mc13783_reg_rmw(priv->mc13783, mc13783_regulators[id].vsel_reg, | |
392 | mc13783_regulators[id].vsel_mask, | |
393 | value << mc13783_regulators[id].vsel_shift); | |
394 | mc13783_unlock(priv->mc13783); | |
395 | ||
396 | return ret; | |
397 | } | |
398 | ||
399 | static int mc13783_regulator_get_voltage(struct regulator_dev *rdev) | |
400 | { | |
401 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); | |
402 | int ret, id = rdev_get_id(rdev); | |
403 | unsigned int val; | |
404 | ||
405 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | |
406 | ||
407 | mc13783_lock(priv->mc13783); | |
408 | ret = mc13783_reg_read(priv->mc13783, | |
409 | mc13783_regulators[id].vsel_reg, &val); | |
410 | mc13783_unlock(priv->mc13783); | |
411 | ||
412 | if (ret) | |
413 | return ret; | |
414 | ||
415 | val = (val & mc13783_regulators[id].vsel_mask) | |
416 | >> mc13783_regulators[id].vsel_shift; | |
417 | ||
418 | dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val); | |
419 | ||
420 | BUG_ON(val < 0 || val > mc13783_regulators[id].desc.n_voltages); | |
421 | ||
422 | return mc13783_regulators[id].voltages[val]; | |
423 | } | |
424 | ||
295c08bc | 425 | static struct regulator_ops mc13783_regulator_ops = { |
a10099bc UKK |
426 | .enable = mc13783_regulator_enable, |
427 | .disable = mc13783_regulator_disable, | |
428 | .is_enabled = mc13783_regulator_is_enabled, | |
1bd588fd AP |
429 | .list_voltage = mc13783_regulator_list_voltage, |
430 | .set_voltage = mc13783_regulator_set_voltage, | |
431 | .get_voltage = mc13783_regulator_get_voltage, | |
432 | }; | |
433 | ||
434 | static int mc13783_fixed_regulator_set_voltage(struct regulator_dev *rdev, | |
435 | int min_uV, int max_uV) | |
436 | { | |
437 | int id = rdev_get_id(rdev); | |
438 | ||
439 | dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", | |
440 | __func__, id, min_uV, max_uV); | |
441 | ||
442 | if (min_uV > mc13783_regulators[id].voltages[0] && | |
443 | max_uV < mc13783_regulators[id].voltages[0]) | |
444 | return 0; | |
445 | else | |
446 | return -EINVAL; | |
447 | } | |
448 | ||
449 | static int mc13783_fixed_regulator_get_voltage(struct regulator_dev *rdev) | |
450 | { | |
451 | int id = rdev_get_id(rdev); | |
452 | ||
453 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | |
454 | ||
455 | return mc13783_regulators[id].voltages[0]; | |
456 | } | |
457 | ||
458 | static struct regulator_ops mc13783_fixed_regulator_ops = { | |
459 | .enable = mc13783_regulator_enable, | |
460 | .disable = mc13783_regulator_disable, | |
461 | .is_enabled = mc13783_regulator_is_enabled, | |
462 | .list_voltage = mc13783_regulator_list_voltage, | |
463 | .set_voltage = mc13783_fixed_regulator_set_voltage, | |
464 | .get_voltage = mc13783_fixed_regulator_get_voltage, | |
295c08bc SH |
465 | }; |
466 | ||
f4b97b36 AP |
467 | int mc13783_powermisc_rmw(struct mc13783_regulator_priv *priv, u32 mask, |
468 | u32 val) | |
469 | { | |
470 | struct mc13783 *mc13783 = priv->mc13783; | |
471 | int ret; | |
472 | u32 valread; | |
473 | ||
474 | BUG_ON(val & ~mask); | |
475 | ||
476 | ret = mc13783_reg_read(mc13783, MC13783_REG_POWERMISC, &valread); | |
477 | if (ret) | |
478 | return ret; | |
479 | ||
480 | /* Update the stored state for Power Gates. */ | |
481 | priv->powermisc_pwgt_state = | |
482 | (priv->powermisc_pwgt_state & ~mask) | val; | |
483 | priv->powermisc_pwgt_state &= MC13783_REG_POWERMISC_PWGTSPI_M; | |
484 | ||
485 | /* Construct the new register value */ | |
486 | valread = (valread & ~mask) | val; | |
487 | /* Overwrite the PWGTxEN with the stored version */ | |
488 | valread = (valread & ~MC13783_REG_POWERMISC_PWGTSPI_M) | | |
489 | priv->powermisc_pwgt_state; | |
490 | ||
491 | return mc13783_reg_write(mc13783, MC13783_REG_POWERMISC, valread); | |
492 | } | |
493 | ||
494 | static int mc13783_gpo_regulator_enable(struct regulator_dev *rdev) | |
495 | { | |
496 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); | |
497 | int id = rdev_get_id(rdev); | |
498 | int ret; | |
499 | u32 en_val = mc13783_regulators[id].enable_bit; | |
500 | ||
501 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | |
502 | ||
503 | /* Power Gate enable value is 0 */ | |
504 | if (id == MC13783_REGU_PWGT1SPI || | |
505 | id == MC13783_REGU_PWGT2SPI) | |
506 | en_val = 0; | |
507 | ||
508 | mc13783_lock(priv->mc13783); | |
509 | ret = mc13783_powermisc_rmw(priv, mc13783_regulators[id].enable_bit, | |
510 | en_val); | |
511 | mc13783_unlock(priv->mc13783); | |
512 | ||
513 | return ret; | |
514 | } | |
515 | ||
516 | static int mc13783_gpo_regulator_disable(struct regulator_dev *rdev) | |
517 | { | |
518 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); | |
519 | int id = rdev_get_id(rdev); | |
520 | int ret; | |
521 | u32 dis_val = 0; | |
522 | ||
523 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | |
524 | ||
525 | /* Power Gate disable value is 1 */ | |
526 | if (id == MC13783_REGU_PWGT1SPI || | |
527 | id == MC13783_REGU_PWGT2SPI) | |
528 | dis_val = mc13783_regulators[id].enable_bit; | |
529 | ||
530 | mc13783_lock(priv->mc13783); | |
531 | ret = mc13783_powermisc_rmw(priv, mc13783_regulators[id].enable_bit, | |
532 | dis_val); | |
533 | mc13783_unlock(priv->mc13783); | |
534 | ||
535 | return ret; | |
536 | } | |
537 | ||
538 | static int mc13783_gpo_regulator_is_enabled(struct regulator_dev *rdev) | |
539 | { | |
540 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); | |
541 | int ret, id = rdev_get_id(rdev); | |
542 | unsigned int val; | |
543 | ||
544 | mc13783_lock(priv->mc13783); | |
545 | ret = mc13783_reg_read(priv->mc13783, mc13783_regulators[id].reg, &val); | |
546 | mc13783_unlock(priv->mc13783); | |
547 | ||
548 | if (ret) | |
549 | return ret; | |
550 | ||
551 | /* Power Gates state is stored in powermisc_pwgt_state | |
552 | * where the meaning of bits is negated */ | |
553 | val = (val & ~MC13783_REG_POWERMISC_PWGTSPI_M) | | |
554 | (priv->powermisc_pwgt_state ^ MC13783_REG_POWERMISC_PWGTSPI_M); | |
555 | ||
556 | return (val & mc13783_regulators[id].enable_bit) != 0; | |
557 | } | |
558 | ||
559 | static struct regulator_ops mc13783_gpo_regulator_ops = { | |
560 | .enable = mc13783_gpo_regulator_enable, | |
561 | .disable = mc13783_gpo_regulator_disable, | |
562 | .is_enabled = mc13783_gpo_regulator_is_enabled, | |
563 | .list_voltage = mc13783_regulator_list_voltage, | |
564 | .set_voltage = mc13783_fixed_regulator_set_voltage, | |
565 | .get_voltage = mc13783_fixed_regulator_get_voltage, | |
566 | }; | |
567 | ||
295c08bc SH |
568 | static int __devinit mc13783_regulator_probe(struct platform_device *pdev) |
569 | { | |
a10099bc | 570 | struct mc13783_regulator_priv *priv; |
295c08bc | 571 | struct mc13783 *mc13783 = dev_get_drvdata(pdev->dev.parent); |
a10099bc UKK |
572 | struct mc13783_regulator_platform_data *pdata = |
573 | dev_get_platdata(&pdev->dev); | |
295c08bc SH |
574 | struct mc13783_regulator_init_data *init_data; |
575 | int i, ret; | |
576 | ||
577 | dev_dbg(&pdev->dev, "mc13783_regulator_probe id %d\n", pdev->id); | |
578 | ||
a10099bc UKK |
579 | priv = kzalloc(sizeof(*priv) + |
580 | pdata->num_regulators * sizeof(priv->regulators[0]), | |
295c08bc SH |
581 | GFP_KERNEL); |
582 | if (!priv) | |
583 | return -ENOMEM; | |
584 | ||
585 | priv->mc13783 = mc13783; | |
586 | ||
a10099bc UKK |
587 | for (i = 0; i < pdata->num_regulators; i++) { |
588 | init_data = &pdata->regulators[i]; | |
295c08bc SH |
589 | priv->regulators[i] = regulator_register( |
590 | &mc13783_regulators[init_data->id].desc, | |
591 | &pdev->dev, init_data->init_data, priv); | |
592 | ||
593 | if (IS_ERR(priv->regulators[i])) { | |
594 | dev_err(&pdev->dev, "failed to register regulator %s\n", | |
595 | mc13783_regulators[i].desc.name); | |
596 | ret = PTR_ERR(priv->regulators[i]); | |
597 | goto err; | |
598 | } | |
599 | } | |
600 | ||
601 | platform_set_drvdata(pdev, priv); | |
602 | ||
603 | return 0; | |
604 | err: | |
605 | while (--i >= 0) | |
606 | regulator_unregister(priv->regulators[i]); | |
607 | ||
608 | kfree(priv); | |
609 | ||
610 | return ret; | |
611 | } | |
612 | ||
613 | static int __devexit mc13783_regulator_remove(struct platform_device *pdev) | |
614 | { | |
a10099bc UKK |
615 | struct mc13783_regulator_priv *priv = platform_get_drvdata(pdev); |
616 | struct mc13783_regulator_platform_data *pdata = | |
617 | dev_get_platdata(&pdev->dev); | |
295c08bc SH |
618 | int i; |
619 | ||
a10099bc | 620 | for (i = 0; i < pdata->num_regulators; i++) |
295c08bc SH |
621 | regulator_unregister(priv->regulators[i]); |
622 | ||
623 | return 0; | |
624 | } | |
625 | ||
626 | static struct platform_driver mc13783_regulator_driver = { | |
627 | .driver = { | |
628 | .name = "mc13783-regulator", | |
629 | .owner = THIS_MODULE, | |
630 | }, | |
631 | .remove = __devexit_p(mc13783_regulator_remove), | |
735eb93a | 632 | .probe = mc13783_regulator_probe, |
295c08bc SH |
633 | }; |
634 | ||
635 | static int __init mc13783_regulator_init(void) | |
636 | { | |
735eb93a | 637 | return platform_driver_register(&mc13783_regulator_driver); |
295c08bc SH |
638 | } |
639 | subsys_initcall(mc13783_regulator_init); | |
640 | ||
641 | static void __exit mc13783_regulator_exit(void) | |
642 | { | |
643 | platform_driver_unregister(&mc13783_regulator_driver); | |
644 | } | |
645 | module_exit(mc13783_regulator_exit); | |
646 | ||
a10099bc | 647 | MODULE_LICENSE("GPL v2"); |
295c08bc SH |
648 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de"); |
649 | MODULE_DESCRIPTION("Regulator Driver for Freescale MC13783 PMIC"); | |
650 | MODULE_ALIAS("platform:mc13783-regulator"); |