18c0984e5SSebastian Reichel /* 28c0984e5SSebastian Reichel * Fuel gauge driver for Maxim 17042 / 8966 / 8997 38c0984e5SSebastian Reichel * Note that Maxim 8966 and 8997 are mfd and this is its subdevice. 48c0984e5SSebastian Reichel * 58c0984e5SSebastian Reichel * Copyright (C) 2011 Samsung Electronics 68c0984e5SSebastian Reichel * MyungJoo Ham <myungjoo.ham@samsung.com> 78c0984e5SSebastian Reichel * 88c0984e5SSebastian Reichel * This program is free software; you can redistribute it and/or modify 98c0984e5SSebastian Reichel * it under the terms of the GNU General Public License as published by 108c0984e5SSebastian Reichel * the Free Software Foundation; either version 2 of the License, or 118c0984e5SSebastian Reichel * (at your option) any later version. 128c0984e5SSebastian Reichel * 138c0984e5SSebastian Reichel * This program is distributed in the hope that it will be useful, 148c0984e5SSebastian Reichel * but WITHOUT ANY WARRANTY; without even the implied warranty of 158c0984e5SSebastian Reichel * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 168c0984e5SSebastian Reichel * GNU General Public License for more details. 178c0984e5SSebastian Reichel * 188c0984e5SSebastian Reichel * You should have received a copy of the GNU General Public License 198c0984e5SSebastian Reichel * along with this program; if not, write to the Free Software 208c0984e5SSebastian Reichel * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 218c0984e5SSebastian Reichel * 228c0984e5SSebastian Reichel * This driver is based on max17040_battery.c 238c0984e5SSebastian Reichel */ 248c0984e5SSebastian Reichel 25*e2116202SHans de Goede #include <linux/acpi.h> 268c0984e5SSebastian Reichel #include <linux/init.h> 278c0984e5SSebastian Reichel #include <linux/module.h> 288c0984e5SSebastian Reichel #include <linux/slab.h> 298c0984e5SSebastian Reichel #include <linux/i2c.h> 308c0984e5SSebastian Reichel #include <linux/delay.h> 318c0984e5SSebastian Reichel #include <linux/interrupt.h> 328c0984e5SSebastian Reichel #include <linux/pm.h> 338c0984e5SSebastian Reichel #include <linux/mod_devicetable.h> 348c0984e5SSebastian Reichel #include <linux/power_supply.h> 358c0984e5SSebastian Reichel #include <linux/power/max17042_battery.h> 368c0984e5SSebastian Reichel #include <linux/of.h> 378c0984e5SSebastian Reichel #include <linux/regmap.h> 388c0984e5SSebastian Reichel 398c0984e5SSebastian Reichel /* Status register bits */ 408c0984e5SSebastian Reichel #define STATUS_POR_BIT (1 << 1) 418c0984e5SSebastian Reichel #define STATUS_BST_BIT (1 << 3) 428c0984e5SSebastian Reichel #define STATUS_VMN_BIT (1 << 8) 438c0984e5SSebastian Reichel #define STATUS_TMN_BIT (1 << 9) 448c0984e5SSebastian Reichel #define STATUS_SMN_BIT (1 << 10) 458c0984e5SSebastian Reichel #define STATUS_BI_BIT (1 << 11) 468c0984e5SSebastian Reichel #define STATUS_VMX_BIT (1 << 12) 478c0984e5SSebastian Reichel #define STATUS_TMX_BIT (1 << 13) 488c0984e5SSebastian Reichel #define STATUS_SMX_BIT (1 << 14) 498c0984e5SSebastian Reichel #define STATUS_BR_BIT (1 << 15) 508c0984e5SSebastian Reichel 518c0984e5SSebastian Reichel /* Interrupt mask bits */ 528c0984e5SSebastian Reichel #define CONFIG_ALRT_BIT_ENBL (1 << 2) 538c0984e5SSebastian Reichel #define STATUS_INTR_SOCMIN_BIT (1 << 10) 548c0984e5SSebastian Reichel #define STATUS_INTR_SOCMAX_BIT (1 << 14) 558c0984e5SSebastian Reichel 568c0984e5SSebastian Reichel #define VFSOC0_LOCK 0x0000 578c0984e5SSebastian Reichel #define VFSOC0_UNLOCK 0x0080 588c0984e5SSebastian Reichel #define MODEL_UNLOCK1 0X0059 598c0984e5SSebastian Reichel #define MODEL_UNLOCK2 0X00C4 608c0984e5SSebastian Reichel #define MODEL_LOCK1 0X0000 618c0984e5SSebastian Reichel #define MODEL_LOCK2 0X0000 628c0984e5SSebastian Reichel 638c0984e5SSebastian Reichel #define dQ_ACC_DIV 0x4 648c0984e5SSebastian Reichel #define dP_ACC_100 0x1900 658c0984e5SSebastian Reichel #define dP_ACC_200 0x3200 668c0984e5SSebastian Reichel 678c0984e5SSebastian Reichel #define MAX17042_VMAX_TOLERANCE 50 /* 50 mV */ 688c0984e5SSebastian Reichel 698c0984e5SSebastian Reichel struct max17042_chip { 708c0984e5SSebastian Reichel struct i2c_client *client; 718c0984e5SSebastian Reichel struct regmap *regmap; 728c0984e5SSebastian Reichel struct power_supply *battery; 738c0984e5SSebastian Reichel enum max170xx_chip_type chip_type; 748c0984e5SSebastian Reichel struct max17042_platform_data *pdata; 758c0984e5SSebastian Reichel struct work_struct work; 768c0984e5SSebastian Reichel int init_complete; 778c0984e5SSebastian Reichel }; 788c0984e5SSebastian Reichel 798c0984e5SSebastian Reichel static enum power_supply_property max17042_battery_props[] = { 80a9df22c0SHans de Goede POWER_SUPPLY_PROP_STATUS, 818c0984e5SSebastian Reichel POWER_SUPPLY_PROP_PRESENT, 82ef7fcdaeSHans de Goede POWER_SUPPLY_PROP_TECHNOLOGY, 838c0984e5SSebastian Reichel POWER_SUPPLY_PROP_CYCLE_COUNT, 848c0984e5SSebastian Reichel POWER_SUPPLY_PROP_VOLTAGE_MAX, 857bfc9397SHans de Goede POWER_SUPPLY_PROP_VOLTAGE_MIN, 868c0984e5SSebastian Reichel POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, 878c0984e5SSebastian Reichel POWER_SUPPLY_PROP_VOLTAGE_NOW, 888c0984e5SSebastian Reichel POWER_SUPPLY_PROP_VOLTAGE_AVG, 898c0984e5SSebastian Reichel POWER_SUPPLY_PROP_VOLTAGE_OCV, 908c0984e5SSebastian Reichel POWER_SUPPLY_PROP_CAPACITY, 912e015412SHans de Goede POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 928c0984e5SSebastian Reichel POWER_SUPPLY_PROP_CHARGE_FULL, 936d6b61eaSHans de Goede POWER_SUPPLY_PROP_CHARGE_NOW, 948c0984e5SSebastian Reichel POWER_SUPPLY_PROP_CHARGE_COUNTER, 958c0984e5SSebastian Reichel POWER_SUPPLY_PROP_TEMP, 968c0984e5SSebastian Reichel POWER_SUPPLY_PROP_TEMP_ALERT_MIN, 978c0984e5SSebastian Reichel POWER_SUPPLY_PROP_TEMP_ALERT_MAX, 988c0984e5SSebastian Reichel POWER_SUPPLY_PROP_TEMP_MIN, 998c0984e5SSebastian Reichel POWER_SUPPLY_PROP_TEMP_MAX, 1008c0984e5SSebastian Reichel POWER_SUPPLY_PROP_HEALTH, 101adb69a3cSHans de Goede POWER_SUPPLY_PROP_SCOPE, 1028c0984e5SSebastian Reichel POWER_SUPPLY_PROP_CURRENT_NOW, 1038c0984e5SSebastian Reichel POWER_SUPPLY_PROP_CURRENT_AVG, 1048c0984e5SSebastian Reichel }; 1058c0984e5SSebastian Reichel 1068c0984e5SSebastian Reichel static int max17042_get_temperature(struct max17042_chip *chip, int *temp) 1078c0984e5SSebastian Reichel { 1088c0984e5SSebastian Reichel int ret; 1098c0984e5SSebastian Reichel u32 data; 1108c0984e5SSebastian Reichel struct regmap *map = chip->regmap; 1118c0984e5SSebastian Reichel 1128c0984e5SSebastian Reichel ret = regmap_read(map, MAX17042_TEMP, &data); 1138c0984e5SSebastian Reichel if (ret < 0) 1148c0984e5SSebastian Reichel return ret; 1158c0984e5SSebastian Reichel 116c67c0693SHans de Goede *temp = sign_extend32(data, 15); 1178c0984e5SSebastian Reichel /* The value is converted into deci-centigrade scale */ 1188c0984e5SSebastian Reichel /* Units of LSB = 1 / 256 degree Celsius */ 1198c0984e5SSebastian Reichel *temp = *temp * 10 / 256; 1208c0984e5SSebastian Reichel return 0; 1218c0984e5SSebastian Reichel } 1228c0984e5SSebastian Reichel 123a9df22c0SHans de Goede static int max17042_get_status(struct max17042_chip *chip, int *status) 124a9df22c0SHans de Goede { 125a9df22c0SHans de Goede int ret, charge_full, charge_now; 126a9df22c0SHans de Goede 127a9df22c0SHans de Goede ret = power_supply_am_i_supplied(chip->battery); 128a9df22c0SHans de Goede if (ret < 0) { 129a9df22c0SHans de Goede *status = POWER_SUPPLY_STATUS_UNKNOWN; 130a9df22c0SHans de Goede return 0; 131a9df22c0SHans de Goede } 132a9df22c0SHans de Goede if (ret == 0) { 133a9df22c0SHans de Goede *status = POWER_SUPPLY_STATUS_DISCHARGING; 134a9df22c0SHans de Goede return 0; 135a9df22c0SHans de Goede } 136a9df22c0SHans de Goede 137a9df22c0SHans de Goede /* 138a9df22c0SHans de Goede * The MAX170xx has builtin end-of-charge detection and will update 139a9df22c0SHans de Goede * FullCAP to match RepCap when it detects end of charging. 140a9df22c0SHans de Goede * 141a9df22c0SHans de Goede * When this cycle the battery gets charged to a higher (calculated) 142a9df22c0SHans de Goede * capacity then the previous cycle then FullCAP will get updated 143a9df22c0SHans de Goede * contineously once end-of-charge detection kicks in, so allow the 144a9df22c0SHans de Goede * 2 to differ a bit. 145a9df22c0SHans de Goede */ 146a9df22c0SHans de Goede 147a9df22c0SHans de Goede ret = regmap_read(chip->regmap, MAX17042_FullCAP, &charge_full); 148a9df22c0SHans de Goede if (ret < 0) 149a9df22c0SHans de Goede return ret; 150a9df22c0SHans de Goede 151a9df22c0SHans de Goede ret = regmap_read(chip->regmap, MAX17042_RepCap, &charge_now); 152a9df22c0SHans de Goede if (ret < 0) 153a9df22c0SHans de Goede return ret; 154a9df22c0SHans de Goede 155a9df22c0SHans de Goede if ((charge_full - charge_now) <= MAX17042_FULL_THRESHOLD) 156a9df22c0SHans de Goede *status = POWER_SUPPLY_STATUS_FULL; 157a9df22c0SHans de Goede else 158a9df22c0SHans de Goede *status = POWER_SUPPLY_STATUS_CHARGING; 159a9df22c0SHans de Goede 160a9df22c0SHans de Goede return 0; 161a9df22c0SHans de Goede } 162a9df22c0SHans de Goede 1638c0984e5SSebastian Reichel static int max17042_get_battery_health(struct max17042_chip *chip, int *health) 1648c0984e5SSebastian Reichel { 1658c0984e5SSebastian Reichel int temp, vavg, vbatt, ret; 1668c0984e5SSebastian Reichel u32 val; 1678c0984e5SSebastian Reichel 1688c0984e5SSebastian Reichel ret = regmap_read(chip->regmap, MAX17042_AvgVCELL, &val); 1698c0984e5SSebastian Reichel if (ret < 0) 1708c0984e5SSebastian Reichel goto health_error; 1718c0984e5SSebastian Reichel 1728c0984e5SSebastian Reichel /* bits [0-3] unused */ 1738c0984e5SSebastian Reichel vavg = val * 625 / 8; 1748c0984e5SSebastian Reichel /* Convert to millivolts */ 1758c0984e5SSebastian Reichel vavg /= 1000; 1768c0984e5SSebastian Reichel 1778c0984e5SSebastian Reichel ret = regmap_read(chip->regmap, MAX17042_VCELL, &val); 1788c0984e5SSebastian Reichel if (ret < 0) 1798c0984e5SSebastian Reichel goto health_error; 1808c0984e5SSebastian Reichel 1818c0984e5SSebastian Reichel /* bits [0-3] unused */ 1828c0984e5SSebastian Reichel vbatt = val * 625 / 8; 1838c0984e5SSebastian Reichel /* Convert to millivolts */ 1848c0984e5SSebastian Reichel vbatt /= 1000; 1858c0984e5SSebastian Reichel 1868c0984e5SSebastian Reichel if (vavg < chip->pdata->vmin) { 1878c0984e5SSebastian Reichel *health = POWER_SUPPLY_HEALTH_DEAD; 1888c0984e5SSebastian Reichel goto out; 1898c0984e5SSebastian Reichel } 1908c0984e5SSebastian Reichel 1918c0984e5SSebastian Reichel if (vbatt > chip->pdata->vmax + MAX17042_VMAX_TOLERANCE) { 1928c0984e5SSebastian Reichel *health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 1938c0984e5SSebastian Reichel goto out; 1948c0984e5SSebastian Reichel } 1958c0984e5SSebastian Reichel 1968c0984e5SSebastian Reichel ret = max17042_get_temperature(chip, &temp); 1978c0984e5SSebastian Reichel if (ret < 0) 1988c0984e5SSebastian Reichel goto health_error; 1998c0984e5SSebastian Reichel 20091736213SHans de Goede if (temp < chip->pdata->temp_min) { 2018c0984e5SSebastian Reichel *health = POWER_SUPPLY_HEALTH_COLD; 2028c0984e5SSebastian Reichel goto out; 2038c0984e5SSebastian Reichel } 2048c0984e5SSebastian Reichel 20591736213SHans de Goede if (temp > chip->pdata->temp_max) { 2068c0984e5SSebastian Reichel *health = POWER_SUPPLY_HEALTH_OVERHEAT; 2078c0984e5SSebastian Reichel goto out; 2088c0984e5SSebastian Reichel } 2098c0984e5SSebastian Reichel 2108c0984e5SSebastian Reichel *health = POWER_SUPPLY_HEALTH_GOOD; 2118c0984e5SSebastian Reichel 2128c0984e5SSebastian Reichel out: 2138c0984e5SSebastian Reichel return 0; 2148c0984e5SSebastian Reichel 2158c0984e5SSebastian Reichel health_error: 2168c0984e5SSebastian Reichel return ret; 2178c0984e5SSebastian Reichel } 2188c0984e5SSebastian Reichel 2198c0984e5SSebastian Reichel static int max17042_get_property(struct power_supply *psy, 2208c0984e5SSebastian Reichel enum power_supply_property psp, 2218c0984e5SSebastian Reichel union power_supply_propval *val) 2228c0984e5SSebastian Reichel { 2238c0984e5SSebastian Reichel struct max17042_chip *chip = power_supply_get_drvdata(psy); 2248c0984e5SSebastian Reichel struct regmap *map = chip->regmap; 2258c0984e5SSebastian Reichel int ret; 2268c0984e5SSebastian Reichel u32 data; 227d7d15fc6SHans de Goede u64 data64; 2288c0984e5SSebastian Reichel 2298c0984e5SSebastian Reichel if (!chip->init_complete) 2308c0984e5SSebastian Reichel return -EAGAIN; 2318c0984e5SSebastian Reichel 2328c0984e5SSebastian Reichel switch (psp) { 233a9df22c0SHans de Goede case POWER_SUPPLY_PROP_STATUS: 234a9df22c0SHans de Goede ret = max17042_get_status(chip, &val->intval); 235a9df22c0SHans de Goede if (ret < 0) 236a9df22c0SHans de Goede return ret; 237a9df22c0SHans de Goede break; 2388c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_PRESENT: 2398c0984e5SSebastian Reichel ret = regmap_read(map, MAX17042_STATUS, &data); 2408c0984e5SSebastian Reichel if (ret < 0) 2418c0984e5SSebastian Reichel return ret; 2428c0984e5SSebastian Reichel 2438c0984e5SSebastian Reichel if (data & MAX17042_STATUS_BattAbsent) 2448c0984e5SSebastian Reichel val->intval = 0; 2458c0984e5SSebastian Reichel else 2468c0984e5SSebastian Reichel val->intval = 1; 2478c0984e5SSebastian Reichel break; 248ef7fcdaeSHans de Goede case POWER_SUPPLY_PROP_TECHNOLOGY: 249ef7fcdaeSHans de Goede val->intval = POWER_SUPPLY_TECHNOLOGY_LION; 250ef7fcdaeSHans de Goede break; 2518c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_CYCLE_COUNT: 2528c0984e5SSebastian Reichel ret = regmap_read(map, MAX17042_Cycles, &data); 2538c0984e5SSebastian Reichel if (ret < 0) 2548c0984e5SSebastian Reichel return ret; 2558c0984e5SSebastian Reichel 2568c0984e5SSebastian Reichel val->intval = data; 2578c0984e5SSebastian Reichel break; 2588c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_VOLTAGE_MAX: 2598c0984e5SSebastian Reichel ret = regmap_read(map, MAX17042_MinMaxVolt, &data); 2608c0984e5SSebastian Reichel if (ret < 0) 2618c0984e5SSebastian Reichel return ret; 2628c0984e5SSebastian Reichel 2638c0984e5SSebastian Reichel val->intval = data >> 8; 2648c0984e5SSebastian Reichel val->intval *= 20000; /* Units of LSB = 20mV */ 2658c0984e5SSebastian Reichel break; 2667bfc9397SHans de Goede case POWER_SUPPLY_PROP_VOLTAGE_MIN: 2677bfc9397SHans de Goede ret = regmap_read(map, MAX17042_MinMaxVolt, &data); 2687bfc9397SHans de Goede if (ret < 0) 2697bfc9397SHans de Goede return ret; 2707bfc9397SHans de Goede 2717bfc9397SHans de Goede val->intval = (data & 0xff) * 20000; /* Units of 20mV */ 2727bfc9397SHans de Goede break; 2738c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 2748c0984e5SSebastian Reichel if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042) 2758c0984e5SSebastian Reichel ret = regmap_read(map, MAX17042_V_empty, &data); 2768c0984e5SSebastian Reichel else 2778c0984e5SSebastian Reichel ret = regmap_read(map, MAX17047_V_empty, &data); 2788c0984e5SSebastian Reichel if (ret < 0) 2798c0984e5SSebastian Reichel return ret; 2808c0984e5SSebastian Reichel 2818c0984e5SSebastian Reichel val->intval = data >> 7; 2828c0984e5SSebastian Reichel val->intval *= 10000; /* Units of LSB = 10mV */ 2838c0984e5SSebastian Reichel break; 2848c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_VOLTAGE_NOW: 2858c0984e5SSebastian Reichel ret = regmap_read(map, MAX17042_VCELL, &data); 2868c0984e5SSebastian Reichel if (ret < 0) 2878c0984e5SSebastian Reichel return ret; 2888c0984e5SSebastian Reichel 2898c0984e5SSebastian Reichel val->intval = data * 625 / 8; 2908c0984e5SSebastian Reichel break; 2918c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_VOLTAGE_AVG: 2928c0984e5SSebastian Reichel ret = regmap_read(map, MAX17042_AvgVCELL, &data); 2938c0984e5SSebastian Reichel if (ret < 0) 2948c0984e5SSebastian Reichel return ret; 2958c0984e5SSebastian Reichel 2968c0984e5SSebastian Reichel val->intval = data * 625 / 8; 2978c0984e5SSebastian Reichel break; 2988c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_VOLTAGE_OCV: 2998c0984e5SSebastian Reichel ret = regmap_read(map, MAX17042_OCVInternal, &data); 3008c0984e5SSebastian Reichel if (ret < 0) 3018c0984e5SSebastian Reichel return ret; 3028c0984e5SSebastian Reichel 3038c0984e5SSebastian Reichel val->intval = data * 625 / 8; 3048c0984e5SSebastian Reichel break; 3058c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_CAPACITY: 3068c0984e5SSebastian Reichel ret = regmap_read(map, MAX17042_RepSOC, &data); 3078c0984e5SSebastian Reichel if (ret < 0) 3088c0984e5SSebastian Reichel return ret; 3098c0984e5SSebastian Reichel 3108c0984e5SSebastian Reichel val->intval = data >> 8; 3118c0984e5SSebastian Reichel break; 3122e015412SHans de Goede case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 3132e015412SHans de Goede ret = regmap_read(map, MAX17042_DesignCap, &data); 3142e015412SHans de Goede if (ret < 0) 3152e015412SHans de Goede return ret; 3162e015412SHans de Goede 3172e015412SHans de Goede data64 = data * 5000000ll; 3182e015412SHans de Goede do_div(data64, chip->pdata->r_sns); 3192e015412SHans de Goede val->intval = data64; 3202e015412SHans de Goede break; 3218c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_CHARGE_FULL: 3228c0984e5SSebastian Reichel ret = regmap_read(map, MAX17042_FullCAP, &data); 3238c0984e5SSebastian Reichel if (ret < 0) 3248c0984e5SSebastian Reichel return ret; 3258c0984e5SSebastian Reichel 326d7d15fc6SHans de Goede data64 = data * 5000000ll; 327d7d15fc6SHans de Goede do_div(data64, chip->pdata->r_sns); 328d7d15fc6SHans de Goede val->intval = data64; 3298c0984e5SSebastian Reichel break; 3306d6b61eaSHans de Goede case POWER_SUPPLY_PROP_CHARGE_NOW: 3316d6b61eaSHans de Goede ret = regmap_read(map, MAX17042_RepCap, &data); 3326d6b61eaSHans de Goede if (ret < 0) 3336d6b61eaSHans de Goede return ret; 3346d6b61eaSHans de Goede 3356d6b61eaSHans de Goede data64 = data * 5000000ll; 3366d6b61eaSHans de Goede do_div(data64, chip->pdata->r_sns); 3376d6b61eaSHans de Goede val->intval = data64; 3386d6b61eaSHans de Goede break; 3398c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_CHARGE_COUNTER: 3408c0984e5SSebastian Reichel ret = regmap_read(map, MAX17042_QH, &data); 3418c0984e5SSebastian Reichel if (ret < 0) 3428c0984e5SSebastian Reichel return ret; 3438c0984e5SSebastian Reichel 3448c0984e5SSebastian Reichel val->intval = data * 1000 / 2; 3458c0984e5SSebastian Reichel break; 3468c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_TEMP: 3478c0984e5SSebastian Reichel ret = max17042_get_temperature(chip, &val->intval); 3488c0984e5SSebastian Reichel if (ret < 0) 3498c0984e5SSebastian Reichel return ret; 3508c0984e5SSebastian Reichel break; 3518c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_TEMP_ALERT_MIN: 3528c0984e5SSebastian Reichel ret = regmap_read(map, MAX17042_TALRT_Th, &data); 3538c0984e5SSebastian Reichel if (ret < 0) 3548c0984e5SSebastian Reichel return ret; 3558c0984e5SSebastian Reichel /* LSB is Alert Minimum. In deci-centigrade */ 3562814913cSHans de Goede val->intval = sign_extend32(data & 0xff, 7) * 10; 3578c0984e5SSebastian Reichel break; 3588c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_TEMP_ALERT_MAX: 3598c0984e5SSebastian Reichel ret = regmap_read(map, MAX17042_TALRT_Th, &data); 3608c0984e5SSebastian Reichel if (ret < 0) 3618c0984e5SSebastian Reichel return ret; 3628c0984e5SSebastian Reichel /* MSB is Alert Maximum. In deci-centigrade */ 3632814913cSHans de Goede val->intval = sign_extend32(data >> 8, 7) * 10; 3648c0984e5SSebastian Reichel break; 3658c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_TEMP_MIN: 3668c0984e5SSebastian Reichel val->intval = chip->pdata->temp_min; 3678c0984e5SSebastian Reichel break; 3688c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_TEMP_MAX: 3698c0984e5SSebastian Reichel val->intval = chip->pdata->temp_max; 3708c0984e5SSebastian Reichel break; 3718c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_HEALTH: 3728c0984e5SSebastian Reichel ret = max17042_get_battery_health(chip, &val->intval); 3738c0984e5SSebastian Reichel if (ret < 0) 3748c0984e5SSebastian Reichel return ret; 3758c0984e5SSebastian Reichel break; 376adb69a3cSHans de Goede case POWER_SUPPLY_PROP_SCOPE: 377adb69a3cSHans de Goede val->intval = POWER_SUPPLY_SCOPE_SYSTEM; 378adb69a3cSHans de Goede break; 3798c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_CURRENT_NOW: 3808c0984e5SSebastian Reichel if (chip->pdata->enable_current_sense) { 3818c0984e5SSebastian Reichel ret = regmap_read(map, MAX17042_Current, &data); 3828c0984e5SSebastian Reichel if (ret < 0) 3838c0984e5SSebastian Reichel return ret; 3848c0984e5SSebastian Reichel 385c67c0693SHans de Goede val->intval = sign_extend32(data, 15); 3868c0984e5SSebastian Reichel val->intval *= 1562500 / chip->pdata->r_sns; 3878c0984e5SSebastian Reichel } else { 3888c0984e5SSebastian Reichel return -EINVAL; 3898c0984e5SSebastian Reichel } 3908c0984e5SSebastian Reichel break; 3918c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_CURRENT_AVG: 3928c0984e5SSebastian Reichel if (chip->pdata->enable_current_sense) { 3938c0984e5SSebastian Reichel ret = regmap_read(map, MAX17042_AvgCurrent, &data); 3948c0984e5SSebastian Reichel if (ret < 0) 3958c0984e5SSebastian Reichel return ret; 3968c0984e5SSebastian Reichel 397c67c0693SHans de Goede val->intval = sign_extend32(data, 15); 3988c0984e5SSebastian Reichel val->intval *= 1562500 / chip->pdata->r_sns; 3998c0984e5SSebastian Reichel } else { 4008c0984e5SSebastian Reichel return -EINVAL; 4018c0984e5SSebastian Reichel } 4028c0984e5SSebastian Reichel break; 4038c0984e5SSebastian Reichel default: 4048c0984e5SSebastian Reichel return -EINVAL; 4058c0984e5SSebastian Reichel } 4068c0984e5SSebastian Reichel return 0; 4078c0984e5SSebastian Reichel } 4088c0984e5SSebastian Reichel 4098c0984e5SSebastian Reichel static int max17042_set_property(struct power_supply *psy, 4108c0984e5SSebastian Reichel enum power_supply_property psp, 4118c0984e5SSebastian Reichel const union power_supply_propval *val) 4128c0984e5SSebastian Reichel { 4138c0984e5SSebastian Reichel struct max17042_chip *chip = power_supply_get_drvdata(psy); 4148c0984e5SSebastian Reichel struct regmap *map = chip->regmap; 4158c0984e5SSebastian Reichel int ret = 0; 4168c0984e5SSebastian Reichel u32 data; 4178c0984e5SSebastian Reichel int8_t temp; 4188c0984e5SSebastian Reichel 4198c0984e5SSebastian Reichel switch (psp) { 4208c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_TEMP_ALERT_MIN: 4218c0984e5SSebastian Reichel ret = regmap_read(map, MAX17042_TALRT_Th, &data); 4228c0984e5SSebastian Reichel if (ret < 0) 4238c0984e5SSebastian Reichel return ret; 4248c0984e5SSebastian Reichel 4258c0984e5SSebastian Reichel /* Input in deci-centigrade, convert to centigrade */ 4268c0984e5SSebastian Reichel temp = val->intval / 10; 4278c0984e5SSebastian Reichel /* force min < max */ 4288c0984e5SSebastian Reichel if (temp >= (int8_t)(data >> 8)) 4298c0984e5SSebastian Reichel temp = (int8_t)(data >> 8) - 1; 4308c0984e5SSebastian Reichel /* Write both MAX and MIN ALERT */ 4318c0984e5SSebastian Reichel data = (data & 0xff00) + temp; 4328c0984e5SSebastian Reichel ret = regmap_write(map, MAX17042_TALRT_Th, data); 4338c0984e5SSebastian Reichel break; 4348c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_TEMP_ALERT_MAX: 4358c0984e5SSebastian Reichel ret = regmap_read(map, MAX17042_TALRT_Th, &data); 4368c0984e5SSebastian Reichel if (ret < 0) 4378c0984e5SSebastian Reichel return ret; 4388c0984e5SSebastian Reichel 4398c0984e5SSebastian Reichel /* Input in Deci-Centigrade, convert to centigrade */ 4408c0984e5SSebastian Reichel temp = val->intval / 10; 4418c0984e5SSebastian Reichel /* force max > min */ 4428c0984e5SSebastian Reichel if (temp <= (int8_t)(data & 0xff)) 4438c0984e5SSebastian Reichel temp = (int8_t)(data & 0xff) + 1; 4448c0984e5SSebastian Reichel /* Write both MAX and MIN ALERT */ 4458c0984e5SSebastian Reichel data = (data & 0xff) + (temp << 8); 4468c0984e5SSebastian Reichel ret = regmap_write(map, MAX17042_TALRT_Th, data); 4478c0984e5SSebastian Reichel break; 4488c0984e5SSebastian Reichel default: 4498c0984e5SSebastian Reichel ret = -EINVAL; 4508c0984e5SSebastian Reichel } 4518c0984e5SSebastian Reichel 4528c0984e5SSebastian Reichel return ret; 4538c0984e5SSebastian Reichel } 4548c0984e5SSebastian Reichel 4558c0984e5SSebastian Reichel static int max17042_property_is_writeable(struct power_supply *psy, 4568c0984e5SSebastian Reichel enum power_supply_property psp) 4578c0984e5SSebastian Reichel { 4588c0984e5SSebastian Reichel int ret; 4598c0984e5SSebastian Reichel 4608c0984e5SSebastian Reichel switch (psp) { 4618c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_TEMP_ALERT_MIN: 4628c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_TEMP_ALERT_MAX: 4638c0984e5SSebastian Reichel ret = 1; 4648c0984e5SSebastian Reichel break; 4658c0984e5SSebastian Reichel default: 4668c0984e5SSebastian Reichel ret = 0; 4678c0984e5SSebastian Reichel } 4688c0984e5SSebastian Reichel 4698c0984e5SSebastian Reichel return ret; 4708c0984e5SSebastian Reichel } 4718c0984e5SSebastian Reichel 472dcdddda8SHans de Goede static void max17042_external_power_changed(struct power_supply *psy) 473dcdddda8SHans de Goede { 474dcdddda8SHans de Goede power_supply_changed(psy); 475dcdddda8SHans de Goede } 476dcdddda8SHans de Goede 4778c0984e5SSebastian Reichel static int max17042_write_verify_reg(struct regmap *map, u8 reg, u32 value) 4788c0984e5SSebastian Reichel { 4798c0984e5SSebastian Reichel int retries = 8; 4808c0984e5SSebastian Reichel int ret; 4818c0984e5SSebastian Reichel u32 read_value; 4828c0984e5SSebastian Reichel 4838c0984e5SSebastian Reichel do { 4848c0984e5SSebastian Reichel ret = regmap_write(map, reg, value); 4858c0984e5SSebastian Reichel regmap_read(map, reg, &read_value); 4868c0984e5SSebastian Reichel if (read_value != value) { 4878c0984e5SSebastian Reichel ret = -EIO; 4888c0984e5SSebastian Reichel retries--; 4898c0984e5SSebastian Reichel } 4908c0984e5SSebastian Reichel } while (retries && read_value != value); 4918c0984e5SSebastian Reichel 4928c0984e5SSebastian Reichel if (ret < 0) 4938c0984e5SSebastian Reichel pr_err("%s: err %d\n", __func__, ret); 4948c0984e5SSebastian Reichel 4958c0984e5SSebastian Reichel return ret; 4968c0984e5SSebastian Reichel } 4978c0984e5SSebastian Reichel 4988c0984e5SSebastian Reichel static inline void max17042_override_por(struct regmap *map, 4998c0984e5SSebastian Reichel u8 reg, u16 value) 5008c0984e5SSebastian Reichel { 5018c0984e5SSebastian Reichel if (value) 5028c0984e5SSebastian Reichel regmap_write(map, reg, value); 5038c0984e5SSebastian Reichel } 5048c0984e5SSebastian Reichel 5058c0984e5SSebastian Reichel static inline void max10742_unlock_model(struct max17042_chip *chip) 5068c0984e5SSebastian Reichel { 5078c0984e5SSebastian Reichel struct regmap *map = chip->regmap; 5088c0984e5SSebastian Reichel 5098c0984e5SSebastian Reichel regmap_write(map, MAX17042_MLOCKReg1, MODEL_UNLOCK1); 5108c0984e5SSebastian Reichel regmap_write(map, MAX17042_MLOCKReg2, MODEL_UNLOCK2); 5118c0984e5SSebastian Reichel } 5128c0984e5SSebastian Reichel 5138c0984e5SSebastian Reichel static inline void max10742_lock_model(struct max17042_chip *chip) 5148c0984e5SSebastian Reichel { 5158c0984e5SSebastian Reichel struct regmap *map = chip->regmap; 5168c0984e5SSebastian Reichel 5178c0984e5SSebastian Reichel regmap_write(map, MAX17042_MLOCKReg1, MODEL_LOCK1); 5188c0984e5SSebastian Reichel regmap_write(map, MAX17042_MLOCKReg2, MODEL_LOCK2); 5198c0984e5SSebastian Reichel } 5208c0984e5SSebastian Reichel 5218c0984e5SSebastian Reichel static inline void max17042_write_model_data(struct max17042_chip *chip, 5228c0984e5SSebastian Reichel u8 addr, int size) 5238c0984e5SSebastian Reichel { 5248c0984e5SSebastian Reichel struct regmap *map = chip->regmap; 5258c0984e5SSebastian Reichel int i; 5268c0984e5SSebastian Reichel 5278c0984e5SSebastian Reichel for (i = 0; i < size; i++) 5288c0984e5SSebastian Reichel regmap_write(map, addr + i, 5298c0984e5SSebastian Reichel chip->pdata->config_data->cell_char_tbl[i]); 5308c0984e5SSebastian Reichel } 5318c0984e5SSebastian Reichel 5328c0984e5SSebastian Reichel static inline void max17042_read_model_data(struct max17042_chip *chip, 533f7c8f1deSSebastian Reichel u8 addr, u16 *data, int size) 5348c0984e5SSebastian Reichel { 5358c0984e5SSebastian Reichel struct regmap *map = chip->regmap; 5368c0984e5SSebastian Reichel int i; 537f7c8f1deSSebastian Reichel u32 tmp; 5388c0984e5SSebastian Reichel 539f7c8f1deSSebastian Reichel for (i = 0; i < size; i++) { 540f7c8f1deSSebastian Reichel regmap_read(map, addr + i, &tmp); 541f7c8f1deSSebastian Reichel data[i] = (u16)tmp; 542f7c8f1deSSebastian Reichel } 5438c0984e5SSebastian Reichel } 5448c0984e5SSebastian Reichel 5458c0984e5SSebastian Reichel static inline int max17042_model_data_compare(struct max17042_chip *chip, 5468c0984e5SSebastian Reichel u16 *data1, u16 *data2, int size) 5478c0984e5SSebastian Reichel { 5488c0984e5SSebastian Reichel int i; 5498c0984e5SSebastian Reichel 5508c0984e5SSebastian Reichel if (memcmp(data1, data2, size)) { 5518c0984e5SSebastian Reichel dev_err(&chip->client->dev, "%s compare failed\n", __func__); 5528c0984e5SSebastian Reichel for (i = 0; i < size; i++) 5538c0984e5SSebastian Reichel dev_info(&chip->client->dev, "0x%x, 0x%x", 5548c0984e5SSebastian Reichel data1[i], data2[i]); 5558c0984e5SSebastian Reichel dev_info(&chip->client->dev, "\n"); 5568c0984e5SSebastian Reichel return -EINVAL; 5578c0984e5SSebastian Reichel } 5588c0984e5SSebastian Reichel return 0; 5598c0984e5SSebastian Reichel } 5608c0984e5SSebastian Reichel 5618c0984e5SSebastian Reichel static int max17042_init_model(struct max17042_chip *chip) 5628c0984e5SSebastian Reichel { 5638c0984e5SSebastian Reichel int ret; 5648c0984e5SSebastian Reichel int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl); 565f7c8f1deSSebastian Reichel u16 *temp_data; 5668c0984e5SSebastian Reichel 5678c0984e5SSebastian Reichel temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL); 5688c0984e5SSebastian Reichel if (!temp_data) 5698c0984e5SSebastian Reichel return -ENOMEM; 5708c0984e5SSebastian Reichel 5718c0984e5SSebastian Reichel max10742_unlock_model(chip); 5728c0984e5SSebastian Reichel max17042_write_model_data(chip, MAX17042_MODELChrTbl, 5738c0984e5SSebastian Reichel table_size); 5748c0984e5SSebastian Reichel max17042_read_model_data(chip, MAX17042_MODELChrTbl, temp_data, 5758c0984e5SSebastian Reichel table_size); 5768c0984e5SSebastian Reichel 5778c0984e5SSebastian Reichel ret = max17042_model_data_compare( 5788c0984e5SSebastian Reichel chip, 5798c0984e5SSebastian Reichel chip->pdata->config_data->cell_char_tbl, 580f7c8f1deSSebastian Reichel temp_data, 5818c0984e5SSebastian Reichel table_size); 5828c0984e5SSebastian Reichel 5838c0984e5SSebastian Reichel max10742_lock_model(chip); 5848c0984e5SSebastian Reichel kfree(temp_data); 5858c0984e5SSebastian Reichel 5868c0984e5SSebastian Reichel return ret; 5878c0984e5SSebastian Reichel } 5888c0984e5SSebastian Reichel 5898c0984e5SSebastian Reichel static int max17042_verify_model_lock(struct max17042_chip *chip) 5908c0984e5SSebastian Reichel { 5918c0984e5SSebastian Reichel int i; 5928c0984e5SSebastian Reichel int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl); 593f7c8f1deSSebastian Reichel u16 *temp_data; 5948c0984e5SSebastian Reichel int ret = 0; 5958c0984e5SSebastian Reichel 5968c0984e5SSebastian Reichel temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL); 5978c0984e5SSebastian Reichel if (!temp_data) 5988c0984e5SSebastian Reichel return -ENOMEM; 5998c0984e5SSebastian Reichel 6008c0984e5SSebastian Reichel max17042_read_model_data(chip, MAX17042_MODELChrTbl, temp_data, 6018c0984e5SSebastian Reichel table_size); 6028c0984e5SSebastian Reichel for (i = 0; i < table_size; i++) 6038c0984e5SSebastian Reichel if (temp_data[i]) 6048c0984e5SSebastian Reichel ret = -EINVAL; 6058c0984e5SSebastian Reichel 6068c0984e5SSebastian Reichel kfree(temp_data); 6078c0984e5SSebastian Reichel return ret; 6088c0984e5SSebastian Reichel } 6098c0984e5SSebastian Reichel 6108c0984e5SSebastian Reichel static void max17042_write_config_regs(struct max17042_chip *chip) 6118c0984e5SSebastian Reichel { 6128c0984e5SSebastian Reichel struct max17042_config_data *config = chip->pdata->config_data; 6138c0984e5SSebastian Reichel struct regmap *map = chip->regmap; 6148c0984e5SSebastian Reichel 6158c0984e5SSebastian Reichel regmap_write(map, MAX17042_CONFIG, config->config); 6168c0984e5SSebastian Reichel regmap_write(map, MAX17042_LearnCFG, config->learn_cfg); 6178c0984e5SSebastian Reichel regmap_write(map, MAX17042_FilterCFG, 6188c0984e5SSebastian Reichel config->filter_cfg); 6198c0984e5SSebastian Reichel regmap_write(map, MAX17042_RelaxCFG, config->relax_cfg); 6208c0984e5SSebastian Reichel if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17047 || 6218c0984e5SSebastian Reichel chip->chip_type == MAXIM_DEVICE_TYPE_MAX17050) 6228c0984e5SSebastian Reichel regmap_write(map, MAX17047_FullSOCThr, 6238c0984e5SSebastian Reichel config->full_soc_thresh); 6248c0984e5SSebastian Reichel } 6258c0984e5SSebastian Reichel 6268c0984e5SSebastian Reichel static void max17042_write_custom_regs(struct max17042_chip *chip) 6278c0984e5SSebastian Reichel { 6288c0984e5SSebastian Reichel struct max17042_config_data *config = chip->pdata->config_data; 6298c0984e5SSebastian Reichel struct regmap *map = chip->regmap; 6308c0984e5SSebastian Reichel 6318c0984e5SSebastian Reichel max17042_write_verify_reg(map, MAX17042_RCOMP0, config->rcomp0); 6328c0984e5SSebastian Reichel max17042_write_verify_reg(map, MAX17042_TempCo, config->tcompc0); 6338c0984e5SSebastian Reichel max17042_write_verify_reg(map, MAX17042_ICHGTerm, config->ichgt_term); 6348c0984e5SSebastian Reichel if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042) { 6358c0984e5SSebastian Reichel regmap_write(map, MAX17042_EmptyTempCo, config->empty_tempco); 6368c0984e5SSebastian Reichel max17042_write_verify_reg(map, MAX17042_K_empty0, 6378c0984e5SSebastian Reichel config->kempty0); 6388c0984e5SSebastian Reichel } else { 6398c0984e5SSebastian Reichel max17042_write_verify_reg(map, MAX17047_QRTbl00, 6408c0984e5SSebastian Reichel config->qrtbl00); 6418c0984e5SSebastian Reichel max17042_write_verify_reg(map, MAX17047_QRTbl10, 6428c0984e5SSebastian Reichel config->qrtbl10); 6438c0984e5SSebastian Reichel max17042_write_verify_reg(map, MAX17047_QRTbl20, 6448c0984e5SSebastian Reichel config->qrtbl20); 6458c0984e5SSebastian Reichel max17042_write_verify_reg(map, MAX17047_QRTbl30, 6468c0984e5SSebastian Reichel config->qrtbl30); 6478c0984e5SSebastian Reichel } 6488c0984e5SSebastian Reichel } 6498c0984e5SSebastian Reichel 6508c0984e5SSebastian Reichel static void max17042_update_capacity_regs(struct max17042_chip *chip) 6518c0984e5SSebastian Reichel { 6528c0984e5SSebastian Reichel struct max17042_config_data *config = chip->pdata->config_data; 6538c0984e5SSebastian Reichel struct regmap *map = chip->regmap; 6548c0984e5SSebastian Reichel 6558c0984e5SSebastian Reichel max17042_write_verify_reg(map, MAX17042_FullCAP, 6568c0984e5SSebastian Reichel config->fullcap); 6578c0984e5SSebastian Reichel regmap_write(map, MAX17042_DesignCap, config->design_cap); 6588c0984e5SSebastian Reichel max17042_write_verify_reg(map, MAX17042_FullCAPNom, 6598c0984e5SSebastian Reichel config->fullcapnom); 6608c0984e5SSebastian Reichel } 6618c0984e5SSebastian Reichel 6628c0984e5SSebastian Reichel static void max17042_reset_vfsoc0_reg(struct max17042_chip *chip) 6638c0984e5SSebastian Reichel { 6648c0984e5SSebastian Reichel unsigned int vfSoc; 6658c0984e5SSebastian Reichel struct regmap *map = chip->regmap; 6668c0984e5SSebastian Reichel 6678c0984e5SSebastian Reichel regmap_read(map, MAX17042_VFSOC, &vfSoc); 6688c0984e5SSebastian Reichel regmap_write(map, MAX17042_VFSOC0Enable, VFSOC0_UNLOCK); 6698c0984e5SSebastian Reichel max17042_write_verify_reg(map, MAX17042_VFSOC0, vfSoc); 6708c0984e5SSebastian Reichel regmap_write(map, MAX17042_VFSOC0Enable, VFSOC0_LOCK); 6718c0984e5SSebastian Reichel } 6728c0984e5SSebastian Reichel 6738c0984e5SSebastian Reichel static void max17042_load_new_capacity_params(struct max17042_chip *chip) 6748c0984e5SSebastian Reichel { 6758c0984e5SSebastian Reichel u32 full_cap0, rep_cap, dq_acc, vfSoc; 6768c0984e5SSebastian Reichel u32 rem_cap; 6778c0984e5SSebastian Reichel 6788c0984e5SSebastian Reichel struct max17042_config_data *config = chip->pdata->config_data; 6798c0984e5SSebastian Reichel struct regmap *map = chip->regmap; 6808c0984e5SSebastian Reichel 6818c0984e5SSebastian Reichel regmap_read(map, MAX17042_FullCAP0, &full_cap0); 6828c0984e5SSebastian Reichel regmap_read(map, MAX17042_VFSOC, &vfSoc); 6838c0984e5SSebastian Reichel 6848c0984e5SSebastian Reichel /* fg_vfSoc needs to shifted by 8 bits to get the 6858c0984e5SSebastian Reichel * perc in 1% accuracy, to get the right rem_cap multiply 6868c0984e5SSebastian Reichel * full_cap0, fg_vfSoc and devide by 100 6878c0984e5SSebastian Reichel */ 6888c0984e5SSebastian Reichel rem_cap = ((vfSoc >> 8) * full_cap0) / 100; 6898c0984e5SSebastian Reichel max17042_write_verify_reg(map, MAX17042_RemCap, rem_cap); 6908c0984e5SSebastian Reichel 6918c0984e5SSebastian Reichel rep_cap = rem_cap; 6928c0984e5SSebastian Reichel max17042_write_verify_reg(map, MAX17042_RepCap, rep_cap); 6938c0984e5SSebastian Reichel 6948c0984e5SSebastian Reichel /* Write dQ_acc to 200% of Capacity and dP_acc to 200% */ 6958c0984e5SSebastian Reichel dq_acc = config->fullcap / dQ_ACC_DIV; 6968c0984e5SSebastian Reichel max17042_write_verify_reg(map, MAX17042_dQacc, dq_acc); 6978c0984e5SSebastian Reichel max17042_write_verify_reg(map, MAX17042_dPacc, dP_ACC_200); 6988c0984e5SSebastian Reichel 6998c0984e5SSebastian Reichel max17042_write_verify_reg(map, MAX17042_FullCAP, 7008c0984e5SSebastian Reichel config->fullcap); 7018c0984e5SSebastian Reichel regmap_write(map, MAX17042_DesignCap, 7028c0984e5SSebastian Reichel config->design_cap); 7038c0984e5SSebastian Reichel max17042_write_verify_reg(map, MAX17042_FullCAPNom, 7048c0984e5SSebastian Reichel config->fullcapnom); 7058c0984e5SSebastian Reichel /* Update SOC register with new SOC */ 7068c0984e5SSebastian Reichel regmap_write(map, MAX17042_RepSOC, vfSoc); 7078c0984e5SSebastian Reichel } 7088c0984e5SSebastian Reichel 7098c0984e5SSebastian Reichel /* 7108c0984e5SSebastian Reichel * Block write all the override values coming from platform data. 7118c0984e5SSebastian Reichel * This function MUST be called before the POR initialization proceedure 7128c0984e5SSebastian Reichel * specified by maxim. 7138c0984e5SSebastian Reichel */ 7148c0984e5SSebastian Reichel static inline void max17042_override_por_values(struct max17042_chip *chip) 7158c0984e5SSebastian Reichel { 7168c0984e5SSebastian Reichel struct regmap *map = chip->regmap; 7178c0984e5SSebastian Reichel struct max17042_config_data *config = chip->pdata->config_data; 7188c0984e5SSebastian Reichel 7198c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_TGAIN, config->tgain); 7208c0984e5SSebastian Reichel max17042_override_por(map, MAx17042_TOFF, config->toff); 7218c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_CGAIN, config->cgain); 7228c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_COFF, config->coff); 7238c0984e5SSebastian Reichel 7248c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_VALRT_Th, config->valrt_thresh); 7258c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_TALRT_Th, config->talrt_thresh); 7268c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_SALRT_Th, 7278c0984e5SSebastian Reichel config->soc_alrt_thresh); 7288c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_CONFIG, config->config); 7298c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_SHDNTIMER, config->shdntimer); 7308c0984e5SSebastian Reichel 7318c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_DesignCap, config->design_cap); 7328c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_ICHGTerm, config->ichgt_term); 7338c0984e5SSebastian Reichel 7348c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_AtRate, config->at_rate); 7358c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_LearnCFG, config->learn_cfg); 7368c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_FilterCFG, config->filter_cfg); 7378c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_RelaxCFG, config->relax_cfg); 7388c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_MiscCFG, config->misc_cfg); 7398c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_MaskSOC, config->masksoc); 7408c0984e5SSebastian Reichel 7418c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_FullCAP, config->fullcap); 7428c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_FullCAPNom, config->fullcapnom); 7438c0984e5SSebastian Reichel if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042) 7448c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_SOC_empty, 7458c0984e5SSebastian Reichel config->socempty); 7468c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_LAvg_empty, config->lavg_empty); 7478c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_dQacc, config->dqacc); 7488c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_dPacc, config->dpacc); 7498c0984e5SSebastian Reichel 7508c0984e5SSebastian Reichel if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042) 7518c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_V_empty, config->vempty); 7528c0984e5SSebastian Reichel else 7538c0984e5SSebastian Reichel max17042_override_por(map, MAX17047_V_empty, config->vempty); 7548c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_TempNom, config->temp_nom); 7558c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_TempLim, config->temp_lim); 7568c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_FCTC, config->fctc); 7578c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_RCOMP0, config->rcomp0); 7588c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_TempCo, config->tcompc0); 7598c0984e5SSebastian Reichel if (chip->chip_type) { 7608c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_EmptyTempCo, 7618c0984e5SSebastian Reichel config->empty_tempco); 7628c0984e5SSebastian Reichel max17042_override_por(map, MAX17042_K_empty0, 7638c0984e5SSebastian Reichel config->kempty0); 7648c0984e5SSebastian Reichel } 7658c0984e5SSebastian Reichel } 7668c0984e5SSebastian Reichel 7678c0984e5SSebastian Reichel static int max17042_init_chip(struct max17042_chip *chip) 7688c0984e5SSebastian Reichel { 7698c0984e5SSebastian Reichel struct regmap *map = chip->regmap; 7708c0984e5SSebastian Reichel int ret; 7718c0984e5SSebastian Reichel 7728c0984e5SSebastian Reichel max17042_override_por_values(chip); 7738c0984e5SSebastian Reichel /* After Power up, the MAX17042 requires 500mS in order 7748c0984e5SSebastian Reichel * to perform signal debouncing and initial SOC reporting 7758c0984e5SSebastian Reichel */ 7768c0984e5SSebastian Reichel msleep(500); 7778c0984e5SSebastian Reichel 7788c0984e5SSebastian Reichel /* Initialize configaration */ 7798c0984e5SSebastian Reichel max17042_write_config_regs(chip); 7808c0984e5SSebastian Reichel 7818c0984e5SSebastian Reichel /* write cell characterization data */ 7828c0984e5SSebastian Reichel ret = max17042_init_model(chip); 7838c0984e5SSebastian Reichel if (ret) { 7848c0984e5SSebastian Reichel dev_err(&chip->client->dev, "%s init failed\n", 7858c0984e5SSebastian Reichel __func__); 7868c0984e5SSebastian Reichel return -EIO; 7878c0984e5SSebastian Reichel } 7888c0984e5SSebastian Reichel 7898c0984e5SSebastian Reichel ret = max17042_verify_model_lock(chip); 7908c0984e5SSebastian Reichel if (ret) { 7918c0984e5SSebastian Reichel dev_err(&chip->client->dev, "%s lock verify failed\n", 7928c0984e5SSebastian Reichel __func__); 7938c0984e5SSebastian Reichel return -EIO; 7948c0984e5SSebastian Reichel } 7958c0984e5SSebastian Reichel /* write custom parameters */ 7968c0984e5SSebastian Reichel max17042_write_custom_regs(chip); 7978c0984e5SSebastian Reichel 7988c0984e5SSebastian Reichel /* update capacity params */ 7998c0984e5SSebastian Reichel max17042_update_capacity_regs(chip); 8008c0984e5SSebastian Reichel 8018c0984e5SSebastian Reichel /* delay must be atleast 350mS to allow VFSOC 8028c0984e5SSebastian Reichel * to be calculated from the new configuration 8038c0984e5SSebastian Reichel */ 8048c0984e5SSebastian Reichel msleep(350); 8058c0984e5SSebastian Reichel 8068c0984e5SSebastian Reichel /* reset vfsoc0 reg */ 8078c0984e5SSebastian Reichel max17042_reset_vfsoc0_reg(chip); 8088c0984e5SSebastian Reichel 8098c0984e5SSebastian Reichel /* load new capacity params */ 8108c0984e5SSebastian Reichel max17042_load_new_capacity_params(chip); 8118c0984e5SSebastian Reichel 8128c0984e5SSebastian Reichel /* Init complete, Clear the POR bit */ 8138c0984e5SSebastian Reichel regmap_update_bits(map, MAX17042_STATUS, STATUS_POR_BIT, 0x0); 8148c0984e5SSebastian Reichel return 0; 8158c0984e5SSebastian Reichel } 8168c0984e5SSebastian Reichel 8178c0984e5SSebastian Reichel static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off) 8188c0984e5SSebastian Reichel { 8198c0984e5SSebastian Reichel struct regmap *map = chip->regmap; 8208c0984e5SSebastian Reichel u32 soc, soc_tr; 8218c0984e5SSebastian Reichel 8228c0984e5SSebastian Reichel /* program interrupt thesholds such that we should 8238c0984e5SSebastian Reichel * get interrupt for every 'off' perc change in the soc 8248c0984e5SSebastian Reichel */ 8258c0984e5SSebastian Reichel regmap_read(map, MAX17042_RepSOC, &soc); 8268c0984e5SSebastian Reichel soc >>= 8; 8278c0984e5SSebastian Reichel soc_tr = (soc + off) << 8; 8288c0984e5SSebastian Reichel soc_tr |= (soc - off); 8298c0984e5SSebastian Reichel regmap_write(map, MAX17042_SALRT_Th, soc_tr); 8308c0984e5SSebastian Reichel } 8318c0984e5SSebastian Reichel 8328c0984e5SSebastian Reichel static irqreturn_t max17042_thread_handler(int id, void *dev) 8338c0984e5SSebastian Reichel { 8348c0984e5SSebastian Reichel struct max17042_chip *chip = dev; 8358c0984e5SSebastian Reichel u32 val; 8368c0984e5SSebastian Reichel 8378c0984e5SSebastian Reichel regmap_read(chip->regmap, MAX17042_STATUS, &val); 8388c0984e5SSebastian Reichel if ((val & STATUS_INTR_SOCMIN_BIT) || 8398c0984e5SSebastian Reichel (val & STATUS_INTR_SOCMAX_BIT)) { 8408c0984e5SSebastian Reichel dev_info(&chip->client->dev, "SOC threshold INTR\n"); 8418c0984e5SSebastian Reichel max17042_set_soc_threshold(chip, 1); 8428c0984e5SSebastian Reichel } 8438c0984e5SSebastian Reichel 8448c0984e5SSebastian Reichel power_supply_changed(chip->battery); 8458c0984e5SSebastian Reichel return IRQ_HANDLED; 8468c0984e5SSebastian Reichel } 8478c0984e5SSebastian Reichel 8488c0984e5SSebastian Reichel static void max17042_init_worker(struct work_struct *work) 8498c0984e5SSebastian Reichel { 8508c0984e5SSebastian Reichel struct max17042_chip *chip = container_of(work, 8518c0984e5SSebastian Reichel struct max17042_chip, work); 8528c0984e5SSebastian Reichel int ret; 8538c0984e5SSebastian Reichel 8548c0984e5SSebastian Reichel /* Initialize registers according to values from the platform data */ 8558c0984e5SSebastian Reichel if (chip->pdata->enable_por_init && chip->pdata->config_data) { 8568c0984e5SSebastian Reichel ret = max17042_init_chip(chip); 8578c0984e5SSebastian Reichel if (ret) 8588c0984e5SSebastian Reichel return; 8598c0984e5SSebastian Reichel } 8608c0984e5SSebastian Reichel 8618c0984e5SSebastian Reichel chip->init_complete = 1; 8628c0984e5SSebastian Reichel } 8638c0984e5SSebastian Reichel 8648c0984e5SSebastian Reichel #ifdef CONFIG_OF 8658c0984e5SSebastian Reichel static struct max17042_platform_data * 86691736213SHans de Goede max17042_get_pdata(struct max17042_chip *chip) 8678c0984e5SSebastian Reichel { 86891736213SHans de Goede struct device *dev = &chip->client->dev; 8698c0984e5SSebastian Reichel struct device_node *np = dev->of_node; 8708c0984e5SSebastian Reichel u32 prop; 8718c0984e5SSebastian Reichel struct max17042_platform_data *pdata; 8728c0984e5SSebastian Reichel 8738c0984e5SSebastian Reichel if (!np) 8748c0984e5SSebastian Reichel return dev->platform_data; 8758c0984e5SSebastian Reichel 8768c0984e5SSebastian Reichel pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 8778c0984e5SSebastian Reichel if (!pdata) 8788c0984e5SSebastian Reichel return NULL; 8798c0984e5SSebastian Reichel 8808c0984e5SSebastian Reichel /* 8818c0984e5SSebastian Reichel * Require current sense resistor value to be specified for 8828c0984e5SSebastian Reichel * current-sense functionality to be enabled at all. 8838c0984e5SSebastian Reichel */ 8848c0984e5SSebastian Reichel if (of_property_read_u32(np, "maxim,rsns-microohm", &prop) == 0) { 8858c0984e5SSebastian Reichel pdata->r_sns = prop; 8868c0984e5SSebastian Reichel pdata->enable_current_sense = true; 8878c0984e5SSebastian Reichel } 8888c0984e5SSebastian Reichel 8898c0984e5SSebastian Reichel if (of_property_read_s32(np, "maxim,cold-temp", &pdata->temp_min)) 8908c0984e5SSebastian Reichel pdata->temp_min = INT_MIN; 8918c0984e5SSebastian Reichel if (of_property_read_s32(np, "maxim,over-heat-temp", &pdata->temp_max)) 8928c0984e5SSebastian Reichel pdata->temp_max = INT_MAX; 8938c0984e5SSebastian Reichel if (of_property_read_s32(np, "maxim,dead-volt", &pdata->vmin)) 8948c0984e5SSebastian Reichel pdata->vmin = INT_MIN; 8958c0984e5SSebastian Reichel if (of_property_read_s32(np, "maxim,over-volt", &pdata->vmax)) 8968c0984e5SSebastian Reichel pdata->vmax = INT_MAX; 8978c0984e5SSebastian Reichel 8988c0984e5SSebastian Reichel return pdata; 8998c0984e5SSebastian Reichel } 9008c0984e5SSebastian Reichel #else 90191736213SHans de Goede static struct max17042_reg_data max17047_default_pdata_init_regs[] = { 90291736213SHans de Goede /* 90391736213SHans de Goede * Some firmwares do not set FullSOCThr, Enable End-of-Charge Detection 90491736213SHans de Goede * when the voltage FG reports 95%, as recommended in the datasheet. 90591736213SHans de Goede */ 90691736213SHans de Goede { MAX17047_FullSOCThr, MAX17042_BATTERY_FULL << 8 }, 90791736213SHans de Goede }; 90891736213SHans de Goede 9098c0984e5SSebastian Reichel static struct max17042_platform_data * 91091736213SHans de Goede max17042_get_pdata(struct max17042_chip *chip) 9118c0984e5SSebastian Reichel { 91291736213SHans de Goede struct device *dev = &chip->client->dev; 91391736213SHans de Goede struct max17042_platform_data *pdata; 91491736213SHans de Goede int ret, misc_cfg; 91591736213SHans de Goede 91691736213SHans de Goede if (dev->platform_data) 9178c0984e5SSebastian Reichel return dev->platform_data; 91891736213SHans de Goede 91991736213SHans de Goede /* 92091736213SHans de Goede * The MAX17047 gets used on x86 where we might not have pdata, assume 92191736213SHans de Goede * the firmware will already have initialized the fuel-gauge and provide 92291736213SHans de Goede * default values for the non init bits to make things work. 92391736213SHans de Goede */ 92491736213SHans de Goede pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 92591736213SHans de Goede if (!pdata) 92691736213SHans de Goede return pdata; 92791736213SHans de Goede 92891736213SHans de Goede if (chip->chip_type != MAXIM_DEVICE_TYPE_MAX17042) { 92991736213SHans de Goede pdata->init_data = max17047_default_pdata_init_regs; 93091736213SHans de Goede pdata->num_init_data = 93191736213SHans de Goede ARRAY_SIZE(max17047_default_pdata_init_regs); 93291736213SHans de Goede } 93391736213SHans de Goede 93491736213SHans de Goede ret = regmap_read(chip->regmap, MAX17042_MiscCFG, &misc_cfg); 93591736213SHans de Goede if (ret < 0) 93691736213SHans de Goede return NULL; 93791736213SHans de Goede 93891736213SHans de Goede /* If bits 0-1 are set to 3 then only Voltage readings are used */ 93991736213SHans de Goede if ((misc_cfg & 0x3) == 0x3) 94091736213SHans de Goede pdata->enable_current_sense = false; 94191736213SHans de Goede else 94291736213SHans de Goede pdata->enable_current_sense = true; 94391736213SHans de Goede 94491736213SHans de Goede pdata->vmin = MAX17042_DEFAULT_VMIN; 94591736213SHans de Goede pdata->vmax = MAX17042_DEFAULT_VMAX; 94691736213SHans de Goede pdata->temp_min = MAX17042_DEFAULT_TEMP_MIN; 94791736213SHans de Goede pdata->temp_max = MAX17042_DEFAULT_TEMP_MAX; 94891736213SHans de Goede 94991736213SHans de Goede return pdata; 9508c0984e5SSebastian Reichel } 9518c0984e5SSebastian Reichel #endif 9528c0984e5SSebastian Reichel 9538c0984e5SSebastian Reichel static const struct regmap_config max17042_regmap_config = { 9548c0984e5SSebastian Reichel .reg_bits = 8, 9558c0984e5SSebastian Reichel .val_bits = 16, 9568c0984e5SSebastian Reichel .val_format_endian = REGMAP_ENDIAN_NATIVE, 9578c0984e5SSebastian Reichel }; 9588c0984e5SSebastian Reichel 9598c0984e5SSebastian Reichel static const struct power_supply_desc max17042_psy_desc = { 9608c0984e5SSebastian Reichel .name = "max170xx_battery", 9618c0984e5SSebastian Reichel .type = POWER_SUPPLY_TYPE_BATTERY, 9628c0984e5SSebastian Reichel .get_property = max17042_get_property, 9638c0984e5SSebastian Reichel .set_property = max17042_set_property, 9648c0984e5SSebastian Reichel .property_is_writeable = max17042_property_is_writeable, 965dcdddda8SHans de Goede .external_power_changed = max17042_external_power_changed, 9668c0984e5SSebastian Reichel .properties = max17042_battery_props, 9678c0984e5SSebastian Reichel .num_properties = ARRAY_SIZE(max17042_battery_props), 9688c0984e5SSebastian Reichel }; 9698c0984e5SSebastian Reichel 9708c0984e5SSebastian Reichel static const struct power_supply_desc max17042_no_current_sense_psy_desc = { 9718c0984e5SSebastian Reichel .name = "max170xx_battery", 9728c0984e5SSebastian Reichel .type = POWER_SUPPLY_TYPE_BATTERY, 9738c0984e5SSebastian Reichel .get_property = max17042_get_property, 9748c0984e5SSebastian Reichel .set_property = max17042_set_property, 9758c0984e5SSebastian Reichel .property_is_writeable = max17042_property_is_writeable, 9768c0984e5SSebastian Reichel .properties = max17042_battery_props, 9778c0984e5SSebastian Reichel .num_properties = ARRAY_SIZE(max17042_battery_props) - 2, 9788c0984e5SSebastian Reichel }; 9798c0984e5SSebastian Reichel 9808c0984e5SSebastian Reichel static int max17042_probe(struct i2c_client *client, 9818c0984e5SSebastian Reichel const struct i2c_device_id *id) 9828c0984e5SSebastian Reichel { 9838c0984e5SSebastian Reichel struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 9848c0984e5SSebastian Reichel const struct power_supply_desc *max17042_desc = &max17042_psy_desc; 9858c0984e5SSebastian Reichel struct power_supply_config psy_cfg = {}; 986*e2116202SHans de Goede const struct acpi_device_id *acpi_id; 987*e2116202SHans de Goede struct device *dev = &client->dev; 9888c0984e5SSebastian Reichel struct max17042_chip *chip; 9898c0984e5SSebastian Reichel int ret; 9908c0984e5SSebastian Reichel int i; 9918c0984e5SSebastian Reichel u32 val; 9928c0984e5SSebastian Reichel 9938c0984e5SSebastian Reichel if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) 9948c0984e5SSebastian Reichel return -EIO; 9958c0984e5SSebastian Reichel 9968c0984e5SSebastian Reichel chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 9978c0984e5SSebastian Reichel if (!chip) 9988c0984e5SSebastian Reichel return -ENOMEM; 9998c0984e5SSebastian Reichel 10008c0984e5SSebastian Reichel chip->client = client; 1001*e2116202SHans de Goede if (id) { 100291736213SHans de Goede chip->chip_type = id->driver_data; 1003*e2116202SHans de Goede } else { 1004*e2116202SHans de Goede acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev); 1005*e2116202SHans de Goede if (!acpi_id) 1006*e2116202SHans de Goede return -ENODEV; 1007*e2116202SHans de Goede 1008*e2116202SHans de Goede chip->chip_type = acpi_id->driver_data; 1009*e2116202SHans de Goede } 10108c0984e5SSebastian Reichel chip->regmap = devm_regmap_init_i2c(client, &max17042_regmap_config); 10118c0984e5SSebastian Reichel if (IS_ERR(chip->regmap)) { 10128c0984e5SSebastian Reichel dev_err(&client->dev, "Failed to initialize regmap\n"); 10138c0984e5SSebastian Reichel return -EINVAL; 10148c0984e5SSebastian Reichel } 10158c0984e5SSebastian Reichel 101691736213SHans de Goede chip->pdata = max17042_get_pdata(chip); 10178c0984e5SSebastian Reichel if (!chip->pdata) { 10188c0984e5SSebastian Reichel dev_err(&client->dev, "no platform data provided\n"); 10198c0984e5SSebastian Reichel return -EINVAL; 10208c0984e5SSebastian Reichel } 10218c0984e5SSebastian Reichel 10228c0984e5SSebastian Reichel i2c_set_clientdata(client, chip); 10238c0984e5SSebastian Reichel psy_cfg.drv_data = chip; 10248c0984e5SSebastian Reichel 10258c0984e5SSebastian Reichel /* When current is not measured, 10268c0984e5SSebastian Reichel * CURRENT_NOW and CURRENT_AVG properties should be invisible. */ 10278c0984e5SSebastian Reichel if (!chip->pdata->enable_current_sense) 10288c0984e5SSebastian Reichel max17042_desc = &max17042_no_current_sense_psy_desc; 10298c0984e5SSebastian Reichel 10308c0984e5SSebastian Reichel if (chip->pdata->r_sns == 0) 10318c0984e5SSebastian Reichel chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR; 10328c0984e5SSebastian Reichel 10338c0984e5SSebastian Reichel if (chip->pdata->init_data) 10348c0984e5SSebastian Reichel for (i = 0; i < chip->pdata->num_init_data; i++) 10358c0984e5SSebastian Reichel regmap_write(chip->regmap, 10368c0984e5SSebastian Reichel chip->pdata->init_data[i].addr, 10378c0984e5SSebastian Reichel chip->pdata->init_data[i].data); 10388c0984e5SSebastian Reichel 10398c0984e5SSebastian Reichel if (!chip->pdata->enable_current_sense) { 10408c0984e5SSebastian Reichel regmap_write(chip->regmap, MAX17042_CGAIN, 0x0000); 10418c0984e5SSebastian Reichel regmap_write(chip->regmap, MAX17042_MiscCFG, 0x0003); 10428c0984e5SSebastian Reichel regmap_write(chip->regmap, MAX17042_LearnCFG, 0x0007); 10438c0984e5SSebastian Reichel } 10448c0984e5SSebastian Reichel 10458c0984e5SSebastian Reichel chip->battery = devm_power_supply_register(&client->dev, max17042_desc, 10468c0984e5SSebastian Reichel &psy_cfg); 10478c0984e5SSebastian Reichel if (IS_ERR(chip->battery)) { 10488c0984e5SSebastian Reichel dev_err(&client->dev, "failed: power supply register\n"); 10498c0984e5SSebastian Reichel return PTR_ERR(chip->battery); 10508c0984e5SSebastian Reichel } 10518c0984e5SSebastian Reichel 10528c0984e5SSebastian Reichel if (client->irq) { 10538c0984e5SSebastian Reichel ret = devm_request_threaded_irq(&client->dev, client->irq, 10548c0984e5SSebastian Reichel NULL, 10558c0984e5SSebastian Reichel max17042_thread_handler, 10568c0984e5SSebastian Reichel IRQF_TRIGGER_FALLING | 10578c0984e5SSebastian Reichel IRQF_ONESHOT, 10588c0984e5SSebastian Reichel chip->battery->desc->name, 10598c0984e5SSebastian Reichel chip); 10608c0984e5SSebastian Reichel if (!ret) { 10618c0984e5SSebastian Reichel regmap_update_bits(chip->regmap, MAX17042_CONFIG, 10628c0984e5SSebastian Reichel CONFIG_ALRT_BIT_ENBL, 10638c0984e5SSebastian Reichel CONFIG_ALRT_BIT_ENBL); 10648c0984e5SSebastian Reichel max17042_set_soc_threshold(chip, 1); 10658c0984e5SSebastian Reichel } else { 10668c0984e5SSebastian Reichel client->irq = 0; 10678c0984e5SSebastian Reichel dev_err(&client->dev, "%s(): cannot get IRQ\n", 10688c0984e5SSebastian Reichel __func__); 10698c0984e5SSebastian Reichel } 10708c0984e5SSebastian Reichel } 10718c0984e5SSebastian Reichel 10728c0984e5SSebastian Reichel regmap_read(chip->regmap, MAX17042_STATUS, &val); 10738c0984e5SSebastian Reichel if (val & STATUS_POR_BIT) { 10748c0984e5SSebastian Reichel INIT_WORK(&chip->work, max17042_init_worker); 10758c0984e5SSebastian Reichel schedule_work(&chip->work); 10768c0984e5SSebastian Reichel } else { 10778c0984e5SSebastian Reichel chip->init_complete = 1; 10788c0984e5SSebastian Reichel } 10798c0984e5SSebastian Reichel 10808c0984e5SSebastian Reichel return 0; 10818c0984e5SSebastian Reichel } 10828c0984e5SSebastian Reichel 10838c0984e5SSebastian Reichel #ifdef CONFIG_PM_SLEEP 10848c0984e5SSebastian Reichel static int max17042_suspend(struct device *dev) 10858c0984e5SSebastian Reichel { 10868c0984e5SSebastian Reichel struct max17042_chip *chip = dev_get_drvdata(dev); 10878c0984e5SSebastian Reichel 10888c0984e5SSebastian Reichel /* 10898c0984e5SSebastian Reichel * disable the irq and enable irq_wake 10908c0984e5SSebastian Reichel * capability to the interrupt line. 10918c0984e5SSebastian Reichel */ 10928c0984e5SSebastian Reichel if (chip->client->irq) { 10938c0984e5SSebastian Reichel disable_irq(chip->client->irq); 10948c0984e5SSebastian Reichel enable_irq_wake(chip->client->irq); 10958c0984e5SSebastian Reichel } 10968c0984e5SSebastian Reichel 10978c0984e5SSebastian Reichel return 0; 10988c0984e5SSebastian Reichel } 10998c0984e5SSebastian Reichel 11008c0984e5SSebastian Reichel static int max17042_resume(struct device *dev) 11018c0984e5SSebastian Reichel { 11028c0984e5SSebastian Reichel struct max17042_chip *chip = dev_get_drvdata(dev); 11038c0984e5SSebastian Reichel 11048c0984e5SSebastian Reichel if (chip->client->irq) { 11058c0984e5SSebastian Reichel disable_irq_wake(chip->client->irq); 11068c0984e5SSebastian Reichel enable_irq(chip->client->irq); 11078c0984e5SSebastian Reichel /* re-program the SOC thresholds to 1% change */ 11088c0984e5SSebastian Reichel max17042_set_soc_threshold(chip, 1); 11098c0984e5SSebastian Reichel } 11108c0984e5SSebastian Reichel 11118c0984e5SSebastian Reichel return 0; 11128c0984e5SSebastian Reichel } 11138c0984e5SSebastian Reichel #endif 11148c0984e5SSebastian Reichel 11158c0984e5SSebastian Reichel static SIMPLE_DEV_PM_OPS(max17042_pm_ops, max17042_suspend, 11168c0984e5SSebastian Reichel max17042_resume); 11178c0984e5SSebastian Reichel 1118*e2116202SHans de Goede #ifdef CONFIG_ACPI 1119*e2116202SHans de Goede static const struct acpi_device_id max17042_acpi_match[] = { 1120*e2116202SHans de Goede { "MAX17047", MAXIM_DEVICE_TYPE_MAX17047 }, 1121*e2116202SHans de Goede { } 1122*e2116202SHans de Goede }; 1123*e2116202SHans de Goede MODULE_DEVICE_TABLE(acpi, max17042_acpi_match); 1124*e2116202SHans de Goede #endif 1125*e2116202SHans de Goede 11268c0984e5SSebastian Reichel #ifdef CONFIG_OF 11278c0984e5SSebastian Reichel static const struct of_device_id max17042_dt_match[] = { 11288c0984e5SSebastian Reichel { .compatible = "maxim,max17042" }, 11298c0984e5SSebastian Reichel { .compatible = "maxim,max17047" }, 11308c0984e5SSebastian Reichel { .compatible = "maxim,max17050" }, 11318c0984e5SSebastian Reichel { }, 11328c0984e5SSebastian Reichel }; 11338c0984e5SSebastian Reichel MODULE_DEVICE_TABLE(of, max17042_dt_match); 11348c0984e5SSebastian Reichel #endif 11358c0984e5SSebastian Reichel 11368c0984e5SSebastian Reichel static const struct i2c_device_id max17042_id[] = { 11378c0984e5SSebastian Reichel { "max17042", MAXIM_DEVICE_TYPE_MAX17042 }, 11388c0984e5SSebastian Reichel { "max17047", MAXIM_DEVICE_TYPE_MAX17047 }, 11398c0984e5SSebastian Reichel { "max17050", MAXIM_DEVICE_TYPE_MAX17050 }, 11408c0984e5SSebastian Reichel { } 11418c0984e5SSebastian Reichel }; 11428c0984e5SSebastian Reichel MODULE_DEVICE_TABLE(i2c, max17042_id); 11438c0984e5SSebastian Reichel 11448c0984e5SSebastian Reichel static struct i2c_driver max17042_i2c_driver = { 11458c0984e5SSebastian Reichel .driver = { 11468c0984e5SSebastian Reichel .name = "max17042", 1147*e2116202SHans de Goede .acpi_match_table = ACPI_PTR(max17042_acpi_match), 11488c0984e5SSebastian Reichel .of_match_table = of_match_ptr(max17042_dt_match), 11498c0984e5SSebastian Reichel .pm = &max17042_pm_ops, 11508c0984e5SSebastian Reichel }, 11518c0984e5SSebastian Reichel .probe = max17042_probe, 11528c0984e5SSebastian Reichel .id_table = max17042_id, 11538c0984e5SSebastian Reichel }; 11548c0984e5SSebastian Reichel module_i2c_driver(max17042_i2c_driver); 11558c0984e5SSebastian Reichel 11568c0984e5SSebastian Reichel MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); 11578c0984e5SSebastian Reichel MODULE_DESCRIPTION("MAX17042 Fuel Gauge"); 11588c0984e5SSebastian Reichel MODULE_LICENSE("GPL"); 1159