1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | // |
3 | // wm831x-ldo.c -- LDO driver for the WM831x series |
4 | // |
5 | // Copyright 2009 Wolfson Microelectronics PLC. |
6 | // |
7 | // Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
8 | |
9 | #include <linux/module.h> |
10 | #include <linux/moduleparam.h> |
11 | #include <linux/init.h> |
12 | #include <linux/bitops.h> |
13 | #include <linux/err.h> |
14 | #include <linux/i2c.h> |
15 | #include <linux/platform_device.h> |
16 | #include <linux/regulator/driver.h> |
17 | #include <linux/slab.h> |
18 | |
19 | #include <linux/mfd/wm831x/core.h> |
20 | #include <linux/mfd/wm831x/regulator.h> |
21 | #include <linux/mfd/wm831x/pdata.h> |
22 | |
23 | #define WM831X_LDO_MAX_NAME 9 |
24 | |
25 | #define WM831X_LDO_CONTROL 0 |
26 | #define WM831X_LDO_ON_CONTROL 1 |
27 | #define WM831X_LDO_SLEEP_CONTROL 2 |
28 | |
29 | #define WM831X_ALIVE_LDO_ON_CONTROL 0 |
30 | #define WM831X_ALIVE_LDO_SLEEP_CONTROL 1 |
31 | |
32 | struct wm831x_ldo { |
33 | char name[WM831X_LDO_MAX_NAME]; |
34 | char supply_name[WM831X_LDO_MAX_NAME]; |
35 | struct regulator_desc desc; |
36 | int base; |
37 | struct wm831x *wm831x; |
38 | struct regulator_dev *regulator; |
39 | }; |
40 | |
41 | /* |
42 | * Shared |
43 | */ |
44 | |
45 | static irqreturn_t wm831x_ldo_uv_irq(int irq, void *data) |
46 | { |
47 | struct wm831x_ldo *ldo = data; |
48 | |
49 | regulator_notifier_call_chain(rdev: ldo->regulator, |
50 | REGULATOR_EVENT_UNDER_VOLTAGE, |
51 | NULL); |
52 | |
53 | return IRQ_HANDLED; |
54 | } |
55 | |
56 | /* |
57 | * General purpose LDOs |
58 | */ |
59 | |
60 | static const struct linear_range wm831x_gp_ldo_ranges[] = { |
61 | REGULATOR_LINEAR_RANGE(900000, 0, 14, 50000), |
62 | REGULATOR_LINEAR_RANGE(1700000, 15, 31, 100000), |
63 | }; |
64 | |
65 | static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev, |
66 | int uV) |
67 | { |
68 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
69 | struct wm831x *wm831x = ldo->wm831x; |
70 | int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL; |
71 | |
72 | sel = regulator_map_voltage_linear_range(rdev, min_uV: uV, max_uV: uV); |
73 | if (sel < 0) |
74 | return sel; |
75 | |
76 | return wm831x_set_bits(wm831x, reg, WM831X_LDO1_ON_VSEL_MASK, val: sel); |
77 | } |
78 | |
79 | static unsigned int wm831x_gp_ldo_get_mode(struct regulator_dev *rdev) |
80 | { |
81 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
82 | struct wm831x *wm831x = ldo->wm831x; |
83 | int ctrl_reg = ldo->base + WM831X_LDO_CONTROL; |
84 | int on_reg = ldo->base + WM831X_LDO_ON_CONTROL; |
85 | int ret; |
86 | |
87 | ret = wm831x_reg_read(wm831x, reg: on_reg); |
88 | if (ret < 0) |
89 | return ret; |
90 | |
91 | if (!(ret & WM831X_LDO1_ON_MODE)) |
92 | return REGULATOR_MODE_NORMAL; |
93 | |
94 | ret = wm831x_reg_read(wm831x, reg: ctrl_reg); |
95 | if (ret < 0) |
96 | return ret; |
97 | |
98 | if (ret & WM831X_LDO1_LP_MODE) |
99 | return REGULATOR_MODE_STANDBY; |
100 | else |
101 | return REGULATOR_MODE_IDLE; |
102 | } |
103 | |
104 | static int wm831x_gp_ldo_set_mode(struct regulator_dev *rdev, |
105 | unsigned int mode) |
106 | { |
107 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
108 | struct wm831x *wm831x = ldo->wm831x; |
109 | int ctrl_reg = ldo->base + WM831X_LDO_CONTROL; |
110 | int on_reg = ldo->base + WM831X_LDO_ON_CONTROL; |
111 | int ret; |
112 | |
113 | |
114 | switch (mode) { |
115 | case REGULATOR_MODE_NORMAL: |
116 | ret = wm831x_set_bits(wm831x, reg: on_reg, |
117 | WM831X_LDO1_ON_MODE, val: 0); |
118 | if (ret < 0) |
119 | return ret; |
120 | break; |
121 | |
122 | case REGULATOR_MODE_IDLE: |
123 | ret = wm831x_set_bits(wm831x, reg: ctrl_reg, |
124 | WM831X_LDO1_LP_MODE, val: 0); |
125 | if (ret < 0) |
126 | return ret; |
127 | |
128 | ret = wm831x_set_bits(wm831x, reg: on_reg, |
129 | WM831X_LDO1_ON_MODE, |
130 | WM831X_LDO1_ON_MODE); |
131 | if (ret < 0) |
132 | return ret; |
133 | break; |
134 | |
135 | case REGULATOR_MODE_STANDBY: |
136 | ret = wm831x_set_bits(wm831x, reg: ctrl_reg, |
137 | WM831X_LDO1_LP_MODE, |
138 | WM831X_LDO1_LP_MODE); |
139 | if (ret < 0) |
140 | return ret; |
141 | |
142 | ret = wm831x_set_bits(wm831x, reg: on_reg, |
143 | WM831X_LDO1_ON_MODE, |
144 | WM831X_LDO1_ON_MODE); |
145 | if (ret < 0) |
146 | return ret; |
147 | break; |
148 | |
149 | default: |
150 | return -EINVAL; |
151 | } |
152 | |
153 | return 0; |
154 | } |
155 | |
156 | static int wm831x_gp_ldo_get_status(struct regulator_dev *rdev) |
157 | { |
158 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
159 | struct wm831x *wm831x = ldo->wm831x; |
160 | int mask = 1 << rdev_get_id(rdev); |
161 | int ret; |
162 | |
163 | /* Is the regulator on? */ |
164 | ret = wm831x_reg_read(wm831x, WM831X_LDO_STATUS); |
165 | if (ret < 0) |
166 | return ret; |
167 | if (!(ret & mask)) |
168 | return REGULATOR_STATUS_OFF; |
169 | |
170 | /* Is it reporting under voltage? */ |
171 | ret = wm831x_reg_read(wm831x, WM831X_LDO_UV_STATUS); |
172 | if (ret < 0) |
173 | return ret; |
174 | if (ret & mask) |
175 | return REGULATOR_STATUS_ERROR; |
176 | |
177 | ret = wm831x_gp_ldo_get_mode(rdev); |
178 | if (ret < 0) |
179 | return ret; |
180 | else |
181 | return regulator_mode_to_status(ret); |
182 | } |
183 | |
184 | static unsigned int wm831x_gp_ldo_get_optimum_mode(struct regulator_dev *rdev, |
185 | int input_uV, |
186 | int output_uV, int load_uA) |
187 | { |
188 | if (load_uA < 20000) |
189 | return REGULATOR_MODE_STANDBY; |
190 | if (load_uA < 50000) |
191 | return REGULATOR_MODE_IDLE; |
192 | return REGULATOR_MODE_NORMAL; |
193 | } |
194 | |
195 | |
196 | static const struct regulator_ops wm831x_gp_ldo_ops = { |
197 | .list_voltage = regulator_list_voltage_linear_range, |
198 | .map_voltage = regulator_map_voltage_linear_range, |
199 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
200 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
201 | .set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage, |
202 | .get_mode = wm831x_gp_ldo_get_mode, |
203 | .set_mode = wm831x_gp_ldo_set_mode, |
204 | .get_status = wm831x_gp_ldo_get_status, |
205 | .get_optimum_mode = wm831x_gp_ldo_get_optimum_mode, |
206 | .get_bypass = regulator_get_bypass_regmap, |
207 | .set_bypass = regulator_set_bypass_regmap, |
208 | |
209 | .is_enabled = regulator_is_enabled_regmap, |
210 | .enable = regulator_enable_regmap, |
211 | .disable = regulator_disable_regmap, |
212 | }; |
213 | |
214 | static int wm831x_gp_ldo_probe(struct platform_device *pdev) |
215 | { |
216 | struct wm831x *wm831x = dev_get_drvdata(dev: pdev->dev.parent); |
217 | struct wm831x_pdata *pdata = dev_get_platdata(dev: wm831x->dev); |
218 | struct regulator_config config = { }; |
219 | int id; |
220 | struct wm831x_ldo *ldo; |
221 | struct resource *res; |
222 | int ret, irq; |
223 | |
224 | if (pdata && pdata->wm831x_num) |
225 | id = (pdata->wm831x_num * 10) + 1; |
226 | else |
227 | id = 0; |
228 | id = pdev->id - id; |
229 | |
230 | dev_dbg(&pdev->dev, "Probing LDO%d\n" , id + 1); |
231 | |
232 | ldo = devm_kzalloc(dev: &pdev->dev, size: sizeof(struct wm831x_ldo), GFP_KERNEL); |
233 | if (!ldo) |
234 | return -ENOMEM; |
235 | |
236 | ldo->wm831x = wm831x; |
237 | |
238 | res = platform_get_resource(pdev, IORESOURCE_REG, 0); |
239 | if (res == NULL) { |
240 | dev_err(&pdev->dev, "No REG resource\n" ); |
241 | ret = -EINVAL; |
242 | goto err; |
243 | } |
244 | ldo->base = res->start; |
245 | |
246 | snprintf(buf: ldo->name, size: sizeof(ldo->name), fmt: "LDO%d" , id + 1); |
247 | ldo->desc.name = ldo->name; |
248 | |
249 | snprintf(buf: ldo->supply_name, size: sizeof(ldo->supply_name), |
250 | fmt: "LDO%dVDD" , id + 1); |
251 | ldo->desc.supply_name = ldo->supply_name; |
252 | |
253 | ldo->desc.id = id; |
254 | ldo->desc.type = REGULATOR_VOLTAGE; |
255 | ldo->desc.n_voltages = 32; |
256 | ldo->desc.ops = &wm831x_gp_ldo_ops; |
257 | ldo->desc.owner = THIS_MODULE; |
258 | ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL; |
259 | ldo->desc.vsel_mask = WM831X_LDO1_ON_VSEL_MASK; |
260 | ldo->desc.enable_reg = WM831X_LDO_ENABLE; |
261 | ldo->desc.enable_mask = 1 << id; |
262 | ldo->desc.bypass_reg = ldo->base; |
263 | ldo->desc.bypass_mask = WM831X_LDO1_SWI; |
264 | ldo->desc.linear_ranges = wm831x_gp_ldo_ranges; |
265 | ldo->desc.n_linear_ranges = ARRAY_SIZE(wm831x_gp_ldo_ranges); |
266 | |
267 | config.dev = pdev->dev.parent; |
268 | if (pdata) |
269 | config.init_data = pdata->ldo[id]; |
270 | config.driver_data = ldo; |
271 | config.regmap = wm831x->regmap; |
272 | |
273 | ldo->regulator = devm_regulator_register(dev: &pdev->dev, regulator_desc: &ldo->desc, |
274 | config: &config); |
275 | if (IS_ERR(ptr: ldo->regulator)) { |
276 | ret = PTR_ERR(ptr: ldo->regulator); |
277 | dev_err(wm831x->dev, "Failed to register LDO%d: %d\n" , |
278 | id + 1, ret); |
279 | goto err; |
280 | } |
281 | |
282 | irq = wm831x_irq(wm831x, irq: platform_get_irq_byname(pdev, "UV" )); |
283 | ret = devm_request_threaded_irq(dev: &pdev->dev, irq, NULL, |
284 | thread_fn: wm831x_ldo_uv_irq, |
285 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, |
286 | devname: ldo->name, |
287 | dev_id: ldo); |
288 | if (ret != 0) { |
289 | dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n" , |
290 | irq, ret); |
291 | goto err; |
292 | } |
293 | |
294 | platform_set_drvdata(pdev, data: ldo); |
295 | |
296 | return 0; |
297 | |
298 | err: |
299 | return ret; |
300 | } |
301 | |
302 | static struct platform_driver wm831x_gp_ldo_driver = { |
303 | .probe = wm831x_gp_ldo_probe, |
304 | .driver = { |
305 | .name = "wm831x-ldo" , |
306 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
307 | }, |
308 | }; |
309 | |
310 | /* |
311 | * Analogue LDOs |
312 | */ |
313 | |
314 | static const struct linear_range wm831x_aldo_ranges[] = { |
315 | REGULATOR_LINEAR_RANGE(1000000, 0, 12, 50000), |
316 | REGULATOR_LINEAR_RANGE(1700000, 13, 31, 100000), |
317 | }; |
318 | |
319 | static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev, |
320 | int uV) |
321 | { |
322 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
323 | struct wm831x *wm831x = ldo->wm831x; |
324 | int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL; |
325 | |
326 | sel = regulator_map_voltage_linear_range(rdev, min_uV: uV, max_uV: uV); |
327 | if (sel < 0) |
328 | return sel; |
329 | |
330 | return wm831x_set_bits(wm831x, reg, WM831X_LDO7_ON_VSEL_MASK, val: sel); |
331 | } |
332 | |
333 | static unsigned int wm831x_aldo_get_mode(struct regulator_dev *rdev) |
334 | { |
335 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
336 | struct wm831x *wm831x = ldo->wm831x; |
337 | int on_reg = ldo->base + WM831X_LDO_ON_CONTROL; |
338 | int ret; |
339 | |
340 | ret = wm831x_reg_read(wm831x, reg: on_reg); |
341 | if (ret < 0) |
342 | return 0; |
343 | |
344 | if (ret & WM831X_LDO7_ON_MODE) |
345 | return REGULATOR_MODE_IDLE; |
346 | else |
347 | return REGULATOR_MODE_NORMAL; |
348 | } |
349 | |
350 | static int wm831x_aldo_set_mode(struct regulator_dev *rdev, |
351 | unsigned int mode) |
352 | { |
353 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
354 | struct wm831x *wm831x = ldo->wm831x; |
355 | int on_reg = ldo->base + WM831X_LDO_ON_CONTROL; |
356 | int ret; |
357 | |
358 | |
359 | switch (mode) { |
360 | case REGULATOR_MODE_NORMAL: |
361 | ret = wm831x_set_bits(wm831x, reg: on_reg, WM831X_LDO7_ON_MODE, val: 0); |
362 | if (ret < 0) |
363 | return ret; |
364 | break; |
365 | |
366 | case REGULATOR_MODE_IDLE: |
367 | ret = wm831x_set_bits(wm831x, reg: on_reg, WM831X_LDO7_ON_MODE, |
368 | WM831X_LDO7_ON_MODE); |
369 | if (ret < 0) |
370 | return ret; |
371 | break; |
372 | |
373 | default: |
374 | return -EINVAL; |
375 | } |
376 | |
377 | return 0; |
378 | } |
379 | |
380 | static int wm831x_aldo_get_status(struct regulator_dev *rdev) |
381 | { |
382 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
383 | struct wm831x *wm831x = ldo->wm831x; |
384 | int mask = 1 << rdev_get_id(rdev); |
385 | int ret; |
386 | |
387 | /* Is the regulator on? */ |
388 | ret = wm831x_reg_read(wm831x, WM831X_LDO_STATUS); |
389 | if (ret < 0) |
390 | return ret; |
391 | if (!(ret & mask)) |
392 | return REGULATOR_STATUS_OFF; |
393 | |
394 | /* Is it reporting under voltage? */ |
395 | ret = wm831x_reg_read(wm831x, WM831X_LDO_UV_STATUS); |
396 | if (ret < 0) |
397 | return ret; |
398 | if (ret & mask) |
399 | return REGULATOR_STATUS_ERROR; |
400 | |
401 | ret = wm831x_aldo_get_mode(rdev); |
402 | if (ret < 0) |
403 | return ret; |
404 | else |
405 | return regulator_mode_to_status(ret); |
406 | } |
407 | |
408 | static const struct regulator_ops wm831x_aldo_ops = { |
409 | .list_voltage = regulator_list_voltage_linear_range, |
410 | .map_voltage = regulator_map_voltage_linear_range, |
411 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
412 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
413 | .set_suspend_voltage = wm831x_aldo_set_suspend_voltage, |
414 | .get_mode = wm831x_aldo_get_mode, |
415 | .set_mode = wm831x_aldo_set_mode, |
416 | .get_status = wm831x_aldo_get_status, |
417 | .set_bypass = regulator_set_bypass_regmap, |
418 | .get_bypass = regulator_get_bypass_regmap, |
419 | |
420 | .is_enabled = regulator_is_enabled_regmap, |
421 | .enable = regulator_enable_regmap, |
422 | .disable = regulator_disable_regmap, |
423 | }; |
424 | |
425 | static int wm831x_aldo_probe(struct platform_device *pdev) |
426 | { |
427 | struct wm831x *wm831x = dev_get_drvdata(dev: pdev->dev.parent); |
428 | struct wm831x_pdata *pdata = dev_get_platdata(dev: wm831x->dev); |
429 | struct regulator_config config = { }; |
430 | int id; |
431 | struct wm831x_ldo *ldo; |
432 | struct resource *res; |
433 | int ret, irq; |
434 | |
435 | if (pdata && pdata->wm831x_num) |
436 | id = (pdata->wm831x_num * 10) + 1; |
437 | else |
438 | id = 0; |
439 | id = pdev->id - id; |
440 | |
441 | dev_dbg(&pdev->dev, "Probing LDO%d\n" , id + 1); |
442 | |
443 | ldo = devm_kzalloc(dev: &pdev->dev, size: sizeof(struct wm831x_ldo), GFP_KERNEL); |
444 | if (!ldo) |
445 | return -ENOMEM; |
446 | |
447 | ldo->wm831x = wm831x; |
448 | |
449 | res = platform_get_resource(pdev, IORESOURCE_REG, 0); |
450 | if (res == NULL) { |
451 | dev_err(&pdev->dev, "No REG resource\n" ); |
452 | ret = -EINVAL; |
453 | goto err; |
454 | } |
455 | ldo->base = res->start; |
456 | |
457 | snprintf(buf: ldo->name, size: sizeof(ldo->name), fmt: "LDO%d" , id + 1); |
458 | ldo->desc.name = ldo->name; |
459 | |
460 | snprintf(buf: ldo->supply_name, size: sizeof(ldo->supply_name), |
461 | fmt: "LDO%dVDD" , id + 1); |
462 | ldo->desc.supply_name = ldo->supply_name; |
463 | |
464 | ldo->desc.id = id; |
465 | ldo->desc.type = REGULATOR_VOLTAGE; |
466 | ldo->desc.n_voltages = 32; |
467 | ldo->desc.linear_ranges = wm831x_aldo_ranges; |
468 | ldo->desc.n_linear_ranges = ARRAY_SIZE(wm831x_aldo_ranges); |
469 | ldo->desc.ops = &wm831x_aldo_ops; |
470 | ldo->desc.owner = THIS_MODULE; |
471 | ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL; |
472 | ldo->desc.vsel_mask = WM831X_LDO7_ON_VSEL_MASK; |
473 | ldo->desc.enable_reg = WM831X_LDO_ENABLE; |
474 | ldo->desc.enable_mask = 1 << id; |
475 | ldo->desc.bypass_reg = ldo->base; |
476 | ldo->desc.bypass_mask = WM831X_LDO7_SWI; |
477 | |
478 | config.dev = pdev->dev.parent; |
479 | if (pdata) |
480 | config.init_data = pdata->ldo[id]; |
481 | config.driver_data = ldo; |
482 | config.regmap = wm831x->regmap; |
483 | |
484 | ldo->regulator = devm_regulator_register(dev: &pdev->dev, regulator_desc: &ldo->desc, |
485 | config: &config); |
486 | if (IS_ERR(ptr: ldo->regulator)) { |
487 | ret = PTR_ERR(ptr: ldo->regulator); |
488 | dev_err(wm831x->dev, "Failed to register LDO%d: %d\n" , |
489 | id + 1, ret); |
490 | goto err; |
491 | } |
492 | |
493 | irq = wm831x_irq(wm831x, irq: platform_get_irq_byname(pdev, "UV" )); |
494 | ret = devm_request_threaded_irq(dev: &pdev->dev, irq, NULL, |
495 | thread_fn: wm831x_ldo_uv_irq, |
496 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, |
497 | devname: ldo->name, dev_id: ldo); |
498 | if (ret != 0) { |
499 | dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n" , |
500 | irq, ret); |
501 | goto err; |
502 | } |
503 | |
504 | platform_set_drvdata(pdev, data: ldo); |
505 | |
506 | return 0; |
507 | |
508 | err: |
509 | return ret; |
510 | } |
511 | |
512 | static struct platform_driver wm831x_aldo_driver = { |
513 | .probe = wm831x_aldo_probe, |
514 | .driver = { |
515 | .name = "wm831x-aldo" , |
516 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
517 | }, |
518 | }; |
519 | |
520 | /* |
521 | * Alive LDO |
522 | */ |
523 | |
524 | #define WM831X_ALIVE_LDO_MAX_SELECTOR 0xf |
525 | |
526 | static int wm831x_alive_ldo_set_suspend_voltage(struct regulator_dev *rdev, |
527 | int uV) |
528 | { |
529 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
530 | struct wm831x *wm831x = ldo->wm831x; |
531 | int sel, reg = ldo->base + WM831X_ALIVE_LDO_SLEEP_CONTROL; |
532 | |
533 | sel = regulator_map_voltage_linear(rdev, min_uV: uV, max_uV: uV); |
534 | if (sel < 0) |
535 | return sel; |
536 | |
537 | return wm831x_set_bits(wm831x, reg, WM831X_LDO11_ON_VSEL_MASK, val: sel); |
538 | } |
539 | |
540 | static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev) |
541 | { |
542 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
543 | struct wm831x *wm831x = ldo->wm831x; |
544 | int mask = 1 << rdev_get_id(rdev); |
545 | int ret; |
546 | |
547 | /* Is the regulator on? */ |
548 | ret = wm831x_reg_read(wm831x, WM831X_LDO_STATUS); |
549 | if (ret < 0) |
550 | return ret; |
551 | if (ret & mask) |
552 | return REGULATOR_STATUS_ON; |
553 | else |
554 | return REGULATOR_STATUS_OFF; |
555 | } |
556 | |
557 | static const struct regulator_ops wm831x_alive_ldo_ops = { |
558 | .list_voltage = regulator_list_voltage_linear, |
559 | .map_voltage = regulator_map_voltage_linear, |
560 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
561 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
562 | .set_suspend_voltage = wm831x_alive_ldo_set_suspend_voltage, |
563 | .get_status = wm831x_alive_ldo_get_status, |
564 | |
565 | .is_enabled = regulator_is_enabled_regmap, |
566 | .enable = regulator_enable_regmap, |
567 | .disable = regulator_disable_regmap, |
568 | }; |
569 | |
570 | static int wm831x_alive_ldo_probe(struct platform_device *pdev) |
571 | { |
572 | struct wm831x *wm831x = dev_get_drvdata(dev: pdev->dev.parent); |
573 | struct wm831x_pdata *pdata = dev_get_platdata(dev: wm831x->dev); |
574 | struct regulator_config config = { }; |
575 | int id; |
576 | struct wm831x_ldo *ldo; |
577 | struct resource *res; |
578 | int ret; |
579 | |
580 | if (pdata && pdata->wm831x_num) |
581 | id = (pdata->wm831x_num * 10) + 1; |
582 | else |
583 | id = 0; |
584 | id = pdev->id - id; |
585 | |
586 | |
587 | dev_dbg(&pdev->dev, "Probing LDO%d\n" , id + 1); |
588 | |
589 | ldo = devm_kzalloc(dev: &pdev->dev, size: sizeof(struct wm831x_ldo), GFP_KERNEL); |
590 | if (!ldo) |
591 | return -ENOMEM; |
592 | |
593 | ldo->wm831x = wm831x; |
594 | |
595 | res = platform_get_resource(pdev, IORESOURCE_REG, 0); |
596 | if (res == NULL) { |
597 | dev_err(&pdev->dev, "No REG resource\n" ); |
598 | ret = -EINVAL; |
599 | goto err; |
600 | } |
601 | ldo->base = res->start; |
602 | |
603 | snprintf(buf: ldo->name, size: sizeof(ldo->name), fmt: "LDO%d" , id + 1); |
604 | ldo->desc.name = ldo->name; |
605 | |
606 | snprintf(buf: ldo->supply_name, size: sizeof(ldo->supply_name), |
607 | fmt: "LDO%dVDD" , id + 1); |
608 | ldo->desc.supply_name = ldo->supply_name; |
609 | |
610 | ldo->desc.id = id; |
611 | ldo->desc.type = REGULATOR_VOLTAGE; |
612 | ldo->desc.n_voltages = WM831X_ALIVE_LDO_MAX_SELECTOR + 1; |
613 | ldo->desc.ops = &wm831x_alive_ldo_ops; |
614 | ldo->desc.owner = THIS_MODULE; |
615 | ldo->desc.vsel_reg = ldo->base + WM831X_ALIVE_LDO_ON_CONTROL; |
616 | ldo->desc.vsel_mask = WM831X_LDO11_ON_VSEL_MASK; |
617 | ldo->desc.enable_reg = WM831X_LDO_ENABLE; |
618 | ldo->desc.enable_mask = 1 << id; |
619 | ldo->desc.min_uV = 800000; |
620 | ldo->desc.uV_step = 50000; |
621 | ldo->desc.enable_time = 1000; |
622 | |
623 | config.dev = pdev->dev.parent; |
624 | if (pdata) |
625 | config.init_data = pdata->ldo[id]; |
626 | config.driver_data = ldo; |
627 | config.regmap = wm831x->regmap; |
628 | |
629 | ldo->regulator = devm_regulator_register(dev: &pdev->dev, regulator_desc: &ldo->desc, |
630 | config: &config); |
631 | if (IS_ERR(ptr: ldo->regulator)) { |
632 | ret = PTR_ERR(ptr: ldo->regulator); |
633 | dev_err(wm831x->dev, "Failed to register LDO%d: %d\n" , |
634 | id + 1, ret); |
635 | goto err; |
636 | } |
637 | |
638 | platform_set_drvdata(pdev, data: ldo); |
639 | |
640 | return 0; |
641 | |
642 | err: |
643 | return ret; |
644 | } |
645 | |
646 | static struct platform_driver wm831x_alive_ldo_driver = { |
647 | .probe = wm831x_alive_ldo_probe, |
648 | .driver = { |
649 | .name = "wm831x-alive-ldo" , |
650 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
651 | }, |
652 | }; |
653 | |
654 | static struct platform_driver * const drivers[] = { |
655 | &wm831x_gp_ldo_driver, |
656 | &wm831x_aldo_driver, |
657 | &wm831x_alive_ldo_driver, |
658 | }; |
659 | |
660 | static int __init wm831x_ldo_init(void) |
661 | { |
662 | return platform_register_drivers(drivers, ARRAY_SIZE(drivers)); |
663 | } |
664 | subsys_initcall(wm831x_ldo_init); |
665 | |
666 | static void __exit wm831x_ldo_exit(void) |
667 | { |
668 | platform_unregister_drivers(drivers, ARRAY_SIZE(drivers)); |
669 | } |
670 | module_exit(wm831x_ldo_exit); |
671 | |
672 | /* Module information */ |
673 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>" ); |
674 | MODULE_DESCRIPTION("WM831x LDO driver" ); |
675 | MODULE_LICENSE("GPL" ); |
676 | MODULE_ALIAS("platform:wm831x-ldo" ); |
677 | MODULE_ALIAS("platform:wm831x-aldo" ); |
678 | MODULE_ALIAS("platform:wm831x-aliveldo" ); |
679 | |