max17040_battery.c (14742B)
1// SPDX-License-Identifier: GPL-2.0 2// 3// max17040_battery.c 4// fuel-gauge systems for lithium-ion (Li+) batteries 5// 6// Copyright (C) 2009 Samsung Electronics 7// Minkyu Kang <mk7.kang@samsung.com> 8 9#include <linux/module.h> 10#include <linux/init.h> 11#include <linux/platform_device.h> 12#include <linux/mutex.h> 13#include <linux/err.h> 14#include <linux/i2c.h> 15#include <linux/delay.h> 16#include <linux/interrupt.h> 17#include <linux/power_supply.h> 18#include <linux/of_device.h> 19#include <linux/regmap.h> 20#include <linux/slab.h> 21 22#define MAX17040_VCELL 0x02 23#define MAX17040_SOC 0x04 24#define MAX17040_MODE 0x06 25#define MAX17040_VER 0x08 26#define MAX17040_CONFIG 0x0C 27#define MAX17040_STATUS 0x1A 28#define MAX17040_CMD 0xFE 29 30 31#define MAX17040_DELAY 1000 32#define MAX17040_BATTERY_FULL 95 33#define MAX17040_RCOMP_DEFAULT 0x9700 34 35#define MAX17040_ATHD_MASK 0x3f 36#define MAX17040_ALSC_MASK 0x40 37#define MAX17040_ATHD_DEFAULT_POWER_UP 4 38#define MAX17040_STATUS_HD_MASK 0x1000 39#define MAX17040_STATUS_SC_MASK 0x2000 40#define MAX17040_CFG_RCOMP_MASK 0xff00 41 42enum chip_id { 43 ID_MAX17040, 44 ID_MAX17041, 45 ID_MAX17043, 46 ID_MAX17044, 47 ID_MAX17048, 48 ID_MAX17049, 49 ID_MAX17058, 50 ID_MAX17059, 51}; 52 53/* values that differ by chip_id */ 54struct chip_data { 55 u16 reset_val; 56 u16 vcell_shift; 57 u16 vcell_mul; 58 u16 vcell_div; 59 u8 has_low_soc_alert; 60 u8 rcomp_bytes; 61 u8 has_soc_alert; 62}; 63 64static struct chip_data max17040_family[] = { 65 [ID_MAX17040] = { 66 .reset_val = 0x0054, 67 .vcell_shift = 4, 68 .vcell_mul = 1250, 69 .vcell_div = 1, 70 .has_low_soc_alert = 0, 71 .rcomp_bytes = 2, 72 .has_soc_alert = 0, 73 }, 74 [ID_MAX17041] = { 75 .reset_val = 0x0054, 76 .vcell_shift = 4, 77 .vcell_mul = 2500, 78 .vcell_div = 1, 79 .has_low_soc_alert = 0, 80 .rcomp_bytes = 2, 81 .has_soc_alert = 0, 82 }, 83 [ID_MAX17043] = { 84 .reset_val = 0x0054, 85 .vcell_shift = 4, 86 .vcell_mul = 1250, 87 .vcell_div = 1, 88 .has_low_soc_alert = 1, 89 .rcomp_bytes = 1, 90 .has_soc_alert = 0, 91 }, 92 [ID_MAX17044] = { 93 .reset_val = 0x0054, 94 .vcell_shift = 4, 95 .vcell_mul = 2500, 96 .vcell_div = 1, 97 .has_low_soc_alert = 1, 98 .rcomp_bytes = 1, 99 .has_soc_alert = 0, 100 }, 101 [ID_MAX17048] = { 102 .reset_val = 0x5400, 103 .vcell_shift = 0, 104 .vcell_mul = 625, 105 .vcell_div = 8, 106 .has_low_soc_alert = 1, 107 .rcomp_bytes = 1, 108 .has_soc_alert = 1, 109 }, 110 [ID_MAX17049] = { 111 .reset_val = 0x5400, 112 .vcell_shift = 0, 113 .vcell_mul = 625, 114 .vcell_div = 4, 115 .has_low_soc_alert = 1, 116 .rcomp_bytes = 1, 117 .has_soc_alert = 1, 118 }, 119 [ID_MAX17058] = { 120 .reset_val = 0x5400, 121 .vcell_shift = 0, 122 .vcell_mul = 625, 123 .vcell_div = 8, 124 .has_low_soc_alert = 1, 125 .rcomp_bytes = 1, 126 .has_soc_alert = 0, 127 }, 128 [ID_MAX17059] = { 129 .reset_val = 0x5400, 130 .vcell_shift = 0, 131 .vcell_mul = 625, 132 .vcell_div = 4, 133 .has_low_soc_alert = 1, 134 .rcomp_bytes = 1, 135 .has_soc_alert = 0, 136 }, 137}; 138 139struct max17040_chip { 140 struct i2c_client *client; 141 struct regmap *regmap; 142 struct delayed_work work; 143 struct power_supply *battery; 144 struct chip_data data; 145 146 /* battery capacity */ 147 int soc; 148 /* Low alert threshold from 32% to 1% of the State of Charge */ 149 u32 low_soc_alert; 150 /* some devices return twice the capacity */ 151 bool quirk_double_soc; 152 /* higher 8 bits for 17043+, 16 bits for 17040,41 */ 153 u16 rcomp; 154}; 155 156static int max17040_reset(struct max17040_chip *chip) 157{ 158 return regmap_write(chip->regmap, MAX17040_CMD, chip->data.reset_val); 159} 160 161static int max17040_set_low_soc_alert(struct max17040_chip *chip, u32 level) 162{ 163 level = 32 - level * (chip->quirk_double_soc ? 2 : 1); 164 return regmap_update_bits(chip->regmap, MAX17040_CONFIG, 165 MAX17040_ATHD_MASK, level); 166} 167 168static int max17040_set_soc_alert(struct max17040_chip *chip, bool enable) 169{ 170 return regmap_update_bits(chip->regmap, MAX17040_CONFIG, 171 MAX17040_ALSC_MASK, enable ? MAX17040_ALSC_MASK : 0); 172} 173 174static int max17040_set_rcomp(struct max17040_chip *chip, u16 rcomp) 175{ 176 u16 mask = chip->data.rcomp_bytes == 2 ? 177 0xffff : MAX17040_CFG_RCOMP_MASK; 178 179 return regmap_update_bits(chip->regmap, MAX17040_CONFIG, mask, rcomp); 180} 181 182static int max17040_raw_vcell_to_uvolts(struct max17040_chip *chip, u16 vcell) 183{ 184 struct chip_data *d = &chip->data; 185 186 return (vcell >> d->vcell_shift) * d->vcell_mul / d->vcell_div; 187} 188 189 190static int max17040_get_vcell(struct max17040_chip *chip) 191{ 192 u32 vcell; 193 194 regmap_read(chip->regmap, MAX17040_VCELL, &vcell); 195 196 return max17040_raw_vcell_to_uvolts(chip, vcell); 197} 198 199static int max17040_get_soc(struct max17040_chip *chip) 200{ 201 u32 soc; 202 203 regmap_read(chip->regmap, MAX17040_SOC, &soc); 204 205 return soc >> (chip->quirk_double_soc ? 9 : 8); 206} 207 208static int max17040_get_version(struct max17040_chip *chip) 209{ 210 int ret; 211 u32 version; 212 213 ret = regmap_read(chip->regmap, MAX17040_VER, &version); 214 215 return ret ? ret : version; 216} 217 218static int max17040_get_online(struct max17040_chip *chip) 219{ 220 return 1; 221} 222 223static int max17040_get_of_data(struct max17040_chip *chip) 224{ 225 struct device *dev = &chip->client->dev; 226 struct chip_data *data = &max17040_family[ 227 (uintptr_t) of_device_get_match_data(dev)]; 228 int rcomp_len; 229 u8 rcomp[2]; 230 231 chip->quirk_double_soc = device_property_read_bool(dev, 232 "maxim,double-soc"); 233 234 chip->low_soc_alert = MAX17040_ATHD_DEFAULT_POWER_UP; 235 device_property_read_u32(dev, 236 "maxim,alert-low-soc-level", 237 &chip->low_soc_alert); 238 239 if (chip->low_soc_alert <= 0 || 240 chip->low_soc_alert > (chip->quirk_double_soc ? 16 : 32)) { 241 dev_err(dev, "maxim,alert-low-soc-level out of bounds\n"); 242 return -EINVAL; 243 } 244 245 rcomp_len = device_property_count_u8(dev, "maxim,rcomp"); 246 chip->rcomp = MAX17040_RCOMP_DEFAULT; 247 if (rcomp_len == data->rcomp_bytes) { 248 if (!device_property_read_u8_array(dev, "maxim,rcomp", 249 rcomp, rcomp_len)) 250 chip->rcomp = rcomp_len == 2 ? rcomp[0] << 8 | rcomp[1] : 251 rcomp[0] << 8; 252 } else if (rcomp_len > 0) { 253 dev_err(dev, "maxim,rcomp has incorrect length\n"); 254 return -EINVAL; 255 } 256 257 return 0; 258} 259 260static void max17040_check_changes(struct max17040_chip *chip) 261{ 262 chip->soc = max17040_get_soc(chip); 263} 264 265static void max17040_queue_work(struct max17040_chip *chip) 266{ 267 queue_delayed_work(system_power_efficient_wq, &chip->work, 268 MAX17040_DELAY); 269} 270 271static void max17040_stop_work(void *data) 272{ 273 struct max17040_chip *chip = data; 274 275 cancel_delayed_work_sync(&chip->work); 276} 277 278static void max17040_work(struct work_struct *work) 279{ 280 struct max17040_chip *chip; 281 int last_soc; 282 283 chip = container_of(work, struct max17040_chip, work.work); 284 285 /* store SOC to check changes */ 286 last_soc = chip->soc; 287 max17040_check_changes(chip); 288 289 /* check changes and send uevent */ 290 if (last_soc != chip->soc) 291 power_supply_changed(chip->battery); 292 293 max17040_queue_work(chip); 294} 295 296/* Returns true if alert cause was SOC change, not low SOC */ 297static bool max17040_handle_soc_alert(struct max17040_chip *chip) 298{ 299 bool ret = true; 300 u32 data; 301 302 regmap_read(chip->regmap, MAX17040_STATUS, &data); 303 304 if (data & MAX17040_STATUS_HD_MASK) { 305 // this alert was caused by low soc 306 ret = false; 307 } 308 if (data & MAX17040_STATUS_SC_MASK) { 309 // soc change bit -- deassert to mark as handled 310 regmap_write(chip->regmap, MAX17040_STATUS, 311 data & ~MAX17040_STATUS_SC_MASK); 312 } 313 314 return ret; 315} 316 317static irqreturn_t max17040_thread_handler(int id, void *dev) 318{ 319 struct max17040_chip *chip = dev; 320 321 if (!(chip->data.has_soc_alert && max17040_handle_soc_alert(chip))) 322 dev_warn(&chip->client->dev, "IRQ: Alert battery low level\n"); 323 324 /* read registers */ 325 max17040_check_changes(chip); 326 327 /* send uevent */ 328 power_supply_changed(chip->battery); 329 330 /* reset alert bit */ 331 max17040_set_low_soc_alert(chip, chip->low_soc_alert); 332 333 return IRQ_HANDLED; 334} 335 336static int max17040_enable_alert_irq(struct max17040_chip *chip) 337{ 338 struct i2c_client *client = chip->client; 339 int ret; 340 341 ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, 342 max17040_thread_handler, IRQF_ONESHOT, 343 chip->battery->desc->name, chip); 344 345 return ret; 346} 347 348static int max17040_prop_writeable(struct power_supply *psy, 349 enum power_supply_property psp) 350{ 351 switch (psp) { 352 case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN: 353 return 1; 354 default: 355 return 0; 356 } 357} 358 359static int max17040_set_property(struct power_supply *psy, 360 enum power_supply_property psp, 361 const union power_supply_propval *val) 362{ 363 struct max17040_chip *chip = power_supply_get_drvdata(psy); 364 int ret; 365 366 switch (psp) { 367 case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN: 368 /* alert threshold can be programmed from 1% up to 16/32% */ 369 if ((val->intval < 1) || 370 (val->intval > (chip->quirk_double_soc ? 16 : 32))) { 371 ret = -EINVAL; 372 break; 373 } 374 ret = max17040_set_low_soc_alert(chip, val->intval); 375 chip->low_soc_alert = val->intval; 376 break; 377 default: 378 ret = -EINVAL; 379 } 380 381 return ret; 382} 383 384static int max17040_get_property(struct power_supply *psy, 385 enum power_supply_property psp, 386 union power_supply_propval *val) 387{ 388 struct max17040_chip *chip = power_supply_get_drvdata(psy); 389 390 switch (psp) { 391 case POWER_SUPPLY_PROP_ONLINE: 392 val->intval = max17040_get_online(chip); 393 break; 394 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 395 val->intval = max17040_get_vcell(chip); 396 break; 397 case POWER_SUPPLY_PROP_CAPACITY: 398 val->intval = max17040_get_soc(chip); 399 break; 400 case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN: 401 val->intval = chip->low_soc_alert; 402 break; 403 default: 404 return -EINVAL; 405 } 406 return 0; 407} 408 409static const struct regmap_config max17040_regmap = { 410 .reg_bits = 8, 411 .reg_stride = 2, 412 .val_bits = 16, 413 .val_format_endian = REGMAP_ENDIAN_BIG, 414}; 415 416static enum power_supply_property max17040_battery_props[] = { 417 POWER_SUPPLY_PROP_ONLINE, 418 POWER_SUPPLY_PROP_VOLTAGE_NOW, 419 POWER_SUPPLY_PROP_CAPACITY, 420 POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN, 421}; 422 423static const struct power_supply_desc max17040_battery_desc = { 424 .name = "battery", 425 .type = POWER_SUPPLY_TYPE_BATTERY, 426 .get_property = max17040_get_property, 427 .set_property = max17040_set_property, 428 .property_is_writeable = max17040_prop_writeable, 429 .properties = max17040_battery_props, 430 .num_properties = ARRAY_SIZE(max17040_battery_props), 431}; 432 433static int max17040_probe(struct i2c_client *client, 434 const struct i2c_device_id *id) 435{ 436 struct i2c_adapter *adapter = client->adapter; 437 struct power_supply_config psy_cfg = {}; 438 struct max17040_chip *chip; 439 enum chip_id chip_id; 440 bool enable_irq = false; 441 int ret; 442 443 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) 444 return -EIO; 445 446 chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 447 if (!chip) 448 return -ENOMEM; 449 450 chip->client = client; 451 chip->regmap = devm_regmap_init_i2c(client, &max17040_regmap); 452 if (IS_ERR(chip->regmap)) 453 return PTR_ERR(chip->regmap); 454 chip_id = (enum chip_id) id->driver_data; 455 if (client->dev.of_node) { 456 ret = max17040_get_of_data(chip); 457 if (ret) 458 return ret; 459 chip_id = (uintptr_t)of_device_get_match_data(&client->dev); 460 } 461 chip->data = max17040_family[chip_id]; 462 463 i2c_set_clientdata(client, chip); 464 psy_cfg.drv_data = chip; 465 466 chip->battery = devm_power_supply_register(&client->dev, 467 &max17040_battery_desc, &psy_cfg); 468 if (IS_ERR(chip->battery)) { 469 dev_err(&client->dev, "failed: power supply register\n"); 470 return PTR_ERR(chip->battery); 471 } 472 473 ret = max17040_get_version(chip); 474 if (ret < 0) 475 return ret; 476 dev_dbg(&chip->client->dev, "MAX17040 Fuel-Gauge Ver 0x%x\n", ret); 477 478 if (chip_id == ID_MAX17040 || chip_id == ID_MAX17041) 479 max17040_reset(chip); 480 481 max17040_set_rcomp(chip, chip->rcomp); 482 483 /* check interrupt */ 484 if (client->irq && chip->data.has_low_soc_alert) { 485 ret = max17040_set_low_soc_alert(chip, chip->low_soc_alert); 486 if (ret) { 487 dev_err(&client->dev, 488 "Failed to set low SOC alert: err %d\n", ret); 489 return ret; 490 } 491 492 enable_irq = true; 493 } 494 495 if (client->irq && chip->data.has_soc_alert) { 496 ret = max17040_set_soc_alert(chip, 1); 497 if (ret) { 498 dev_err(&client->dev, 499 "Failed to set SOC alert: err %d\n", ret); 500 return ret; 501 } 502 enable_irq = true; 503 } else { 504 /* soc alerts negate the need for polling */ 505 INIT_DEFERRABLE_WORK(&chip->work, max17040_work); 506 ret = devm_add_action(&client->dev, max17040_stop_work, chip); 507 if (ret) 508 return ret; 509 max17040_queue_work(chip); 510 } 511 512 if (enable_irq) { 513 ret = max17040_enable_alert_irq(chip); 514 if (ret) { 515 client->irq = 0; 516 dev_warn(&client->dev, 517 "Failed to get IRQ err %d\n", ret); 518 } 519 } 520 521 return 0; 522} 523 524#ifdef CONFIG_PM_SLEEP 525 526static int max17040_suspend(struct device *dev) 527{ 528 struct i2c_client *client = to_i2c_client(dev); 529 struct max17040_chip *chip = i2c_get_clientdata(client); 530 531 if (client->irq && chip->data.has_soc_alert) 532 // disable soc alert to prevent wakeup 533 max17040_set_soc_alert(chip, 0); 534 else 535 cancel_delayed_work(&chip->work); 536 537 if (client->irq && device_may_wakeup(dev)) 538 enable_irq_wake(client->irq); 539 540 return 0; 541} 542 543static int max17040_resume(struct device *dev) 544{ 545 struct i2c_client *client = to_i2c_client(dev); 546 struct max17040_chip *chip = i2c_get_clientdata(client); 547 548 if (client->irq && device_may_wakeup(dev)) 549 disable_irq_wake(client->irq); 550 551 if (client->irq && chip->data.has_soc_alert) 552 max17040_set_soc_alert(chip, 1); 553 else 554 max17040_queue_work(chip); 555 556 return 0; 557} 558 559static SIMPLE_DEV_PM_OPS(max17040_pm_ops, max17040_suspend, max17040_resume); 560#define MAX17040_PM_OPS (&max17040_pm_ops) 561 562#else 563 564#define MAX17040_PM_OPS NULL 565 566#endif /* CONFIG_PM_SLEEP */ 567 568static const struct i2c_device_id max17040_id[] = { 569 { "max17040", ID_MAX17040 }, 570 { "max17041", ID_MAX17041 }, 571 { "max17043", ID_MAX17043 }, 572 { "max77836-battery", ID_MAX17043 }, 573 { "max17044", ID_MAX17044 }, 574 { "max17048", ID_MAX17048 }, 575 { "max17049", ID_MAX17049 }, 576 { "max17058", ID_MAX17058 }, 577 { "max17059", ID_MAX17059 }, 578 { /* sentinel */ } 579}; 580MODULE_DEVICE_TABLE(i2c, max17040_id); 581 582static const struct of_device_id max17040_of_match[] = { 583 { .compatible = "maxim,max17040", .data = (void *) ID_MAX17040 }, 584 { .compatible = "maxim,max17041", .data = (void *) ID_MAX17041 }, 585 { .compatible = "maxim,max17043", .data = (void *) ID_MAX17043 }, 586 { .compatible = "maxim,max77836-battery", .data = (void *) ID_MAX17043 }, 587 { .compatible = "maxim,max17044", .data = (void *) ID_MAX17044 }, 588 { .compatible = "maxim,max17048", .data = (void *) ID_MAX17048 }, 589 { .compatible = "maxim,max17049", .data = (void *) ID_MAX17049 }, 590 { .compatible = "maxim,max17058", .data = (void *) ID_MAX17058 }, 591 { .compatible = "maxim,max17059", .data = (void *) ID_MAX17059 }, 592 { /* sentinel */ }, 593}; 594MODULE_DEVICE_TABLE(of, max17040_of_match); 595 596static struct i2c_driver max17040_i2c_driver = { 597 .driver = { 598 .name = "max17040", 599 .of_match_table = max17040_of_match, 600 .pm = MAX17040_PM_OPS, 601 }, 602 .probe = max17040_probe, 603 .id_table = max17040_id, 604}; 605module_i2c_driver(max17040_i2c_driver); 606 607MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>"); 608MODULE_DESCRIPTION("MAX17040 Fuel Gauge"); 609MODULE_LICENSE("GPL");