diff options
| -rw-r--r-- | drivers/power/Kconfig | 5 | ||||
| -rw-r--r-- | drivers/power/max17042_battery.c | 69 | ||||
| -rw-r--r-- | include/linux/power/max17042_battery.h | 17 |
3 files changed, 78 insertions, 13 deletions
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index b711795c6664..e3a3b4956f08 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
| @@ -181,14 +181,15 @@ config BATTERY_MAX17040 | |||
| 181 | to operate with a single lithium cell | 181 | to operate with a single lithium cell |
| 182 | 182 | ||
| 183 | config BATTERY_MAX17042 | 183 | config BATTERY_MAX17042 |
| 184 | tristate "Maxim MAX17042/8997/8966 Fuel Gauge" | 184 | tristate "Maxim MAX17042/17047/17050/8997/8966 Fuel Gauge" |
| 185 | depends on I2C | 185 | depends on I2C |
| 186 | help | 186 | help |
| 187 | MAX17042 is fuel-gauge systems for lithium-ion (Li+) batteries | 187 | MAX17042 is fuel-gauge systems for lithium-ion (Li+) batteries |
| 188 | in handheld and portable equipment. The MAX17042 is configured | 188 | in handheld and portable equipment. The MAX17042 is configured |
| 189 | to operate with a single lithium cell. MAX8997 and MAX8966 are | 189 | to operate with a single lithium cell. MAX8997 and MAX8966 are |
| 190 | multi-function devices that include fuel gauages that are compatible | 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 | config BATTERY_Z2 | 194 | config BATTERY_Z2 |
| 194 | tristate "Z2 battery driver" | 195 | tristate "Z2 battery driver" |
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c index 8d28006322e9..140788b309f8 100644 --- a/drivers/power/max17042_battery.c +++ b/drivers/power/max17042_battery.c | |||
| @@ -62,9 +62,13 @@ | |||
| 62 | #define dP_ACC_100 0x1900 | 62 | #define dP_ACC_100 0x1900 |
| 63 | #define dP_ACC_200 0x3200 | 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 | struct max17042_chip { | 68 | struct max17042_chip { |
| 66 | struct i2c_client *client; | 69 | struct i2c_client *client; |
| 67 | struct power_supply battery; | 70 | struct power_supply battery; |
| 71 | enum max170xx_chip_type chip_type; | ||
| 68 | struct max17042_platform_data *pdata; | 72 | struct max17042_platform_data *pdata; |
| 69 | struct work_struct work; | 73 | struct work_struct work; |
| 70 | int init_complete; | 74 | int init_complete; |
| @@ -152,7 +156,10 @@ static int max17042_get_property(struct power_supply *psy, | |||
| 152 | val->intval *= 20000; /* Units of LSB = 20mV */ | 156 | val->intval *= 20000; /* Units of LSB = 20mV */ |
| 153 | break; | 157 | break; |
| 154 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: | 158 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: |
| 155 | ret = max17042_read_reg(chip->client, MAX17042_V_empty); | 159 | if (chip->chip_type == MAX17042) |
| 160 | ret = max17042_read_reg(chip->client, MAX17042_V_empty); | ||
| 161 | else | ||
| 162 | ret = max17042_read_reg(chip->client, MAX17047_V_empty); | ||
| 156 | if (ret < 0) | 163 | if (ret < 0) |
| 157 | return ret; | 164 | return ret; |
| 158 | 165 | ||
| @@ -389,6 +396,9 @@ static void max17042_write_config_regs(struct max17042_chip *chip) | |||
| 389 | max17042_write_reg(chip->client, MAX17042_FilterCFG, | 396 | max17042_write_reg(chip->client, MAX17042_FilterCFG, |
| 390 | config->filter_cfg); | 397 | config->filter_cfg); |
| 391 | max17042_write_reg(chip->client, MAX17042_RelaxCFG, config->relax_cfg); | 398 | max17042_write_reg(chip->client, MAX17042_RelaxCFG, config->relax_cfg); |
| 399 | if (chip->chip_type == MAX17047) | ||
| 400 | max17042_write_reg(chip->client, MAX17047_FullSOCThr, | ||
| 401 | config->full_soc_thresh); | ||
| 392 | } | 402 | } |
| 393 | 403 | ||
| 394 | static void max17042_write_custom_regs(struct max17042_chip *chip) | 404 | static void max17042_write_custom_regs(struct max17042_chip *chip) |
| @@ -399,12 +409,23 @@ static void max17042_write_custom_regs(struct max17042_chip *chip) | |||
| 399 | config->rcomp0); | 409 | config->rcomp0); |
| 400 | max17042_write_verify_reg(chip->client, MAX17042_TempCo, | 410 | max17042_write_verify_reg(chip->client, MAX17042_TempCo, |
| 401 | config->tcompc0); | 411 | config->tcompc0); |
| 402 | max17042_write_reg(chip->client, MAX17042_EmptyTempCo, | ||
| 403 | config->empty_tempco); | ||
| 404 | max17042_write_verify_reg(chip->client, MAX17042_K_empty0, | ||
| 405 | config->kempty0); | ||
| 406 | max17042_write_verify_reg(chip->client, MAX17042_ICHGTerm, | 412 | max17042_write_verify_reg(chip->client, MAX17042_ICHGTerm, |
| 407 | config->ichgt_term); | 413 | config->ichgt_term); |
| 414 | if (chip->chip_type == MAX17042) { | ||
| 415 | max17042_write_reg(chip->client, MAX17042_EmptyTempCo, | ||
| 416 | config->empty_tempco); | ||
| 417 | max17042_write_verify_reg(chip->client, MAX17042_K_empty0, | ||
| 418 | config->kempty0); | ||
| 419 | } else { | ||
| 420 | max17042_write_verify_reg(chip->client, MAX17047_QRTbl00, | ||
| 421 | config->qrtbl00); | ||
| 422 | max17042_write_verify_reg(chip->client, MAX17047_QRTbl10, | ||
| 423 | config->qrtbl10); | ||
| 424 | max17042_write_verify_reg(chip->client, MAX17047_QRTbl20, | ||
| 425 | config->qrtbl20); | ||
| 426 | max17042_write_verify_reg(chip->client, MAX17047_QRTbl30, | ||
| 427 | config->qrtbl30); | ||
| 428 | } | ||
| 408 | } | 429 | } |
| 409 | 430 | ||
| 410 | static void max17042_update_capacity_regs(struct max17042_chip *chip) | 431 | static void max17042_update_capacity_regs(struct max17042_chip *chip) |
| @@ -460,6 +481,8 @@ static void max17042_load_new_capacity_params(struct max17042_chip *chip) | |||
| 460 | config->design_cap); | 481 | config->design_cap); |
| 461 | max17042_write_verify_reg(chip->client, MAX17042_FullCAPNom, | 482 | max17042_write_verify_reg(chip->client, MAX17042_FullCAPNom, |
| 462 | config->fullcapnom); | 483 | config->fullcapnom); |
| 484 | /* Update SOC register with new SOC */ | ||
| 485 | max17042_write_reg(chip->client, MAX17042_RepSOC, vfSoc); | ||
| 463 | } | 486 | } |
| 464 | 487 | ||
| 465 | /* | 488 | /* |
| @@ -496,20 +519,28 @@ static inline void max17042_override_por_values(struct max17042_chip *chip) | |||
| 496 | 519 | ||
| 497 | max17042_override_por(client, MAX17042_FullCAP, config->fullcap); | 520 | max17042_override_por(client, MAX17042_FullCAP, config->fullcap); |
| 498 | max17042_override_por(client, MAX17042_FullCAPNom, config->fullcapnom); | 521 | max17042_override_por(client, MAX17042_FullCAPNom, config->fullcapnom); |
| 499 | max17042_override_por(client, MAX17042_SOC_empty, config->socempty); | 522 | if (chip->chip_type == MAX17042) |
| 523 | max17042_override_por(client, MAX17042_SOC_empty, | ||
| 524 | config->socempty); | ||
| 500 | max17042_override_por(client, MAX17042_LAvg_empty, config->lavg_empty); | 525 | max17042_override_por(client, MAX17042_LAvg_empty, config->lavg_empty); |
| 501 | max17042_override_por(client, MAX17042_dQacc, config->dqacc); | 526 | max17042_override_por(client, MAX17042_dQacc, config->dqacc); |
| 502 | max17042_override_por(client, MAX17042_dPacc, config->dpacc); | 527 | max17042_override_por(client, MAX17042_dPacc, config->dpacc); |
| 503 | 528 | ||
| 504 | max17042_override_por(client, MAX17042_V_empty, config->vempty); | 529 | if (chip->chip_type == MAX17042) |
| 530 | max17042_override_por(client, MAX17042_V_empty, config->vempty); | ||
| 531 | else | ||
| 532 | max17042_override_por(client, MAX17047_V_empty, config->vempty); | ||
| 505 | max17042_override_por(client, MAX17042_TempNom, config->temp_nom); | 533 | max17042_override_por(client, MAX17042_TempNom, config->temp_nom); |
| 506 | max17042_override_por(client, MAX17042_TempLim, config->temp_lim); | 534 | max17042_override_por(client, MAX17042_TempLim, config->temp_lim); |
| 507 | max17042_override_por(client, MAX17042_FCTC, config->fctc); | 535 | max17042_override_por(client, MAX17042_FCTC, config->fctc); |
| 508 | max17042_override_por(client, MAX17042_RCOMP0, config->rcomp0); | 536 | max17042_override_por(client, MAX17042_RCOMP0, config->rcomp0); |
| 509 | max17042_override_por(client, MAX17042_TempCo, config->tcompc0); | 537 | max17042_override_por(client, MAX17042_TempCo, config->tcompc0); |
| 510 | max17042_override_por(client, MAX17042_EmptyTempCo, | 538 | if (chip->chip_type) { |
| 511 | config->empty_tempco); | 539 | max17042_override_por(client, MAX17042_EmptyTempCo, |
| 512 | max17042_override_por(client, MAX17042_K_empty0, config->kempty0); | 540 | config->empty_tempco); |
| 541 | max17042_override_por(client, MAX17042_K_empty0, | ||
| 542 | config->kempty0); | ||
| 543 | } | ||
| 513 | } | 544 | } |
| 514 | 545 | ||
| 515 | static int max17042_init_chip(struct max17042_chip *chip) | 546 | static int max17042_init_chip(struct max17042_chip *chip) |
| @@ -666,7 +697,19 @@ static int __devinit max17042_probe(struct i2c_client *client, | |||
| 666 | 697 | ||
| 667 | i2c_set_clientdata(client, chip); | 698 | i2c_set_clientdata(client, chip); |
| 668 | 699 | ||
| 669 | chip->battery.name = "max17042_battery"; | 700 | ret = max17042_read_reg(chip->client, MAX17042_DevName); |
| 701 | if (ret == MAX17042_IC_VERSION) { | ||
| 702 | dev_dbg(&client->dev, "chip type max17042 detected\n"); | ||
| 703 | chip->chip_type = MAX17042; | ||
| 704 | } else if (ret == MAX17047_IC_VERSION) { | ||
| 705 | dev_dbg(&client->dev, "chip type max17047/50 detected\n"); | ||
| 706 | chip->chip_type = MAX17047; | ||
| 707 | } else { | ||
| 708 | dev_err(&client->dev, "device version mismatch: %x\n", ret); | ||
| 709 | return -EIO; | ||
| 710 | } | ||
| 711 | |||
| 712 | chip->battery.name = "max170xx_battery"; | ||
| 670 | chip->battery.type = POWER_SUPPLY_TYPE_BATTERY; | 713 | chip->battery.type = POWER_SUPPLY_TYPE_BATTERY; |
| 671 | chip->battery.get_property = max17042_get_property; | 714 | chip->battery.get_property = max17042_get_property; |
| 672 | chip->battery.properties = max17042_battery_props; | 715 | chip->battery.properties = max17042_battery_props; |
| @@ -778,6 +821,8 @@ static const struct dev_pm_ops max17042_pm_ops = { | |||
| 778 | #ifdef CONFIG_OF | 821 | #ifdef CONFIG_OF |
| 779 | static const struct of_device_id max17042_dt_match[] = { | 822 | static const struct of_device_id max17042_dt_match[] = { |
| 780 | { .compatible = "maxim,max17042" }, | 823 | { .compatible = "maxim,max17042" }, |
| 824 | { .compatible = "maxim,max17047" }, | ||
| 825 | { .compatible = "maxim,max17050" }, | ||
| 781 | { }, | 826 | { }, |
| 782 | }; | 827 | }; |
| 783 | MODULE_DEVICE_TABLE(of, max17042_dt_match); | 828 | MODULE_DEVICE_TABLE(of, max17042_dt_match); |
| @@ -785,6 +830,8 @@ MODULE_DEVICE_TABLE(of, max17042_dt_match); | |||
| 785 | 830 | ||
| 786 | static const struct i2c_device_id max17042_id[] = { | 831 | static const struct i2c_device_id max17042_id[] = { |
| 787 | { "max17042", 0 }, | 832 | { "max17042", 0 }, |
| 833 | { "max17047", 1 }, | ||
| 834 | { "max17050", 2 }, | ||
| 788 | { } | 835 | { } |
| 789 | }; | 836 | }; |
| 790 | MODULE_DEVICE_TABLE(i2c, max17042_id); | 837 | MODULE_DEVICE_TABLE(i2c, max17042_id); |
diff --git a/include/linux/power/max17042_battery.h b/include/linux/power/max17042_battery.h index e01b167e66f0..89dd84f47c6e 100644 --- a/include/linux/power/max17042_battery.h +++ b/include/linux/power/max17042_battery.h | |||
| @@ -116,6 +116,18 @@ enum max17042_register { | |||
| 116 | MAX17042_VFSOC = 0xFF, | 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 | * used for setting a register to a desired value | 132 | * used for setting a register to a desired value |
| 121 | * addr : address for a register | 133 | * addr : address for a register |
| @@ -144,6 +156,7 @@ struct max17042_config_data { | |||
| 144 | u16 shdntimer; /* 0x03F */ | 156 | u16 shdntimer; /* 0x03F */ |
| 145 | 157 | ||
| 146 | /* App data */ | 158 | /* App data */ |
| 159 | u16 full_soc_thresh; /* 0x13 */ | ||
| 147 | u16 design_cap; /* 0x18 */ | 160 | u16 design_cap; /* 0x18 */ |
| 148 | u16 ichgt_term; /* 0x1E */ | 161 | u16 ichgt_term; /* 0x1E */ |
| 149 | 162 | ||
| @@ -162,6 +175,10 @@ struct max17042_config_data { | |||
| 162 | u16 lavg_empty; /* 0x36 */ | 175 | u16 lavg_empty; /* 0x36 */ |
| 163 | u16 dqacc; /* 0x45 */ | 176 | u16 dqacc; /* 0x45 */ |
| 164 | u16 dpacc; /* 0x46 */ | 177 | u16 dpacc; /* 0x46 */ |
| 178 | u16 qrtbl00; /* 0x12 */ | ||
| 179 | u16 qrtbl10; /* 0x22 */ | ||
| 180 | u16 qrtbl20; /* 0x32 */ | ||
| 181 | u16 qrtbl30; /* 0x42 */ | ||
| 165 | 182 | ||
| 166 | /* Cell technology from power_supply.h */ | 183 | /* Cell technology from power_supply.h */ |
| 167 | u16 cell_technology; | 184 | u16 cell_technology; |
