Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

max17042_battery: Add support for max17047/50 chip

max17047 is improved version of max17042 chip. It has few HW bug
fixes with minor changes in register set.

max17050 is same as max17047 chip except its silicon packging. So from
driver's point of view there is no difference btw max1047 and max1050.

This patch adds the support to dynamically detect the chip type and
adds steps to initialize the max17047 chip.

Signed-off-by: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>

authored by

Ramakrishna Pallala and committed by
Anton Vorontsov
9a8422d2 b1f092f6

+78 -13
+3 -2
drivers/power/Kconfig
··· 181 181 to operate with a single lithium cell 182 182 183 183 config BATTERY_MAX17042 184 - tristate "Maxim MAX17042/8997/8966 Fuel Gauge" 184 + tristate "Maxim MAX17042/17047/17050/8997/8966 Fuel Gauge" 185 185 depends on I2C 186 186 help 187 187 MAX17042 is fuel-gauge systems for lithium-ion (Li+) batteries 188 188 in handheld and portable equipment. The MAX17042 is configured 189 189 to operate with a single lithium cell. MAX8997 and MAX8966 are 190 190 multi-function devices that include fuel gauages that are compatible 191 - with MAX17042. 191 + with MAX17042. This driver also supports max17047/50 chips which are 192 + improved version of max17042. 192 193 193 194 config BATTERY_Z2 194 195 tristate "Z2 battery driver"
+58 -11
drivers/power/max17042_battery.c
··· 62 62 #define dP_ACC_100 0x1900 63 63 #define dP_ACC_200 0x3200 64 64 65 + #define MAX17042_IC_VERSION 0x0092 66 + #define MAX17047_IC_VERSION 0x00AC /* same for max17050 */ 67 + 65 68 struct max17042_chip { 66 69 struct i2c_client *client; 67 70 struct power_supply battery; 71 + enum max170xx_chip_type chip_type; 68 72 struct max17042_platform_data *pdata; 69 73 struct work_struct work; 70 74 int init_complete; ··· 156 152 val->intval *= 20000; /* Units of LSB = 20mV */ 157 153 break; 158 154 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 159 - ret = max17042_read_reg(chip->client, MAX17042_V_empty); 155 + if (chip->chip_type == MAX17042) 156 + ret = max17042_read_reg(chip->client, MAX17042_V_empty); 157 + else 158 + ret = max17042_read_reg(chip->client, MAX17047_V_empty); 160 159 if (ret < 0) 161 160 return ret; 162 161 ··· 396 389 max17042_write_reg(chip->client, MAX17042_FilterCFG, 397 390 config->filter_cfg); 398 391 max17042_write_reg(chip->client, MAX17042_RelaxCFG, config->relax_cfg); 392 + if (chip->chip_type == MAX17047) 393 + max17042_write_reg(chip->client, MAX17047_FullSOCThr, 394 + config->full_soc_thresh); 399 395 } 400 396 401 397 static void max17042_write_custom_regs(struct max17042_chip *chip) ··· 409 399 config->rcomp0); 410 400 max17042_write_verify_reg(chip->client, MAX17042_TempCo, 411 401 config->tcompc0); 412 - max17042_write_reg(chip->client, MAX17042_EmptyTempCo, 413 - config->empty_tempco); 414 - max17042_write_verify_reg(chip->client, MAX17042_K_empty0, 415 - config->kempty0); 416 402 max17042_write_verify_reg(chip->client, MAX17042_ICHGTerm, 417 403 config->ichgt_term); 404 + if (chip->chip_type == MAX17042) { 405 + max17042_write_reg(chip->client, MAX17042_EmptyTempCo, 406 + config->empty_tempco); 407 + max17042_write_verify_reg(chip->client, MAX17042_K_empty0, 408 + config->kempty0); 409 + } else { 410 + max17042_write_verify_reg(chip->client, MAX17047_QRTbl00, 411 + config->qrtbl00); 412 + max17042_write_verify_reg(chip->client, MAX17047_QRTbl10, 413 + config->qrtbl10); 414 + max17042_write_verify_reg(chip->client, MAX17047_QRTbl20, 415 + config->qrtbl20); 416 + max17042_write_verify_reg(chip->client, MAX17047_QRTbl30, 417 + config->qrtbl30); 418 + } 418 419 } 419 420 420 421 static void max17042_update_capacity_regs(struct max17042_chip *chip) ··· 481 460 config->design_cap); 482 461 max17042_write_verify_reg(chip->client, MAX17042_FullCAPNom, 483 462 config->fullcapnom); 463 + /* Update SOC register with new SOC */ 464 + max17042_write_reg(chip->client, MAX17042_RepSOC, vfSoc); 484 465 } 485 466 486 467 /* ··· 519 496 520 497 max17042_override_por(client, MAX17042_FullCAP, config->fullcap); 521 498 max17042_override_por(client, MAX17042_FullCAPNom, config->fullcapnom); 522 - max17042_override_por(client, MAX17042_SOC_empty, config->socempty); 499 + if (chip->chip_type == MAX17042) 500 + max17042_override_por(client, MAX17042_SOC_empty, 501 + config->socempty); 523 502 max17042_override_por(client, MAX17042_LAvg_empty, config->lavg_empty); 524 503 max17042_override_por(client, MAX17042_dQacc, config->dqacc); 525 504 max17042_override_por(client, MAX17042_dPacc, config->dpacc); 526 505 527 - max17042_override_por(client, MAX17042_V_empty, config->vempty); 506 + if (chip->chip_type == MAX17042) 507 + max17042_override_por(client, MAX17042_V_empty, config->vempty); 508 + else 509 + max17042_override_por(client, MAX17047_V_empty, config->vempty); 528 510 max17042_override_por(client, MAX17042_TempNom, config->temp_nom); 529 511 max17042_override_por(client, MAX17042_TempLim, config->temp_lim); 530 512 max17042_override_por(client, MAX17042_FCTC, config->fctc); 531 513 max17042_override_por(client, MAX17042_RCOMP0, config->rcomp0); 532 514 max17042_override_por(client, MAX17042_TempCo, config->tcompc0); 533 - max17042_override_por(client, MAX17042_EmptyTempCo, 534 - config->empty_tempco); 535 - max17042_override_por(client, MAX17042_K_empty0, config->kempty0); 515 + if (chip->chip_type) { 516 + max17042_override_por(client, MAX17042_EmptyTempCo, 517 + config->empty_tempco); 518 + max17042_override_por(client, MAX17042_K_empty0, 519 + config->kempty0); 520 + } 536 521 } 537 522 538 523 static int max17042_init_chip(struct max17042_chip *chip) ··· 697 666 698 667 i2c_set_clientdata(client, chip); 699 668 700 - chip->battery.name = "max17042_battery"; 669 + ret = max17042_read_reg(chip->client, MAX17042_DevName); 670 + if (ret == MAX17042_IC_VERSION) { 671 + dev_dbg(&client->dev, "chip type max17042 detected\n"); 672 + chip->chip_type = MAX17042; 673 + } else if (ret == MAX17047_IC_VERSION) { 674 + dev_dbg(&client->dev, "chip type max17047/50 detected\n"); 675 + chip->chip_type = MAX17047; 676 + } else { 677 + dev_err(&client->dev, "device version mismatch: %x\n", ret); 678 + return -EIO; 679 + } 680 + 681 + chip->battery.name = "max170xx_battery"; 701 682 chip->battery.type = POWER_SUPPLY_TYPE_BATTERY; 702 683 chip->battery.get_property = max17042_get_property; 703 684 chip->battery.properties = max17042_battery_props; ··· 821 778 #ifdef CONFIG_OF 822 779 static const struct of_device_id max17042_dt_match[] = { 823 780 { .compatible = "maxim,max17042" }, 781 + { .compatible = "maxim,max17047" }, 782 + { .compatible = "maxim,max17050" }, 824 783 { }, 825 784 }; 826 785 MODULE_DEVICE_TABLE(of, max17042_dt_match); ··· 830 785 831 786 static const struct i2c_device_id max17042_id[] = { 832 787 { "max17042", 0 }, 788 + { "max17047", 1 }, 789 + { "max17050", 2 }, 833 790 { } 834 791 }; 835 792 MODULE_DEVICE_TABLE(i2c, max17042_id);
+17
include/linux/power/max17042_battery.h
··· 116 116 MAX17042_VFSOC = 0xFF, 117 117 }; 118 118 119 + /* Registers specific to max17047/50 */ 120 + enum max17047_register { 121 + MAX17047_QRTbl00 = 0x12, 122 + MAX17047_FullSOCThr = 0x13, 123 + MAX17047_QRTbl10 = 0x22, 124 + MAX17047_QRTbl20 = 0x32, 125 + MAX17047_V_empty = 0x3A, 126 + MAX17047_QRTbl30 = 0x42, 127 + }; 128 + 129 + enum max170xx_chip_type {MAX17042, MAX17047}; 130 + 119 131 /* 120 132 * used for setting a register to a desired value 121 133 * addr : address for a register ··· 156 144 u16 shdntimer; /* 0x03F */ 157 145 158 146 /* App data */ 147 + u16 full_soc_thresh; /* 0x13 */ 159 148 u16 design_cap; /* 0x18 */ 160 149 u16 ichgt_term; /* 0x1E */ 161 150 ··· 175 162 u16 lavg_empty; /* 0x36 */ 176 163 u16 dqacc; /* 0x45 */ 177 164 u16 dpacc; /* 0x46 */ 165 + u16 qrtbl00; /* 0x12 */ 166 + u16 qrtbl10; /* 0x22 */ 167 + u16 qrtbl20; /* 0x32 */ 168 + u16 qrtbl30; /* 0x42 */ 178 169 179 170 /* Cell technology from power_supply.h */ 180 171 u16 cell_technology;