Commit | Line | Data |
---|---|---|
6a1beee2 AL |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // | |
3 | // FAN53555 Fairchild Digitally Programmable TinyBuck Regulator Driver. | |
4 | // | |
5 | // Supported Part Numbers: | |
6 | // FAN53555UC00X/01X/03X/04X/05X | |
7 | // | |
8 | // Copyright (c) 2012 Marvell Technology Ltd. | |
9 | // Yunfan Zhang <yfzhang@marvell.com> | |
10 | ||
6bb18339 | 11 | #include <linux/bitops.h> |
4fb9a506 CC |
12 | #include <linux/err.h> |
13 | #include <linux/i2c.h> | |
49d8c599 | 14 | #include <linux/module.h> |
4fb9a506 | 15 | #include <linux/of_device.h> |
49d8c599 | 16 | #include <linux/param.h> |
49d8c599 | 17 | #include <linux/platform_device.h> |
4fb9a506 | 18 | #include <linux/regmap.h> |
49d8c599 | 19 | #include <linux/regulator/driver.h> |
4fb9a506 | 20 | #include <linux/regulator/fan53555.h> |
49d8c599 | 21 | #include <linux/regulator/machine.h> |
91f23d8f | 22 | #include <linux/regulator/of_regulator.h> |
49d8c599 | 23 | #include <linux/slab.h> |
49d8c599 YZ |
24 | |
25 | /* Voltage setting */ | |
26 | #define FAN53555_VSEL0 0x00 | |
27 | #define FAN53555_VSEL1 0x01 | |
914df8fa | 28 | |
a27e71a6 CC |
29 | #define RK8602_VSEL0 0x06 |
30 | #define RK8602_VSEL1 0x07 | |
31 | ||
914df8fa JC |
32 | #define TCS4525_VSEL0 0x11 |
33 | #define TCS4525_VSEL1 0x10 | |
34 | #define TCS4525_TIME 0x13 | |
35 | #define TCS4525_COMMAND 0x14 | |
36 | ||
49d8c599 YZ |
37 | /* Control register */ |
38 | #define FAN53555_CONTROL 0x02 | |
39 | /* IC Type */ | |
40 | #define FAN53555_ID1 0x03 | |
41 | /* IC mask version */ | |
42 | #define FAN53555_ID2 0x04 | |
43 | /* Monitor register */ | |
44 | #define FAN53555_MONITOR 0x05 | |
45 | ||
46 | /* VSEL bit definitions */ | |
d2501661 CC |
47 | #define VSEL_BUCK_EN BIT(7) |
48 | #define VSEL_MODE BIT(6) | |
49d8c599 | 49 | /* Chip ID and Verison */ |
d2501661 CC |
50 | #define DIE_ID 0x0F /* ID1 */ |
51 | #define DIE_REV 0x0F /* ID2 */ | |
49d8c599 | 52 | /* Control bit definitions */ |
d2501661 CC |
53 | #define CTL_OUTPUT_DISCHG BIT(7) |
54 | #define CTL_SLEW_MASK GENMASK(6, 4) | |
55 | #define CTL_RESET BIT(2) | |
f2a9eb97 BA |
56 | #define CTL_MODE_VSEL0_MODE BIT(0) |
57 | #define CTL_MODE_VSEL1_MODE BIT(1) | |
49d8c599 YZ |
58 | |
59 | #define FAN53555_NVOLTAGES 64 /* Numbers of voltages */ | |
f2a9eb97 | 60 | #define FAN53526_NVOLTAGES 128 |
a27e71a6 | 61 | #define RK8602_NVOLTAGES 160 |
914df8fa | 62 | |
d2501661 CC |
63 | #define TCS_VSEL0_MODE BIT(7) |
64 | #define TCS_VSEL1_MODE BIT(6) | |
914df8fa | 65 | |
c5d5b55b | 66 | #define TCS_SLEW_MASK GENMASK(4, 3) |
49d8c599 | 67 | |
ee30928a | 68 | enum fan53555_vendor { |
f2a9eb97 BA |
69 | FAN53526_VENDOR_FAIRCHILD = 0, |
70 | FAN53555_VENDOR_FAIRCHILD, | |
a27e71a6 CC |
71 | FAN53555_VENDOR_ROCKCHIP, /* RK8600, RK8601 */ |
72 | RK8602_VENDOR_ROCKCHIP, /* RK8602, RK8603 */ | |
ee30928a | 73 | FAN53555_VENDOR_SILERGY, |
b3cc8ec0 | 74 | FAN53526_VENDOR_TCS, |
ee30928a HS |
75 | }; |
76 | ||
f2a9eb97 BA |
77 | enum { |
78 | FAN53526_CHIP_ID_01 = 1, | |
79 | }; | |
80 | ||
81 | enum { | |
82 | FAN53526_CHIP_REV_08 = 8, | |
83 | }; | |
84 | ||
49d8c599 YZ |
85 | /* IC Type */ |
86 | enum { | |
87 | FAN53555_CHIP_ID_00 = 0, | |
88 | FAN53555_CHIP_ID_01, | |
89 | FAN53555_CHIP_ID_02, | |
90 | FAN53555_CHIP_ID_03, | |
91 | FAN53555_CHIP_ID_04, | |
92 | FAN53555_CHIP_ID_05, | |
5e39cf49 | 93 | FAN53555_CHIP_ID_08 = 8, |
49d8c599 YZ |
94 | }; |
95 | ||
a27e71a6 CC |
96 | enum { |
97 | RK8600_CHIP_ID_08 = 8, /* RK8600, RK8601 */ | |
98 | }; | |
99 | ||
100 | enum { | |
101 | RK8602_CHIP_ID_10 = 10, /* RK8602, RK8603 */ | |
102 | }; | |
103 | ||
f9028dcd PG |
104 | enum { |
105 | TCS4525_CHIP_ID_12 = 12, | |
106 | }; | |
107 | ||
5eee5ece RH |
108 | enum { |
109 | TCS4526_CHIP_ID_00 = 0, | |
110 | }; | |
111 | ||
e57cbb70 WE |
112 | /* IC mask revision */ |
113 | enum { | |
114 | FAN53555_CHIP_REV_00 = 0x3, | |
115 | FAN53555_CHIP_REV_13 = 0xf, | |
116 | }; | |
117 | ||
ee30928a HS |
118 | enum { |
119 | SILERGY_SYR82X = 8, | |
5365e3df | 120 | SILERGY_SYR83X = 9, |
ee30928a HS |
121 | }; |
122 | ||
49d8c599 | 123 | struct fan53555_device_info { |
ee30928a | 124 | enum fan53555_vendor vendor; |
49d8c599 YZ |
125 | struct device *dev; |
126 | struct regulator_desc desc; | |
49d8c599 YZ |
127 | struct regulator_init_data *regulator; |
128 | /* IC Type and Rev */ | |
129 | int chip_id; | |
130 | int chip_rev; | |
131 | /* Voltage setting register */ | |
132 | unsigned int vol_reg; | |
133 | unsigned int sleep_reg; | |
a27e71a6 CC |
134 | unsigned int en_reg; |
135 | unsigned int sleep_en_reg; | |
49d8c599 YZ |
136 | /* Voltage range and step(linear) */ |
137 | unsigned int vsel_min; | |
49d8c599 | 138 | unsigned int vsel_step; |
f2a9eb97 | 139 | unsigned int vsel_count; |
f2a9eb97 BA |
140 | /* Mode */ |
141 | unsigned int mode_reg; | |
142 | unsigned int mode_mask; | |
49d8c599 YZ |
143 | /* Sleep voltage cache */ |
144 | unsigned int sleep_vol_cache; | |
914df8fa JC |
145 | /* Slew rate */ |
146 | unsigned int slew_reg; | |
147 | unsigned int slew_mask; | |
b61ac767 AL |
148 | const unsigned int *ramp_delay_table; |
149 | unsigned int n_ramp_values; | |
914df8fa | 150 | unsigned int slew_rate; |
49d8c599 YZ |
151 | }; |
152 | ||
153 | static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV) | |
154 | { | |
155 | struct fan53555_device_info *di = rdev_get_drvdata(rdev); | |
156 | int ret; | |
157 | ||
158 | if (di->sleep_vol_cache == uV) | |
159 | return 0; | |
160 | ret = regulator_map_voltage_linear(rdev, uV, uV); | |
161 | if (ret < 0) | |
145fe1e1 | 162 | return ret; |
a69929c7 | 163 | ret = regmap_update_bits(rdev->regmap, di->sleep_reg, |
f2a9eb97 | 164 | di->desc.vsel_mask, ret); |
49d8c599 | 165 | if (ret < 0) |
145fe1e1 | 166 | return ret; |
49d8c599 YZ |
167 | /* Cache the sleep voltage setting. |
168 | * Might not be the real voltage which is rounded */ | |
169 | di->sleep_vol_cache = uV; | |
170 | ||
171 | return 0; | |
172 | } | |
173 | ||
ab7cad33 | 174 | static int fan53555_set_suspend_enable(struct regulator_dev *rdev) |
175 | { | |
176 | struct fan53555_device_info *di = rdev_get_drvdata(rdev); | |
177 | ||
a27e71a6 | 178 | return regmap_update_bits(rdev->regmap, di->sleep_en_reg, |
ab7cad33 | 179 | VSEL_BUCK_EN, VSEL_BUCK_EN); |
180 | } | |
181 | ||
182 | static int fan53555_set_suspend_disable(struct regulator_dev *rdev) | |
183 | { | |
184 | struct fan53555_device_info *di = rdev_get_drvdata(rdev); | |
185 | ||
a27e71a6 | 186 | return regmap_update_bits(rdev->regmap, di->sleep_en_reg, |
ab7cad33 | 187 | VSEL_BUCK_EN, 0); |
188 | } | |
189 | ||
49d8c599 YZ |
190 | static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode) |
191 | { | |
192 | struct fan53555_device_info *di = rdev_get_drvdata(rdev); | |
193 | ||
194 | switch (mode) { | |
195 | case REGULATOR_MODE_FAST: | |
a69929c7 | 196 | regmap_update_bits(rdev->regmap, di->mode_reg, |
f2a9eb97 | 197 | di->mode_mask, di->mode_mask); |
49d8c599 YZ |
198 | break; |
199 | case REGULATOR_MODE_NORMAL: | |
a69929c7 | 200 | regmap_update_bits(rdev->regmap, di->vol_reg, di->mode_mask, 0); |
49d8c599 YZ |
201 | break; |
202 | default: | |
203 | return -EINVAL; | |
204 | } | |
205 | return 0; | |
206 | } | |
207 | ||
208 | static unsigned int fan53555_get_mode(struct regulator_dev *rdev) | |
209 | { | |
210 | struct fan53555_device_info *di = rdev_get_drvdata(rdev); | |
211 | unsigned int val; | |
212 | int ret = 0; | |
213 | ||
a69929c7 | 214 | ret = regmap_read(rdev->regmap, di->mode_reg, &val); |
49d8c599 YZ |
215 | if (ret < 0) |
216 | return ret; | |
f2a9eb97 | 217 | if (val & di->mode_mask) |
49d8c599 YZ |
218 | return REGULATOR_MODE_FAST; |
219 | else | |
220 | return REGULATOR_MODE_NORMAL; | |
221 | } | |
222 | ||
b61ac767 | 223 | static const unsigned int slew_rates[] = { |
dd7e71fb HS |
224 | 64000, |
225 | 32000, | |
226 | 16000, | |
227 | 8000, | |
228 | 4000, | |
229 | 2000, | |
230 | 1000, | |
231 | 500, | |
232 | }; | |
233 | ||
b61ac767 | 234 | static const unsigned int tcs_slew_rates[] = { |
914df8fa JC |
235 | 18700, |
236 | 9300, | |
237 | 4600, | |
238 | 2300, | |
239 | }; | |
240 | ||
71880ab2 | 241 | static const struct regulator_ops fan53555_regulator_ops = { |
49d8c599 YZ |
242 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
243 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | |
fda87a42 | 244 | .set_voltage_time_sel = regulator_set_voltage_time_sel, |
49d8c599 YZ |
245 | .map_voltage = regulator_map_voltage_linear, |
246 | .list_voltage = regulator_list_voltage_linear, | |
247 | .set_suspend_voltage = fan53555_set_suspend_voltage, | |
248 | .enable = regulator_enable_regmap, | |
249 | .disable = regulator_disable_regmap, | |
250 | .is_enabled = regulator_is_enabled_regmap, | |
251 | .set_mode = fan53555_set_mode, | |
252 | .get_mode = fan53555_get_mode, | |
b61ac767 | 253 | .set_ramp_delay = regulator_set_ramp_delay_regmap, |
ab7cad33 | 254 | .set_suspend_enable = fan53555_set_suspend_enable, |
255 | .set_suspend_disable = fan53555_set_suspend_disable, | |
49d8c599 YZ |
256 | }; |
257 | ||
f2a9eb97 BA |
258 | static int fan53526_voltages_setup_fairchild(struct fan53555_device_info *di) |
259 | { | |
260 | /* Init voltage range and step */ | |
261 | switch (di->chip_id) { | |
262 | case FAN53526_CHIP_ID_01: | |
263 | switch (di->chip_rev) { | |
264 | case FAN53526_CHIP_REV_08: | |
265 | di->vsel_min = 600000; | |
266 | di->vsel_step = 6250; | |
267 | break; | |
268 | default: | |
269 | dev_err(di->dev, | |
270 | "Chip ID %d with rev %d not supported!\n", | |
271 | di->chip_id, di->chip_rev); | |
272 | return -EINVAL; | |
273 | } | |
274 | break; | |
275 | default: | |
276 | dev_err(di->dev, | |
277 | "Chip ID %d not supported!\n", di->chip_id); | |
278 | return -EINVAL; | |
279 | } | |
280 | ||
30b38b80 AL |
281 | di->slew_reg = FAN53555_CONTROL; |
282 | di->slew_mask = CTL_SLEW_MASK; | |
b61ac767 AL |
283 | di->ramp_delay_table = slew_rates; |
284 | di->n_ramp_values = ARRAY_SIZE(slew_rates); | |
f2a9eb97 BA |
285 | di->vsel_count = FAN53526_NVOLTAGES; |
286 | ||
287 | return 0; | |
288 | } | |
289 | ||
ee30928a HS |
290 | static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di) |
291 | { | |
292 | /* Init voltage range and step */ | |
293 | switch (di->chip_id) { | |
294 | case FAN53555_CHIP_ID_00: | |
e57cbb70 WE |
295 | switch (di->chip_rev) { |
296 | case FAN53555_CHIP_REV_00: | |
297 | di->vsel_min = 600000; | |
298 | di->vsel_step = 10000; | |
299 | break; | |
300 | case FAN53555_CHIP_REV_13: | |
301 | di->vsel_min = 800000; | |
302 | di->vsel_step = 10000; | |
303 | break; | |
304 | default: | |
305 | dev_err(di->dev, | |
306 | "Chip ID %d with rev %d not supported!\n", | |
307 | di->chip_id, di->chip_rev); | |
308 | return -EINVAL; | |
309 | } | |
310 | break; | |
ee30928a HS |
311 | case FAN53555_CHIP_ID_01: |
312 | case FAN53555_CHIP_ID_03: | |
313 | case FAN53555_CHIP_ID_05: | |
5e39cf49 | 314 | case FAN53555_CHIP_ID_08: |
ee30928a HS |
315 | di->vsel_min = 600000; |
316 | di->vsel_step = 10000; | |
317 | break; | |
318 | case FAN53555_CHIP_ID_04: | |
319 | di->vsel_min = 603000; | |
320 | di->vsel_step = 12826; | |
321 | break; | |
322 | default: | |
323 | dev_err(di->dev, | |
324 | "Chip ID %d not supported!\n", di->chip_id); | |
325 | return -EINVAL; | |
326 | } | |
914df8fa JC |
327 | di->slew_reg = FAN53555_CONTROL; |
328 | di->slew_mask = CTL_SLEW_MASK; | |
b61ac767 AL |
329 | di->ramp_delay_table = slew_rates; |
330 | di->n_ramp_values = ARRAY_SIZE(slew_rates); | |
f2a9eb97 BA |
331 | di->vsel_count = FAN53555_NVOLTAGES; |
332 | ||
ee30928a HS |
333 | return 0; |
334 | } | |
335 | ||
a27e71a6 CC |
336 | static int fan53555_voltages_setup_rockchip(struct fan53555_device_info *di) |
337 | { | |
338 | /* Init voltage range and step */ | |
339 | switch (di->chip_id) { | |
340 | case RK8600_CHIP_ID_08: | |
341 | di->vsel_min = 712500; | |
342 | di->vsel_step = 12500; | |
343 | break; | |
344 | default: | |
345 | dev_err(di->dev, | |
346 | "Chip ID %d not supported!\n", di->chip_id); | |
347 | return -EINVAL; | |
348 | } | |
349 | di->slew_reg = FAN53555_CONTROL; | |
350 | di->slew_mask = CTL_SLEW_MASK; | |
351 | di->ramp_delay_table = slew_rates; | |
352 | di->n_ramp_values = ARRAY_SIZE(slew_rates); | |
353 | di->vsel_count = FAN53555_NVOLTAGES; | |
354 | ||
355 | return 0; | |
356 | } | |
357 | ||
358 | static int rk8602_voltages_setup_rockchip(struct fan53555_device_info *di) | |
359 | { | |
360 | /* Init voltage range and step */ | |
361 | switch (di->chip_id) { | |
362 | case RK8602_CHIP_ID_10: | |
363 | di->vsel_min = 500000; | |
364 | di->vsel_step = 6250; | |
365 | break; | |
366 | default: | |
367 | dev_err(di->dev, | |
368 | "Chip ID %d not supported!\n", di->chip_id); | |
369 | return -EINVAL; | |
370 | } | |
371 | di->slew_reg = FAN53555_CONTROL; | |
372 | di->slew_mask = CTL_SLEW_MASK; | |
373 | di->ramp_delay_table = slew_rates; | |
374 | di->n_ramp_values = ARRAY_SIZE(slew_rates); | |
375 | di->vsel_count = RK8602_NVOLTAGES; | |
376 | ||
377 | return 0; | |
378 | } | |
379 | ||
ee30928a HS |
380 | static int fan53555_voltages_setup_silergy(struct fan53555_device_info *di) |
381 | { | |
382 | /* Init voltage range and step */ | |
383 | switch (di->chip_id) { | |
384 | case SILERGY_SYR82X: | |
5365e3df | 385 | case SILERGY_SYR83X: |
ee30928a HS |
386 | di->vsel_min = 712500; |
387 | di->vsel_step = 12500; | |
388 | break; | |
389 | default: | |
390 | dev_err(di->dev, | |
391 | "Chip ID %d not supported!\n", di->chip_id); | |
392 | return -EINVAL; | |
393 | } | |
914df8fa | 394 | di->slew_reg = FAN53555_CONTROL; |
914df8fa | 395 | di->slew_mask = CTL_SLEW_MASK; |
b61ac767 AL |
396 | di->ramp_delay_table = slew_rates; |
397 | di->n_ramp_values = ARRAY_SIZE(slew_rates); | |
f2a9eb97 BA |
398 | di->vsel_count = FAN53555_NVOLTAGES; |
399 | ||
ee30928a HS |
400 | return 0; |
401 | } | |
402 | ||
b3cc8ec0 | 403 | static int fan53526_voltages_setup_tcs(struct fan53555_device_info *di) |
914df8fa | 404 | { |
f9028dcd PG |
405 | switch (di->chip_id) { |
406 | case TCS4525_CHIP_ID_12: | |
5eee5ece | 407 | case TCS4526_CHIP_ID_00: |
f9028dcd PG |
408 | di->slew_reg = TCS4525_TIME; |
409 | di->slew_mask = TCS_SLEW_MASK; | |
b61ac767 AL |
410 | di->ramp_delay_table = tcs_slew_rates; |
411 | di->n_ramp_values = ARRAY_SIZE(tcs_slew_rates); | |
914df8fa | 412 | |
f9028dcd PG |
413 | /* Init voltage range and step */ |
414 | di->vsel_min = 600000; | |
415 | di->vsel_step = 6250; | |
416 | di->vsel_count = FAN53526_NVOLTAGES; | |
417 | break; | |
418 | default: | |
419 | dev_err(di->dev, "Chip ID %d not supported!\n", di->chip_id); | |
420 | return -EINVAL; | |
421 | } | |
914df8fa JC |
422 | |
423 | return 0; | |
424 | } | |
425 | ||
49d8c599 YZ |
426 | /* For 00,01,03,05 options: |
427 | * VOUT = 0.60V + NSELx * 10mV, from 0.60 to 1.23V. | |
428 | * For 04 option: | |
429 | * VOUT = 0.603V + NSELx * 12.826mV, from 0.603 to 1.411V. | |
430 | * */ | |
431 | static int fan53555_device_setup(struct fan53555_device_info *di, | |
432 | struct fan53555_platform_data *pdata) | |
433 | { | |
ee30928a HS |
434 | int ret = 0; |
435 | ||
49d8c599 | 436 | /* Setup voltage control register */ |
914df8fa JC |
437 | switch (di->vendor) { |
438 | case FAN53526_VENDOR_FAIRCHILD: | |
439 | case FAN53555_VENDOR_FAIRCHILD: | |
a27e71a6 | 440 | case FAN53555_VENDOR_ROCKCHIP: |
914df8fa JC |
441 | case FAN53555_VENDOR_SILERGY: |
442 | switch (pdata->sleep_vsel_id) { | |
443 | case FAN53555_VSEL_ID_0: | |
444 | di->sleep_reg = FAN53555_VSEL0; | |
445 | di->vol_reg = FAN53555_VSEL1; | |
446 | break; | |
447 | case FAN53555_VSEL_ID_1: | |
448 | di->sleep_reg = FAN53555_VSEL1; | |
449 | di->vol_reg = FAN53555_VSEL0; | |
450 | break; | |
451 | default: | |
452 | dev_err(di->dev, "Invalid VSEL ID!\n"); | |
453 | return -EINVAL; | |
454 | } | |
a27e71a6 CC |
455 | di->sleep_en_reg = di->sleep_reg; |
456 | di->en_reg = di->vol_reg; | |
457 | break; | |
458 | case RK8602_VENDOR_ROCKCHIP: | |
459 | switch (pdata->sleep_vsel_id) { | |
460 | case FAN53555_VSEL_ID_0: | |
461 | di->sleep_reg = RK8602_VSEL0; | |
462 | di->vol_reg = RK8602_VSEL1; | |
463 | di->sleep_en_reg = FAN53555_VSEL0; | |
464 | di->en_reg = FAN53555_VSEL1; | |
465 | break; | |
466 | case FAN53555_VSEL_ID_1: | |
467 | di->sleep_reg = RK8602_VSEL1; | |
468 | di->vol_reg = RK8602_VSEL0; | |
469 | di->sleep_en_reg = FAN53555_VSEL1; | |
470 | di->en_reg = FAN53555_VSEL0; | |
471 | break; | |
472 | default: | |
473 | dev_err(di->dev, "Invalid VSEL ID!\n"); | |
474 | return -EINVAL; | |
475 | } | |
49d8c599 | 476 | break; |
b3cc8ec0 | 477 | case FAN53526_VENDOR_TCS: |
914df8fa JC |
478 | switch (pdata->sleep_vsel_id) { |
479 | case FAN53555_VSEL_ID_0: | |
480 | di->sleep_reg = TCS4525_VSEL0; | |
481 | di->vol_reg = TCS4525_VSEL1; | |
482 | break; | |
483 | case FAN53555_VSEL_ID_1: | |
484 | di->sleep_reg = TCS4525_VSEL1; | |
485 | di->vol_reg = TCS4525_VSEL0; | |
486 | break; | |
487 | default: | |
488 | dev_err(di->dev, "Invalid VSEL ID!\n"); | |
489 | return -EINVAL; | |
490 | } | |
a27e71a6 CC |
491 | di->sleep_en_reg = di->sleep_reg; |
492 | di->en_reg = di->vol_reg; | |
49d8c599 YZ |
493 | break; |
494 | default: | |
914df8fa | 495 | dev_err(di->dev, "vendor %d not supported!\n", di->vendor); |
49d8c599 YZ |
496 | return -EINVAL; |
497 | } | |
ee30928a | 498 | |
f2a9eb97 BA |
499 | /* Setup mode control register */ |
500 | switch (di->vendor) { | |
501 | case FAN53526_VENDOR_FAIRCHILD: | |
502 | di->mode_reg = FAN53555_CONTROL; | |
503 | ||
504 | switch (pdata->sleep_vsel_id) { | |
505 | case FAN53555_VSEL_ID_0: | |
506 | di->mode_mask = CTL_MODE_VSEL1_MODE; | |
507 | break; | |
508 | case FAN53555_VSEL_ID_1: | |
509 | di->mode_mask = CTL_MODE_VSEL0_MODE; | |
510 | break; | |
511 | } | |
512 | break; | |
513 | case FAN53555_VENDOR_FAIRCHILD: | |
a27e71a6 | 514 | case FAN53555_VENDOR_ROCKCHIP: |
f2a9eb97 BA |
515 | case FAN53555_VENDOR_SILERGY: |
516 | di->mode_reg = di->vol_reg; | |
517 | di->mode_mask = VSEL_MODE; | |
518 | break; | |
a27e71a6 CC |
519 | case RK8602_VENDOR_ROCKCHIP: |
520 | di->mode_mask = VSEL_MODE; | |
521 | ||
522 | switch (pdata->sleep_vsel_id) { | |
523 | case FAN53555_VSEL_ID_0: | |
524 | di->mode_reg = FAN53555_VSEL1; | |
525 | break; | |
526 | case FAN53555_VSEL_ID_1: | |
527 | di->mode_reg = FAN53555_VSEL0; | |
528 | break; | |
529 | } | |
530 | break; | |
b3cc8ec0 | 531 | case FAN53526_VENDOR_TCS: |
914df8fa JC |
532 | di->mode_reg = TCS4525_COMMAND; |
533 | ||
534 | switch (pdata->sleep_vsel_id) { | |
535 | case FAN53555_VSEL_ID_0: | |
536 | di->mode_mask = TCS_VSEL1_MODE; | |
537 | break; | |
538 | case FAN53555_VSEL_ID_1: | |
539 | di->mode_mask = TCS_VSEL0_MODE; | |
540 | break; | |
541 | } | |
542 | break; | |
f2a9eb97 BA |
543 | default: |
544 | dev_err(di->dev, "vendor %d not supported!\n", di->vendor); | |
545 | return -EINVAL; | |
546 | } | |
547 | ||
548 | /* Setup voltage range */ | |
ee30928a | 549 | switch (di->vendor) { |
f2a9eb97 BA |
550 | case FAN53526_VENDOR_FAIRCHILD: |
551 | ret = fan53526_voltages_setup_fairchild(di); | |
552 | break; | |
ee30928a HS |
553 | case FAN53555_VENDOR_FAIRCHILD: |
554 | ret = fan53555_voltages_setup_fairchild(di); | |
49d8c599 | 555 | break; |
a27e71a6 CC |
556 | case FAN53555_VENDOR_ROCKCHIP: |
557 | ret = fan53555_voltages_setup_rockchip(di); | |
558 | break; | |
559 | case RK8602_VENDOR_ROCKCHIP: | |
560 | ret = rk8602_voltages_setup_rockchip(di); | |
561 | break; | |
ee30928a HS |
562 | case FAN53555_VENDOR_SILERGY: |
563 | ret = fan53555_voltages_setup_silergy(di); | |
49d8c599 | 564 | break; |
b3cc8ec0 PG |
565 | case FAN53526_VENDOR_TCS: |
566 | ret = fan53526_voltages_setup_tcs(di); | |
914df8fa | 567 | break; |
49d8c599 | 568 | default: |
fe230531 | 569 | dev_err(di->dev, "vendor %d not supported!\n", di->vendor); |
49d8c599 YZ |
570 | return -EINVAL; |
571 | } | |
dd7e71fb | 572 | |
ee30928a | 573 | return ret; |
49d8c599 YZ |
574 | } |
575 | ||
576 | static int fan53555_regulator_register(struct fan53555_device_info *di, | |
577 | struct regulator_config *config) | |
578 | { | |
579 | struct regulator_desc *rdesc = &di->desc; | |
a69929c7 | 580 | struct regulator_dev *rdev; |
49d8c599 YZ |
581 | |
582 | rdesc->name = "fan53555-reg"; | |
3415d601 | 583 | rdesc->supply_name = "vin"; |
49d8c599 YZ |
584 | rdesc->ops = &fan53555_regulator_ops; |
585 | rdesc->type = REGULATOR_VOLTAGE; | |
f2a9eb97 | 586 | rdesc->n_voltages = di->vsel_count; |
a27e71a6 | 587 | rdesc->enable_reg = di->en_reg; |
49d8c599 YZ |
588 | rdesc->enable_mask = VSEL_BUCK_EN; |
589 | rdesc->min_uV = di->vsel_min; | |
590 | rdesc->uV_step = di->vsel_step; | |
591 | rdesc->vsel_reg = di->vol_reg; | |
6bb18339 | 592 | rdesc->vsel_mask = BIT(fls(di->vsel_count - 1)) - 1; |
b61ac767 AL |
593 | rdesc->ramp_reg = di->slew_reg; |
594 | rdesc->ramp_mask = di->slew_mask; | |
595 | rdesc->ramp_delay_table = di->ramp_delay_table; | |
596 | rdesc->n_ramp_values = di->n_ramp_values; | |
49d8c599 YZ |
597 | rdesc->owner = THIS_MODULE; |
598 | ||
a69929c7 AL |
599 | rdev = devm_regulator_register(di->dev, &di->desc, config); |
600 | return PTR_ERR_OR_ZERO(rdev); | |
49d8c599 YZ |
601 | } |
602 | ||
121b567d | 603 | static const struct regmap_config fan53555_regmap_config = { |
49d8c599 YZ |
604 | .reg_bits = 8, |
605 | .val_bits = 8, | |
606 | }; | |
607 | ||
91f23d8f | 608 | static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev, |
072e78b1 JMC |
609 | struct device_node *np, |
610 | const struct regulator_desc *desc) | |
91f23d8f HS |
611 | { |
612 | struct fan53555_platform_data *pdata; | |
613 | int ret; | |
614 | u32 tmp; | |
615 | ||
616 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | |
617 | if (!pdata) | |
618 | return NULL; | |
619 | ||
072e78b1 | 620 | pdata->regulator = of_get_regulator_init_data(dev, np, desc); |
91f23d8f HS |
621 | |
622 | ret = of_property_read_u32(np, "fcs,suspend-voltage-selector", | |
623 | &tmp); | |
624 | if (!ret) | |
625 | pdata->sleep_vsel_id = tmp; | |
626 | ||
627 | return pdata; | |
628 | } | |
629 | ||
5e97d7e8 | 630 | static const struct of_device_id __maybe_unused fan53555_dt_ids[] = { |
91f23d8f | 631 | { |
f2a9eb97 BA |
632 | .compatible = "fcs,fan53526", |
633 | .data = (void *)FAN53526_VENDOR_FAIRCHILD, | |
634 | }, { | |
91f23d8f | 635 | .compatible = "fcs,fan53555", |
ee30928a | 636 | .data = (void *)FAN53555_VENDOR_FAIRCHILD |
a27e71a6 CC |
637 | }, { |
638 | .compatible = "rockchip,rk8600", | |
639 | .data = (void *)FAN53555_VENDOR_ROCKCHIP | |
640 | }, { | |
641 | .compatible = "rockchip,rk8602", | |
642 | .data = (void *)RK8602_VENDOR_ROCKCHIP | |
ee30928a HS |
643 | }, { |
644 | .compatible = "silergy,syr827", | |
645 | .data = (void *)FAN53555_VENDOR_SILERGY, | |
646 | }, { | |
647 | .compatible = "silergy,syr828", | |
648 | .data = (void *)FAN53555_VENDOR_SILERGY, | |
914df8fa JC |
649 | }, { |
650 | .compatible = "tcs,tcs4525", | |
b3cc8ec0 | 651 | .data = (void *)FAN53526_VENDOR_TCS |
5eee5ece RH |
652 | }, { |
653 | .compatible = "tcs,tcs4526", | |
654 | .data = (void *)FAN53526_VENDOR_TCS | |
91f23d8f HS |
655 | }, |
656 | { } | |
657 | }; | |
658 | MODULE_DEVICE_TABLE(of, fan53555_dt_ids); | |
659 | ||
65542565 | 660 | static int fan53555_regulator_probe(struct i2c_client *client) |
49d8c599 | 661 | { |
65542565 | 662 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
91f23d8f | 663 | struct device_node *np = client->dev.of_node; |
49d8c599 YZ |
664 | struct fan53555_device_info *di; |
665 | struct fan53555_platform_data *pdata; | |
666 | struct regulator_config config = { }; | |
a69929c7 | 667 | struct regmap *regmap; |
49d8c599 YZ |
668 | unsigned int val; |
669 | int ret; | |
670 | ||
072e78b1 JMC |
671 | di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info), |
672 | GFP_KERNEL); | |
673 | if (!di) | |
674 | return -ENOMEM; | |
675 | ||
dff91d0b | 676 | pdata = dev_get_platdata(&client->dev); |
91f23d8f | 677 | if (!pdata) |
072e78b1 | 678 | pdata = fan53555_parse_dt(&client->dev, np, &di->desc); |
91f23d8f | 679 | |
2c82f5b8 CC |
680 | if (!pdata || !pdata->regulator) |
681 | return dev_err_probe(&client->dev, -ENODEV, | |
682 | "Platform data not found!\n"); | |
49d8c599 | 683 | |
e13426bf | 684 | di->regulator = pdata->regulator; |
ee30928a | 685 | if (client->dev.of_node) { |
d110e3e9 JZ |
686 | di->vendor = |
687 | (unsigned long)of_device_get_match_data(&client->dev); | |
ee30928a | 688 | } else { |
91f23d8f HS |
689 | /* if no ramp constraint set, get the pdata ramp_delay */ |
690 | if (!di->regulator->constraints.ramp_delay) { | |
2c82f5b8 CC |
691 | if (pdata->slew_rate >= ARRAY_SIZE(slew_rates)) |
692 | return dev_err_probe(&client->dev, -EINVAL, | |
693 | "Invalid slew_rate\n"); | |
dd7e71fb | 694 | |
91f23d8f | 695 | di->regulator->constraints.ramp_delay |
87919e0c | 696 | = slew_rates[pdata->slew_rate]; |
91f23d8f | 697 | } |
ee30928a HS |
698 | |
699 | di->vendor = id->driver_data; | |
dd7e71fb HS |
700 | } |
701 | ||
a69929c7 | 702 | regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config); |
2c82f5b8 CC |
703 | if (IS_ERR(regmap)) |
704 | return dev_err_probe(&client->dev, PTR_ERR(regmap), | |
705 | "Failed to allocate regmap!\n"); | |
706 | ||
49d8c599 | 707 | di->dev = &client->dev; |
49d8c599 YZ |
708 | i2c_set_clientdata(client, di); |
709 | /* Get chip ID */ | |
a69929c7 | 710 | ret = regmap_read(regmap, FAN53555_ID1, &val); |
2c82f5b8 CC |
711 | if (ret < 0) |
712 | return dev_err_probe(&client->dev, ret, "Failed to get chip ID!\n"); | |
713 | ||
49d8c599 YZ |
714 | di->chip_id = val & DIE_ID; |
715 | /* Get chip revision */ | |
a69929c7 | 716 | ret = regmap_read(regmap, FAN53555_ID2, &val); |
2c82f5b8 CC |
717 | if (ret < 0) |
718 | return dev_err_probe(&client->dev, ret, "Failed to get chip Rev!\n"); | |
719 | ||
49d8c599 YZ |
720 | di->chip_rev = val & DIE_REV; |
721 | dev_info(&client->dev, "FAN53555 Option[%d] Rev[%d] Detected!\n", | |
722 | di->chip_id, di->chip_rev); | |
723 | /* Device init */ | |
724 | ret = fan53555_device_setup(di, pdata); | |
2c82f5b8 CC |
725 | if (ret < 0) |
726 | return dev_err_probe(&client->dev, ret, "Failed to setup device!\n"); | |
727 | ||
49d8c599 YZ |
728 | /* Register regulator */ |
729 | config.dev = di->dev; | |
730 | config.init_data = di->regulator; | |
a69929c7 | 731 | config.regmap = regmap; |
49d8c599 | 732 | config.driver_data = di; |
91f23d8f HS |
733 | config.of_node = np; |
734 | ||
49d8c599 YZ |
735 | ret = fan53555_regulator_register(di, &config); |
736 | if (ret < 0) | |
2c82f5b8 | 737 | dev_err_probe(&client->dev, ret, "Failed to register regulator!\n"); |
49d8c599 | 738 | |
2c82f5b8 | 739 | return ret; |
49d8c599 YZ |
740 | } |
741 | ||
49d8c599 | 742 | static const struct i2c_device_id fan53555_id[] = { |
ee30928a | 743 | { |
f2a9eb97 BA |
744 | .name = "fan53526", |
745 | .driver_data = FAN53526_VENDOR_FAIRCHILD | |
746 | }, { | |
ee30928a HS |
747 | .name = "fan53555", |
748 | .driver_data = FAN53555_VENDOR_FAIRCHILD | |
a27e71a6 CC |
749 | }, { |
750 | .name = "rk8600", | |
751 | .driver_data = FAN53555_VENDOR_ROCKCHIP | |
752 | }, { | |
753 | .name = "rk8602", | |
754 | .driver_data = RK8602_VENDOR_ROCKCHIP | |
ee30928a | 755 | }, { |
fc1111b8 GT |
756 | .name = "syr827", |
757 | .driver_data = FAN53555_VENDOR_SILERGY | |
758 | }, { | |
759 | .name = "syr828", | |
ee30928a | 760 | .driver_data = FAN53555_VENDOR_SILERGY |
914df8fa JC |
761 | }, { |
762 | .name = "tcs4525", | |
b3cc8ec0 | 763 | .driver_data = FAN53526_VENDOR_TCS |
5eee5ece RH |
764 | }, { |
765 | .name = "tcs4526", | |
766 | .driver_data = FAN53526_VENDOR_TCS | |
ee30928a | 767 | }, |
49d8c599 YZ |
768 | { }, |
769 | }; | |
e80c47bd | 770 | MODULE_DEVICE_TABLE(i2c, fan53555_id); |
49d8c599 YZ |
771 | |
772 | static struct i2c_driver fan53555_regulator_driver = { | |
773 | .driver = { | |
774 | .name = "fan53555-regulator", | |
259b93b2 | 775 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
91f23d8f | 776 | .of_match_table = of_match_ptr(fan53555_dt_ids), |
49d8c599 | 777 | }, |
964e1865 | 778 | .probe = fan53555_regulator_probe, |
49d8c599 YZ |
779 | .id_table = fan53555_id, |
780 | }; | |
781 | ||
782 | module_i2c_driver(fan53555_regulator_driver); | |
783 | ||
784 | MODULE_AUTHOR("Yunfan Zhang <yfzhang@marvell.com>"); | |
785 | MODULE_DESCRIPTION("FAN53555 regulator driver"); | |
786 | MODULE_LICENSE("GPL v2"); |