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
17static const char *max77976_manufacturer	= "Maxim Integrated";
18static 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 */
34enum 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 */
54enum 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 */
66enum 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
81enum 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
92static 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
104static 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
114struct 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
124static 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
162static 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
200static 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
234static 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
248static 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
264static 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
275static 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
325static 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
354static 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
366static 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
378static 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
392static 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
416static 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
436err:
437	return dev_err_probe(dev, err, "error while configuring");
438}
439
440static 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
485static const struct i2c_device_id max77976_i2c_id[] = {
486	{ MAX77976_DRIVER_NAME, 0 },
487	{ },
488};
489MODULE_DEVICE_TABLE(i2c, max77976_i2c_id);
490
491static const struct of_device_id max77976_of_id[] = {
492	{ .compatible = "maxim,max77976" },
493	{ },
494};
495MODULE_DEVICE_TABLE(of, max77976_of_id);
496
497static 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};
505module_i2c_driver(max77976_driver);
506
507MODULE_AUTHOR("Luca Ceresoli <luca.ceresoli@bootlin.com>");
508MODULE_DESCRIPTION("Maxim MAX77976 charger driver");
509MODULE_LICENSE("GPL v2");
510