1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (c) 2023 Analog Devices, Inc. |
4 | * ADI Regulator driver for the MAX77857 |
5 | * MAX77859 and MAX77831. |
6 | */ |
7 | #include <linux/bitfield.h> |
8 | #include <linux/i2c.h> |
9 | #include <linux/interrupt.h> |
10 | #include <linux/module.h> |
11 | #include <linux/regmap.h> |
12 | #include <linux/regulator/driver.h> |
13 | #include <linux/regulator/machine.h> |
14 | #include <linux/regulator/of_regulator.h> |
15 | #include <linux/util_macros.h> |
16 | |
17 | #define MAX77857_REG_INT_SRC 0x10 |
18 | #define MAX77857_REG_INT_MASK 0x11 |
19 | #define MAX77857_REG_CONT1 0x12 |
20 | #define MAX77857_REG_CONT2 0x13 |
21 | #define MAX77857_REG_CONT3 0x14 |
22 | |
23 | #define MAX77857_INT_SRC_OCP BIT(0) |
24 | #define MAX77857_INT_SRC_THS BIT(1) |
25 | #define MAX77857_INT_SRC_HARDSHORT BIT(2) |
26 | #define MAX77857_INT_SRC_OVP BIT(3) |
27 | #define MAX77857_INT_SRC_POK BIT(4) |
28 | |
29 | #define MAX77857_ILIM_MASK GENMASK(2, 0) |
30 | #define MAX77857_CONT1_FREQ GENMASK(4, 3) |
31 | #define MAX77857_CONT3_FPWM BIT(5) |
32 | |
33 | #define MAX77859_REG_INT_SRC 0x11 |
34 | #define MAX77859_REG_CONT1 0x13 |
35 | #define MAX77859_REG_CONT2 0x14 |
36 | #define MAX77859_REG_CONT3 0x15 |
37 | #define MAX77859_REG_CONT5 0x17 |
38 | #define MAX77859_CONT2_FPWM BIT(2) |
39 | #define MAX77859_CONT2_INTB BIT(3) |
40 | #define MAX77859_CONT3_DVS_START BIT(2) |
41 | #define MAX77859_VOLTAGE_SEL_MASK GENMASK(9, 0) |
42 | |
43 | #define MAX77859_CURRENT_MIN 1000000 |
44 | #define MAX77859_CURRENT_MAX 5000000 |
45 | #define MAX77859_CURRENT_STEP 50000 |
46 | |
47 | enum max77857_id { |
48 | ID_MAX77831 = 1, |
49 | ID_MAX77857, |
50 | ID_MAX77859, |
51 | ID_MAX77859A, |
52 | }; |
53 | |
54 | static bool max77857_volatile_reg(struct device *dev, unsigned int reg) |
55 | { |
56 | enum max77857_id id = (uintptr_t)dev_get_drvdata(dev); |
57 | |
58 | switch (id) { |
59 | case ID_MAX77831: |
60 | case ID_MAX77857: |
61 | return reg == MAX77857_REG_INT_SRC; |
62 | case ID_MAX77859: |
63 | case ID_MAX77859A: |
64 | return reg == MAX77859_REG_INT_SRC; |
65 | default: |
66 | return true; |
67 | } |
68 | } |
69 | |
70 | static struct regmap_config max77857_regmap_config = { |
71 | .reg_bits = 8, |
72 | .val_bits = 8, |
73 | .cache_type = REGCACHE_MAPLE, |
74 | .volatile_reg = max77857_volatile_reg, |
75 | }; |
76 | |
77 | static int max77857_get_status(struct regulator_dev *rdev) |
78 | { |
79 | unsigned int val; |
80 | int ret; |
81 | |
82 | ret = regmap_read(map: rdev->regmap, MAX77857_REG_INT_SRC, val: &val); |
83 | if (ret) |
84 | return ret; |
85 | |
86 | if (FIELD_GET(MAX77857_INT_SRC_POK, val)) |
87 | return REGULATOR_STATUS_ON; |
88 | |
89 | return REGULATOR_STATUS_ERROR; |
90 | } |
91 | |
92 | static unsigned int max77857_get_mode(struct regulator_dev *rdev) |
93 | { |
94 | enum max77857_id id = (uintptr_t)rdev_get_drvdata(rdev); |
95 | unsigned int regval; |
96 | int ret; |
97 | |
98 | switch (id) { |
99 | case ID_MAX77831: |
100 | case ID_MAX77857: |
101 | ret = regmap_read(map: rdev->regmap, MAX77857_REG_CONT3, val: ®val); |
102 | if (ret) |
103 | return ret; |
104 | |
105 | if (FIELD_GET(MAX77857_CONT3_FPWM, regval)) |
106 | return REGULATOR_MODE_FAST; |
107 | |
108 | break; |
109 | case ID_MAX77859: |
110 | case ID_MAX77859A: |
111 | ret = regmap_read(map: rdev->regmap, MAX77859_REG_CONT2, val: ®val); |
112 | if (ret) |
113 | return ret; |
114 | |
115 | if (FIELD_GET(MAX77859_CONT2_FPWM, regval)) |
116 | return REGULATOR_MODE_FAST; |
117 | |
118 | break; |
119 | default: |
120 | return -EINVAL; |
121 | } |
122 | |
123 | return REGULATOR_MODE_NORMAL; |
124 | } |
125 | |
126 | static int max77857_set_mode(struct regulator_dev *rdev, unsigned int mode) |
127 | { |
128 | enum max77857_id id = (uintptr_t)rdev_get_drvdata(rdev); |
129 | unsigned int reg, val; |
130 | |
131 | switch (id) { |
132 | case ID_MAX77831: |
133 | case ID_MAX77857: |
134 | reg = MAX77857_REG_CONT3; |
135 | val = MAX77857_CONT3_FPWM; |
136 | break; |
137 | case ID_MAX77859: |
138 | case ID_MAX77859A: |
139 | reg = MAX77859_REG_CONT2; |
140 | val = MAX77859_CONT2_FPWM; |
141 | break; |
142 | default: |
143 | return -EINVAL; |
144 | } |
145 | |
146 | switch (mode) { |
147 | case REGULATOR_MODE_FAST: |
148 | return regmap_set_bits(map: rdev->regmap, reg, bits: val); |
149 | case REGULATOR_MODE_NORMAL: |
150 | return regmap_clear_bits(map: rdev->regmap, reg, bits: val); |
151 | default: |
152 | return -EINVAL; |
153 | } |
154 | } |
155 | |
156 | static int max77857_get_error_flags(struct regulator_dev *rdev, |
157 | unsigned int *flags) |
158 | { |
159 | unsigned int val; |
160 | int ret; |
161 | |
162 | ret = regmap_read(map: rdev->regmap, MAX77857_REG_INT_SRC, val: &val); |
163 | if (ret) |
164 | return ret; |
165 | |
166 | *flags = 0; |
167 | |
168 | if (FIELD_GET(MAX77857_INT_SRC_OVP, val)) |
169 | *flags |= REGULATOR_ERROR_OVER_VOLTAGE_WARN; |
170 | |
171 | if (FIELD_GET(MAX77857_INT_SRC_OCP, val) || |
172 | FIELD_GET(MAX77857_INT_SRC_HARDSHORT, val)) |
173 | *flags |= REGULATOR_ERROR_OVER_CURRENT; |
174 | |
175 | if (FIELD_GET(MAX77857_INT_SRC_THS, val)) |
176 | *flags |= REGULATOR_ERROR_OVER_TEMP; |
177 | |
178 | if (!FIELD_GET(MAX77857_INT_SRC_POK, val)) |
179 | *flags |= REGULATOR_ERROR_FAIL; |
180 | |
181 | return 0; |
182 | } |
183 | |
184 | static struct linear_range max77859_lin_ranges[] = { |
185 | REGULATOR_LINEAR_RANGE(3200000, 0x0A0, 0x320, 20000) |
186 | }; |
187 | |
188 | static const unsigned int max77859_ramp_table[4] = { |
189 | 1000, 500, 250, 125 |
190 | }; |
191 | |
192 | static int max77859_set_voltage_sel(struct regulator_dev *rdev, |
193 | unsigned int sel) |
194 | { |
195 | __be16 reg; |
196 | int ret; |
197 | |
198 | reg = cpu_to_be16(sel); |
199 | |
200 | ret = regmap_bulk_write(map: rdev->regmap, MAX77859_REG_CONT3, val: ®, val_count: 2); |
201 | if (ret) |
202 | return ret; |
203 | |
204 | /* actually apply new voltage */ |
205 | return regmap_set_bits(map: rdev->regmap, MAX77859_REG_CONT3, |
206 | MAX77859_CONT3_DVS_START); |
207 | } |
208 | |
209 | static int max77859_get_voltage_sel(struct regulator_dev *rdev) |
210 | { |
211 | __be16 reg; |
212 | int ret; |
213 | |
214 | ret = regmap_bulk_read(map: rdev->regmap, MAX77859_REG_CONT3, val: ®, val_count: 2); |
215 | if (ret) |
216 | return ret; |
217 | |
218 | return FIELD_GET(MAX77859_VOLTAGE_SEL_MASK, __be16_to_cpu(reg)); |
219 | } |
220 | |
221 | static int max77859_set_current_limit(struct regulator_dev *rdev, int min_uA, int max_uA) |
222 | { |
223 | u32 selector; |
224 | |
225 | if (max_uA < MAX77859_CURRENT_MIN) |
226 | return -EINVAL; |
227 | |
228 | selector = 0x12 + (max_uA - MAX77859_CURRENT_MIN) / MAX77859_CURRENT_STEP; |
229 | |
230 | selector = clamp_val(selector, 0x00, 0x7F); |
231 | |
232 | return regmap_write(map: rdev->regmap, MAX77859_REG_CONT5, val: selector); |
233 | } |
234 | |
235 | static int max77859_get_current_limit(struct regulator_dev *rdev) |
236 | { |
237 | u32 selector; |
238 | int ret; |
239 | |
240 | ret = regmap_read(map: rdev->regmap, MAX77859_REG_CONT5, val: &selector); |
241 | if (ret) |
242 | return ret; |
243 | |
244 | if (selector <= 0x12) |
245 | return MAX77859_CURRENT_MIN; |
246 | |
247 | if (selector >= 0x64) |
248 | return MAX77859_CURRENT_MAX; |
249 | |
250 | return MAX77859_CURRENT_MIN + (selector - 0x12) * MAX77859_CURRENT_STEP; |
251 | } |
252 | |
253 | static const struct regulator_ops max77859_regulator_ops = { |
254 | .list_voltage = regulator_list_voltage_linear_range, |
255 | .set_voltage_sel = max77859_set_voltage_sel, |
256 | .get_voltage_sel = max77859_get_voltage_sel, |
257 | .set_ramp_delay = regulator_set_ramp_delay_regmap, |
258 | .get_status = max77857_get_status, |
259 | .set_mode = max77857_set_mode, |
260 | .get_mode = max77857_get_mode, |
261 | .get_error_flags = max77857_get_error_flags, |
262 | }; |
263 | |
264 | static const struct regulator_ops max77859a_regulator_ops = { |
265 | .list_voltage = regulator_list_voltage_linear_range, |
266 | .set_voltage_sel = max77859_set_voltage_sel, |
267 | .get_voltage_sel = max77859_get_voltage_sel, |
268 | .set_current_limit = max77859_set_current_limit, |
269 | .get_current_limit = max77859_get_current_limit, |
270 | .set_ramp_delay = regulator_set_ramp_delay_regmap, |
271 | .get_status = max77857_get_status, |
272 | .set_mode = max77857_set_mode, |
273 | .get_mode = max77857_get_mode, |
274 | .get_error_flags = max77857_get_error_flags, |
275 | }; |
276 | |
277 | static const struct regulator_ops max77857_regulator_ops = { |
278 | .list_voltage = regulator_list_voltage_linear_range, |
279 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
280 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
281 | .set_ramp_delay = regulator_set_ramp_delay_regmap, |
282 | .get_status = max77857_get_status, |
283 | .set_mode = max77857_set_mode, |
284 | .get_mode = max77857_get_mode, |
285 | .get_error_flags = max77857_get_error_flags, |
286 | }; |
287 | |
288 | static struct linear_range max77857_lin_ranges[] = { |
289 | REGULATOR_LINEAR_RANGE(4485000, 0x3D, 0xCC, 73500) |
290 | }; |
291 | |
292 | static const unsigned int max77857_switch_freq[] = { |
293 | 1200000, 1500000, 1800000, 2100000 |
294 | }; |
295 | |
296 | #define RAMAP_DELAY_INIT_VAL 1333 |
297 | |
298 | static const unsigned int max77857_ramp_table[2][4] = { |
299 | { RAMAP_DELAY_INIT_VAL, 667, 333, 227 }, /* when switch freq is 1.8MHz or 2.1MHz */ |
300 | { 1166, 667, 333, 167 }, /* when switch freq is 1.2MHz or 1.5MHz */ |
301 | }; |
302 | |
303 | static struct regulator_desc max77857_regulator_desc = { |
304 | .ops = &max77857_regulator_ops, |
305 | .name = "max77857" , |
306 | .linear_ranges = max77857_lin_ranges, |
307 | .n_linear_ranges = ARRAY_SIZE(max77857_lin_ranges), |
308 | .vsel_mask = 0xFF, |
309 | .vsel_reg = MAX77857_REG_CONT2, |
310 | .ramp_delay_table = max77857_ramp_table[0], |
311 | .n_ramp_values = ARRAY_SIZE(max77857_ramp_table[0]), |
312 | .ramp_reg = MAX77857_REG_CONT3, |
313 | .ramp_mask = GENMASK(1, 0), |
314 | .ramp_delay = RAMAP_DELAY_INIT_VAL, |
315 | .owner = THIS_MODULE, |
316 | }; |
317 | |
318 | static void max77857_calc_range(struct device *dev, enum max77857_id id) |
319 | { |
320 | struct linear_range *range; |
321 | unsigned long vref_step; |
322 | u32 rtop = 0; |
323 | u32 rbot = 0; |
324 | |
325 | device_property_read_u32(dev, propname: "adi,rtop-ohms" , val: &rtop); |
326 | device_property_read_u32(dev, propname: "adi,rbot-ohms" , val: &rbot); |
327 | |
328 | if (!rbot || !rtop) |
329 | return; |
330 | |
331 | switch (id) { |
332 | case ID_MAX77831: |
333 | case ID_MAX77857: |
334 | range = max77857_lin_ranges; |
335 | vref_step = 4900UL; |
336 | break; |
337 | case ID_MAX77859: |
338 | case ID_MAX77859A: |
339 | range = max77859_lin_ranges; |
340 | vref_step = 1250UL; |
341 | break; |
342 | } |
343 | |
344 | range->step = DIV_ROUND_CLOSEST(vref_step * (rbot + rtop), rbot); |
345 | range->min = range->step * range->min_sel; |
346 | } |
347 | |
348 | static int max77857_probe(struct i2c_client *client) |
349 | { |
350 | const struct i2c_device_id *i2c_id; |
351 | struct device *dev = &client->dev; |
352 | struct regulator_config cfg = { }; |
353 | struct regulator_dev *rdev; |
354 | struct regmap *regmap; |
355 | enum max77857_id id; |
356 | u32 switch_freq = 0; |
357 | int ret; |
358 | |
359 | i2c_id = i2c_client_get_device_id(client); |
360 | if (!i2c_id) |
361 | return -EINVAL; |
362 | |
363 | id = i2c_id->driver_data; |
364 | |
365 | dev_set_drvdata(dev, data: (void *)id); |
366 | |
367 | if (id == ID_MAX77859 || id == ID_MAX77859A) { |
368 | max77857_regulator_desc.ops = &max77859_regulator_ops; |
369 | max77857_regulator_desc.linear_ranges = max77859_lin_ranges; |
370 | max77857_regulator_desc.ramp_delay_table = max77859_ramp_table; |
371 | max77857_regulator_desc.ramp_delay = max77859_ramp_table[0]; |
372 | } |
373 | |
374 | if (id == ID_MAX77859A) |
375 | max77857_regulator_desc.ops = &max77859a_regulator_ops; |
376 | |
377 | max77857_calc_range(dev, id); |
378 | |
379 | regmap = devm_regmap_init_i2c(client, &max77857_regmap_config); |
380 | if (IS_ERR(ptr: regmap)) |
381 | return dev_err_probe(dev, err: PTR_ERR(ptr: regmap), |
382 | fmt: "cannot initialize regmap\n" ); |
383 | |
384 | device_property_read_u32(dev, propname: "adi,switch-frequency-hz" , val: &switch_freq); |
385 | if (switch_freq) { |
386 | switch_freq = find_closest(switch_freq, max77857_switch_freq, |
387 | ARRAY_SIZE(max77857_switch_freq)); |
388 | |
389 | if (id == ID_MAX77831 && switch_freq == 3) |
390 | switch_freq = 2; |
391 | |
392 | switch (id) { |
393 | case ID_MAX77831: |
394 | case ID_MAX77857: |
395 | ret = regmap_update_bits(map: regmap, MAX77857_REG_CONT1, |
396 | MAX77857_CONT1_FREQ, val: switch_freq); |
397 | |
398 | if (switch_freq >= 2) |
399 | break; |
400 | |
401 | max77857_regulator_desc.ramp_delay_table = max77857_ramp_table[1]; |
402 | max77857_regulator_desc.ramp_delay = max77857_ramp_table[1][0]; |
403 | break; |
404 | case ID_MAX77859: |
405 | case ID_MAX77859A: |
406 | ret = regmap_update_bits(map: regmap, MAX77859_REG_CONT1, |
407 | MAX77857_CONT1_FREQ, val: switch_freq); |
408 | break; |
409 | } |
410 | if (ret) |
411 | return ret; |
412 | } |
413 | |
414 | cfg.dev = dev; |
415 | cfg.driver_data = (void *)id; |
416 | cfg.regmap = regmap; |
417 | cfg.init_data = of_get_regulator_init_data(dev, node: dev->of_node, |
418 | desc: &max77857_regulator_desc); |
419 | if (!cfg.init_data) |
420 | return -ENOMEM; |
421 | |
422 | rdev = devm_regulator_register(dev, regulator_desc: &max77857_regulator_desc, config: &cfg); |
423 | if (IS_ERR(ptr: rdev)) |
424 | return dev_err_probe(dev, err: PTR_ERR(ptr: rdev), |
425 | fmt: "cannot register regulator\n" ); |
426 | |
427 | return 0; |
428 | } |
429 | |
430 | const struct i2c_device_id max77857_id[] = { |
431 | { "max77831" , ID_MAX77831 }, |
432 | { "max77857" , ID_MAX77857 }, |
433 | { "max77859" , ID_MAX77859 }, |
434 | { "max77859a" , ID_MAX77859A }, |
435 | { } |
436 | }; |
437 | MODULE_DEVICE_TABLE(i2c, max77857_id); |
438 | |
439 | static const struct of_device_id max77857_of_id[] = { |
440 | { .compatible = "adi,max77831" , .data = (void *)ID_MAX77831 }, |
441 | { .compatible = "adi,max77857" , .data = (void *)ID_MAX77857 }, |
442 | { .compatible = "adi,max77859" , .data = (void *)ID_MAX77859 }, |
443 | { .compatible = "adi,max77859a" , .data = (void *)ID_MAX77859A }, |
444 | { } |
445 | }; |
446 | MODULE_DEVICE_TABLE(of, max77857_of_id); |
447 | |
448 | static struct i2c_driver max77857_driver = { |
449 | .driver = { |
450 | .name = "max77857" , |
451 | .of_match_table = max77857_of_id, |
452 | }, |
453 | .id_table = max77857_id, |
454 | .probe = max77857_probe, |
455 | }; |
456 | module_i2c_driver(max77857_driver); |
457 | |
458 | MODULE_DESCRIPTION("Analog Devices MAX77857 Buck-Boost Converter Driver" ); |
459 | MODULE_AUTHOR("Ibrahim Tilki <Ibrahim.Tilki@analog.com>" ); |
460 | MODULE_AUTHOR("Okan Sahin <Okan.Sahin@analog.com>" ); |
461 | MODULE_LICENSE("GPL" ); |
462 | |