Merge tag 'trace-tools-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[linux-2.6-microblaze.git] / drivers / power / supply / max77976_charger.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * max77976_charger.c - Driver for the Maxim MAX77976 battery charger
4  *
5  * Copyright (C) 2021 Luca Ceresoli
6  * Author: Luca Ceresoli <luca.ceresoli@bootlin.com>
7  */
8
9 #include <linux/i2c.h>
10 #include <linux/module.h>
11 #include <linux/power_supply.h>
12 #include <linux/regmap.h>
13
14 #define MAX77976_DRIVER_NAME    "max77976-charger"
15 #define MAX77976_CHIP_ID        0x76
16
17 static const char *max77976_manufacturer        = "Maxim Integrated";
18 static const char *max77976_model               = "MAX77976";
19
20 /* --------------------------------------------------------------------------
21  * Register map
22  */
23
24 #define MAX77976_REG_CHIP_ID            0x00
25 #define MAX77976_REG_CHIP_REVISION      0x01
26 #define MAX77976_REG_CHG_INT_OK         0x12
27 #define MAX77976_REG_CHG_DETAILS_01     0x14
28 #define MAX77976_REG_CHG_CNFG_00        0x16
29 #define MAX77976_REG_CHG_CNFG_02        0x18
30 #define MAX77976_REG_CHG_CNFG_06        0x1c
31 #define MAX77976_REG_CHG_CNFG_09        0x1f
32
33 /* CHG_DETAILS_01.CHG_DTLS values */
34 enum max77976_charging_state {
35         MAX77976_CHARGING_PREQUALIFICATION = 0x0,
36         MAX77976_CHARGING_FAST_CONST_CURRENT,
37         MAX77976_CHARGING_FAST_CONST_VOLTAGE,
38         MAX77976_CHARGING_TOP_OFF,
39         MAX77976_CHARGING_DONE,
40         MAX77976_CHARGING_RESERVED_05,
41         MAX77976_CHARGING_TIMER_FAULT,
42         MAX77976_CHARGING_SUSPENDED_QBATT_OFF,
43         MAX77976_CHARGING_OFF,
44         MAX77976_CHARGING_RESERVED_09,
45         MAX77976_CHARGING_THERMAL_SHUTDOWN,
46         MAX77976_CHARGING_WATCHDOG_EXPIRED,
47         MAX77976_CHARGING_SUSPENDED_JEITA,
48         MAX77976_CHARGING_SUSPENDED_THM_REMOVAL,
49         MAX77976_CHARGING_SUSPENDED_PIN,
50         MAX77976_CHARGING_RESERVED_0F,
51 };
52
53 /* CHG_DETAILS_01.BAT_DTLS values */
54 enum max77976_battery_state {
55         MAX77976_BATTERY_BATTERY_REMOVAL = 0x0,
56         MAX77976_BATTERY_PREQUALIFICATION,
57         MAX77976_BATTERY_TIMER_FAULT,
58         MAX77976_BATTERY_REGULAR_VOLTAGE,
59         MAX77976_BATTERY_LOW_VOLTAGE,
60         MAX77976_BATTERY_OVERVOLTAGE,
61         MAX77976_BATTERY_RESERVED,
62         MAX77976_BATTERY_BATTERY_ONLY, // No valid adapter is present
63 };
64
65 /* CHG_CNFG_00.MODE values */
66 enum max77976_mode {
67         MAX77976_MODE_CHARGER_BUCK              = 0x5,
68         MAX77976_MODE_BOOST                     = 0x9,
69 };
70
71 /* CHG_CNFG_02.CHG_CC: charge current limit, 100..5500 mA, 50 mA steps */
72 #define MAX77976_CHG_CC_STEP                      50000U
73 #define MAX77976_CHG_CC_MIN                      100000U
74 #define MAX77976_CHG_CC_MAX                     5500000U
75
76 /* CHG_CNFG_09.CHGIN_ILIM: input current limit, 100..3200 mA, 100 mA steps */
77 #define MAX77976_CHGIN_ILIM_STEP                 100000U
78 #define MAX77976_CHGIN_ILIM_MIN                  100000U
79 #define MAX77976_CHGIN_ILIM_MAX                 3200000U
80
81 enum max77976_field_idx {
82         VERSION, REVISION,                      /* CHIP_REVISION */
83         CHGIN_OK,                               /* CHG_INT_OK */
84         BAT_DTLS, CHG_DTLS,                     /* CHG_DETAILS_01 */
85         MODE,                                   /* CHG_CNFG_00 */
86         CHG_CC,                                 /* CHG_CNFG_02 */
87         CHGPROT,                                /* CHG_CNFG_06 */
88         CHGIN_ILIM,                             /* CHG_CNFG_09 */
89         MAX77976_N_REGMAP_FIELDS
90 };
91
92 static const struct reg_field max77976_reg_field[MAX77976_N_REGMAP_FIELDS] = {
93         [VERSION]        = REG_FIELD(MAX77976_REG_CHIP_REVISION,   4, 7),
94         [REVISION]       = REG_FIELD(MAX77976_REG_CHIP_REVISION,   0, 3),
95         [CHGIN_OK]       = REG_FIELD(MAX77976_REG_CHG_INT_OK,      6, 6),
96         [CHG_DTLS]       = REG_FIELD(MAX77976_REG_CHG_DETAILS_01,  0, 3),
97         [BAT_DTLS]       = REG_FIELD(MAX77976_REG_CHG_DETAILS_01,  4, 6),
98         [MODE]           = REG_FIELD(MAX77976_REG_CHG_CNFG_00,     0, 3),
99         [CHG_CC]         = REG_FIELD(MAX77976_REG_CHG_CNFG_02,     0, 6),
100         [CHGPROT]        = REG_FIELD(MAX77976_REG_CHG_CNFG_06,     2, 3),
101         [CHGIN_ILIM]     = REG_FIELD(MAX77976_REG_CHG_CNFG_09,     0, 5),
102 };
103
104 static const struct regmap_config max77976_regmap_config = {
105         .reg_bits = 8,
106         .val_bits = 8,
107         .max_register = 0x24,
108 };
109
110 /* --------------------------------------------------------------------------
111  * Data structures
112  */
113
114 struct max77976 {
115         struct i2c_client       *client;
116         struct regmap           *regmap;
117         struct regmap_field     *rfield[MAX77976_N_REGMAP_FIELDS];
118 };
119
120 /* --------------------------------------------------------------------------
121  * power_supply properties
122  */
123
124 static int max77976_get_status(struct max77976 *chg, int *val)
125 {
126         unsigned int regval;
127         int err;
128
129         err = regmap_field_read(chg->rfield[CHG_DTLS], &regval);
130         if (err < 0)
131                 return err;
132
133         switch (regval) {
134         case MAX77976_CHARGING_PREQUALIFICATION:
135         case MAX77976_CHARGING_FAST_CONST_CURRENT:
136         case MAX77976_CHARGING_FAST_CONST_VOLTAGE:
137         case MAX77976_CHARGING_TOP_OFF:
138                 *val = POWER_SUPPLY_STATUS_CHARGING;
139                 break;
140         case MAX77976_CHARGING_DONE:
141                 *val = POWER_SUPPLY_STATUS_FULL;
142                 break;
143         case MAX77976_CHARGING_TIMER_FAULT:
144         case MAX77976_CHARGING_SUSPENDED_QBATT_OFF:
145         case MAX77976_CHARGING_SUSPENDED_JEITA:
146         case MAX77976_CHARGING_SUSPENDED_THM_REMOVAL:
147         case MAX77976_CHARGING_SUSPENDED_PIN:
148                 *val = POWER_SUPPLY_STATUS_NOT_CHARGING;
149                 break;
150         case MAX77976_CHARGING_OFF:
151         case MAX77976_CHARGING_THERMAL_SHUTDOWN:
152         case MAX77976_CHARGING_WATCHDOG_EXPIRED:
153                 *val = POWER_SUPPLY_STATUS_DISCHARGING;
154                 break;
155         default:
156                 *val = POWER_SUPPLY_STATUS_UNKNOWN;
157         }
158
159         return 0;
160 }
161
162 static int max77976_get_charge_type(struct max77976 *chg, int *val)
163 {
164         unsigned int regval;
165         int err;
166
167         err = regmap_field_read(chg->rfield[CHG_DTLS], &regval);
168         if (err < 0)
169                 return err;
170
171         switch (regval) {
172         case MAX77976_CHARGING_PREQUALIFICATION:
173                 *val = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
174                 break;
175         case MAX77976_CHARGING_FAST_CONST_CURRENT:
176         case MAX77976_CHARGING_FAST_CONST_VOLTAGE:
177                 *val = POWER_SUPPLY_CHARGE_TYPE_FAST;
178                 break;
179         case MAX77976_CHARGING_TOP_OFF:
180                 *val = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
181                 break;
182         case MAX77976_CHARGING_DONE:
183         case MAX77976_CHARGING_TIMER_FAULT:
184         case MAX77976_CHARGING_SUSPENDED_QBATT_OFF:
185         case MAX77976_CHARGING_OFF:
186         case MAX77976_CHARGING_THERMAL_SHUTDOWN:
187         case MAX77976_CHARGING_WATCHDOG_EXPIRED:
188         case MAX77976_CHARGING_SUSPENDED_JEITA:
189         case MAX77976_CHARGING_SUSPENDED_THM_REMOVAL:
190         case MAX77976_CHARGING_SUSPENDED_PIN:
191                 *val = POWER_SUPPLY_CHARGE_TYPE_NONE;
192                 break;
193         default:
194                 *val = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
195         }
196
197         return 0;
198 }
199
200 static int max77976_get_health(struct max77976 *chg, int *val)
201 {
202         unsigned int regval;
203         int err;
204
205         err = regmap_field_read(chg->rfield[BAT_DTLS], &regval);
206         if (err < 0)
207                 return err;
208
209         switch (regval) {
210         case MAX77976_BATTERY_BATTERY_REMOVAL:
211                 *val = POWER_SUPPLY_HEALTH_NO_BATTERY;
212                 break;
213         case MAX77976_BATTERY_LOW_VOLTAGE:
214         case MAX77976_BATTERY_REGULAR_VOLTAGE:
215                 *val = POWER_SUPPLY_HEALTH_GOOD;
216                 break;
217         case MAX77976_BATTERY_TIMER_FAULT:
218                 *val = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
219                 break;
220         case MAX77976_BATTERY_OVERVOLTAGE:
221                 *val = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
222                 break;
223         case MAX77976_BATTERY_PREQUALIFICATION:
224         case MAX77976_BATTERY_BATTERY_ONLY:
225                 *val = POWER_SUPPLY_HEALTH_UNKNOWN;
226                 break;
227         default:
228                 *val = POWER_SUPPLY_HEALTH_UNKNOWN;
229         }
230
231         return 0;
232 }
233
234 static int max77976_get_online(struct max77976 *chg, int *val)
235 {
236         unsigned int regval;
237         int err;
238
239         err = regmap_field_read(chg->rfield[CHGIN_OK], &regval);
240         if (err < 0)
241                 return err;
242
243         *val = (regval ? 1 : 0);
244
245         return 0;
246 }
247
248 static int max77976_get_integer(struct max77976 *chg, enum max77976_field_idx fidx,
249                                 unsigned int clamp_min, unsigned int clamp_max,
250                                 unsigned int mult, int *val)
251 {
252         unsigned int regval;
253         int err;
254
255         err = regmap_field_read(chg->rfield[fidx], &regval);
256         if (err < 0)
257                 return err;
258
259         *val = clamp_val(regval * mult, clamp_min, clamp_max);
260
261         return 0;
262 }
263
264 static int max77976_set_integer(struct max77976 *chg, enum max77976_field_idx fidx,
265                                 unsigned int clamp_min, unsigned int clamp_max,
266                                 unsigned int div, int val)
267 {
268         unsigned int regval;
269
270         regval = clamp_val(val, clamp_min, clamp_max) / div;
271
272         return regmap_field_write(chg->rfield[fidx], regval);
273 }
274
275 static int max77976_get_property(struct power_supply *psy,
276                                  enum power_supply_property psp,
277                                  union power_supply_propval *val)
278 {
279         struct max77976 *chg = power_supply_get_drvdata(psy);
280         int err = 0;
281
282         switch (psp) {
283         case POWER_SUPPLY_PROP_STATUS:
284                 err = max77976_get_status(chg, &val->intval);
285                 break;
286         case POWER_SUPPLY_PROP_CHARGE_TYPE:
287                 err = max77976_get_charge_type(chg, &val->intval);
288                 break;
289         case POWER_SUPPLY_PROP_HEALTH:
290                 err = max77976_get_health(chg, &val->intval);
291                 break;
292         case POWER_SUPPLY_PROP_ONLINE:
293                 err = max77976_get_online(chg, &val->intval);
294                 break;
295         case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
296                 val->intval = MAX77976_CHG_CC_MAX;
297                 break;
298         case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
299                 err = max77976_get_integer(chg, CHG_CC,
300                                            MAX77976_CHG_CC_MIN,
301                                            MAX77976_CHG_CC_MAX,
302                                            MAX77976_CHG_CC_STEP,
303                                            &val->intval);
304                 break;
305         case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
306                 err = max77976_get_integer(chg, CHGIN_ILIM,
307                                            MAX77976_CHGIN_ILIM_MIN,
308                                            MAX77976_CHGIN_ILIM_MAX,
309                                            MAX77976_CHGIN_ILIM_STEP,
310                                            &val->intval);
311                 break;
312         case POWER_SUPPLY_PROP_MODEL_NAME:
313                 val->strval = max77976_model;
314                 break;
315         case POWER_SUPPLY_PROP_MANUFACTURER:
316                 val->strval = max77976_manufacturer;
317                 break;
318         default:
319                 err = -EINVAL;
320         }
321
322         return err;
323 }
324
325 static int max77976_set_property(struct power_supply *psy,
326                                  enum power_supply_property psp,
327                                  const union power_supply_propval *val)
328 {
329         struct max77976 *chg = power_supply_get_drvdata(psy);
330         int err = 0;
331
332         switch (psp) {
333         case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
334                 err = max77976_set_integer(chg, CHG_CC,
335                                            MAX77976_CHG_CC_MIN,
336                                            MAX77976_CHG_CC_MAX,
337                                            MAX77976_CHG_CC_STEP,
338                                            val->intval);
339                 break;
340         case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
341                 err = max77976_set_integer(chg, CHGIN_ILIM,
342                                            MAX77976_CHGIN_ILIM_MIN,
343                                            MAX77976_CHGIN_ILIM_MAX,
344                                            MAX77976_CHGIN_ILIM_STEP,
345                                            val->intval);
346                 break;
347         default:
348                 err = -EINVAL;
349         }
350
351         return err;
352 };
353
354 static int max77976_property_is_writeable(struct power_supply *psy,
355                                           enum power_supply_property psp)
356 {
357         switch (psp) {
358         case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
359         case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
360                 return true;
361         default:
362                 return false;
363         }
364 }
365
366 static enum power_supply_property max77976_psy_props[] = {
367         POWER_SUPPLY_PROP_STATUS,
368         POWER_SUPPLY_PROP_CHARGE_TYPE,
369         POWER_SUPPLY_PROP_HEALTH,
370         POWER_SUPPLY_PROP_ONLINE,
371         POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
372         POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
373         POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
374         POWER_SUPPLY_PROP_MODEL_NAME,
375         POWER_SUPPLY_PROP_MANUFACTURER,
376 };
377
378 static const struct power_supply_desc max77976_psy_desc = {
379         .name                   = MAX77976_DRIVER_NAME,
380         .type                   = POWER_SUPPLY_TYPE_USB,
381         .properties             = max77976_psy_props,
382         .num_properties         = ARRAY_SIZE(max77976_psy_props),
383         .get_property           = max77976_get_property,
384         .set_property           = max77976_set_property,
385         .property_is_writeable  = max77976_property_is_writeable,
386 };
387
388 /* --------------------------------------------------------------------------
389  * Entry point
390  */
391
392 static int max77976_detect(struct max77976 *chg)
393 {
394         struct device *dev = &chg->client->dev;
395         unsigned int id, ver, rev;
396         int err;
397
398         err = regmap_read(chg->regmap, MAX77976_REG_CHIP_ID, &id);
399         if (err)
400                 return dev_err_probe(dev, err, "cannot read chip ID\n");
401
402         if (id != MAX77976_CHIP_ID)
403                 return dev_err_probe(dev, -ENXIO, "unknown model ID 0x%02x\n", id);
404
405         err = regmap_field_read(chg->rfield[VERSION], &ver);
406         if (!err)
407                 err = regmap_field_read(chg->rfield[REVISION], &rev);
408         if (err)
409                 return dev_err_probe(dev, -ENXIO, "cannot read version/revision\n");
410
411         dev_info(dev, "detected model MAX779%02x ver %u rev %u", id, ver, rev);
412
413         return 0;
414 }
415
416 static int max77976_configure(struct max77976 *chg)
417 {
418         struct device *dev = &chg->client->dev;
419         int err;
420
421         /* Magic value to unlock writing to some registers */
422         err = regmap_field_write(chg->rfield[CHGPROT], 0x3);
423         if (err)
424                 goto err;
425
426         /*
427          * Mode 5 = Charger ON, OTG OFF, buck ON, boost OFF.
428          * Other modes are not implemented by this driver.
429          */
430         err = regmap_field_write(chg->rfield[MODE], MAX77976_MODE_CHARGER_BUCK);
431         if (err)
432                 goto err;
433
434         return 0;
435
436 err:
437         return dev_err_probe(dev, err, "error while configuring");
438 }
439
440 static int max77976_probe(struct i2c_client *client)
441 {
442         struct device *dev = &client->dev;
443         struct power_supply_config psy_cfg = {};
444         struct power_supply *psy;
445         struct max77976 *chg;
446         int err;
447         int i;
448
449         chg = devm_kzalloc(dev, sizeof(*chg), GFP_KERNEL);
450         if (!chg)
451                 return -ENOMEM;
452
453         i2c_set_clientdata(client, chg);
454         psy_cfg.drv_data = chg;
455         chg->client = client;
456
457         chg->regmap = devm_regmap_init_i2c(client, &max77976_regmap_config);
458         if (IS_ERR(chg->regmap))
459                 return dev_err_probe(dev, PTR_ERR(chg->regmap),
460                                      "cannot allocate regmap\n");
461
462         for (i = 0; i < MAX77976_N_REGMAP_FIELDS; i++) {
463                 chg->rfield[i] = devm_regmap_field_alloc(dev, chg->regmap,
464                                                          max77976_reg_field[i]);
465                 if (IS_ERR(chg->rfield[i]))
466                         return dev_err_probe(dev, PTR_ERR(chg->rfield[i]),
467                                              "cannot allocate regmap field\n");
468         }
469
470         err = max77976_detect(chg);
471         if (err)
472                 return err;
473
474         err = max77976_configure(chg);
475         if (err)
476                 return err;
477
478         psy = devm_power_supply_register_no_ws(dev, &max77976_psy_desc, &psy_cfg);
479         if (IS_ERR(psy))
480                 return dev_err_probe(dev, PTR_ERR(psy), "cannot register\n");
481
482         return 0;
483 }
484
485 static const struct i2c_device_id max77976_i2c_id[] = {
486         { MAX77976_DRIVER_NAME, 0 },
487         { },
488 };
489 MODULE_DEVICE_TABLE(i2c, max77976_i2c_id);
490
491 static const struct of_device_id max77976_of_id[] = {
492         { .compatible = "maxim,max77976" },
493         { },
494 };
495 MODULE_DEVICE_TABLE(of, max77976_of_id);
496
497 static struct i2c_driver max77976_driver = {
498         .driver = {
499                 .name           = MAX77976_DRIVER_NAME,
500                 .of_match_table = max77976_of_id,
501         },
502         .probe          = max77976_probe,
503         .id_table       = max77976_i2c_id,
504 };
505 module_i2c_driver(max77976_driver);
506
507 MODULE_AUTHOR("Luca Ceresoli <luca.ceresoli@bootlin.com>");
508 MODULE_DESCRIPTION("Maxim MAX77976 charger driver");
509 MODULE_LICENSE("GPL v2");