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