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@lucaceresoli.net>
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_new	= max77976_probe,
503 	.id_table	= max77976_i2c_id,
504 };
505 module_i2c_driver(max77976_driver);
506 
507 MODULE_AUTHOR("Luca Ceresoli <luca@lucaceresoli.net>");
508 MODULE_DESCRIPTION("Maxim MAX77976 charger driver");
509 MODULE_LICENSE("GPL v2");
510