1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | // |
3 | // max77686.c - Regulator driver for the Maxim 77686 |
4 | // |
5 | // Copyright (C) 2012 Samsung Electronics |
6 | // Chiwoong Byun <woong.byun@samsung.com> |
7 | // Jonghwa Lee <jonghwa3.lee@samsung.com> |
8 | // |
9 | // This driver is based on max8997.c |
10 | |
11 | #include <linux/kernel.h> |
12 | #include <linux/bug.h> |
13 | #include <linux/err.h> |
14 | #include <linux/gpio/consumer.h> |
15 | #include <linux/slab.h> |
16 | #include <linux/platform_device.h> |
17 | #include <linux/regulator/driver.h> |
18 | #include <linux/regulator/machine.h> |
19 | #include <linux/regulator/of_regulator.h> |
20 | #include <linux/mfd/max77686.h> |
21 | #include <linux/mfd/max77686-private.h> |
22 | |
23 | #define MAX77686_LDO_MINUV 800000 |
24 | #define MAX77686_LDO_UVSTEP 50000 |
25 | #define MAX77686_LDO_LOW_MINUV 800000 |
26 | #define MAX77686_LDO_LOW_UVSTEP 25000 |
27 | #define MAX77686_BUCK_MINUV 750000 |
28 | #define MAX77686_BUCK_UVSTEP 50000 |
29 | #define MAX77686_BUCK_ENABLE_TIME 40 /* us */ |
30 | #define MAX77686_DVS_ENABLE_TIME 22 /* us */ |
31 | #define MAX77686_RAMP_DELAY 100000 /* uV/us */ |
32 | #define MAX77686_DVS_RAMP_DELAY 27500 /* uV/us */ |
33 | #define MAX77686_DVS_MINUV 600000 |
34 | #define MAX77686_DVS_UVSTEP 12500 |
35 | |
36 | /* |
37 | * Value for configuring buck[89] and LDO{20,21,22} as GPIO control. |
38 | * It is the same as 'off' for other regulators. |
39 | */ |
40 | #define MAX77686_GPIO_CONTROL 0x0 |
41 | /* |
42 | * Values used for configuring LDOs and bucks. |
43 | * Forcing low power mode: LDO1, 3-5, 9, 13, 17-26 |
44 | */ |
45 | #define MAX77686_LDO_LOWPOWER 0x1 |
46 | /* |
47 | * On/off controlled by PWRREQ: |
48 | * - LDO2, 6-8, 10-12, 14-16 |
49 | * - buck[1234] |
50 | */ |
51 | #define MAX77686_OFF_PWRREQ 0x1 |
52 | /* Low power mode controlled by PWRREQ: All LDOs */ |
53 | #define MAX77686_LDO_LOWPOWER_PWRREQ 0x2 |
54 | /* Forcing low power mode: buck[234] */ |
55 | #define MAX77686_BUCK_LOWPOWER 0x2 |
56 | #define MAX77686_NORMAL 0x3 |
57 | |
58 | #define MAX77686_OPMODE_SHIFT 6 |
59 | #define MAX77686_OPMODE_BUCK234_SHIFT 4 |
60 | #define MAX77686_OPMODE_MASK 0x3 |
61 | |
62 | #define MAX77686_VSEL_MASK 0x3F |
63 | #define MAX77686_DVS_VSEL_MASK 0xFF |
64 | |
65 | #define MAX77686_RAMP_RATE_MASK 0xC0 |
66 | |
67 | #define MAX77686_REGULATORS MAX77686_REG_MAX |
68 | #define MAX77686_LDOS 26 |
69 | |
70 | struct max77686_data { |
71 | struct device *dev; |
72 | DECLARE_BITMAP(gpio_enabled, MAX77686_REGULATORS); |
73 | |
74 | /* Array indexed by regulator id */ |
75 | unsigned int opmode[MAX77686_REGULATORS]; |
76 | }; |
77 | |
78 | static unsigned int max77686_get_opmode_shift(int id) |
79 | { |
80 | switch (id) { |
81 | case MAX77686_BUCK1: |
82 | case MAX77686_BUCK5 ... MAX77686_BUCK9: |
83 | return 0; |
84 | case MAX77686_BUCK2 ... MAX77686_BUCK4: |
85 | return MAX77686_OPMODE_BUCK234_SHIFT; |
86 | default: |
87 | /* all LDOs */ |
88 | return MAX77686_OPMODE_SHIFT; |
89 | } |
90 | } |
91 | |
92 | /* |
93 | * When regulator is configured for GPIO control then it |
94 | * replaces "normal" mode. Any change from low power mode to normal |
95 | * should actually change to GPIO control. |
96 | * Map normal mode to proper value for such regulators. |
97 | */ |
98 | static unsigned int max77686_map_normal_mode(struct max77686_data *max77686, |
99 | int id) |
100 | { |
101 | switch (id) { |
102 | case MAX77686_BUCK8: |
103 | case MAX77686_BUCK9: |
104 | case MAX77686_LDO20 ... MAX77686_LDO22: |
105 | if (test_bit(id, max77686->gpio_enabled)) |
106 | return MAX77686_GPIO_CONTROL; |
107 | } |
108 | |
109 | return MAX77686_NORMAL; |
110 | } |
111 | |
112 | /* Some BUCKs and LDOs supports Normal[ON/OFF] mode during suspend */ |
113 | static int max77686_set_suspend_disable(struct regulator_dev *rdev) |
114 | { |
115 | unsigned int val, shift; |
116 | struct max77686_data *max77686 = rdev_get_drvdata(rdev); |
117 | int ret, id = rdev_get_id(rdev); |
118 | |
119 | shift = max77686_get_opmode_shift(id); |
120 | val = MAX77686_OFF_PWRREQ; |
121 | |
122 | ret = regmap_update_bits(map: rdev->regmap, reg: rdev->desc->enable_reg, |
123 | mask: rdev->desc->enable_mask, val: val << shift); |
124 | if (ret) |
125 | return ret; |
126 | |
127 | max77686->opmode[id] = val; |
128 | return 0; |
129 | } |
130 | |
131 | /* Some LDOs supports [LPM/Normal]ON mode during suspend state */ |
132 | static int max77686_set_suspend_mode(struct regulator_dev *rdev, |
133 | unsigned int mode) |
134 | { |
135 | struct max77686_data *max77686 = rdev_get_drvdata(rdev); |
136 | unsigned int val; |
137 | int ret, id = rdev_get_id(rdev); |
138 | |
139 | /* BUCK[5-9] doesn't support this feature */ |
140 | if (id >= MAX77686_BUCK5) |
141 | return 0; |
142 | |
143 | switch (mode) { |
144 | case REGULATOR_MODE_IDLE: /* ON in LP Mode */ |
145 | val = MAX77686_LDO_LOWPOWER_PWRREQ; |
146 | break; |
147 | case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ |
148 | val = max77686_map_normal_mode(max77686, id); |
149 | break; |
150 | default: |
151 | pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n" , |
152 | rdev->desc->name, mode); |
153 | return -EINVAL; |
154 | } |
155 | |
156 | ret = regmap_update_bits(map: rdev->regmap, reg: rdev->desc->enable_reg, |
157 | mask: rdev->desc->enable_mask, |
158 | val: val << MAX77686_OPMODE_SHIFT); |
159 | if (ret) |
160 | return ret; |
161 | |
162 | max77686->opmode[id] = val; |
163 | return 0; |
164 | } |
165 | |
166 | /* Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state */ |
167 | static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev, |
168 | unsigned int mode) |
169 | { |
170 | unsigned int val; |
171 | struct max77686_data *max77686 = rdev_get_drvdata(rdev); |
172 | int ret, id = rdev_get_id(rdev); |
173 | |
174 | switch (mode) { |
175 | case REGULATOR_MODE_STANDBY: /* switch off */ |
176 | val = MAX77686_OFF_PWRREQ; |
177 | break; |
178 | case REGULATOR_MODE_IDLE: /* ON in LP Mode */ |
179 | val = MAX77686_LDO_LOWPOWER_PWRREQ; |
180 | break; |
181 | case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ |
182 | val = max77686_map_normal_mode(max77686, id); |
183 | break; |
184 | default: |
185 | pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n" , |
186 | rdev->desc->name, mode); |
187 | return -EINVAL; |
188 | } |
189 | |
190 | ret = regmap_update_bits(map: rdev->regmap, reg: rdev->desc->enable_reg, |
191 | mask: rdev->desc->enable_mask, |
192 | val: val << MAX77686_OPMODE_SHIFT); |
193 | if (ret) |
194 | return ret; |
195 | |
196 | max77686->opmode[id] = val; |
197 | return 0; |
198 | } |
199 | |
200 | static int max77686_enable(struct regulator_dev *rdev) |
201 | { |
202 | struct max77686_data *max77686 = rdev_get_drvdata(rdev); |
203 | unsigned int shift; |
204 | int id = rdev_get_id(rdev); |
205 | |
206 | shift = max77686_get_opmode_shift(id); |
207 | |
208 | if (max77686->opmode[id] == MAX77686_OFF_PWRREQ) |
209 | max77686->opmode[id] = max77686_map_normal_mode(max77686, id); |
210 | |
211 | return regmap_update_bits(map: rdev->regmap, reg: rdev->desc->enable_reg, |
212 | mask: rdev->desc->enable_mask, |
213 | val: max77686->opmode[id] << shift); |
214 | } |
215 | |
216 | static int max77686_of_parse_cb(struct device_node *np, |
217 | const struct regulator_desc *desc, |
218 | struct regulator_config *config) |
219 | { |
220 | struct max77686_data *max77686 = config->driver_data; |
221 | int ret; |
222 | |
223 | switch (desc->id) { |
224 | case MAX77686_BUCK8: |
225 | case MAX77686_BUCK9: |
226 | case MAX77686_LDO20 ... MAX77686_LDO22: |
227 | config->ena_gpiod = fwnode_gpiod_get_index( |
228 | of_fwnode_handle(np), |
229 | con_id: "maxim,ena" , |
230 | index: 0, |
231 | flags: GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE, |
232 | label: "max77686-regulator" ); |
233 | if (IS_ERR(ptr: config->ena_gpiod)) |
234 | config->ena_gpiod = NULL; |
235 | break; |
236 | default: |
237 | return 0; |
238 | } |
239 | |
240 | if (config->ena_gpiod) { |
241 | set_bit(nr: desc->id, addr: max77686->gpio_enabled); |
242 | |
243 | ret = regmap_update_bits(map: config->regmap, reg: desc->enable_reg, |
244 | mask: desc->enable_mask, |
245 | MAX77686_GPIO_CONTROL); |
246 | if (ret) { |
247 | gpiod_put(desc: config->ena_gpiod); |
248 | config->ena_gpiod = NULL; |
249 | } |
250 | } |
251 | |
252 | return 0; |
253 | } |
254 | |
255 | static const unsigned int max77686_buck_dvs_ramp_table[] = { |
256 | 13750, 27500, 55000, 100000 |
257 | }; |
258 | |
259 | static const struct regulator_ops max77686_ops = { |
260 | .list_voltage = regulator_list_voltage_linear, |
261 | .map_voltage = regulator_map_voltage_linear, |
262 | .is_enabled = regulator_is_enabled_regmap, |
263 | .enable = max77686_enable, |
264 | .disable = regulator_disable_regmap, |
265 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
266 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
267 | .set_voltage_time_sel = regulator_set_voltage_time_sel, |
268 | .set_suspend_mode = max77686_set_suspend_mode, |
269 | }; |
270 | |
271 | static const struct regulator_ops max77686_ldo_ops = { |
272 | .list_voltage = regulator_list_voltage_linear, |
273 | .map_voltage = regulator_map_voltage_linear, |
274 | .is_enabled = regulator_is_enabled_regmap, |
275 | .enable = max77686_enable, |
276 | .disable = regulator_disable_regmap, |
277 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
278 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
279 | .set_voltage_time_sel = regulator_set_voltage_time_sel, |
280 | .set_suspend_mode = max77686_ldo_set_suspend_mode, |
281 | .set_suspend_disable = max77686_set_suspend_disable, |
282 | }; |
283 | |
284 | static const struct regulator_ops max77686_buck1_ops = { |
285 | .list_voltage = regulator_list_voltage_linear, |
286 | .map_voltage = regulator_map_voltage_linear, |
287 | .is_enabled = regulator_is_enabled_regmap, |
288 | .enable = max77686_enable, |
289 | .disable = regulator_disable_regmap, |
290 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
291 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
292 | .set_voltage_time_sel = regulator_set_voltage_time_sel, |
293 | .set_suspend_disable = max77686_set_suspend_disable, |
294 | }; |
295 | |
296 | static const struct regulator_ops max77686_buck_dvs_ops = { |
297 | .list_voltage = regulator_list_voltage_linear, |
298 | .map_voltage = regulator_map_voltage_linear, |
299 | .is_enabled = regulator_is_enabled_regmap, |
300 | .enable = max77686_enable, |
301 | .disable = regulator_disable_regmap, |
302 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
303 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
304 | .set_voltage_time_sel = regulator_set_voltage_time_sel, |
305 | .set_ramp_delay = regulator_set_ramp_delay_regmap, |
306 | .set_suspend_disable = max77686_set_suspend_disable, |
307 | }; |
308 | |
309 | #define regulator_desc_ldo(num) { \ |
310 | .name = "LDO"#num, \ |
311 | .of_match = of_match_ptr("LDO"#num), \ |
312 | .regulators_node = of_match_ptr("voltage-regulators"), \ |
313 | .of_parse_cb = max77686_of_parse_cb, \ |
314 | .id = MAX77686_LDO##num, \ |
315 | .ops = &max77686_ops, \ |
316 | .type = REGULATOR_VOLTAGE, \ |
317 | .owner = THIS_MODULE, \ |
318 | .min_uV = MAX77686_LDO_MINUV, \ |
319 | .uV_step = MAX77686_LDO_UVSTEP, \ |
320 | .ramp_delay = MAX77686_RAMP_DELAY, \ |
321 | .n_voltages = MAX77686_VSEL_MASK + 1, \ |
322 | .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ |
323 | .vsel_mask = MAX77686_VSEL_MASK, \ |
324 | .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ |
325 | .enable_mask = MAX77686_OPMODE_MASK \ |
326 | << MAX77686_OPMODE_SHIFT, \ |
327 | } |
328 | #define regulator_desc_lpm_ldo(num) { \ |
329 | .name = "LDO"#num, \ |
330 | .of_match = of_match_ptr("LDO"#num), \ |
331 | .regulators_node = of_match_ptr("voltage-regulators"), \ |
332 | .id = MAX77686_LDO##num, \ |
333 | .ops = &max77686_ldo_ops, \ |
334 | .type = REGULATOR_VOLTAGE, \ |
335 | .owner = THIS_MODULE, \ |
336 | .min_uV = MAX77686_LDO_MINUV, \ |
337 | .uV_step = MAX77686_LDO_UVSTEP, \ |
338 | .ramp_delay = MAX77686_RAMP_DELAY, \ |
339 | .n_voltages = MAX77686_VSEL_MASK + 1, \ |
340 | .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ |
341 | .vsel_mask = MAX77686_VSEL_MASK, \ |
342 | .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ |
343 | .enable_mask = MAX77686_OPMODE_MASK \ |
344 | << MAX77686_OPMODE_SHIFT, \ |
345 | } |
346 | #define regulator_desc_ldo_low(num) { \ |
347 | .name = "LDO"#num, \ |
348 | .of_match = of_match_ptr("LDO"#num), \ |
349 | .regulators_node = of_match_ptr("voltage-regulators"), \ |
350 | .id = MAX77686_LDO##num, \ |
351 | .ops = &max77686_ldo_ops, \ |
352 | .type = REGULATOR_VOLTAGE, \ |
353 | .owner = THIS_MODULE, \ |
354 | .min_uV = MAX77686_LDO_LOW_MINUV, \ |
355 | .uV_step = MAX77686_LDO_LOW_UVSTEP, \ |
356 | .ramp_delay = MAX77686_RAMP_DELAY, \ |
357 | .n_voltages = MAX77686_VSEL_MASK + 1, \ |
358 | .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ |
359 | .vsel_mask = MAX77686_VSEL_MASK, \ |
360 | .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ |
361 | .enable_mask = MAX77686_OPMODE_MASK \ |
362 | << MAX77686_OPMODE_SHIFT, \ |
363 | } |
364 | #define regulator_desc_ldo1_low(num) { \ |
365 | .name = "LDO"#num, \ |
366 | .of_match = of_match_ptr("LDO"#num), \ |
367 | .regulators_node = of_match_ptr("voltage-regulators"), \ |
368 | .id = MAX77686_LDO##num, \ |
369 | .ops = &max77686_ops, \ |
370 | .type = REGULATOR_VOLTAGE, \ |
371 | .owner = THIS_MODULE, \ |
372 | .min_uV = MAX77686_LDO_LOW_MINUV, \ |
373 | .uV_step = MAX77686_LDO_LOW_UVSTEP, \ |
374 | .ramp_delay = MAX77686_RAMP_DELAY, \ |
375 | .n_voltages = MAX77686_VSEL_MASK + 1, \ |
376 | .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ |
377 | .vsel_mask = MAX77686_VSEL_MASK, \ |
378 | .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ |
379 | .enable_mask = MAX77686_OPMODE_MASK \ |
380 | << MAX77686_OPMODE_SHIFT, \ |
381 | } |
382 | #define regulator_desc_buck(num) { \ |
383 | .name = "BUCK"#num, \ |
384 | .of_match = of_match_ptr("BUCK"#num), \ |
385 | .regulators_node = of_match_ptr("voltage-regulators"), \ |
386 | .of_parse_cb = max77686_of_parse_cb, \ |
387 | .id = MAX77686_BUCK##num, \ |
388 | .ops = &max77686_ops, \ |
389 | .type = REGULATOR_VOLTAGE, \ |
390 | .owner = THIS_MODULE, \ |
391 | .min_uV = MAX77686_BUCK_MINUV, \ |
392 | .uV_step = MAX77686_BUCK_UVSTEP, \ |
393 | .ramp_delay = MAX77686_RAMP_DELAY, \ |
394 | .enable_time = MAX77686_BUCK_ENABLE_TIME, \ |
395 | .n_voltages = MAX77686_VSEL_MASK + 1, \ |
396 | .vsel_reg = MAX77686_REG_BUCK5OUT + (num - 5) * 2, \ |
397 | .vsel_mask = MAX77686_VSEL_MASK, \ |
398 | .enable_reg = MAX77686_REG_BUCK5CTRL + (num - 5) * 2, \ |
399 | .enable_mask = MAX77686_OPMODE_MASK, \ |
400 | } |
401 | #define regulator_desc_buck1(num) { \ |
402 | .name = "BUCK"#num, \ |
403 | .of_match = of_match_ptr("BUCK"#num), \ |
404 | .regulators_node = of_match_ptr("voltage-regulators"), \ |
405 | .id = MAX77686_BUCK##num, \ |
406 | .ops = &max77686_buck1_ops, \ |
407 | .type = REGULATOR_VOLTAGE, \ |
408 | .owner = THIS_MODULE, \ |
409 | .min_uV = MAX77686_BUCK_MINUV, \ |
410 | .uV_step = MAX77686_BUCK_UVSTEP, \ |
411 | .ramp_delay = MAX77686_RAMP_DELAY, \ |
412 | .enable_time = MAX77686_BUCK_ENABLE_TIME, \ |
413 | .n_voltages = MAX77686_VSEL_MASK + 1, \ |
414 | .vsel_reg = MAX77686_REG_BUCK1OUT, \ |
415 | .vsel_mask = MAX77686_VSEL_MASK, \ |
416 | .enable_reg = MAX77686_REG_BUCK1CTRL, \ |
417 | .enable_mask = MAX77686_OPMODE_MASK, \ |
418 | } |
419 | #define regulator_desc_buck_dvs(num) { \ |
420 | .name = "BUCK"#num, \ |
421 | .of_match = of_match_ptr("BUCK"#num), \ |
422 | .regulators_node = of_match_ptr("voltage-regulators"), \ |
423 | .id = MAX77686_BUCK##num, \ |
424 | .ops = &max77686_buck_dvs_ops, \ |
425 | .type = REGULATOR_VOLTAGE, \ |
426 | .owner = THIS_MODULE, \ |
427 | .min_uV = MAX77686_DVS_MINUV, \ |
428 | .uV_step = MAX77686_DVS_UVSTEP, \ |
429 | .ramp_delay = MAX77686_DVS_RAMP_DELAY, \ |
430 | .enable_time = MAX77686_DVS_ENABLE_TIME, \ |
431 | .n_voltages = MAX77686_DVS_VSEL_MASK + 1, \ |
432 | .vsel_reg = MAX77686_REG_BUCK2DVS1 + (num - 2) * 10, \ |
433 | .vsel_mask = MAX77686_DVS_VSEL_MASK, \ |
434 | .enable_reg = MAX77686_REG_BUCK2CTRL1 + (num - 2) * 10, \ |
435 | .enable_mask = MAX77686_OPMODE_MASK \ |
436 | << MAX77686_OPMODE_BUCK234_SHIFT, \ |
437 | .ramp_reg = MAX77686_REG_BUCK2CTRL1 + (num - 2) * 10, \ |
438 | .ramp_mask = MAX77686_RAMP_RATE_MASK, \ |
439 | .ramp_delay_table = max77686_buck_dvs_ramp_table, \ |
440 | .n_ramp_values = ARRAY_SIZE(max77686_buck_dvs_ramp_table), \ |
441 | } |
442 | |
443 | static const struct regulator_desc regulators[] = { |
444 | regulator_desc_ldo1_low(1), |
445 | regulator_desc_ldo_low(2), |
446 | regulator_desc_ldo(3), |
447 | regulator_desc_ldo(4), |
448 | regulator_desc_ldo(5), |
449 | regulator_desc_ldo_low(6), |
450 | regulator_desc_ldo_low(7), |
451 | regulator_desc_ldo_low(8), |
452 | regulator_desc_ldo(9), |
453 | regulator_desc_lpm_ldo(10), |
454 | regulator_desc_lpm_ldo(11), |
455 | regulator_desc_lpm_ldo(12), |
456 | regulator_desc_ldo(13), |
457 | regulator_desc_lpm_ldo(14), |
458 | regulator_desc_ldo_low(15), |
459 | regulator_desc_lpm_ldo(16), |
460 | regulator_desc_ldo(17), |
461 | regulator_desc_ldo(18), |
462 | regulator_desc_ldo(19), |
463 | regulator_desc_ldo(20), |
464 | regulator_desc_ldo(21), |
465 | regulator_desc_ldo(22), |
466 | regulator_desc_ldo(23), |
467 | regulator_desc_ldo(24), |
468 | regulator_desc_ldo(25), |
469 | regulator_desc_ldo(26), |
470 | regulator_desc_buck1(1), |
471 | regulator_desc_buck_dvs(2), |
472 | regulator_desc_buck_dvs(3), |
473 | regulator_desc_buck_dvs(4), |
474 | regulator_desc_buck(5), |
475 | regulator_desc_buck(6), |
476 | regulator_desc_buck(7), |
477 | regulator_desc_buck(8), |
478 | regulator_desc_buck(9), |
479 | }; |
480 | |
481 | static int max77686_pmic_probe(struct platform_device *pdev) |
482 | { |
483 | struct max77686_dev *iodev = dev_get_drvdata(dev: pdev->dev.parent); |
484 | struct max77686_data *max77686; |
485 | int i; |
486 | struct regulator_config config = { }; |
487 | |
488 | dev_dbg(&pdev->dev, "%s\n" , __func__); |
489 | |
490 | max77686 = devm_kzalloc(dev: &pdev->dev, size: sizeof(struct max77686_data), |
491 | GFP_KERNEL); |
492 | if (!max77686) |
493 | return -ENOMEM; |
494 | |
495 | max77686->dev = &pdev->dev; |
496 | config.dev = iodev->dev; |
497 | config.regmap = iodev->regmap; |
498 | config.driver_data = max77686; |
499 | platform_set_drvdata(pdev, data: max77686); |
500 | |
501 | for (i = 0; i < MAX77686_REGULATORS; i++) { |
502 | struct regulator_dev *rdev; |
503 | int id = regulators[i].id; |
504 | |
505 | max77686->opmode[id] = MAX77686_NORMAL; |
506 | rdev = devm_regulator_register(dev: &pdev->dev, |
507 | regulator_desc: ®ulators[i], config: &config); |
508 | if (IS_ERR(ptr: rdev)) { |
509 | int ret = PTR_ERR(ptr: rdev); |
510 | dev_err(&pdev->dev, |
511 | "regulator init failed for %d: %d\n" , i, ret); |
512 | return ret; |
513 | } |
514 | } |
515 | |
516 | return 0; |
517 | } |
518 | |
519 | static const struct platform_device_id max77686_pmic_id[] = { |
520 | {"max77686-pmic" , 0}, |
521 | { }, |
522 | }; |
523 | MODULE_DEVICE_TABLE(platform, max77686_pmic_id); |
524 | |
525 | static struct platform_driver max77686_pmic_driver = { |
526 | .driver = { |
527 | .name = "max77686-pmic" , |
528 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
529 | }, |
530 | .probe = max77686_pmic_probe, |
531 | .id_table = max77686_pmic_id, |
532 | }; |
533 | |
534 | module_platform_driver(max77686_pmic_driver); |
535 | |
536 | MODULE_DESCRIPTION("MAXIM 77686 Regulator Driver" ); |
537 | MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>" ); |
538 | MODULE_LICENSE("GPL" ); |
539 | |