1 // SPDX-License-Identifier: GPL-2.0+
3 * max77976_charger.c - Driver for the Maxim MAX77976 battery charger
5 * Copyright (C) 2021 Luca Ceresoli
6 * Author: Luca Ceresoli <luca.ceresoli@bootlin.com>
10 #include <linux/module.h>
11 #include <linux/power_supply.h>
12 #include <linux/regmap.h>
14 #define MAX77976_DRIVER_NAME "max77976-charger"
15 #define MAX77976_CHIP_ID 0x76
17 static const char *max77976_manufacturer
= "Maxim Integrated";
18 static const char *max77976_model
= "MAX77976";
20 /* --------------------------------------------------------------------------
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
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
,
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
65 /* CHG_CNFG_00.MODE values */
67 MAX77976_MODE_CHARGER_BUCK
= 0x5,
68 MAX77976_MODE_BOOST
= 0x9,
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
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
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
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),
104 static const struct regmap_config max77976_regmap_config
= {
107 .max_register
= 0x24,
110 /* --------------------------------------------------------------------------
115 struct i2c_client
*client
;
116 struct regmap
*regmap
;
117 struct regmap_field
*rfield
[MAX77976_N_REGMAP_FIELDS
];
120 /* --------------------------------------------------------------------------
121 * power_supply properties
124 static int max77976_get_status(struct max77976
*chg
, int *val
)
129 err
= regmap_field_read(chg
->rfield
[CHG_DTLS
], ®val
);
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
;
140 case MAX77976_CHARGING_DONE
:
141 *val
= POWER_SUPPLY_STATUS_FULL
;
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
;
150 case MAX77976_CHARGING_OFF
:
151 case MAX77976_CHARGING_THERMAL_SHUTDOWN
:
152 case MAX77976_CHARGING_WATCHDOG_EXPIRED
:
153 *val
= POWER_SUPPLY_STATUS_DISCHARGING
;
156 *val
= POWER_SUPPLY_STATUS_UNKNOWN
;
162 static int max77976_get_charge_type(struct max77976
*chg
, int *val
)
167 err
= regmap_field_read(chg
->rfield
[CHG_DTLS
], ®val
);
172 case MAX77976_CHARGING_PREQUALIFICATION
:
173 *val
= POWER_SUPPLY_CHARGE_TYPE_TRICKLE
;
175 case MAX77976_CHARGING_FAST_CONST_CURRENT
:
176 case MAX77976_CHARGING_FAST_CONST_VOLTAGE
:
177 *val
= POWER_SUPPLY_CHARGE_TYPE_FAST
;
179 case MAX77976_CHARGING_TOP_OFF
:
180 *val
= POWER_SUPPLY_CHARGE_TYPE_STANDARD
;
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
;
194 *val
= POWER_SUPPLY_CHARGE_TYPE_UNKNOWN
;
200 static int max77976_get_health(struct max77976
*chg
, int *val
)
205 err
= regmap_field_read(chg
->rfield
[BAT_DTLS
], ®val
);
210 case MAX77976_BATTERY_BATTERY_REMOVAL
:
211 *val
= POWER_SUPPLY_HEALTH_NO_BATTERY
;
213 case MAX77976_BATTERY_LOW_VOLTAGE
:
214 case MAX77976_BATTERY_REGULAR_VOLTAGE
:
215 *val
= POWER_SUPPLY_HEALTH_GOOD
;
217 case MAX77976_BATTERY_TIMER_FAULT
:
218 *val
= POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE
;
220 case MAX77976_BATTERY_OVERVOLTAGE
:
221 *val
= POWER_SUPPLY_HEALTH_OVERVOLTAGE
;
223 case MAX77976_BATTERY_PREQUALIFICATION
:
224 case MAX77976_BATTERY_BATTERY_ONLY
:
225 *val
= POWER_SUPPLY_HEALTH_UNKNOWN
;
228 *val
= POWER_SUPPLY_HEALTH_UNKNOWN
;
234 static int max77976_get_online(struct max77976
*chg
, int *val
)
239 err
= regmap_field_read(chg
->rfield
[CHGIN_OK
], ®val
);
243 *val
= (regval
? 1 : 0);
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
)
255 err
= regmap_field_read(chg
->rfield
[fidx
], ®val
);
259 *val
= clamp_val(regval
* mult
, clamp_min
, clamp_max
);
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
)
270 regval
= clamp_val(val
, clamp_min
, clamp_max
) / div
;
272 return regmap_field_write(chg
->rfield
[fidx
], regval
);
275 static int max77976_get_property(struct power_supply
*psy
,
276 enum power_supply_property psp
,
277 union power_supply_propval
*val
)
279 struct max77976
*chg
= power_supply_get_drvdata(psy
);
283 case POWER_SUPPLY_PROP_STATUS
:
284 err
= max77976_get_status(chg
, &val
->intval
);
286 case POWER_SUPPLY_PROP_CHARGE_TYPE
:
287 err
= max77976_get_charge_type(chg
, &val
->intval
);
289 case POWER_SUPPLY_PROP_HEALTH
:
290 err
= max77976_get_health(chg
, &val
->intval
);
292 case POWER_SUPPLY_PROP_ONLINE
:
293 err
= max77976_get_online(chg
, &val
->intval
);
295 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX
:
296 val
->intval
= MAX77976_CHG_CC_MAX
;
298 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT
:
299 err
= max77976_get_integer(chg
, CHG_CC
,
302 MAX77976_CHG_CC_STEP
,
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
,
312 case POWER_SUPPLY_PROP_MODEL_NAME
:
313 val
->strval
= max77976_model
;
315 case POWER_SUPPLY_PROP_MANUFACTURER
:
316 val
->strval
= max77976_manufacturer
;
325 static int max77976_set_property(struct power_supply
*psy
,
326 enum power_supply_property psp
,
327 const union power_supply_propval
*val
)
329 struct max77976
*chg
= power_supply_get_drvdata(psy
);
333 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT
:
334 err
= max77976_set_integer(chg
, CHG_CC
,
337 MAX77976_CHG_CC_STEP
,
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
,
354 static int max77976_property_is_writeable(struct power_supply
*psy
,
355 enum power_supply_property psp
)
358 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT
:
359 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT
:
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
,
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
,
388 /* --------------------------------------------------------------------------
392 static int max77976_detect(struct max77976
*chg
)
394 struct device
*dev
= &chg
->client
->dev
;
395 unsigned int id
, ver
, rev
;
398 err
= regmap_read(chg
->regmap
, MAX77976_REG_CHIP_ID
, &id
);
400 return dev_err_probe(dev
, err
, "cannot read chip ID\n");
402 if (id
!= MAX77976_CHIP_ID
)
403 return dev_err_probe(dev
, -ENXIO
, "unknown model ID 0x%02x\n", id
);
405 err
= regmap_field_read(chg
->rfield
[VERSION
], &ver
);
407 err
= regmap_field_read(chg
->rfield
[REVISION
], &rev
);
409 return dev_err_probe(dev
, -ENXIO
, "cannot read version/revision\n");
411 dev_info(dev
, "detected model MAX779%02x ver %u rev %u", id
, ver
, rev
);
416 static int max77976_configure(struct max77976
*chg
)
418 struct device
*dev
= &chg
->client
->dev
;
421 /* Magic value to unlock writing to some registers */
422 err
= regmap_field_write(chg
->rfield
[CHGPROT
], 0x3);
427 * Mode 5 = Charger ON, OTG OFF, buck ON, boost OFF.
428 * Other modes are not implemented by this driver.
430 err
= regmap_field_write(chg
->rfield
[MODE
], MAX77976_MODE_CHARGER_BUCK
);
437 return dev_err_probe(dev
, err
, "error while configuring");
440 static int max77976_probe(struct i2c_client
*client
)
442 struct device
*dev
= &client
->dev
;
443 struct power_supply_config psy_cfg
= {};
444 struct power_supply
*psy
;
445 struct max77976
*chg
;
449 chg
= devm_kzalloc(dev
, sizeof(*chg
), GFP_KERNEL
);
453 i2c_set_clientdata(client
, chg
);
454 psy_cfg
.drv_data
= chg
;
455 psy_cfg
.no_wakeup_source
= true;
456 chg
->client
= client
;
458 chg
->regmap
= devm_regmap_init_i2c(client
, &max77976_regmap_config
);
459 if (IS_ERR(chg
->regmap
))
460 return dev_err_probe(dev
, PTR_ERR(chg
->regmap
),
461 "cannot allocate regmap\n");
463 for (i
= 0; i
< MAX77976_N_REGMAP_FIELDS
; i
++) {
464 chg
->rfield
[i
] = devm_regmap_field_alloc(dev
, chg
->regmap
,
465 max77976_reg_field
[i
]);
466 if (IS_ERR(chg
->rfield
[i
]))
467 return dev_err_probe(dev
, PTR_ERR(chg
->rfield
[i
]),
468 "cannot allocate regmap field\n");
471 err
= max77976_detect(chg
);
475 err
= max77976_configure(chg
);
479 psy
= devm_power_supply_register(dev
, &max77976_psy_desc
, &psy_cfg
);
481 return dev_err_probe(dev
, PTR_ERR(psy
), "cannot register\n");
486 static const struct i2c_device_id max77976_i2c_id
[] = {
487 { MAX77976_DRIVER_NAME
},
490 MODULE_DEVICE_TABLE(i2c
, max77976_i2c_id
);
492 static const struct of_device_id max77976_of_id
[] = {
493 { .compatible
= "maxim,max77976" },
496 MODULE_DEVICE_TABLE(of
, max77976_of_id
);
498 static struct i2c_driver max77976_driver
= {
500 .name
= MAX77976_DRIVER_NAME
,
501 .of_match_table
= max77976_of_id
,
503 .probe
= max77976_probe
,
504 .id_table
= max77976_i2c_id
,
506 module_i2c_driver(max77976_driver
);
508 MODULE_AUTHOR("Luca Ceresoli <luca.ceresoli@bootlin.com>");
509 MODULE_DESCRIPTION("Maxim MAX77976 charger driver");
510 MODULE_LICENSE("GPL v2");