1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Based on max77650-charger.c 4 * 5 * Copyright (C) 2025 Dzmitry Sankouski <dsankouski@gmail.org> 6 * 7 * Battery charger driver for MAXIM 77705 charger/power-supply. 8 */ 9 10 #include <linux/devm-helpers.h> 11 #include <linux/i2c.h> 12 #include <linux/interrupt.h> 13 #include <linux/mfd/max77693-common.h> 14 #include <linux/mfd/max77705-private.h> 15 #include <linux/power/max77705_charger.h> 16 #include <linux/module.h> 17 #include <linux/platform_device.h> 18 #include <linux/power_supply.h> 19 #include <linux/regmap.h> 20 21 static const char *max77705_charger_model = "max77705"; 22 static const char *max77705_charger_manufacturer = "Maxim Integrated"; 23 24 static const struct regmap_config max77705_chg_regmap_config = { 25 .reg_base = MAX77705_CHG_REG_BASE, 26 .reg_bits = 8, 27 .val_bits = 8, 28 .max_register = MAX77705_CHG_REG_SAFEOUT_CTRL, 29 }; 30 31 static enum power_supply_property max77705_charger_props[] = { 32 POWER_SUPPLY_PROP_ONLINE, 33 POWER_SUPPLY_PROP_PRESENT, 34 POWER_SUPPLY_PROP_STATUS, 35 POWER_SUPPLY_PROP_CHARGE_TYPE, 36 POWER_SUPPLY_PROP_HEALTH, 37 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 38 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, 39 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, 40 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, 41 }; 42 43 static int max77705_chgin_irq(void *irq_drv_data) 44 { 45 struct max77705_charger_data *charger = irq_drv_data; 46 47 queue_work(charger->wqueue, &charger->chgin_work); 48 49 return 0; 50 } 51 52 static const struct regmap_irq max77705_charger_irqs[] = { 53 { .mask = MAX77705_BYP_IM, }, 54 { .mask = MAX77705_INP_LIMIT_IM, }, 55 { .mask = MAX77705_BATP_IM, }, 56 { .mask = MAX77705_BAT_IM, }, 57 { .mask = MAX77705_CHG_IM, }, 58 { .mask = MAX77705_WCIN_IM, }, 59 { .mask = MAX77705_CHGIN_IM, }, 60 { .mask = MAX77705_AICL_IM, }, 61 }; 62 63 static struct regmap_irq_chip max77705_charger_irq_chip = { 64 .name = "max77705-charger", 65 .status_base = MAX77705_CHG_REG_INT, 66 .mask_base = MAX77705_CHG_REG_INT_MASK, 67 .handle_post_irq = max77705_chgin_irq, 68 .num_regs = 1, 69 .irqs = max77705_charger_irqs, 70 .num_irqs = ARRAY_SIZE(max77705_charger_irqs), 71 }; 72 73 static int max77705_charger_enable(struct max77705_charger_data *chg) 74 { 75 int rv; 76 77 rv = regmap_update_bits(chg->regmap, MAX77705_CHG_REG_CNFG_09, 78 MAX77705_CHG_EN_MASK, MAX77705_CHG_EN_MASK); 79 if (rv) 80 dev_err(chg->dev, "unable to enable the charger: %d\n", rv); 81 82 return rv; 83 } 84 85 static void max77705_charger_disable(void *data) 86 { 87 struct max77705_charger_data *chg = data; 88 int rv; 89 90 rv = regmap_update_bits(chg->regmap, 91 MAX77705_CHG_REG_CNFG_09, 92 MAX77705_CHG_EN_MASK, 93 MAX77705_CHG_DISABLE); 94 if (rv) 95 dev_err(chg->dev, "unable to disable the charger: %d\n", rv); 96 } 97 98 static int max77705_get_online(struct regmap *regmap, int *val) 99 { 100 unsigned int data; 101 int ret; 102 103 ret = regmap_read(regmap, MAX77705_CHG_REG_INT_OK, &data); 104 if (ret < 0) 105 return ret; 106 107 *val = !!(data & MAX77705_CHGIN_OK); 108 109 return 0; 110 } 111 112 static int max77705_check_battery(struct max77705_charger_data *charger, int *val) 113 { 114 unsigned int reg_data; 115 unsigned int reg_data2; 116 struct regmap *regmap = charger->regmap; 117 118 regmap_read(regmap, MAX77705_CHG_REG_INT_OK, ®_data); 119 120 dev_dbg(charger->dev, "CHG_INT_OK(0x%x)\n", reg_data); 121 122 regmap_read(regmap, MAX77705_CHG_REG_DETAILS_00, ®_data2); 123 124 dev_dbg(charger->dev, "CHG_DETAILS00(0x%x)\n", reg_data2); 125 126 if ((reg_data & MAX77705_BATP_OK) || !(reg_data2 & MAX77705_BATP_DTLS)) 127 *val = true; 128 else 129 *val = false; 130 131 return 0; 132 } 133 134 static int max77705_get_charge_type(struct max77705_charger_data *charger, int *val) 135 { 136 struct regmap *regmap = charger->regmap; 137 unsigned int reg_data; 138 139 regmap_read(regmap, MAX77705_CHG_REG_CNFG_09, ®_data); 140 if (!MAX77705_CHARGER_CHG_CHARGING(reg_data)) { 141 *val = POWER_SUPPLY_CHARGE_TYPE_NONE; 142 return 0; 143 } 144 145 regmap_read(regmap, MAX77705_CHG_REG_DETAILS_01, ®_data); 146 reg_data &= MAX77705_CHG_DTLS; 147 148 switch (reg_data) { 149 case 0x0: 150 case MAX77705_CHARGER_CONSTANT_CURRENT: 151 case MAX77705_CHARGER_CONSTANT_VOLTAGE: 152 *val = POWER_SUPPLY_CHARGE_TYPE_FAST; 153 return 0; 154 default: 155 *val = POWER_SUPPLY_CHARGE_TYPE_NONE; 156 return 0; 157 } 158 159 return 0; 160 } 161 162 static int max77705_get_status(struct max77705_charger_data *charger, int *val) 163 { 164 struct regmap *regmap = charger->regmap; 165 unsigned int reg_data; 166 167 regmap_read(regmap, MAX77705_CHG_REG_CNFG_09, ®_data); 168 if (!MAX77705_CHARGER_CHG_CHARGING(reg_data)) { 169 *val = POWER_SUPPLY_CHARGE_TYPE_NONE; 170 return 0; 171 } 172 173 regmap_read(regmap, MAX77705_CHG_REG_DETAILS_01, ®_data); 174 reg_data &= MAX77705_CHG_DTLS; 175 176 switch (reg_data) { 177 case 0x0: 178 case MAX77705_CHARGER_CONSTANT_CURRENT: 179 case MAX77705_CHARGER_CONSTANT_VOLTAGE: 180 *val = POWER_SUPPLY_STATUS_CHARGING; 181 return 0; 182 case MAX77705_CHARGER_END_OF_CHARGE: 183 case MAX77705_CHARGER_DONE: 184 *val = POWER_SUPPLY_STATUS_FULL; 185 return 0; 186 /* those values hard coded as in vendor kernel, because of */ 187 /* failure to determine it's actual meaning. */ 188 case 0x05: 189 case 0x06: 190 case 0x07: 191 *val = POWER_SUPPLY_STATUS_NOT_CHARGING; 192 return 0; 193 case 0x08: 194 case 0xA: 195 case 0xB: 196 *val = POWER_SUPPLY_STATUS_DISCHARGING; 197 return 0; 198 default: 199 *val = POWER_SUPPLY_STATUS_UNKNOWN; 200 return 0; 201 } 202 203 return 0; 204 } 205 206 static int max77705_get_vbus_state(struct regmap *regmap, int *value) 207 { 208 int ret; 209 unsigned int charge_dtls; 210 211 ret = regmap_read(regmap, MAX77705_CHG_REG_DETAILS_00, &charge_dtls); 212 if (ret) 213 return ret; 214 215 charge_dtls = ((charge_dtls & MAX77705_CHGIN_DTLS) >> 216 MAX77705_CHGIN_DTLS_SHIFT); 217 218 switch (charge_dtls) { 219 case 0x00: 220 *value = POWER_SUPPLY_HEALTH_UNDERVOLTAGE; 221 break; 222 case 0x01: 223 *value = POWER_SUPPLY_HEALTH_UNDERVOLTAGE; 224 break; 225 case 0x02: 226 *value = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 227 break; 228 case 0x03: 229 *value = POWER_SUPPLY_HEALTH_GOOD; 230 break; 231 default: 232 return 0; 233 } 234 return 0; 235 } 236 237 static int max77705_get_battery_health(struct max77705_charger_data *charger, 238 int *value) 239 { 240 struct regmap *regmap = charger->regmap; 241 unsigned int bat_dtls; 242 243 regmap_read(regmap, MAX77705_CHG_REG_DETAILS_01, &bat_dtls); 244 bat_dtls = ((bat_dtls & MAX77705_BAT_DTLS) >> MAX77705_BAT_DTLS_SHIFT); 245 246 switch (bat_dtls) { 247 case MAX77705_BATTERY_NOBAT: 248 dev_dbg(charger->dev, "%s: No battery and the charger is suspended\n", 249 __func__); 250 *value = POWER_SUPPLY_HEALTH_NO_BATTERY; 251 break; 252 case MAX77705_BATTERY_PREQUALIFICATION: 253 dev_dbg(charger->dev, "%s: battery is okay but its voltage is low(~VPQLB)\n", 254 __func__); 255 break; 256 case MAX77705_BATTERY_DEAD: 257 dev_dbg(charger->dev, "%s: battery dead\n", __func__); 258 *value = POWER_SUPPLY_HEALTH_DEAD; 259 break; 260 case MAX77705_BATTERY_GOOD: 261 case MAX77705_BATTERY_LOWVOLTAGE: 262 *value = POWER_SUPPLY_HEALTH_GOOD; 263 break; 264 case MAX77705_BATTERY_OVERVOLTAGE: 265 dev_dbg(charger->dev, "%s: battery ovp\n", __func__); 266 *value = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 267 break; 268 default: 269 dev_dbg(charger->dev, "%s: battery unknown\n", __func__); 270 *value = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; 271 break; 272 } 273 274 return 0; 275 } 276 277 static int max77705_get_health(struct max77705_charger_data *charger, int *val) 278 { 279 struct regmap *regmap = charger->regmap; 280 int ret, is_online = 0; 281 282 ret = max77705_get_online(regmap, &is_online); 283 if (ret) 284 return ret; 285 if (is_online) { 286 ret = max77705_get_vbus_state(regmap, val); 287 if (ret || (*val != POWER_SUPPLY_HEALTH_GOOD)) 288 return ret; 289 } 290 return max77705_get_battery_health(charger, val); 291 } 292 293 static int max77705_get_input_current(struct max77705_charger_data *charger, 294 int *val) 295 { 296 unsigned int reg_data; 297 int get_current = 0; 298 struct regmap *regmap = charger->regmap; 299 300 regmap_read(regmap, MAX77705_CHG_REG_CNFG_09, ®_data); 301 302 reg_data &= MAX77705_CHG_CHGIN_LIM_MASK; 303 304 if (reg_data <= 3) 305 get_current = MAX77705_CURRENT_CHGIN_MIN; 306 else if (reg_data >= MAX77705_CHG_CHGIN_LIM_MASK) 307 get_current = MAX77705_CURRENT_CHGIN_MAX; 308 else 309 get_current = (reg_data + 1) * MAX77705_CURRENT_CHGIN_STEP; 310 311 *val = get_current; 312 313 return 0; 314 } 315 316 static int max77705_get_charge_current(struct max77705_charger_data *charger, 317 int *val) 318 { 319 unsigned int reg_data; 320 struct regmap *regmap = charger->regmap; 321 322 regmap_read(regmap, MAX77705_CHG_REG_CNFG_02, ®_data); 323 reg_data &= MAX77705_CHG_CC; 324 325 *val = reg_data <= 0x2 ? MAX77705_CURRENT_CHGIN_MIN : reg_data * MAX77705_CURRENT_CHG_STEP; 326 327 return 0; 328 } 329 330 static int max77705_set_float_voltage(struct max77705_charger_data *charger, 331 int float_voltage) 332 { 333 int float_voltage_mv; 334 unsigned int reg_data = 0; 335 struct regmap *regmap = charger->regmap; 336 337 float_voltage_mv = float_voltage / 1000; 338 reg_data = float_voltage_mv <= 4000 ? 0x0 : 339 float_voltage_mv >= 4500 ? 0x23 : 340 (float_voltage_mv <= 4200) ? (float_voltage_mv - 4000) / 50 : 341 (((float_voltage_mv - 4200) / 10) + 0x04); 342 343 return regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_04, 344 MAX77705_CHG_CV_PRM_MASK, 345 (reg_data << MAX77705_CHG_CV_PRM_SHIFT)); 346 } 347 348 static int max77705_get_float_voltage(struct max77705_charger_data *charger, 349 int *val) 350 { 351 unsigned int reg_data = 0; 352 int voltage_mv; 353 struct regmap *regmap = charger->regmap; 354 355 regmap_read(regmap, MAX77705_CHG_REG_CNFG_04, ®_data); 356 reg_data &= MAX77705_CHG_PRM_MASK; 357 voltage_mv = reg_data <= 0x04 ? reg_data * 50 + 4000 : 358 (reg_data - 4) * 10 + 4200; 359 *val = voltage_mv * 1000; 360 361 return 0; 362 } 363 364 static int max77705_chg_get_property(struct power_supply *psy, 365 enum power_supply_property psp, 366 union power_supply_propval *val) 367 { 368 struct max77705_charger_data *charger = power_supply_get_drvdata(psy); 369 struct regmap *regmap = charger->regmap; 370 371 switch (psp) { 372 case POWER_SUPPLY_PROP_ONLINE: 373 return max77705_get_online(regmap, &val->intval); 374 case POWER_SUPPLY_PROP_PRESENT: 375 return max77705_check_battery(charger, &val->intval); 376 case POWER_SUPPLY_PROP_STATUS: 377 return max77705_get_status(charger, &val->intval); 378 case POWER_SUPPLY_PROP_CHARGE_TYPE: 379 return max77705_get_charge_type(charger, &val->intval); 380 case POWER_SUPPLY_PROP_HEALTH: 381 return max77705_get_health(charger, &val->intval); 382 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 383 return max77705_get_input_current(charger, &val->intval); 384 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 385 return max77705_get_charge_current(charger, &val->intval); 386 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 387 return max77705_get_float_voltage(charger, &val->intval); 388 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 389 val->intval = charger->bat_info->voltage_max_design_uv; 390 break; 391 case POWER_SUPPLY_PROP_MODEL_NAME: 392 val->strval = max77705_charger_model; 393 break; 394 case POWER_SUPPLY_PROP_MANUFACTURER: 395 val->strval = max77705_charger_manufacturer; 396 break; 397 default: 398 return -EINVAL; 399 } 400 return 0; 401 } 402 403 static const struct power_supply_desc max77705_charger_psy_desc = { 404 .name = "max77705-charger", 405 .type = POWER_SUPPLY_TYPE_USB, 406 .properties = max77705_charger_props, 407 .num_properties = ARRAY_SIZE(max77705_charger_props), 408 .get_property = max77705_chg_get_property, 409 }; 410 411 static void max77705_chgin_isr_work(struct work_struct *work) 412 { 413 struct max77705_charger_data *charger = 414 container_of(work, struct max77705_charger_data, chgin_work); 415 416 power_supply_changed(charger->psy_chg); 417 } 418 419 static void max77705_charger_initialize(struct max77705_charger_data *chg) 420 { 421 u8 reg_data; 422 struct power_supply_battery_info *info; 423 struct regmap *regmap = chg->regmap; 424 425 if (power_supply_get_battery_info(chg->psy_chg, &info) < 0) 426 return; 427 428 chg->bat_info = info; 429 430 /* unlock charger setting protect */ 431 /* slowest LX slope */ 432 reg_data = MAX77705_CHGPROT_MASK | MAX77705_SLOWEST_LX_SLOPE; 433 regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_06, reg_data, 434 reg_data); 435 436 /* fast charge timer disable */ 437 /* restart threshold disable */ 438 /* pre-qual charge disable */ 439 reg_data = (MAX77705_FCHGTIME_DISABLE << MAX77705_FCHGTIME_SHIFT) | 440 (MAX77705_CHG_RSTRT_DISABLE << MAX77705_CHG_RSTRT_SHIFT) | 441 (MAX77705_CHG_PQEN_DISABLE << MAX77705_PQEN_SHIFT); 442 regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_01, 443 (MAX77705_FCHGTIME_MASK | 444 MAX77705_CHG_RSTRT_MASK | 445 MAX77705_PQEN_MASK), 446 reg_data); 447 448 /* OTG off(UNO on), boost off */ 449 regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_00, 450 MAX77705_OTG_CTRL, 0); 451 452 /* charge current 450mA(default) */ 453 /* otg current limit 900mA */ 454 regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_02, 455 MAX77705_OTG_ILIM_MASK, 456 MAX77705_OTG_ILIM_900 << MAX77705_OTG_ILIM_SHIFT); 457 458 /* BAT to SYS OCP 4.80A */ 459 regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_05, 460 MAX77705_REG_B2SOVRC_MASK, 461 MAX77705_B2SOVRC_4_8A << MAX77705_REG_B2SOVRC_SHIFT); 462 /* top off current 150mA */ 463 /* top off timer 30min */ 464 reg_data = (MAX77705_TO_ITH_150MA << MAX77705_TO_ITH_SHIFT) | 465 (MAX77705_TO_TIME_30M << MAX77705_TO_TIME_SHIFT) | 466 (MAX77705_SYS_TRACK_DISABLE << MAX77705_SYS_TRACK_DIS_SHIFT); 467 regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_03, 468 (MAX77705_TO_ITH_MASK | 469 MAX77705_TO_TIME_MASK | 470 MAX77705_SYS_TRACK_DIS_MASK), reg_data); 471 472 /* cv voltage 4.2V or 4.35V */ 473 /* MINVSYS 3.6V(default) */ 474 if (info->voltage_max_design_uv < 0) { 475 dev_warn(chg->dev, "missing battery:voltage-max-design-microvolt\n"); 476 max77705_set_float_voltage(chg, 4200000); 477 } else { 478 max77705_set_float_voltage(chg, info->voltage_max_design_uv); 479 } 480 481 regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_12, 482 MAX77705_VCHGIN_REG_MASK, MAX77705_VCHGIN_4_5); 483 regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_12, 484 MAX77705_WCIN_REG_MASK, MAX77705_WCIN_4_5); 485 486 /* Watchdog timer */ 487 regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_00, 488 MAX77705_WDTEN_MASK, 0); 489 490 /* Active Discharge Enable */ 491 regmap_update_bits(regmap, MAX77705_PMIC_REG_MAINCTRL1, 1, 1); 492 493 /* VBYPSET=5.0V */ 494 regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_11, MAX77705_VBYPSET_MASK, 0); 495 496 /* Switching Frequency : 1.5MHz */ 497 regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_08, MAX77705_REG_FSW_MASK, 498 (MAX77705_CHG_FSW_1_5MHz << MAX77705_REG_FSW_SHIFT)); 499 500 /* Auto skip mode */ 501 regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_12, MAX77705_REG_DISKIP_MASK, 502 (MAX77705_AUTO_SKIP << MAX77705_REG_DISKIP_SHIFT)); 503 } 504 505 static int max77705_charger_probe(struct i2c_client *i2c) 506 { 507 struct power_supply_config pscfg = {}; 508 struct max77705_charger_data *chg; 509 struct device *dev; 510 struct regmap_irq_chip_data *irq_data; 511 int ret; 512 513 dev = &i2c->dev; 514 515 chg = devm_kzalloc(dev, sizeof(*chg), GFP_KERNEL); 516 if (!chg) 517 return -ENOMEM; 518 519 chg->dev = dev; 520 i2c_set_clientdata(i2c, chg); 521 522 chg->regmap = devm_regmap_init_i2c(i2c, &max77705_chg_regmap_config); 523 if (IS_ERR(chg->regmap)) 524 return PTR_ERR(chg->regmap); 525 526 ret = regmap_update_bits(chg->regmap, 527 MAX77705_CHG_REG_INT_MASK, 528 MAX77705_CHGIN_IM, 0); 529 if (ret) 530 return ret; 531 532 pscfg.fwnode = dev_fwnode(dev); 533 pscfg.drv_data = chg; 534 535 chg->psy_chg = devm_power_supply_register(dev, &max77705_charger_psy_desc, &pscfg); 536 if (IS_ERR(chg->psy_chg)) 537 return PTR_ERR(chg->psy_chg); 538 539 max77705_charger_irq_chip.irq_drv_data = chg; 540 ret = devm_regmap_add_irq_chip(chg->dev, chg->regmap, i2c->irq, 541 IRQF_ONESHOT | IRQF_SHARED, 0, 542 &max77705_charger_irq_chip, 543 &irq_data); 544 if (ret) 545 return dev_err_probe(dev, ret, "failed to add irq chip\n"); 546 547 chg->wqueue = create_singlethread_workqueue(dev_name(dev)); 548 if (!chg->wqueue) 549 return dev_err_probe(dev, -ENOMEM, "failed to create workqueue\n"); 550 551 ret = devm_work_autocancel(dev, &chg->chgin_work, max77705_chgin_isr_work); 552 if (ret) { 553 dev_err_probe(dev, ret, "failed to initialize interrupt work\n"); 554 goto destroy_wq; 555 } 556 557 max77705_charger_initialize(chg); 558 559 ret = max77705_charger_enable(chg); 560 if (ret) { 561 dev_err_probe(dev, ret, "failed to enable charge\n"); 562 goto destroy_wq; 563 } 564 565 return devm_add_action_or_reset(dev, max77705_charger_disable, chg); 566 567 destroy_wq: 568 destroy_workqueue(chg->wqueue); 569 return ret; 570 } 571 572 static const struct of_device_id max77705_charger_of_match[] = { 573 { .compatible = "maxim,max77705-charger" }, 574 { } 575 }; 576 MODULE_DEVICE_TABLE(of, max77705_charger_of_match); 577 578 static struct i2c_driver max77705_charger_driver = { 579 .driver = { 580 .name = "max77705-charger", 581 .of_match_table = max77705_charger_of_match, 582 }, 583 .probe = max77705_charger_probe, 584 }; 585 module_i2c_driver(max77705_charger_driver); 586 587 MODULE_AUTHOR("Dzmitry Sankouski <dsankouski@gmail.com>"); 588 MODULE_DESCRIPTION("Maxim MAX77705 charger driver"); 589 MODULE_LICENSE("GPL"); 590