1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * axp288_fuel_gauge.c - Xpower AXP288 PMIC Fuel Gauge Driver 4 * 5 * Copyright (C) 2020-2021 Andrejus Basovas <xxx@yyy.tld> 6 * Copyright (C) 2016-2021 Hans de Goede <hdegoede@redhat.com> 7 * Copyright (C) 2014 Intel Corporation 8 * 9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10 */ 11 12 #include <linux/acpi.h> 13 #include <linux/dmi.h> 14 #include <linux/module.h> 15 #include <linux/kernel.h> 16 #include <linux/device.h> 17 #include <linux/regmap.h> 18 #include <linux/jiffies.h> 19 #include <linux/interrupt.h> 20 #include <linux/mfd/axp20x.h> 21 #include <linux/platform_device.h> 22 #include <linux/power_supply.h> 23 #include <linux/iio/consumer.h> 24 #include <asm/unaligned.h> 25 #include <asm/iosf_mbi.h> 26 27 #define PS_STAT_VBUS_TRIGGER (1 << 0) 28 #define PS_STAT_BAT_CHRG_DIR (1 << 2) 29 #define PS_STAT_VBAT_ABOVE_VHOLD (1 << 3) 30 #define PS_STAT_VBUS_VALID (1 << 4) 31 #define PS_STAT_VBUS_PRESENT (1 << 5) 32 33 #define CHRG_STAT_BAT_SAFE_MODE (1 << 3) 34 #define CHRG_STAT_BAT_VALID (1 << 4) 35 #define CHRG_STAT_BAT_PRESENT (1 << 5) 36 #define CHRG_STAT_CHARGING (1 << 6) 37 #define CHRG_STAT_PMIC_OTP (1 << 7) 38 39 #define CHRG_CCCV_CC_MASK 0xf /* 4 bits */ 40 #define CHRG_CCCV_CC_BIT_POS 0 41 #define CHRG_CCCV_CC_OFFSET 200 /* 200mA */ 42 #define CHRG_CCCV_CC_LSB_RES 200 /* 200mA */ 43 #define CHRG_CCCV_ITERM_20P (1 << 4) /* 20% of CC */ 44 #define CHRG_CCCV_CV_MASK 0x60 /* 2 bits */ 45 #define CHRG_CCCV_CV_BIT_POS 5 46 #define CHRG_CCCV_CV_4100MV 0x0 /* 4.10V */ 47 #define CHRG_CCCV_CV_4150MV 0x1 /* 4.15V */ 48 #define CHRG_CCCV_CV_4200MV 0x2 /* 4.20V */ 49 #define CHRG_CCCV_CV_4350MV 0x3 /* 4.35V */ 50 #define CHRG_CCCV_CHG_EN (1 << 7) 51 52 #define FG_CNTL_OCV_ADJ_STAT (1 << 2) 53 #define FG_CNTL_OCV_ADJ_EN (1 << 3) 54 #define FG_CNTL_CAP_ADJ_STAT (1 << 4) 55 #define FG_CNTL_CAP_ADJ_EN (1 << 5) 56 #define FG_CNTL_CC_EN (1 << 6) 57 #define FG_CNTL_GAUGE_EN (1 << 7) 58 59 #define FG_15BIT_WORD_VALID (1 << 15) 60 #define FG_15BIT_VAL_MASK 0x7fff 61 62 #define FG_REP_CAP_VALID (1 << 7) 63 #define FG_REP_CAP_VAL_MASK 0x7F 64 65 #define FG_DES_CAP1_VALID (1 << 7) 66 #define FG_DES_CAP_RES_LSB 1456 /* 1.456mAhr */ 67 68 #define FG_DES_CC_RES_LSB 1456 /* 1.456mAhr */ 69 70 #define FG_OCV_CAP_VALID (1 << 7) 71 #define FG_OCV_CAP_VAL_MASK 0x7F 72 #define FG_CC_CAP_VALID (1 << 7) 73 #define FG_CC_CAP_VAL_MASK 0x7F 74 75 #define FG_LOW_CAP_THR1_MASK 0xf0 /* 5% tp 20% */ 76 #define FG_LOW_CAP_THR1_VAL 0xa0 /* 15 perc */ 77 #define FG_LOW_CAP_THR2_MASK 0x0f /* 0% to 15% */ 78 #define FG_LOW_CAP_WARN_THR 14 /* 14 perc */ 79 #define FG_LOW_CAP_CRIT_THR 4 /* 4 perc */ 80 #define FG_LOW_CAP_SHDN_THR 0 /* 0 perc */ 81 82 #define DEV_NAME "axp288_fuel_gauge" 83 84 /* 1.1mV per LSB expressed in uV */ 85 #define VOLTAGE_FROM_ADC(a) ((a * 11) / 10) 86 /* properties converted to uV, uA */ 87 #define PROP_VOLT(a) ((a) * 1000) 88 #define PROP_CURR(a) ((a) * 1000) 89 90 #define AXP288_REG_UPDATE_INTERVAL (60 * HZ) 91 #define AXP288_FG_INTR_NUM 6 92 93 static bool no_current_sense_res; 94 module_param(no_current_sense_res, bool, 0444); 95 MODULE_PARM_DESC(no_current_sense_res, "No (or broken) current sense resistor"); 96 97 enum { 98 QWBTU_IRQ = 0, 99 WBTU_IRQ, 100 QWBTO_IRQ, 101 WBTO_IRQ, 102 WL2_IRQ, 103 WL1_IRQ, 104 }; 105 106 enum { 107 BAT_CHRG_CURR, 108 BAT_D_CURR, 109 BAT_VOLT, 110 IIO_CHANNEL_NUM 111 }; 112 113 struct axp288_fg_info { 114 struct device *dev; 115 struct regmap *regmap; 116 int irq[AXP288_FG_INTR_NUM]; 117 struct iio_channel *iio_channel[IIO_CHANNEL_NUM]; 118 struct power_supply *bat; 119 struct mutex lock; 120 int status; 121 int max_volt; 122 int pwr_op; 123 int low_cap; 124 struct dentry *debug_file; 125 126 char valid; /* zero until following fields are valid */ 127 unsigned long last_updated; /* in jiffies */ 128 129 int pwr_stat; 130 int fg_res; 131 int bat_volt; 132 int d_curr; 133 int c_curr; 134 int ocv; 135 int fg_cc_mtr1; 136 int fg_des_cap1; 137 }; 138 139 static enum power_supply_property fuel_gauge_props[] = { 140 POWER_SUPPLY_PROP_STATUS, 141 POWER_SUPPLY_PROP_PRESENT, 142 POWER_SUPPLY_PROP_HEALTH, 143 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 144 POWER_SUPPLY_PROP_VOLTAGE_NOW, 145 POWER_SUPPLY_PROP_VOLTAGE_OCV, 146 POWER_SUPPLY_PROP_CAPACITY, 147 POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN, 148 POWER_SUPPLY_PROP_TECHNOLOGY, 149 /* The 3 props below are not used when no_current_sense_res is set */ 150 POWER_SUPPLY_PROP_CHARGE_FULL, 151 POWER_SUPPLY_PROP_CHARGE_NOW, 152 POWER_SUPPLY_PROP_CURRENT_NOW, 153 }; 154 155 static int fuel_gauge_reg_readb(struct axp288_fg_info *info, int reg) 156 { 157 unsigned int val; 158 int ret; 159 160 ret = regmap_read(info->regmap, reg, &val); 161 if (ret < 0) { 162 dev_err(info->dev, "Error reading reg 0x%02x err: %d\n", reg, ret); 163 return ret; 164 } 165 166 return val; 167 } 168 169 static int fuel_gauge_reg_writeb(struct axp288_fg_info *info, int reg, u8 val) 170 { 171 int ret; 172 173 ret = regmap_write(info->regmap, reg, (unsigned int)val); 174 175 if (ret < 0) 176 dev_err(info->dev, "Error writing reg 0x%02x err: %d\n", reg, ret); 177 178 return ret; 179 } 180 181 static int fuel_gauge_read_15bit_word(struct axp288_fg_info *info, int reg) 182 { 183 unsigned char buf[2]; 184 int ret; 185 186 ret = regmap_bulk_read(info->regmap, reg, buf, 2); 187 if (ret < 0) { 188 dev_err(info->dev, "Error reading reg 0x%02x err: %d\n", reg, ret); 189 return ret; 190 } 191 192 ret = get_unaligned_be16(buf); 193 if (!(ret & FG_15BIT_WORD_VALID)) { 194 dev_err(info->dev, "Error reg 0x%02x contents not valid\n", reg); 195 return -ENXIO; 196 } 197 198 return ret & FG_15BIT_VAL_MASK; 199 } 200 201 static int fuel_gauge_read_12bit_word(struct axp288_fg_info *info, int reg) 202 { 203 unsigned char buf[2]; 204 int ret; 205 206 ret = regmap_bulk_read(info->regmap, reg, buf, 2); 207 if (ret < 0) { 208 dev_err(info->dev, "Error reading reg 0x%02x err: %d\n", reg, ret); 209 return ret; 210 } 211 212 /* 12-bit data values have upper 8 bits in buf[0], lower 4 in buf[1] */ 213 return (buf[0] << 4) | ((buf[1] >> 4) & 0x0f); 214 } 215 216 static int fuel_gauge_update_registers(struct axp288_fg_info *info) 217 { 218 int ret; 219 220 if (info->valid && time_before(jiffies, info->last_updated + AXP288_REG_UPDATE_INTERVAL)) 221 return 0; 222 223 dev_dbg(info->dev, "Fuel Gauge updating register values...\n"); 224 225 ret = iosf_mbi_block_punit_i2c_access(); 226 if (ret < 0) 227 return ret; 228 229 ret = fuel_gauge_reg_readb(info, AXP20X_PWR_INPUT_STATUS); 230 if (ret < 0) 231 goto out; 232 info->pwr_stat = ret; 233 234 if (no_current_sense_res) 235 ret = fuel_gauge_reg_readb(info, AXP288_FG_OCV_CAP_REG); 236 else 237 ret = fuel_gauge_reg_readb(info, AXP20X_FG_RES); 238 if (ret < 0) 239 goto out; 240 info->fg_res = ret; 241 242 ret = iio_read_channel_raw(info->iio_channel[BAT_VOLT], &info->bat_volt); 243 if (ret < 0) 244 goto out; 245 246 ret = fuel_gauge_read_12bit_word(info, AXP288_FG_OCVH_REG); 247 if (ret < 0) 248 goto out; 249 info->ocv = ret; 250 251 if (no_current_sense_res) 252 goto out_no_current_sense_res; 253 254 if (info->pwr_stat & PS_STAT_BAT_CHRG_DIR) { 255 info->d_curr = 0; 256 ret = iio_read_channel_raw(info->iio_channel[BAT_CHRG_CURR], &info->c_curr); 257 if (ret < 0) 258 goto out; 259 } else { 260 info->c_curr = 0; 261 ret = iio_read_channel_raw(info->iio_channel[BAT_D_CURR], &info->d_curr); 262 if (ret < 0) 263 goto out; 264 } 265 266 ret = fuel_gauge_read_15bit_word(info, AXP288_FG_CC_MTR1_REG); 267 if (ret < 0) 268 goto out; 269 info->fg_cc_mtr1 = ret; 270 271 ret = fuel_gauge_read_15bit_word(info, AXP288_FG_DES_CAP1_REG); 272 if (ret < 0) 273 goto out; 274 info->fg_des_cap1 = ret; 275 276 out_no_current_sense_res: 277 info->last_updated = jiffies; 278 info->valid = 1; 279 ret = 0; 280 out: 281 iosf_mbi_unblock_punit_i2c_access(); 282 return ret; 283 } 284 285 static void fuel_gauge_get_status(struct axp288_fg_info *info) 286 { 287 int pwr_stat = info->pwr_stat; 288 int fg_res = info->fg_res; 289 int curr = info->d_curr; 290 291 /* Report full if Vbus is valid and the reported capacity is 100% */ 292 if (!(pwr_stat & PS_STAT_VBUS_VALID)) 293 goto not_full; 294 295 if (!(fg_res & FG_REP_CAP_VALID)) 296 goto not_full; 297 298 fg_res &= ~FG_REP_CAP_VALID; 299 if (fg_res == 100) { 300 info->status = POWER_SUPPLY_STATUS_FULL; 301 return; 302 } 303 304 /* 305 * Sometimes the charger turns itself off before fg-res reaches 100%. 306 * When this happens the AXP288 reports a not-charging status and 307 * 0 mA discharge current. 308 */ 309 if (fg_res < 90 || (pwr_stat & PS_STAT_BAT_CHRG_DIR) || no_current_sense_res) 310 goto not_full; 311 312 if (curr == 0) { 313 info->status = POWER_SUPPLY_STATUS_FULL; 314 return; 315 } 316 317 not_full: 318 if (pwr_stat & PS_STAT_BAT_CHRG_DIR) 319 info->status = POWER_SUPPLY_STATUS_CHARGING; 320 else 321 info->status = POWER_SUPPLY_STATUS_DISCHARGING; 322 } 323 324 static int fuel_gauge_battery_health(struct axp288_fg_info *info) 325 { 326 int vocv = VOLTAGE_FROM_ADC(info->ocv); 327 int health = POWER_SUPPLY_HEALTH_UNKNOWN; 328 329 if (vocv > info->max_volt) 330 health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 331 else 332 health = POWER_SUPPLY_HEALTH_GOOD; 333 334 return health; 335 } 336 337 static int fuel_gauge_get_property(struct power_supply *ps, 338 enum power_supply_property prop, 339 union power_supply_propval *val) 340 { 341 struct axp288_fg_info *info = power_supply_get_drvdata(ps); 342 int ret, value; 343 344 mutex_lock(&info->lock); 345 346 ret = fuel_gauge_update_registers(info); 347 if (ret < 0) 348 goto out; 349 350 switch (prop) { 351 case POWER_SUPPLY_PROP_STATUS: 352 fuel_gauge_get_status(info); 353 val->intval = info->status; 354 break; 355 case POWER_SUPPLY_PROP_HEALTH: 356 val->intval = fuel_gauge_battery_health(info); 357 break; 358 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 359 value = VOLTAGE_FROM_ADC(info->bat_volt); 360 val->intval = PROP_VOLT(value); 361 break; 362 case POWER_SUPPLY_PROP_VOLTAGE_OCV: 363 value = VOLTAGE_FROM_ADC(info->ocv); 364 val->intval = PROP_VOLT(value); 365 break; 366 case POWER_SUPPLY_PROP_CURRENT_NOW: 367 if (info->d_curr > 0) 368 value = -1 * info->d_curr; 369 else 370 value = info->c_curr; 371 372 val->intval = PROP_CURR(value); 373 break; 374 case POWER_SUPPLY_PROP_PRESENT: 375 if (info->pwr_op & CHRG_STAT_BAT_PRESENT) 376 val->intval = 1; 377 else 378 val->intval = 0; 379 break; 380 case POWER_SUPPLY_PROP_CAPACITY: 381 if (!(info->fg_res & FG_REP_CAP_VALID)) 382 dev_err(info->dev, "capacity measurement not valid\n"); 383 val->intval = (info->fg_res & FG_REP_CAP_VAL_MASK); 384 break; 385 case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN: 386 val->intval = (info->low_cap & 0x0f); 387 break; 388 case POWER_SUPPLY_PROP_TECHNOLOGY: 389 val->intval = POWER_SUPPLY_TECHNOLOGY_LION; 390 break; 391 case POWER_SUPPLY_PROP_CHARGE_NOW: 392 val->intval = info->fg_cc_mtr1 * FG_DES_CAP_RES_LSB; 393 break; 394 case POWER_SUPPLY_PROP_CHARGE_FULL: 395 val->intval = info->fg_des_cap1 * FG_DES_CAP_RES_LSB; 396 break; 397 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 398 val->intval = PROP_VOLT(info->max_volt); 399 break; 400 default: 401 ret = -EINVAL; 402 } 403 404 out: 405 mutex_unlock(&info->lock); 406 return ret; 407 } 408 409 static int fuel_gauge_set_property(struct power_supply *ps, 410 enum power_supply_property prop, 411 const union power_supply_propval *val) 412 { 413 struct axp288_fg_info *info = power_supply_get_drvdata(ps); 414 int new_low_cap, ret = 0; 415 416 mutex_lock(&info->lock); 417 switch (prop) { 418 case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN: 419 if ((val->intval < 0) || (val->intval > 15)) { 420 ret = -EINVAL; 421 break; 422 } 423 new_low_cap = info->low_cap; 424 new_low_cap &= 0xf0; 425 new_low_cap |= (val->intval & 0xf); 426 ret = fuel_gauge_reg_writeb(info, AXP288_FG_LOW_CAP_REG, new_low_cap); 427 if (ret == 0) 428 info->low_cap = new_low_cap; 429 break; 430 default: 431 ret = -EINVAL; 432 break; 433 } 434 435 mutex_unlock(&info->lock); 436 return ret; 437 } 438 439 static int fuel_gauge_property_is_writeable(struct power_supply *psy, 440 enum power_supply_property psp) 441 { 442 int ret; 443 444 switch (psp) { 445 case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN: 446 ret = 1; 447 break; 448 default: 449 ret = 0; 450 } 451 452 return ret; 453 } 454 455 static irqreturn_t fuel_gauge_thread_handler(int irq, void *dev) 456 { 457 struct axp288_fg_info *info = dev; 458 int i; 459 460 for (i = 0; i < AXP288_FG_INTR_NUM; i++) { 461 if (info->irq[i] == irq) 462 break; 463 } 464 465 if (i >= AXP288_FG_INTR_NUM) { 466 dev_warn(info->dev, "spurious interrupt!!\n"); 467 return IRQ_NONE; 468 } 469 470 switch (i) { 471 case QWBTU_IRQ: 472 dev_info(info->dev, "Quit Battery under temperature in work mode IRQ (QWBTU)\n"); 473 break; 474 case WBTU_IRQ: 475 dev_info(info->dev, "Battery under temperature in work mode IRQ (WBTU)\n"); 476 break; 477 case QWBTO_IRQ: 478 dev_info(info->dev, "Quit Battery over temperature in work mode IRQ (QWBTO)\n"); 479 break; 480 case WBTO_IRQ: 481 dev_info(info->dev, "Battery over temperature in work mode IRQ (WBTO)\n"); 482 break; 483 case WL2_IRQ: 484 dev_info(info->dev, "Low Batt Warning(2) INTR\n"); 485 break; 486 case WL1_IRQ: 487 dev_info(info->dev, "Low Batt Warning(1) INTR\n"); 488 break; 489 default: 490 dev_warn(info->dev, "Spurious Interrupt!!!\n"); 491 } 492 493 mutex_lock(&info->lock); 494 info->valid = 0; /* Force updating of the cached registers */ 495 mutex_unlock(&info->lock); 496 497 power_supply_changed(info->bat); 498 return IRQ_HANDLED; 499 } 500 501 static void fuel_gauge_external_power_changed(struct power_supply *psy) 502 { 503 struct axp288_fg_info *info = power_supply_get_drvdata(psy); 504 505 mutex_lock(&info->lock); 506 info->valid = 0; /* Force updating of the cached registers */ 507 mutex_unlock(&info->lock); 508 power_supply_changed(info->bat); 509 } 510 511 static struct power_supply_desc fuel_gauge_desc = { 512 .name = DEV_NAME, 513 .type = POWER_SUPPLY_TYPE_BATTERY, 514 .properties = fuel_gauge_props, 515 .num_properties = ARRAY_SIZE(fuel_gauge_props), 516 .get_property = fuel_gauge_get_property, 517 .set_property = fuel_gauge_set_property, 518 .property_is_writeable = fuel_gauge_property_is_writeable, 519 .external_power_changed = fuel_gauge_external_power_changed, 520 }; 521 522 /* 523 * Some devices have no battery (HDMI sticks) and the axp288 battery's 524 * detection reports one despite it not being there. 525 * Please keep this listed sorted alphabetically. 526 */ 527 static const struct dmi_system_id axp288_no_battery_list[] = { 528 { 529 /* ACEPC T8 Cherry Trail Z8350 mini PC */ 530 .matches = { 531 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."), 532 DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), 533 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "T8"), 534 /* also match on somewhat unique bios-version */ 535 DMI_EXACT_MATCH(DMI_BIOS_VERSION, "1.000"), 536 }, 537 }, 538 { 539 /* ACEPC T11 Cherry Trail Z8350 mini PC */ 540 .matches = { 541 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."), 542 DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), 543 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "T11"), 544 /* also match on somewhat unique bios-version */ 545 DMI_EXACT_MATCH(DMI_BIOS_VERSION, "1.000"), 546 }, 547 }, 548 { 549 /* Intel Cherry Trail Compute Stick, Windows version */ 550 .matches = { 551 DMI_MATCH(DMI_SYS_VENDOR, "Intel"), 552 DMI_MATCH(DMI_PRODUCT_NAME, "STK1AW32SC"), 553 }, 554 }, 555 { 556 /* Intel Cherry Trail Compute Stick, version without an OS */ 557 .matches = { 558 DMI_MATCH(DMI_SYS_VENDOR, "Intel"), 559 DMI_MATCH(DMI_PRODUCT_NAME, "STK1A32SC"), 560 }, 561 }, 562 { 563 /* Meegopad T02 */ 564 .matches = { 565 DMI_MATCH(DMI_PRODUCT_NAME, "MEEGOPAD T02"), 566 }, 567 }, 568 { /* Mele PCG03 Mini PC */ 569 .matches = { 570 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Mini PC"), 571 DMI_EXACT_MATCH(DMI_BOARD_NAME, "Mini PC"), 572 }, 573 }, 574 { 575 /* Minix Neo Z83-4 mini PC */ 576 .matches = { 577 DMI_MATCH(DMI_SYS_VENDOR, "MINIX"), 578 DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"), 579 } 580 }, 581 { 582 /* Various Ace PC/Meegopad/MinisForum/Wintel Mini-PCs/HDMI-sticks */ 583 .matches = { 584 DMI_MATCH(DMI_BOARD_NAME, "T3 MRD"), 585 DMI_MATCH(DMI_CHASSIS_TYPE, "3"), 586 DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), 587 DMI_MATCH(DMI_BIOS_VERSION, "5.11"), 588 }, 589 }, 590 {} 591 }; 592 593 static int axp288_fuel_gauge_read_initial_regs(struct axp288_fg_info *info) 594 { 595 unsigned int val; 596 int ret; 597 598 /* 599 * On some devices the fuelgauge and charger parts of the axp288 are 600 * not used, check that the fuelgauge is enabled (CC_CTRL != 0). 601 */ 602 ret = regmap_read(info->regmap, AXP20X_CC_CTRL, &val); 603 if (ret < 0) 604 return ret; 605 if (val == 0) 606 return -ENODEV; 607 608 ret = fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP1_REG); 609 if (ret < 0) 610 return ret; 611 612 if (!(ret & FG_DES_CAP1_VALID)) { 613 dev_err(info->dev, "axp288 not configured by firmware\n"); 614 return -ENODEV; 615 } 616 617 ret = fuel_gauge_reg_readb(info, AXP20X_CHRG_CTRL1); 618 if (ret < 0) 619 return ret; 620 switch ((ret & CHRG_CCCV_CV_MASK) >> CHRG_CCCV_CV_BIT_POS) { 621 case CHRG_CCCV_CV_4100MV: 622 info->max_volt = 4100; 623 break; 624 case CHRG_CCCV_CV_4150MV: 625 info->max_volt = 4150; 626 break; 627 case CHRG_CCCV_CV_4200MV: 628 info->max_volt = 4200; 629 break; 630 case CHRG_CCCV_CV_4350MV: 631 info->max_volt = 4350; 632 break; 633 } 634 635 ret = fuel_gauge_reg_readb(info, AXP20X_PWR_OP_MODE); 636 if (ret < 0) 637 return ret; 638 info->pwr_op = ret; 639 640 ret = fuel_gauge_reg_readb(info, AXP288_FG_LOW_CAP_REG); 641 if (ret < 0) 642 return ret; 643 info->low_cap = ret; 644 645 return 0; 646 } 647 648 static void axp288_fuel_gauge_release_iio_chans(void *data) 649 { 650 struct axp288_fg_info *info = data; 651 int i; 652 653 for (i = 0; i < IIO_CHANNEL_NUM; i++) 654 if (!IS_ERR_OR_NULL(info->iio_channel[i])) 655 iio_channel_release(info->iio_channel[i]); 656 } 657 658 static int axp288_fuel_gauge_probe(struct platform_device *pdev) 659 { 660 struct axp288_fg_info *info; 661 struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); 662 struct power_supply_config psy_cfg = {}; 663 static const char * const iio_chan_name[] = { 664 [BAT_CHRG_CURR] = "axp288-chrg-curr", 665 [BAT_D_CURR] = "axp288-chrg-d-curr", 666 [BAT_VOLT] = "axp288-batt-volt", 667 }; 668 struct device *dev = &pdev->dev; 669 int i, pirq, ret; 670 671 /* 672 * Normally the native AXP288 fg/charger drivers are preferred but 673 * on some devices the ACPI drivers should be used instead. 674 */ 675 if (!acpi_quirk_skip_acpi_ac_and_battery()) 676 return -ENODEV; 677 678 if (dmi_check_system(axp288_no_battery_list)) 679 return -ENODEV; 680 681 info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); 682 if (!info) 683 return -ENOMEM; 684 685 info->dev = dev; 686 info->regmap = axp20x->regmap; 687 info->status = POWER_SUPPLY_STATUS_UNKNOWN; 688 info->valid = 0; 689 690 platform_set_drvdata(pdev, info); 691 692 mutex_init(&info->lock); 693 694 for (i = 0; i < AXP288_FG_INTR_NUM; i++) { 695 pirq = platform_get_irq(pdev, i); 696 ret = regmap_irq_get_virq(axp20x->regmap_irqc, pirq); 697 if (ret < 0) 698 return dev_err_probe(dev, ret, "getting vIRQ %d\n", pirq); 699 700 info->irq[i] = ret; 701 } 702 703 for (i = 0; i < IIO_CHANNEL_NUM; i++) { 704 /* 705 * Note cannot use devm_iio_channel_get because x86 systems 706 * lack the device<->channel maps which iio_channel_get will 707 * try to use when passed a non NULL device pointer. 708 */ 709 info->iio_channel[i] = 710 iio_channel_get(NULL, iio_chan_name[i]); 711 if (IS_ERR(info->iio_channel[i])) { 712 ret = PTR_ERR(info->iio_channel[i]); 713 dev_dbg(dev, "error getting iiochan %s: %d\n", iio_chan_name[i], ret); 714 /* Wait for axp288_adc to load */ 715 if (ret == -ENODEV) 716 ret = -EPROBE_DEFER; 717 718 axp288_fuel_gauge_release_iio_chans(info); 719 return ret; 720 } 721 } 722 723 ret = devm_add_action_or_reset(dev, axp288_fuel_gauge_release_iio_chans, info); 724 if (ret) 725 return ret; 726 727 ret = iosf_mbi_block_punit_i2c_access(); 728 if (ret < 0) 729 return ret; 730 731 ret = axp288_fuel_gauge_read_initial_regs(info); 732 iosf_mbi_unblock_punit_i2c_access(); 733 if (ret < 0) 734 return ret; 735 736 psy_cfg.drv_data = info; 737 if (no_current_sense_res) 738 fuel_gauge_desc.num_properties = ARRAY_SIZE(fuel_gauge_props) - 3; 739 info->bat = devm_power_supply_register(dev, &fuel_gauge_desc, &psy_cfg); 740 if (IS_ERR(info->bat)) { 741 ret = PTR_ERR(info->bat); 742 dev_err(dev, "failed to register battery: %d\n", ret); 743 return ret; 744 } 745 746 for (i = 0; i < AXP288_FG_INTR_NUM; i++) { 747 ret = devm_request_threaded_irq(dev, info->irq[i], NULL, 748 fuel_gauge_thread_handler, 749 IRQF_ONESHOT, DEV_NAME, info); 750 if (ret) 751 return dev_err_probe(dev, ret, "requesting IRQ %d\n", info->irq[i]); 752 } 753 754 return 0; 755 } 756 757 static const struct platform_device_id axp288_fg_id_table[] = { 758 { .name = DEV_NAME }, 759 {}, 760 }; 761 MODULE_DEVICE_TABLE(platform, axp288_fg_id_table); 762 763 static struct platform_driver axp288_fuel_gauge_driver = { 764 .probe = axp288_fuel_gauge_probe, 765 .id_table = axp288_fg_id_table, 766 .driver = { 767 .name = DEV_NAME, 768 }, 769 }; 770 771 module_platform_driver(axp288_fuel_gauge_driver); 772 773 MODULE_AUTHOR("Ramakrishna Pallala <ramakrishna.pallala@intel.com>"); 774 MODULE_AUTHOR("Todd Brandt <todd.e.brandt@linux.intel.com>"); 775 MODULE_DESCRIPTION("Xpower AXP288 Fuel Gauge Driver"); 776 MODULE_LICENSE("GPL"); 777