]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
237868c9 PF |
2 | /* |
3 | * Copyright 2017 NXP | |
4 | * | |
5 | * Peng Fan <peng.fan@nxp.com> | |
237868c9 PF |
6 | */ |
7 | ||
8fa46350 PF |
8 | #include <common.h> |
9 | #include <fdtdec.h> | |
10 | #include <errno.h> | |
11 | #include <dm.h> | |
12 | #include <i2c.h> | |
13 | #include <power/pmic.h> | |
14 | #include <power/regulator.h> | |
15 | #include <power/pfuze100_pmic.h> | |
16 | ||
17 | /** | |
18 | * struct pfuze100_regulator_desc - regulator descriptor | |
19 | * | |
20 | * @name: Identify name for the regulator. | |
21 | * @type: Indicates the regulator type. | |
22 | * @uV_step: Voltage increase for each selector. | |
23 | * @vsel_reg: Register for adjust regulator voltage for normal. | |
24 | * @vsel_mask: Mask bit for setting regulator voltage for normal. | |
25 | * @stby_reg: Register for adjust regulator voltage for standby. | |
26 | * @stby_mask: Mask bit for setting regulator voltage for standby. | |
27 | * @volt_table: Voltage mapping table (if table based mapping). | |
28 | * @voltage: Current voltage for REGULATOR_TYPE_FIXED type regulator. | |
29 | */ | |
30 | struct pfuze100_regulator_desc { | |
31 | char *name; | |
32 | enum regulator_type type; | |
33 | unsigned int uV_step; | |
34 | unsigned int vsel_reg; | |
35 | unsigned int vsel_mask; | |
36 | unsigned int stby_reg; | |
37 | unsigned int stby_mask; | |
38 | unsigned int *volt_table; | |
39 | unsigned int voltage; | |
40 | }; | |
41 | ||
42 | /** | |
43 | * struct pfuze100_regulator_platdata - platform data for pfuze100 | |
44 | * | |
45 | * @desc: Points the description entry of one regulator of pfuze100 | |
46 | */ | |
47 | struct pfuze100_regulator_platdata { | |
48 | struct pfuze100_regulator_desc *desc; | |
49 | }; | |
50 | ||
51 | #define PFUZE100_FIXED_REG(_name, base, vol) \ | |
52 | { \ | |
53 | .name = #_name, \ | |
54 | .type = REGULATOR_TYPE_FIXED, \ | |
55 | .voltage = (vol), \ | |
56 | } | |
57 | ||
58 | #define PFUZE100_SW_REG(_name, base, step) \ | |
59 | { \ | |
60 | .name = #_name, \ | |
61 | .type = REGULATOR_TYPE_BUCK, \ | |
62 | .uV_step = (step), \ | |
63 | .vsel_reg = (base) + PFUZE100_VOL_OFFSET, \ | |
64 | .vsel_mask = 0x3F, \ | |
65 | .stby_reg = (base) + PFUZE100_STBY_OFFSET, \ | |
66 | .stby_mask = 0x3F, \ | |
67 | } | |
68 | ||
69 | #define PFUZE100_SWB_REG(_name, base, mask, step, voltages) \ | |
70 | { \ | |
71 | .name = #_name, \ | |
72 | .type = REGULATOR_TYPE_BUCK, \ | |
73 | .uV_step = (step), \ | |
74 | .vsel_reg = (base), \ | |
75 | .vsel_mask = (mask), \ | |
76 | .volt_table = (voltages), \ | |
77 | } | |
78 | ||
79 | #define PFUZE100_SNVS_REG(_name, base, mask, voltages) \ | |
80 | { \ | |
81 | .name = #_name, \ | |
82 | .type = REGULATOR_TYPE_OTHER, \ | |
83 | .vsel_reg = (base), \ | |
84 | .vsel_mask = (mask), \ | |
85 | .volt_table = (voltages), \ | |
86 | } | |
87 | ||
88 | #define PFUZE100_VGEN_REG(_name, base, step) \ | |
89 | { \ | |
90 | .name = #_name, \ | |
91 | .type = REGULATOR_TYPE_LDO, \ | |
92 | .uV_step = (step), \ | |
93 | .vsel_reg = (base), \ | |
94 | .vsel_mask = 0xF, \ | |
95 | .stby_reg = (base), \ | |
96 | .stby_mask = 0x20, \ | |
97 | } | |
98 | ||
99 | #define PFUZE3000_VCC_REG(_name, base, step) \ | |
100 | { \ | |
101 | .name = #_name, \ | |
102 | .type = REGULATOR_TYPE_LDO, \ | |
103 | .uV_step = (step), \ | |
104 | .vsel_reg = (base), \ | |
105 | .vsel_mask = 0x3, \ | |
106 | .stby_reg = (base), \ | |
107 | .stby_mask = 0x20, \ | |
108 | } | |
109 | ||
110 | #define PFUZE3000_SW1_REG(_name, base, step) \ | |
111 | { \ | |
112 | .name = #_name, \ | |
113 | .type = REGULATOR_TYPE_BUCK, \ | |
114 | .uV_step = (step), \ | |
115 | .vsel_reg = (base) + PFUZE100_VOL_OFFSET, \ | |
116 | .vsel_mask = 0x1F, \ | |
117 | .stby_reg = (base) + PFUZE100_STBY_OFFSET, \ | |
118 | .stby_mask = 0x1F, \ | |
119 | } | |
120 | ||
121 | #define PFUZE3000_SW2_REG(_name, base, step) \ | |
122 | { \ | |
123 | .name = #_name, \ | |
124 | .type = REGULATOR_TYPE_BUCK, \ | |
125 | .uV_step = (step), \ | |
126 | .vsel_reg = (base) + PFUZE100_VOL_OFFSET, \ | |
127 | .vsel_mask = 0x7, \ | |
128 | .stby_reg = (base) + PFUZE100_STBY_OFFSET, \ | |
129 | .stby_mask = 0x7, \ | |
130 | } | |
131 | ||
132 | #define PFUZE3000_SW3_REG(_name, base, step) \ | |
133 | { \ | |
134 | .name = #_name, \ | |
135 | .type = REGULATOR_TYPE_BUCK, \ | |
136 | .uV_step = (step), \ | |
137 | .vsel_reg = (base) + PFUZE100_VOL_OFFSET, \ | |
138 | .vsel_mask = 0xF, \ | |
139 | .stby_reg = (base) + PFUZE100_STBY_OFFSET, \ | |
140 | .stby_mask = 0xF, \ | |
141 | } | |
142 | ||
143 | static unsigned int pfuze100_swbst[] = { | |
144 | 5000000, 5050000, 5100000, 5150000 | |
145 | }; | |
146 | ||
147 | static unsigned int pfuze100_vsnvs[] = { | |
148 | 1000000, 1100000, 1200000, 1300000, 1500000, 1800000, 3000000, -1 | |
149 | }; | |
150 | ||
151 | static unsigned int pfuze3000_vsnvs[] = { | |
152 | -1, -1, -1, -1, -1, -1, 3000000, -1 | |
153 | }; | |
154 | ||
155 | static unsigned int pfuze3000_sw2lo[] = { | |
156 | 1500000, 1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000 | |
157 | }; | |
158 | ||
159 | /* PFUZE100 */ | |
160 | static struct pfuze100_regulator_desc pfuze100_regulators[] = { | |
161 | PFUZE100_SW_REG(sw1ab, PFUZE100_SW1ABVOL, 25000), | |
162 | PFUZE100_SW_REG(sw1c, PFUZE100_SW1CVOL, 25000), | |
163 | PFUZE100_SW_REG(sw2, PFUZE100_SW2VOL, 25000), | |
164 | PFUZE100_SW_REG(sw3a, PFUZE100_SW3AVOL, 25000), | |
165 | PFUZE100_SW_REG(sw3b, PFUZE100_SW3BVOL, 25000), | |
166 | PFUZE100_SW_REG(sw4, PFUZE100_SW4VOL, 25000), | |
167 | PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000, pfuze100_swbst), | |
168 | PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs), | |
169 | PFUZE100_FIXED_REG(vrefddr, PFUZE100_VREFDDRCON, 750000), | |
170 | PFUZE100_VGEN_REG(vgen1, PFUZE100_VGEN1VOL, 50000), | |
171 | PFUZE100_VGEN_REG(vgen2, PFUZE100_VGEN2VOL, 50000), | |
172 | PFUZE100_VGEN_REG(vgen3, PFUZE100_VGEN3VOL, 100000), | |
173 | PFUZE100_VGEN_REG(vgen4, PFUZE100_VGEN4VOL, 100000), | |
174 | PFUZE100_VGEN_REG(vgen5, PFUZE100_VGEN5VOL, 100000), | |
175 | PFUZE100_VGEN_REG(vgen6, PFUZE100_VGEN6VOL, 100000), | |
176 | }; | |
177 | ||
178 | /* PFUZE200 */ | |
179 | static struct pfuze100_regulator_desc pfuze200_regulators[] = { | |
180 | PFUZE100_SW_REG(sw1ab, PFUZE100_SW1ABVOL, 25000), | |
181 | PFUZE100_SW_REG(sw2, PFUZE100_SW2VOL, 25000), | |
182 | PFUZE100_SW_REG(sw3a, PFUZE100_SW3AVOL, 25000), | |
183 | PFUZE100_SW_REG(sw3b, PFUZE100_SW3BVOL, 25000), | |
184 | PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000, pfuze100_swbst), | |
185 | PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs), | |
186 | PFUZE100_FIXED_REG(vrefddr, PFUZE100_VREFDDRCON, 750000), | |
187 | PFUZE100_VGEN_REG(vgen1, PFUZE100_VGEN1VOL, 50000), | |
188 | PFUZE100_VGEN_REG(vgen2, PFUZE100_VGEN2VOL, 50000), | |
189 | PFUZE100_VGEN_REG(vgen3, PFUZE100_VGEN3VOL, 100000), | |
190 | PFUZE100_VGEN_REG(vgen4, PFUZE100_VGEN4VOL, 100000), | |
191 | PFUZE100_VGEN_REG(vgen5, PFUZE100_VGEN5VOL, 100000), | |
192 | PFUZE100_VGEN_REG(vgen6, PFUZE100_VGEN6VOL, 100000), | |
193 | }; | |
194 | ||
195 | /* PFUZE3000 */ | |
196 | static struct pfuze100_regulator_desc pfuze3000_regulators[] = { | |
197 | PFUZE3000_SW1_REG(sw1a, PFUZE100_SW1ABVOL, 25000), | |
198 | PFUZE3000_SW1_REG(sw1b, PFUZE100_SW1CVOL, 25000), | |
199 | PFUZE100_SWB_REG(sw2, PFUZE100_SW2VOL, 0x7, 50000, pfuze3000_sw2lo), | |
200 | PFUZE3000_SW3_REG(sw3, PFUZE100_SW3AVOL, 50000), | |
201 | PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000, pfuze100_swbst), | |
202 | PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze3000_vsnvs), | |
203 | PFUZE100_FIXED_REG(vrefddr, PFUZE100_VREFDDRCON, 750000), | |
204 | PFUZE100_VGEN_REG(vldo1, PFUZE100_VGEN1VOL, 100000), | |
205 | PFUZE100_VGEN_REG(vldo2, PFUZE100_VGEN2VOL, 50000), | |
206 | PFUZE3000_VCC_REG(vccsd, PFUZE100_VGEN3VOL, 150000), | |
207 | PFUZE3000_VCC_REG(v33, PFUZE100_VGEN4VOL, 150000), | |
208 | PFUZE100_VGEN_REG(vldo3, PFUZE100_VGEN5VOL, 100000), | |
209 | PFUZE100_VGEN_REG(vldo4, PFUZE100_VGEN6VOL, 100000), | |
210 | }; | |
211 | ||
212 | #define MODE(_id, _val, _name) { \ | |
213 | .id = _id, \ | |
214 | .register_value = _val, \ | |
215 | .name = _name, \ | |
216 | } | |
217 | ||
218 | /* SWx Buck regulator mode */ | |
219 | static struct dm_regulator_mode pfuze_sw_modes[] = { | |
220 | MODE(OFF_OFF, OFF_OFF, "OFF_OFF"), | |
221 | MODE(PWM_OFF, PWM_OFF, "PWM_OFF"), | |
222 | MODE(PFM_OFF, PFM_OFF, "PFM_OFF"), | |
223 | MODE(APS_OFF, APS_OFF, "APS_OFF"), | |
224 | MODE(PWM_PWM, PWM_PWM, "PWM_PWM"), | |
225 | MODE(PWM_APS, PWM_APS, "PWM_APS"), | |
226 | MODE(APS_APS, APS_APS, "APS_APS"), | |
227 | MODE(APS_PFM, APS_PFM, "APS_PFM"), | |
228 | MODE(PWM_PFM, PWM_PFM, "PWM_PFM"), | |
229 | }; | |
230 | ||
231 | /* Boost Buck regulator mode for normal operation */ | |
232 | static struct dm_regulator_mode pfuze_swbst_modes[] = { | |
233 | MODE(SWBST_MODE_OFF, SWBST_MODE_OFF , "SWBST_MODE_OFF"), | |
234 | MODE(SWBST_MODE_PFM, SWBST_MODE_PFM, "SWBST_MODE_PFM"), | |
235 | MODE(SWBST_MODE_AUTO, SWBST_MODE_AUTO, "SWBST_MODE_AUTO"), | |
236 | MODE(SWBST_MODE_APS, SWBST_MODE_APS, "SWBST_MODE_APS"), | |
237 | }; | |
238 | ||
239 | /* VGENx LDO regulator mode for normal operation */ | |
240 | static struct dm_regulator_mode pfuze_ldo_modes[] = { | |
241 | MODE(LDO_MODE_OFF, LDO_MODE_OFF, "LDO_MODE_OFF"), | |
242 | MODE(LDO_MODE_ON, LDO_MODE_ON, "LDO_MODE_ON"), | |
243 | }; | |
244 | ||
245 | static struct pfuze100_regulator_desc *se_desc(struct pfuze100_regulator_desc *desc, | |
246 | int size, | |
247 | const char *name) | |
248 | { | |
249 | int i; | |
250 | ||
251 | for (i = 0; i < size; desc++) { | |
252 | if (!strcmp(desc->name, name)) | |
253 | return desc; | |
254 | continue; | |
255 | } | |
256 | ||
257 | return NULL; | |
258 | } | |
259 | ||
260 | static int pfuze100_regulator_probe(struct udevice *dev) | |
261 | { | |
262 | struct dm_regulator_uclass_platdata *uc_pdata; | |
263 | struct pfuze100_regulator_platdata *plat = dev_get_platdata(dev); | |
264 | struct pfuze100_regulator_desc *desc; | |
265 | ||
266 | switch (dev_get_driver_data(dev_get_parent(dev))) { | |
267 | case PFUZE100: | |
268 | desc = se_desc(pfuze100_regulators, | |
269 | ARRAY_SIZE(pfuze100_regulators), | |
270 | dev->name); | |
271 | break; | |
272 | case PFUZE200: | |
273 | desc = se_desc(pfuze200_regulators, | |
274 | ARRAY_SIZE(pfuze200_regulators), | |
275 | dev->name); | |
276 | break; | |
277 | case PFUZE3000: | |
278 | desc = se_desc(pfuze3000_regulators, | |
279 | ARRAY_SIZE(pfuze3000_regulators), | |
280 | dev->name); | |
281 | break; | |
282 | default: | |
283 | debug("Unsupported PFUZE\n"); | |
284 | return -EINVAL; | |
285 | } | |
286 | if (!desc) { | |
287 | debug("Do not support regulator %s\n", dev->name); | |
288 | return -EINVAL; | |
289 | } | |
290 | ||
291 | plat->desc = desc; | |
292 | uc_pdata = dev_get_uclass_platdata(dev); | |
293 | ||
294 | uc_pdata->type = desc->type; | |
295 | if (uc_pdata->type == REGULATOR_TYPE_BUCK) { | |
296 | if (!strcmp(dev->name, "swbst")) { | |
297 | uc_pdata->mode = pfuze_swbst_modes; | |
298 | uc_pdata->mode_count = ARRAY_SIZE(pfuze_swbst_modes); | |
299 | } else { | |
300 | uc_pdata->mode = pfuze_sw_modes; | |
301 | uc_pdata->mode_count = ARRAY_SIZE(pfuze_sw_modes); | |
302 | } | |
303 | } else if (uc_pdata->type == REGULATOR_TYPE_LDO) { | |
304 | uc_pdata->mode = pfuze_ldo_modes; | |
305 | uc_pdata->mode_count = ARRAY_SIZE(pfuze_ldo_modes); | |
306 | } else { | |
307 | uc_pdata->mode = NULL; | |
308 | uc_pdata->mode_count = 0; | |
309 | } | |
310 | ||
311 | return 0; | |
312 | } | |
313 | ||
314 | static int pfuze100_regulator_mode(struct udevice *dev, int op, int *opmode) | |
315 | { | |
fcdb5319 | 316 | int val; |
8fa46350 PF |
317 | struct pfuze100_regulator_platdata *plat = dev_get_platdata(dev); |
318 | struct pfuze100_regulator_desc *desc = plat->desc; | |
319 | ||
320 | if (op == PMIC_OP_GET) { | |
321 | if (desc->type == REGULATOR_TYPE_BUCK) { | |
322 | if (!strcmp(dev->name, "swbst")) { | |
323 | val = pmic_reg_read(dev->parent, | |
324 | desc->vsel_reg); | |
325 | if (val < 0) | |
326 | return val; | |
327 | ||
328 | val &= SWBST_MODE_MASK; | |
329 | val >>= SWBST_MODE_SHIFT; | |
330 | *opmode = val; | |
331 | ||
332 | return 0; | |
333 | } | |
334 | val = pmic_reg_read(dev->parent, | |
335 | desc->vsel_reg + | |
336 | PFUZE100_MODE_OFFSET); | |
337 | if (val < 0) | |
338 | return val; | |
339 | ||
340 | val &= SW_MODE_MASK; | |
341 | val >>= SW_MODE_SHIFT; | |
342 | *opmode = val; | |
343 | ||
344 | return 0; | |
345 | ||
346 | } else if (desc->type == REGULATOR_TYPE_LDO) { | |
347 | val = pmic_reg_read(dev->parent, desc->vsel_reg); | |
348 | if (val < 0) | |
349 | return val; | |
350 | ||
351 | val &= LDO_MODE_MASK; | |
352 | val >>= LDO_MODE_SHIFT; | |
353 | *opmode = val; | |
354 | ||
355 | return 0; | |
356 | } else { | |
357 | return -EINVAL; | |
358 | } | |
359 | } | |
360 | ||
361 | if (desc->type == REGULATOR_TYPE_BUCK) { | |
362 | if (!strcmp(dev->name, "swbst")) | |
363 | return pmic_clrsetbits(dev->parent, desc->vsel_reg, | |
364 | SWBST_MODE_MASK, | |
365 | *opmode << SWBST_MODE_SHIFT); | |
366 | ||
367 | val = pmic_clrsetbits(dev->parent, | |
368 | desc->vsel_reg + PFUZE100_MODE_OFFSET, | |
369 | SW_MODE_MASK, | |
370 | *opmode << SW_MODE_SHIFT); | |
371 | ||
372 | } else if (desc->type == REGULATOR_TYPE_LDO) { | |
373 | val = pmic_clrsetbits(dev->parent, desc->vsel_reg, | |
374 | LDO_MODE_MASK, | |
375 | *opmode << LDO_MODE_SHIFT); | |
376 | return val; | |
377 | } else { | |
378 | return -EINVAL; | |
379 | } | |
380 | ||
381 | return 0; | |
382 | } | |
383 | ||
384 | static int pfuze100_regulator_enable(struct udevice *dev, int op, bool *enable) | |
385 | { | |
fcdb5319 | 386 | int val; |
8fa46350 PF |
387 | int ret, on_off; |
388 | struct dm_regulator_uclass_platdata *uc_pdata = | |
389 | dev_get_uclass_platdata(dev); | |
390 | ||
391 | if (op == PMIC_OP_GET) { | |
392 | if (!strcmp(dev->name, "vrefddr")) { | |
393 | val = pmic_reg_read(dev->parent, PFUZE100_VREFDDRCON); | |
394 | if (val < 0) | |
395 | return val; | |
396 | ||
397 | if (val & VREFDDRCON_EN) | |
398 | *enable = true; | |
399 | else | |
400 | *enable = false; | |
401 | return 0; | |
402 | } | |
403 | ret = pfuze100_regulator_mode(dev, op, &on_off); | |
404 | if (ret) | |
405 | return ret; | |
406 | switch (on_off) { | |
407 | /* OFF_OFF, SWBST_MODE_OFF, LDO_MODE_OFF have same value */ | |
408 | case OFF_OFF: | |
409 | *enable = false; | |
410 | break; | |
411 | default: | |
412 | *enable = true; | |
413 | break; | |
414 | } | |
415 | } else if (op == PMIC_OP_SET) { | |
416 | if (!strcmp(dev->name, "vrefddr")) { | |
417 | val = pmic_reg_read(dev->parent, PFUZE100_VREFDDRCON); | |
418 | if (val < 0) | |
419 | return val; | |
420 | ||
421 | if (val & VREFDDRCON_EN) | |
422 | return 0; | |
423 | val |= VREFDDRCON_EN; | |
424 | ||
425 | return pmic_reg_write(dev->parent, PFUZE100_VREFDDRCON, | |
426 | val); | |
427 | } | |
428 | ||
429 | if (uc_pdata->type == REGULATOR_TYPE_LDO) { | |
430 | on_off = *enable ? LDO_MODE_ON : LDO_MODE_OFF; | |
431 | } else if (uc_pdata->type == REGULATOR_TYPE_BUCK) { | |
432 | if (!strcmp(dev->name, "swbst")) | |
433 | on_off = *enable ? SWBST_MODE_AUTO : | |
434 | SWBST_MODE_OFF; | |
435 | else | |
436 | on_off = *enable ? APS_PFM : OFF_OFF; | |
437 | } else { | |
438 | return -EINVAL; | |
439 | } | |
440 | ||
441 | return pfuze100_regulator_mode(dev, op, &on_off); | |
442 | } | |
443 | ||
444 | return 0; | |
445 | } | |
446 | ||
447 | static int pfuze100_regulator_val(struct udevice *dev, int op, int *uV) | |
448 | { | |
449 | int i; | |
fcdb5319 | 450 | int val; |
8fa46350 PF |
451 | struct pfuze100_regulator_platdata *plat = dev_get_platdata(dev); |
452 | struct pfuze100_regulator_desc *desc = plat->desc; | |
453 | struct dm_regulator_uclass_platdata *uc_pdata = | |
454 | dev_get_uclass_platdata(dev); | |
455 | ||
456 | if (op == PMIC_OP_GET) { | |
457 | *uV = 0; | |
458 | if (uc_pdata->type == REGULATOR_TYPE_FIXED) { | |
459 | *uV = desc->voltage; | |
460 | } else if (desc->volt_table) { | |
461 | val = pmic_reg_read(dev->parent, desc->vsel_reg); | |
462 | if (val < 0) | |
463 | return val; | |
464 | val &= desc->vsel_mask; | |
465 | *uV = desc->volt_table[val]; | |
466 | } else { | |
467 | if (uc_pdata->min_uV < 0) { | |
468 | debug("Need to provide min_uV in dts.\n"); | |
469 | return -EINVAL; | |
470 | } | |
471 | val = pmic_reg_read(dev->parent, desc->vsel_reg); | |
472 | if (val < 0) | |
473 | return val; | |
474 | val &= desc->vsel_mask; | |
475 | *uV = uc_pdata->min_uV + (int)val * desc->uV_step; | |
476 | } | |
477 | ||
478 | return 0; | |
479 | } | |
480 | ||
481 | if (uc_pdata->type == REGULATOR_TYPE_FIXED) { | |
482 | debug("Set voltage for REGULATOR_TYPE_FIXED regulator\n"); | |
483 | return -EINVAL; | |
484 | } else if (desc->volt_table) { | |
485 | for (i = 0; i < desc->vsel_mask; i++) { | |
486 | if (*uV == desc->volt_table[i]) | |
487 | break; | |
488 | } | |
489 | if (i == desc->vsel_mask) { | |
490 | debug("Unsupported voltage %u\n", *uV); | |
491 | return -EINVAL; | |
492 | } | |
493 | ||
494 | return pmic_clrsetbits(dev->parent, desc->vsel_reg, | |
495 | desc->vsel_mask, i); | |
496 | } else { | |
497 | if (uc_pdata->min_uV < 0) { | |
498 | debug("Need to provide min_uV in dts.\n"); | |
499 | return -EINVAL; | |
500 | } | |
501 | return pmic_clrsetbits(dev->parent, desc->vsel_reg, | |
502 | desc->vsel_mask, | |
503 | (*uV - uc_pdata->min_uV) / desc->uV_step); | |
504 | } | |
505 | ||
506 | return 0; | |
507 | } | |
508 | ||
509 | static int pfuze100_regulator_get_value(struct udevice *dev) | |
510 | { | |
511 | int uV; | |
512 | int ret; | |
513 | ||
514 | ret = pfuze100_regulator_val(dev, PMIC_OP_GET, &uV); | |
515 | if (ret) | |
516 | return ret; | |
517 | ||
518 | return uV; | |
519 | } | |
520 | ||
521 | static int pfuze100_regulator_set_value(struct udevice *dev, int uV) | |
522 | { | |
523 | return pfuze100_regulator_val(dev, PMIC_OP_SET, &uV); | |
524 | } | |
525 | ||
117daa82 | 526 | static int pfuze100_regulator_get_enable(struct udevice *dev) |
8fa46350 PF |
527 | { |
528 | int ret; | |
529 | bool enable = false; | |
530 | ||
531 | ret = pfuze100_regulator_enable(dev, PMIC_OP_GET, &enable); | |
532 | if (ret) | |
533 | return ret; | |
534 | ||
535 | return enable; | |
536 | } | |
537 | ||
538 | static int pfuze100_regulator_set_enable(struct udevice *dev, bool enable) | |
539 | { | |
540 | return pfuze100_regulator_enable(dev, PMIC_OP_SET, &enable); | |
541 | } | |
542 | ||
543 | static int pfuze100_regulator_get_mode(struct udevice *dev) | |
544 | { | |
545 | int mode; | |
546 | int ret; | |
547 | ||
548 | ret = pfuze100_regulator_mode(dev, PMIC_OP_GET, &mode); | |
549 | if (ret) | |
550 | return ret; | |
551 | ||
552 | return mode; | |
553 | } | |
554 | ||
555 | static int pfuze100_regulator_set_mode(struct udevice *dev, int mode) | |
556 | { | |
557 | return pfuze100_regulator_mode(dev, PMIC_OP_SET, &mode); | |
558 | } | |
559 | ||
560 | static const struct dm_regulator_ops pfuze100_regulator_ops = { | |
561 | .get_value = pfuze100_regulator_get_value, | |
562 | .set_value = pfuze100_regulator_set_value, | |
563 | .get_enable = pfuze100_regulator_get_enable, | |
564 | .set_enable = pfuze100_regulator_set_enable, | |
565 | .get_mode = pfuze100_regulator_get_mode, | |
566 | .set_mode = pfuze100_regulator_set_mode, | |
567 | }; | |
568 | ||
569 | U_BOOT_DRIVER(pfuze100_regulator) = { | |
570 | .name = "pfuze100_regulator", | |
571 | .id = UCLASS_REGULATOR, | |
572 | .ops = &pfuze100_regulator_ops, | |
573 | .probe = pfuze100_regulator_probe, | |
574 | .platdata_auto_alloc_size = sizeof(struct pfuze100_regulator_platdata), | |
575 | }; |