]>
Commit | Line | Data |
---|---|---|
5e9384c7 KK |
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 <[email protected]> | |
7 | // Jonghwa Lee <[email protected]> | |
8 | // | |
9 | // This driver is based on max8997.c | |
133d4016 JL |
10 | |
11 | #include <linux/kernel.h> | |
12 | #include <linux/bug.h> | |
133d4016 | 13 | #include <linux/err.h> |
96392c3d | 14 | #include <linux/gpio/consumer.h> |
133d4016 JL |
15 | #include <linux/slab.h> |
16 | #include <linux/platform_device.h> | |
17 | #include <linux/regulator/driver.h> | |
18 | #include <linux/regulator/machine.h> | |
4706fcab | 19 | #include <linux/regulator/of_regulator.h> |
133d4016 JL |
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 | |
a9597305 KK |
29 | #define MAX77686_BUCK_ENABLE_TIME 40 /* us */ |
30 | #define MAX77686_DVS_ENABLE_TIME 22 /* us */ | |
852abad2 YSB |
31 | #define MAX77686_RAMP_DELAY 100000 /* uV/us */ |
32 | #define MAX77686_DVS_RAMP_DELAY 27500 /* uV/us */ | |
133d4016 JL |
33 | #define MAX77686_DVS_MINUV 600000 |
34 | #define MAX77686_DVS_UVSTEP 12500 | |
35 | ||
3307e902 KK |
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 | |
7636f19c KK |
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 | ||
133d4016 JL |
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 | ||
133d4016 | 70 | struct max77686_data { |
96392c3d | 71 | struct device *dev; |
c53403a3 | 72 | DECLARE_BITMAP(gpio_enabled, MAX77686_REGULATORS); |
3307e902 | 73 | |
eca29da9 | 74 | /* Array indexed by regulator id */ |
6d2c896b | 75 | unsigned int opmode[MAX77686_REGULATORS]; |
133d4016 JL |
76 | }; |
77 | ||
68c5d186 KK |
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 | ||
3307e902 KK |
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: | |
c53403a3 | 105 | if (test_bit(id, max77686->gpio_enabled)) |
3307e902 KK |
106 | return MAX77686_GPIO_CONTROL; |
107 | } | |
108 | ||
109 | return MAX77686_NORMAL; | |
110 | } | |
111 | ||
78ce6128 KK |
112 | /* Some BUCKs and LDOs supports Normal[ON/OFF] mode during suspend */ |
113 | static int max77686_set_suspend_disable(struct regulator_dev *rdev) | |
15282ba9 | 114 | { |
68c5d186 | 115 | unsigned int val, shift; |
15282ba9 | 116 | struct max77686_data *max77686 = rdev_get_drvdata(rdev); |
3ecf198e | 117 | int ret, id = rdev_get_id(rdev); |
15282ba9 | 118 | |
68c5d186 KK |
119 | shift = max77686_get_opmode_shift(id); |
120 | val = MAX77686_OFF_PWRREQ; | |
15282ba9 | 121 | |
3ecf198e | 122 | ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, |
68c5d186 | 123 | rdev->desc->enable_mask, val << shift); |
3ecf198e AL |
124 | if (ret) |
125 | return ret; | |
126 | ||
40e72149 | 127 | max77686->opmode[id] = val; |
3ecf198e | 128 | return 0; |
15282ba9 YSB |
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; | |
3ecf198e | 137 | int ret, id = rdev_get_id(rdev); |
15282ba9 YSB |
138 | |
139 | /* BUCK[5-9] doesn't support this feature */ | |
40e72149 | 140 | if (id >= MAX77686_BUCK5) |
15282ba9 YSB |
141 | return 0; |
142 | ||
143 | switch (mode) { | |
144 | case REGULATOR_MODE_IDLE: /* ON in LP Mode */ | |
68c5d186 | 145 | val = MAX77686_LDO_LOWPOWER_PWRREQ; |
15282ba9 YSB |
146 | break; |
147 | case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ | |
3307e902 | 148 | val = max77686_map_normal_mode(max77686, id); |
15282ba9 YSB |
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 | ||
3ecf198e | 156 | ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, |
68c5d186 KK |
157 | rdev->desc->enable_mask, |
158 | val << MAX77686_OPMODE_SHIFT); | |
3ecf198e AL |
159 | if (ret) |
160 | return ret; | |
161 | ||
40e72149 | 162 | max77686->opmode[id] = val; |
3ecf198e | 163 | return 0; |
15282ba9 YSB |
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); | |
3307e902 | 172 | int ret, id = rdev_get_id(rdev); |
15282ba9 YSB |
173 | |
174 | switch (mode) { | |
175 | case REGULATOR_MODE_STANDBY: /* switch off */ | |
68c5d186 | 176 | val = MAX77686_OFF_PWRREQ; |
15282ba9 YSB |
177 | break; |
178 | case REGULATOR_MODE_IDLE: /* ON in LP Mode */ | |
68c5d186 | 179 | val = MAX77686_LDO_LOWPOWER_PWRREQ; |
15282ba9 YSB |
180 | break; |
181 | case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ | |
3307e902 | 182 | val = max77686_map_normal_mode(max77686, id); |
15282ba9 YSB |
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 | ||
3ecf198e | 190 | ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, |
68c5d186 KK |
191 | rdev->desc->enable_mask, |
192 | val << MAX77686_OPMODE_SHIFT); | |
3ecf198e AL |
193 | if (ret) |
194 | return ret; | |
195 | ||
3307e902 | 196 | max77686->opmode[id] = val; |
3ecf198e | 197 | return 0; |
15282ba9 YSB |
198 | } |
199 | ||
38d34035 | 200 | static int max77686_enable(struct regulator_dev *rdev) |
6d2c896b YSB |
201 | { |
202 | struct max77686_data *max77686 = rdev_get_drvdata(rdev); | |
68c5d186 KK |
203 | unsigned int shift; |
204 | int id = rdev_get_id(rdev); | |
205 | ||
206 | shift = max77686_get_opmode_shift(id); | |
6d2c896b | 207 | |
78ce6128 | 208 | if (max77686->opmode[id] == MAX77686_OFF_PWRREQ) |
3307e902 | 209 | max77686->opmode[id] = max77686_map_normal_mode(max77686, id); |
78ce6128 | 210 | |
6d2c896b YSB |
211 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, |
212 | rdev->desc->enable_mask, | |
68c5d186 | 213 | max77686->opmode[id] << shift); |
6d2c896b YSB |
214 | } |
215 | ||
3307e902 KK |
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; | |
d03c63db | 221 | int ret; |
3307e902 KK |
222 | |
223 | switch (desc->id) { | |
224 | case MAX77686_BUCK8: | |
225 | case MAX77686_BUCK9: | |
226 | case MAX77686_LDO20 ... MAX77686_LDO22: | |
0b2ba815 DT |
227 | config->ena_gpiod = fwnode_gpiod_get_index( |
228 | of_fwnode_handle(np), | |
229 | "maxim,ena", | |
96392c3d LW |
230 | 0, |
231 | GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE, | |
232 | "max77686-regulator"); | |
233 | if (IS_ERR(config->ena_gpiod)) | |
234 | config->ena_gpiod = NULL; | |
3307e902 KK |
235 | break; |
236 | default: | |
237 | return 0; | |
238 | } | |
239 | ||
96392c3d | 240 | if (config->ena_gpiod) { |
c53403a3 | 241 | set_bit(desc->id, max77686->gpio_enabled); |
3307e902 | 242 | |
d03c63db LW |
243 | ret = regmap_update_bits(config->regmap, desc->enable_reg, |
244 | desc->enable_mask, | |
245 | MAX77686_GPIO_CONTROL); | |
246 | if (ret) { | |
247 | gpiod_put(config->ena_gpiod); | |
248 | config->ena_gpiod = NULL; | |
249 | } | |
3307e902 KK |
250 | } |
251 | ||
252 | return 0; | |
253 | } | |
254 | ||
3c37d899 AL |
255 | static const unsigned int max77686_buck_dvs_ramp_table[] = { |
256 | 13750, 27500, 55000, 100000 | |
257 | }; | |
258 | ||
404826cb | 259 | static const struct regulator_ops max77686_ops = { |
133d4016 | 260 | .list_voltage = regulator_list_voltage_linear, |
2e3f7f26 | 261 | .map_voltage = regulator_map_voltage_linear, |
133d4016 | 262 | .is_enabled = regulator_is_enabled_regmap, |
6d2c896b | 263 | .enable = max77686_enable, |
133d4016 JL |
264 | .disable = regulator_disable_regmap, |
265 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | |
266 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | |
852abad2 | 267 | .set_voltage_time_sel = regulator_set_voltage_time_sel, |
15282ba9 YSB |
268 | .set_suspend_mode = max77686_set_suspend_mode, |
269 | }; | |
270 | ||
404826cb | 271 | static const struct regulator_ops max77686_ldo_ops = { |
15282ba9 YSB |
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, | |
133d4016 JL |
276 | .disable = regulator_disable_regmap, |
277 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | |
278 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | |
852abad2 | 279 | .set_voltage_time_sel = regulator_set_voltage_time_sel, |
15282ba9 | 280 | .set_suspend_mode = max77686_ldo_set_suspend_mode, |
78ce6128 | 281 | .set_suspend_disable = max77686_set_suspend_disable, |
15282ba9 YSB |
282 | }; |
283 | ||
404826cb | 284 | static const struct regulator_ops max77686_buck1_ops = { |
15282ba9 YSB |
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, | |
78ce6128 | 293 | .set_suspend_disable = max77686_set_suspend_disable, |
133d4016 JL |
294 | }; |
295 | ||
404826cb | 296 | static const struct regulator_ops max77686_buck_dvs_ops = { |
133d4016 | 297 | .list_voltage = regulator_list_voltage_linear, |
2e3f7f26 | 298 | .map_voltage = regulator_map_voltage_linear, |
133d4016 | 299 | .is_enabled = regulator_is_enabled_regmap, |
6d2c896b | 300 | .enable = max77686_enable, |
133d4016 JL |
301 | .disable = regulator_disable_regmap, |
302 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | |
303 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | |
852abad2 | 304 | .set_voltage_time_sel = regulator_set_voltage_time_sel, |
3c37d899 | 305 | .set_ramp_delay = regulator_set_ramp_delay_regmap, |
78ce6128 | 306 | .set_suspend_disable = max77686_set_suspend_disable, |
133d4016 JL |
307 | }; |
308 | ||
309 | #define regulator_desc_ldo(num) { \ | |
310 | .name = "LDO"#num, \ | |
04803952 KK |
311 | .of_match = of_match_ptr("LDO"#num), \ |
312 | .regulators_node = of_match_ptr("voltage-regulators"), \ | |
3307e902 | 313 | .of_parse_cb = max77686_of_parse_cb, \ |
133d4016 JL |
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, \ | |
852abad2 | 320 | .ramp_delay = MAX77686_RAMP_DELAY, \ |
133d4016 JL |
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 | } | |
15282ba9 YSB |
328 | #define regulator_desc_lpm_ldo(num) { \ |
329 | .name = "LDO"#num, \ | |
04803952 KK |
330 | .of_match = of_match_ptr("LDO"#num), \ |
331 | .regulators_node = of_match_ptr("voltage-regulators"), \ | |
15282ba9 YSB |
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 | } | |
133d4016 | 346 | #define regulator_desc_ldo_low(num) { \ |
15282ba9 | 347 | .name = "LDO"#num, \ |
04803952 KK |
348 | .of_match = of_match_ptr("LDO"#num), \ |
349 | .regulators_node = of_match_ptr("voltage-regulators"), \ | |
15282ba9 YSB |
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) { \ | |
133d4016 | 365 | .name = "LDO"#num, \ |
04803952 KK |
366 | .of_match = of_match_ptr("LDO"#num), \ |
367 | .regulators_node = of_match_ptr("voltage-regulators"), \ | |
133d4016 JL |
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, \ | |
852abad2 | 374 | .ramp_delay = MAX77686_RAMP_DELAY, \ |
133d4016 JL |
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, \ | |
04803952 KK |
384 | .of_match = of_match_ptr("BUCK"#num), \ |
385 | .regulators_node = of_match_ptr("voltage-regulators"), \ | |
3307e902 | 386 | .of_parse_cb = max77686_of_parse_cb, \ |
133d4016 JL |
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, \ | |
852abad2 | 393 | .ramp_delay = MAX77686_RAMP_DELAY, \ |
a9597305 | 394 | .enable_time = MAX77686_BUCK_ENABLE_TIME, \ |
133d4016 JL |
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, \ | |
04803952 KK |
403 | .of_match = of_match_ptr("BUCK"#num), \ |
404 | .regulators_node = of_match_ptr("voltage-regulators"), \ | |
133d4016 | 405 | .id = MAX77686_BUCK##num, \ |
15282ba9 | 406 | .ops = &max77686_buck1_ops, \ |
133d4016 JL |
407 | .type = REGULATOR_VOLTAGE, \ |
408 | .owner = THIS_MODULE, \ | |
409 | .min_uV = MAX77686_BUCK_MINUV, \ | |
410 | .uV_step = MAX77686_BUCK_UVSTEP, \ | |
852abad2 | 411 | .ramp_delay = MAX77686_RAMP_DELAY, \ |
a9597305 | 412 | .enable_time = MAX77686_BUCK_ENABLE_TIME, \ |
133d4016 JL |
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, \ | |
04803952 KK |
421 | .of_match = of_match_ptr("BUCK"#num), \ |
422 | .regulators_node = of_match_ptr("voltage-regulators"), \ | |
133d4016 | 423 | .id = MAX77686_BUCK##num, \ |
74adfee5 | 424 | .ops = &max77686_buck_dvs_ops, \ |
133d4016 JL |
425 | .type = REGULATOR_VOLTAGE, \ |
426 | .owner = THIS_MODULE, \ | |
427 | .min_uV = MAX77686_DVS_MINUV, \ | |
428 | .uV_step = MAX77686_DVS_UVSTEP, \ | |
852abad2 | 429 | .ramp_delay = MAX77686_DVS_RAMP_DELAY, \ |
a9597305 | 430 | .enable_time = MAX77686_DVS_ENABLE_TIME, \ |
133d4016 JL |
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, \ | |
3c37d899 AL |
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), \ | |
133d4016 JL |
441 | } |
442 | ||
73dbdf8f | 443 | static const struct regulator_desc regulators[] = { |
15282ba9 | 444 | regulator_desc_ldo1_low(1), |
133d4016 JL |
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), | |
15282ba9 YSB |
453 | regulator_desc_lpm_ldo(10), |
454 | regulator_desc_lpm_ldo(11), | |
455 | regulator_desc_lpm_ldo(12), | |
133d4016 | 456 | regulator_desc_ldo(13), |
15282ba9 | 457 | regulator_desc_lpm_ldo(14), |
133d4016 | 458 | regulator_desc_ldo_low(15), |
15282ba9 | 459 | regulator_desc_lpm_ldo(16), |
133d4016 JL |
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 | ||
a5023574 | 481 | static int max77686_pmic_probe(struct platform_device *pdev) |
133d4016 JL |
482 | { |
483 | struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); | |
133d4016 | 484 | struct max77686_data *max77686; |
04803952 | 485 | int i; |
c59d2a6b | 486 | struct regulator_config config = { }; |
133d4016 JL |
487 | |
488 | dev_dbg(&pdev->dev, "%s\n", __func__); | |
489 | ||
490 | max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data), | |
491 | GFP_KERNEL); | |
492 | if (!max77686) | |
493 | return -ENOMEM; | |
494 | ||
96392c3d | 495 | max77686->dev = &pdev->dev; |
04803952 | 496 | config.dev = iodev->dev; |
f503071b | 497 | config.regmap = iodev->regmap; |
6d2c896b | 498 | config.driver_data = max77686; |
133d4016 JL |
499 | platform_set_drvdata(pdev, max77686); |
500 | ||
ab0d1cbe | 501 | for (i = 0; i < MAX77686_REGULATORS; i++) { |
b0c13e80 | 502 | struct regulator_dev *rdev; |
eca29da9 | 503 | int id = regulators[i].id; |
b0c13e80 | 504 | |
4524df83 | 505 | max77686->opmode[id] = MAX77686_NORMAL; |
b0c13e80 | 506 | rdev = devm_regulator_register(&pdev->dev, |
44815b4a | 507 | ®ulators[i], &config); |
b0c13e80 | 508 | if (IS_ERR(rdev)) { |
04803952 | 509 | int ret = PTR_ERR(rdev); |
f503071b | 510 | dev_err(&pdev->dev, |
04803952 KK |
511 | "regulator init failed for %d: %d\n", i, ret); |
512 | return ret; | |
133d4016 | 513 | } |
133d4016 | 514 | } |
ab0d1cbe | 515 | |
133d4016 JL |
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", | |
259b93b2 | 528 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
133d4016 JL |
529 | }, |
530 | .probe = max77686_pmic_probe, | |
133d4016 JL |
531 | .id_table = max77686_pmic_id, |
532 | }; | |
533 | ||
314a8203 | 534 | module_platform_driver(max77686_pmic_driver); |
133d4016 JL |
535 | |
536 | MODULE_DESCRIPTION("MAXIM 77686 Regulator Driver"); | |
537 | MODULE_AUTHOR("Chiwoong Byun <[email protected]>"); | |
538 | MODULE_LICENSE("GPL"); |