0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/i2c.h>
0010 #include <linux/module.h>
0011 #include <linux/power_supply.h>
0012 #include <linux/regmap.h>
0013
0014 #define MAX77976_DRIVER_NAME "max77976-charger"
0015 #define MAX77976_CHIP_ID 0x76
0016
0017 static const char *max77976_manufacturer = "Maxim Integrated";
0018 static const char *max77976_model = "MAX77976";
0019
0020
0021
0022
0023
0024 #define MAX77976_REG_CHIP_ID 0x00
0025 #define MAX77976_REG_CHIP_REVISION 0x01
0026 #define MAX77976_REG_CHG_INT_OK 0x12
0027 #define MAX77976_REG_CHG_DETAILS_01 0x14
0028 #define MAX77976_REG_CHG_CNFG_00 0x16
0029 #define MAX77976_REG_CHG_CNFG_02 0x18
0030 #define MAX77976_REG_CHG_CNFG_06 0x1c
0031 #define MAX77976_REG_CHG_CNFG_09 0x1f
0032
0033
0034 enum max77976_charging_state {
0035 MAX77976_CHARGING_PREQUALIFICATION = 0x0,
0036 MAX77976_CHARGING_FAST_CONST_CURRENT,
0037 MAX77976_CHARGING_FAST_CONST_VOLTAGE,
0038 MAX77976_CHARGING_TOP_OFF,
0039 MAX77976_CHARGING_DONE,
0040 MAX77976_CHARGING_RESERVED_05,
0041 MAX77976_CHARGING_TIMER_FAULT,
0042 MAX77976_CHARGING_SUSPENDED_QBATT_OFF,
0043 MAX77976_CHARGING_OFF,
0044 MAX77976_CHARGING_RESERVED_09,
0045 MAX77976_CHARGING_THERMAL_SHUTDOWN,
0046 MAX77976_CHARGING_WATCHDOG_EXPIRED,
0047 MAX77976_CHARGING_SUSPENDED_JEITA,
0048 MAX77976_CHARGING_SUSPENDED_THM_REMOVAL,
0049 MAX77976_CHARGING_SUSPENDED_PIN,
0050 MAX77976_CHARGING_RESERVED_0F,
0051 };
0052
0053
0054 enum max77976_battery_state {
0055 MAX77976_BATTERY_BATTERY_REMOVAL = 0x0,
0056 MAX77976_BATTERY_PREQUALIFICATION,
0057 MAX77976_BATTERY_TIMER_FAULT,
0058 MAX77976_BATTERY_REGULAR_VOLTAGE,
0059 MAX77976_BATTERY_LOW_VOLTAGE,
0060 MAX77976_BATTERY_OVERVOLTAGE,
0061 MAX77976_BATTERY_RESERVED,
0062 MAX77976_BATTERY_BATTERY_ONLY,
0063 };
0064
0065
0066 enum max77976_mode {
0067 MAX77976_MODE_CHARGER_BUCK = 0x5,
0068 MAX77976_MODE_BOOST = 0x9,
0069 };
0070
0071
0072 #define MAX77976_CHG_CC_STEP 50000U
0073 #define MAX77976_CHG_CC_MIN 100000U
0074 #define MAX77976_CHG_CC_MAX 5500000U
0075
0076
0077 #define MAX77976_CHGIN_ILIM_STEP 100000U
0078 #define MAX77976_CHGIN_ILIM_MIN 100000U
0079 #define MAX77976_CHGIN_ILIM_MAX 3200000U
0080
0081 enum max77976_field_idx {
0082 VERSION, REVISION,
0083 CHGIN_OK,
0084 BAT_DTLS, CHG_DTLS,
0085 MODE,
0086 CHG_CC,
0087 CHGPROT,
0088 CHGIN_ILIM,
0089 MAX77976_N_REGMAP_FIELDS
0090 };
0091
0092 static const struct reg_field max77976_reg_field[MAX77976_N_REGMAP_FIELDS] = {
0093 [VERSION] = REG_FIELD(MAX77976_REG_CHIP_REVISION, 4, 7),
0094 [REVISION] = REG_FIELD(MAX77976_REG_CHIP_REVISION, 0, 3),
0095 [CHGIN_OK] = REG_FIELD(MAX77976_REG_CHG_INT_OK, 6, 6),
0096 [CHG_DTLS] = REG_FIELD(MAX77976_REG_CHG_DETAILS_01, 0, 3),
0097 [BAT_DTLS] = REG_FIELD(MAX77976_REG_CHG_DETAILS_01, 4, 6),
0098 [MODE] = REG_FIELD(MAX77976_REG_CHG_CNFG_00, 0, 3),
0099 [CHG_CC] = REG_FIELD(MAX77976_REG_CHG_CNFG_02, 0, 6),
0100 [CHGPROT] = REG_FIELD(MAX77976_REG_CHG_CNFG_06, 2, 3),
0101 [CHGIN_ILIM] = REG_FIELD(MAX77976_REG_CHG_CNFG_09, 0, 5),
0102 };
0103
0104 static const struct regmap_config max77976_regmap_config = {
0105 .reg_bits = 8,
0106 .val_bits = 8,
0107 .max_register = 0x24,
0108 };
0109
0110
0111
0112
0113
0114 struct max77976 {
0115 struct i2c_client *client;
0116 struct regmap *regmap;
0117 struct regmap_field *rfield[MAX77976_N_REGMAP_FIELDS];
0118 };
0119
0120
0121
0122
0123
0124 static int max77976_get_status(struct max77976 *chg, int *val)
0125 {
0126 unsigned int regval;
0127 int err;
0128
0129 err = regmap_field_read(chg->rfield[CHG_DTLS], ®val);
0130 if (err < 0)
0131 return err;
0132
0133 switch (regval) {
0134 case MAX77976_CHARGING_PREQUALIFICATION:
0135 case MAX77976_CHARGING_FAST_CONST_CURRENT:
0136 case MAX77976_CHARGING_FAST_CONST_VOLTAGE:
0137 case MAX77976_CHARGING_TOP_OFF:
0138 *val = POWER_SUPPLY_STATUS_CHARGING;
0139 break;
0140 case MAX77976_CHARGING_DONE:
0141 *val = POWER_SUPPLY_STATUS_FULL;
0142 break;
0143 case MAX77976_CHARGING_TIMER_FAULT:
0144 case MAX77976_CHARGING_SUSPENDED_QBATT_OFF:
0145 case MAX77976_CHARGING_SUSPENDED_JEITA:
0146 case MAX77976_CHARGING_SUSPENDED_THM_REMOVAL:
0147 case MAX77976_CHARGING_SUSPENDED_PIN:
0148 *val = POWER_SUPPLY_STATUS_NOT_CHARGING;
0149 break;
0150 case MAX77976_CHARGING_OFF:
0151 case MAX77976_CHARGING_THERMAL_SHUTDOWN:
0152 case MAX77976_CHARGING_WATCHDOG_EXPIRED:
0153 *val = POWER_SUPPLY_STATUS_DISCHARGING;
0154 break;
0155 default:
0156 *val = POWER_SUPPLY_STATUS_UNKNOWN;
0157 }
0158
0159 return 0;
0160 }
0161
0162 static int max77976_get_charge_type(struct max77976 *chg, int *val)
0163 {
0164 unsigned int regval;
0165 int err;
0166
0167 err = regmap_field_read(chg->rfield[CHG_DTLS], ®val);
0168 if (err < 0)
0169 return err;
0170
0171 switch (regval) {
0172 case MAX77976_CHARGING_PREQUALIFICATION:
0173 *val = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
0174 break;
0175 case MAX77976_CHARGING_FAST_CONST_CURRENT:
0176 case MAX77976_CHARGING_FAST_CONST_VOLTAGE:
0177 *val = POWER_SUPPLY_CHARGE_TYPE_FAST;
0178 break;
0179 case MAX77976_CHARGING_TOP_OFF:
0180 *val = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
0181 break;
0182 case MAX77976_CHARGING_DONE:
0183 case MAX77976_CHARGING_TIMER_FAULT:
0184 case MAX77976_CHARGING_SUSPENDED_QBATT_OFF:
0185 case MAX77976_CHARGING_OFF:
0186 case MAX77976_CHARGING_THERMAL_SHUTDOWN:
0187 case MAX77976_CHARGING_WATCHDOG_EXPIRED:
0188 case MAX77976_CHARGING_SUSPENDED_JEITA:
0189 case MAX77976_CHARGING_SUSPENDED_THM_REMOVAL:
0190 case MAX77976_CHARGING_SUSPENDED_PIN:
0191 *val = POWER_SUPPLY_CHARGE_TYPE_NONE;
0192 break;
0193 default:
0194 *val = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
0195 }
0196
0197 return 0;
0198 }
0199
0200 static int max77976_get_health(struct max77976 *chg, int *val)
0201 {
0202 unsigned int regval;
0203 int err;
0204
0205 err = regmap_field_read(chg->rfield[BAT_DTLS], ®val);
0206 if (err < 0)
0207 return err;
0208
0209 switch (regval) {
0210 case MAX77976_BATTERY_BATTERY_REMOVAL:
0211 *val = POWER_SUPPLY_HEALTH_NO_BATTERY;
0212 break;
0213 case MAX77976_BATTERY_LOW_VOLTAGE:
0214 case MAX77976_BATTERY_REGULAR_VOLTAGE:
0215 *val = POWER_SUPPLY_HEALTH_GOOD;
0216 break;
0217 case MAX77976_BATTERY_TIMER_FAULT:
0218 *val = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
0219 break;
0220 case MAX77976_BATTERY_OVERVOLTAGE:
0221 *val = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
0222 break;
0223 case MAX77976_BATTERY_PREQUALIFICATION:
0224 case MAX77976_BATTERY_BATTERY_ONLY:
0225 *val = POWER_SUPPLY_HEALTH_UNKNOWN;
0226 break;
0227 default:
0228 *val = POWER_SUPPLY_HEALTH_UNKNOWN;
0229 }
0230
0231 return 0;
0232 }
0233
0234 static int max77976_get_online(struct max77976 *chg, int *val)
0235 {
0236 unsigned int regval;
0237 int err;
0238
0239 err = regmap_field_read(chg->rfield[CHGIN_OK], ®val);
0240 if (err < 0)
0241 return err;
0242
0243 *val = (regval ? 1 : 0);
0244
0245 return 0;
0246 }
0247
0248 static int max77976_get_integer(struct max77976 *chg, enum max77976_field_idx fidx,
0249 unsigned int clamp_min, unsigned int clamp_max,
0250 unsigned int mult, int *val)
0251 {
0252 unsigned int regval;
0253 int err;
0254
0255 err = regmap_field_read(chg->rfield[fidx], ®val);
0256 if (err < 0)
0257 return err;
0258
0259 *val = clamp_val(regval * mult, clamp_min, clamp_max);
0260
0261 return 0;
0262 }
0263
0264 static int max77976_set_integer(struct max77976 *chg, enum max77976_field_idx fidx,
0265 unsigned int clamp_min, unsigned int clamp_max,
0266 unsigned int div, int val)
0267 {
0268 unsigned int regval;
0269
0270 regval = clamp_val(val, clamp_min, clamp_max) / div;
0271
0272 return regmap_field_write(chg->rfield[fidx], regval);
0273 }
0274
0275 static int max77976_get_property(struct power_supply *psy,
0276 enum power_supply_property psp,
0277 union power_supply_propval *val)
0278 {
0279 struct max77976 *chg = power_supply_get_drvdata(psy);
0280 int err = 0;
0281
0282 switch (psp) {
0283 case POWER_SUPPLY_PROP_STATUS:
0284 err = max77976_get_status(chg, &val->intval);
0285 break;
0286 case POWER_SUPPLY_PROP_CHARGE_TYPE:
0287 err = max77976_get_charge_type(chg, &val->intval);
0288 break;
0289 case POWER_SUPPLY_PROP_HEALTH:
0290 err = max77976_get_health(chg, &val->intval);
0291 break;
0292 case POWER_SUPPLY_PROP_ONLINE:
0293 err = max77976_get_online(chg, &val->intval);
0294 break;
0295 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
0296 val->intval = MAX77976_CHG_CC_MAX;
0297 break;
0298 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
0299 err = max77976_get_integer(chg, CHG_CC,
0300 MAX77976_CHG_CC_MIN,
0301 MAX77976_CHG_CC_MAX,
0302 MAX77976_CHG_CC_STEP,
0303 &val->intval);
0304 break;
0305 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
0306 err = max77976_get_integer(chg, CHGIN_ILIM,
0307 MAX77976_CHGIN_ILIM_MIN,
0308 MAX77976_CHGIN_ILIM_MAX,
0309 MAX77976_CHGIN_ILIM_STEP,
0310 &val->intval);
0311 break;
0312 case POWER_SUPPLY_PROP_MODEL_NAME:
0313 val->strval = max77976_model;
0314 break;
0315 case POWER_SUPPLY_PROP_MANUFACTURER:
0316 val->strval = max77976_manufacturer;
0317 break;
0318 default:
0319 err = -EINVAL;
0320 }
0321
0322 return err;
0323 }
0324
0325 static int max77976_set_property(struct power_supply *psy,
0326 enum power_supply_property psp,
0327 const union power_supply_propval *val)
0328 {
0329 struct max77976 *chg = power_supply_get_drvdata(psy);
0330 int err = 0;
0331
0332 switch (psp) {
0333 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
0334 err = max77976_set_integer(chg, CHG_CC,
0335 MAX77976_CHG_CC_MIN,
0336 MAX77976_CHG_CC_MAX,
0337 MAX77976_CHG_CC_STEP,
0338 val->intval);
0339 break;
0340 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
0341 err = max77976_set_integer(chg, CHGIN_ILIM,
0342 MAX77976_CHGIN_ILIM_MIN,
0343 MAX77976_CHGIN_ILIM_MAX,
0344 MAX77976_CHGIN_ILIM_STEP,
0345 val->intval);
0346 break;
0347 default:
0348 err = -EINVAL;
0349 }
0350
0351 return err;
0352 };
0353
0354 static int max77976_property_is_writeable(struct power_supply *psy,
0355 enum power_supply_property psp)
0356 {
0357 switch (psp) {
0358 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
0359 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
0360 return true;
0361 default:
0362 return false;
0363 }
0364 }
0365
0366 static enum power_supply_property max77976_psy_props[] = {
0367 POWER_SUPPLY_PROP_STATUS,
0368 POWER_SUPPLY_PROP_CHARGE_TYPE,
0369 POWER_SUPPLY_PROP_HEALTH,
0370 POWER_SUPPLY_PROP_ONLINE,
0371 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
0372 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
0373 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
0374 POWER_SUPPLY_PROP_MODEL_NAME,
0375 POWER_SUPPLY_PROP_MANUFACTURER,
0376 };
0377
0378 static const struct power_supply_desc max77976_psy_desc = {
0379 .name = MAX77976_DRIVER_NAME,
0380 .type = POWER_SUPPLY_TYPE_USB,
0381 .properties = max77976_psy_props,
0382 .num_properties = ARRAY_SIZE(max77976_psy_props),
0383 .get_property = max77976_get_property,
0384 .set_property = max77976_set_property,
0385 .property_is_writeable = max77976_property_is_writeable,
0386 };
0387
0388
0389
0390
0391
0392 static int max77976_detect(struct max77976 *chg)
0393 {
0394 struct device *dev = &chg->client->dev;
0395 unsigned int id, ver, rev;
0396 int err;
0397
0398 err = regmap_read(chg->regmap, MAX77976_REG_CHIP_ID, &id);
0399 if (err)
0400 return dev_err_probe(dev, err, "cannot read chip ID\n");
0401
0402 if (id != MAX77976_CHIP_ID)
0403 return dev_err_probe(dev, -ENXIO, "unknown model ID 0x%02x\n", id);
0404
0405 err = regmap_field_read(chg->rfield[VERSION], &ver);
0406 if (!err)
0407 err = regmap_field_read(chg->rfield[REVISION], &rev);
0408 if (err)
0409 return dev_err_probe(dev, -ENXIO, "cannot read version/revision\n");
0410
0411 dev_info(dev, "detected model MAX779%02x ver %u rev %u", id, ver, rev);
0412
0413 return 0;
0414 }
0415
0416 static int max77976_configure(struct max77976 *chg)
0417 {
0418 struct device *dev = &chg->client->dev;
0419 int err;
0420
0421
0422 err = regmap_field_write(chg->rfield[CHGPROT], 0x3);
0423 if (err)
0424 goto err;
0425
0426
0427
0428
0429
0430 err = regmap_field_write(chg->rfield[MODE], MAX77976_MODE_CHARGER_BUCK);
0431 if (err)
0432 goto err;
0433
0434 return 0;
0435
0436 err:
0437 return dev_err_probe(dev, err, "error while configuring");
0438 }
0439
0440 static int max77976_probe(struct i2c_client *client)
0441 {
0442 struct device *dev = &client->dev;
0443 struct power_supply_config psy_cfg = {};
0444 struct power_supply *psy;
0445 struct max77976 *chg;
0446 int err;
0447 int i;
0448
0449 chg = devm_kzalloc(dev, sizeof(*chg), GFP_KERNEL);
0450 if (!chg)
0451 return -ENOMEM;
0452
0453 i2c_set_clientdata(client, chg);
0454 psy_cfg.drv_data = chg;
0455 chg->client = client;
0456
0457 chg->regmap = devm_regmap_init_i2c(client, &max77976_regmap_config);
0458 if (IS_ERR(chg->regmap))
0459 return dev_err_probe(dev, PTR_ERR(chg->regmap),
0460 "cannot allocate regmap\n");
0461
0462 for (i = 0; i < MAX77976_N_REGMAP_FIELDS; i++) {
0463 chg->rfield[i] = devm_regmap_field_alloc(dev, chg->regmap,
0464 max77976_reg_field[i]);
0465 if (IS_ERR(chg->rfield[i]))
0466 return dev_err_probe(dev, PTR_ERR(chg->rfield[i]),
0467 "cannot allocate regmap field\n");
0468 }
0469
0470 err = max77976_detect(chg);
0471 if (err)
0472 return err;
0473
0474 err = max77976_configure(chg);
0475 if (err)
0476 return err;
0477
0478 psy = devm_power_supply_register_no_ws(dev, &max77976_psy_desc, &psy_cfg);
0479 if (IS_ERR(psy))
0480 return dev_err_probe(dev, PTR_ERR(psy), "cannot register\n");
0481
0482 return 0;
0483 }
0484
0485 static const struct i2c_device_id max77976_i2c_id[] = {
0486 { MAX77976_DRIVER_NAME, 0 },
0487 { },
0488 };
0489 MODULE_DEVICE_TABLE(i2c, max77976_i2c_id);
0490
0491 static const struct of_device_id max77976_of_id[] = {
0492 { .compatible = "maxim,max77976" },
0493 { },
0494 };
0495 MODULE_DEVICE_TABLE(of, max77976_of_id);
0496
0497 static struct i2c_driver max77976_driver = {
0498 .driver = {
0499 .name = MAX77976_DRIVER_NAME,
0500 .of_match_table = max77976_of_id,
0501 },
0502 .probe_new = max77976_probe,
0503 .id_table = max77976_i2c_id,
0504 };
0505 module_i2c_driver(max77976_driver);
0506
0507 MODULE_AUTHOR("Luca Ceresoli <luca.ceresoli@bootlin.com>");
0508 MODULE_DESCRIPTION("Maxim MAX77976 charger driver");
0509 MODULE_LICENSE("GPL v2");