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; |