.. | .. |
---|
1 | | -/* |
---|
2 | | - * Fuel gauge driver for Maxim 17042 / 8966 / 8997 |
---|
3 | | - * Note that Maxim 8966 and 8997 are mfd and this is its subdevice. |
---|
4 | | - * |
---|
5 | | - * Copyright (C) 2011 Samsung Electronics |
---|
6 | | - * MyungJoo Ham <myungjoo.ham@samsung.com> |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify |
---|
9 | | - * it under the terms of the GNU General Public License as published by |
---|
10 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
11 | | - * (at your option) any later version. |
---|
12 | | - * |
---|
13 | | - * This program is distributed in the hope that it will be useful, |
---|
14 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
15 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
16 | | - * GNU General Public License for more details. |
---|
17 | | - * |
---|
18 | | - * You should have received a copy of the GNU General Public License |
---|
19 | | - * along with this program; if not, write to the Free Software |
---|
20 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
21 | | - * |
---|
22 | | - * This driver is based on max17040_battery.c |
---|
23 | | - */ |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0+ |
---|
| 2 | +// |
---|
| 3 | +// Fuel gauge driver for Maxim 17042 / 8966 / 8997 |
---|
| 4 | +// Note that Maxim 8966 and 8997 are mfd and this is its subdevice. |
---|
| 5 | +// |
---|
| 6 | +// Copyright (C) 2011 Samsung Electronics |
---|
| 7 | +// MyungJoo Ham <myungjoo.ham@samsung.com> |
---|
| 8 | +// |
---|
| 9 | +// This driver is based on max17040_battery.c |
---|
24 | 10 | |
---|
25 | 11 | #include <linux/acpi.h> |
---|
26 | 12 | #include <linux/init.h> |
---|
.. | .. |
---|
99 | 85 | POWER_SUPPLY_PROP_TEMP_MAX, |
---|
100 | 86 | POWER_SUPPLY_PROP_HEALTH, |
---|
101 | 87 | POWER_SUPPLY_PROP_SCOPE, |
---|
| 88 | + POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, |
---|
| 89 | + // these two have to be at the end on the list |
---|
102 | 90 | POWER_SUPPLY_PROP_CURRENT_NOW, |
---|
103 | 91 | POWER_SUPPLY_PROP_CURRENT_AVG, |
---|
104 | 92 | }; |
---|
.. | .. |
---|
296 | 284 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: |
---|
297 | 285 | if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042) |
---|
298 | 286 | ret = regmap_read(map, MAX17042_V_empty, &data); |
---|
| 287 | + else if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17055) |
---|
| 288 | + ret = regmap_read(map, MAX17055_V_empty, &data); |
---|
299 | 289 | else |
---|
300 | 290 | ret = regmap_read(map, MAX17047_V_empty, &data); |
---|
301 | 291 | if (ret < 0) |
---|
.. | .. |
---|
426 | 416 | return -EINVAL; |
---|
427 | 417 | } |
---|
428 | 418 | break; |
---|
| 419 | + case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: |
---|
| 420 | + ret = regmap_read(map, MAX17042_TTE, &data); |
---|
| 421 | + if (ret < 0) |
---|
| 422 | + return ret; |
---|
| 423 | + |
---|
| 424 | + val->intval = data * 5625 / 1000; |
---|
| 425 | + break; |
---|
429 | 426 | default: |
---|
430 | 427 | return -EINVAL; |
---|
431 | 428 | } |
---|
.. | .. |
---|
528 | 525 | regmap_write(map, reg, value); |
---|
529 | 526 | } |
---|
530 | 527 | |
---|
531 | | -static inline void max10742_unlock_model(struct max17042_chip *chip) |
---|
| 528 | +static inline void max17042_unlock_model(struct max17042_chip *chip) |
---|
532 | 529 | { |
---|
533 | 530 | struct regmap *map = chip->regmap; |
---|
534 | 531 | |
---|
.. | .. |
---|
536 | 533 | regmap_write(map, MAX17042_MLOCKReg2, MODEL_UNLOCK2); |
---|
537 | 534 | } |
---|
538 | 535 | |
---|
539 | | -static inline void max10742_lock_model(struct max17042_chip *chip) |
---|
| 536 | +static inline void max17042_lock_model(struct max17042_chip *chip) |
---|
540 | 537 | { |
---|
541 | 538 | struct regmap *map = chip->regmap; |
---|
542 | 539 | |
---|
.. | .. |
---|
594 | 591 | if (!temp_data) |
---|
595 | 592 | return -ENOMEM; |
---|
596 | 593 | |
---|
597 | | - max10742_unlock_model(chip); |
---|
| 594 | + max17042_unlock_model(chip); |
---|
598 | 595 | max17042_write_model_data(chip, MAX17042_MODELChrTbl, |
---|
599 | 596 | table_size); |
---|
600 | 597 | max17042_read_model_data(chip, MAX17042_MODELChrTbl, temp_data, |
---|
.. | .. |
---|
606 | 603 | temp_data, |
---|
607 | 604 | table_size); |
---|
608 | 605 | |
---|
609 | | - max10742_lock_model(chip); |
---|
| 606 | + max17042_lock_model(chip); |
---|
610 | 607 | kfree(temp_data); |
---|
611 | 608 | |
---|
612 | 609 | return ret; |
---|
.. | .. |
---|
644 | 641 | config->filter_cfg); |
---|
645 | 642 | regmap_write(map, MAX17042_RelaxCFG, config->relax_cfg); |
---|
646 | 643 | if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17047 || |
---|
647 | | - chip->chip_type == MAXIM_DEVICE_TYPE_MAX17050) |
---|
| 644 | + chip->chip_type == MAXIM_DEVICE_TYPE_MAX17050 || |
---|
| 645 | + chip->chip_type == MAXIM_DEVICE_TYPE_MAX17055) |
---|
648 | 646 | regmap_write(map, MAX17047_FullSOCThr, |
---|
649 | 647 | config->full_soc_thresh); |
---|
650 | 648 | } |
---|
.. | .. |
---|
775 | 773 | |
---|
776 | 774 | if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042) |
---|
777 | 775 | max17042_override_por(map, MAX17042_V_empty, config->vempty); |
---|
| 776 | + if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17055) |
---|
| 777 | + max17042_override_por(map, MAX17055_V_empty, config->vempty); |
---|
778 | 778 | else |
---|
779 | 779 | max17042_override_por(map, MAX17047_V_empty, config->vempty); |
---|
780 | 780 | max17042_override_por(map, MAX17042_TempNom, config->temp_nom); |
---|
.. | .. |
---|
782 | 782 | max17042_override_por(map, MAX17042_FCTC, config->fctc); |
---|
783 | 783 | max17042_override_por(map, MAX17042_RCOMP0, config->rcomp0); |
---|
784 | 784 | max17042_override_por(map, MAX17042_TempCo, config->tcompc0); |
---|
785 | | - if (chip->chip_type) { |
---|
| 785 | + if (chip->chip_type && |
---|
| 786 | + ((chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042) || |
---|
| 787 | + (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17047) || |
---|
| 788 | + (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17050))) { |
---|
786 | 789 | max17042_override_por(map, MAX17042_EmptyTempCo, |
---|
787 | 790 | config->empty_tempco); |
---|
788 | 791 | max17042_override_por(map, MAX17042_K_empty0, |
---|
.. | .. |
---|
872 | 875 | max17042_set_soc_threshold(chip, 1); |
---|
873 | 876 | } |
---|
874 | 877 | |
---|
| 878 | + /* we implicitly handle all alerts via power_supply_changed */ |
---|
| 879 | + regmap_clear_bits(chip->regmap, MAX17042_STATUS, |
---|
| 880 | + 0xFFFF & ~(STATUS_POR_BIT | STATUS_BST_BIT)); |
---|
| 881 | + |
---|
875 | 882 | power_supply_changed(chip->battery); |
---|
876 | 883 | return IRQ_HANDLED; |
---|
877 | 884 | } |
---|
.. | .. |
---|
951 | 958 | if (!pdata) |
---|
952 | 959 | return pdata; |
---|
953 | 960 | |
---|
954 | | - if (chip->chip_type != MAXIM_DEVICE_TYPE_MAX17042) { |
---|
| 961 | + if ((chip->chip_type == MAXIM_DEVICE_TYPE_MAX17047) || |
---|
| 962 | + (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17050)) { |
---|
955 | 963 | pdata->init_data = max17047_default_pdata_init_regs; |
---|
956 | 964 | pdata->num_init_data = |
---|
957 | 965 | ARRAY_SIZE(max17047_default_pdata_init_regs); |
---|
.. | .. |
---|
1017 | 1025 | .num_properties = ARRAY_SIZE(max17042_battery_props) - 2, |
---|
1018 | 1026 | }; |
---|
1019 | 1027 | |
---|
| 1028 | +static void max17042_stop_work(void *data) |
---|
| 1029 | +{ |
---|
| 1030 | + struct max17042_chip *chip = data; |
---|
| 1031 | + |
---|
| 1032 | + cancel_work_sync(&chip->work); |
---|
| 1033 | +} |
---|
| 1034 | + |
---|
1020 | 1035 | static int max17042_probe(struct i2c_client *client, |
---|
1021 | 1036 | const struct i2c_device_id *id) |
---|
1022 | 1037 | { |
---|
1023 | | - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
---|
| 1038 | + struct i2c_adapter *adapter = client->adapter; |
---|
1024 | 1039 | const struct power_supply_desc *max17042_desc = &max17042_psy_desc; |
---|
1025 | 1040 | struct power_supply_config psy_cfg = {}; |
---|
1026 | 1041 | const struct acpi_device_id *acpi_id = NULL; |
---|
.. | .. |
---|
1123 | 1138 | regmap_read(chip->regmap, MAX17042_STATUS, &val); |
---|
1124 | 1139 | if (val & STATUS_POR_BIT) { |
---|
1125 | 1140 | INIT_WORK(&chip->work, max17042_init_worker); |
---|
| 1141 | + ret = devm_add_action(&client->dev, max17042_stop_work, chip); |
---|
| 1142 | + if (ret) |
---|
| 1143 | + return ret; |
---|
1126 | 1144 | schedule_work(&chip->work); |
---|
1127 | 1145 | } else { |
---|
1128 | 1146 | chip->init_complete = 1; |
---|
.. | .. |
---|
1179 | 1197 | { .compatible = "maxim,max17042" }, |
---|
1180 | 1198 | { .compatible = "maxim,max17047" }, |
---|
1181 | 1199 | { .compatible = "maxim,max17050" }, |
---|
| 1200 | + { .compatible = "maxim,max17055" }, |
---|
1182 | 1201 | { }, |
---|
1183 | 1202 | }; |
---|
1184 | 1203 | MODULE_DEVICE_TABLE(of, max17042_dt_match); |
---|
.. | .. |
---|
1188 | 1207 | { "max17042", MAXIM_DEVICE_TYPE_MAX17042 }, |
---|
1189 | 1208 | { "max17047", MAXIM_DEVICE_TYPE_MAX17047 }, |
---|
1190 | 1209 | { "max17050", MAXIM_DEVICE_TYPE_MAX17050 }, |
---|
| 1210 | + { "max17055", MAXIM_DEVICE_TYPE_MAX17055 }, |
---|
1191 | 1211 | { } |
---|
1192 | 1212 | }; |
---|
1193 | 1213 | MODULE_DEVICE_TABLE(i2c, max17042_id); |
---|