From d556f21cb0f8b66f2e7956244c1a739ee6401579 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 21 Dec 2016 15:36:46 +0100 Subject: power: supply: axp288_charger: Make charger_init_hw_regs propagate i2c errors Make charger_init_hw_regs propagate i2c errors, instead of only warning about them and then ignoring them. Signed-off-by: Hans de Goede Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp288_charger.c | 62 ++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/drivers/power/supply/axp288_charger.c b/drivers/power/supply/axp288_charger.c index 75b8e0c7402b..f1e3b0ec3b82 100644 --- a/drivers/power/supply/axp288_charger.c +++ b/drivers/power/supply/axp288_charger.c @@ -701,59 +701,73 @@ static int axp288_charger_handle_otg_evt(struct notifier_block *nb, return NOTIFY_OK; } -static void charger_init_hw_regs(struct axp288_chrg_info *info) +static int charger_init_hw_regs(struct axp288_chrg_info *info) { int ret, cc, cv; unsigned int val; /* Program temperature thresholds */ ret = regmap_write(info->regmap, AXP20X_V_LTF_CHRG, CHRG_VLTFC_0C); - if (ret < 0) - dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n", + if (ret < 0) { + dev_err(&info->pdev->dev, "register(%x) write error(%d)\n", AXP20X_V_LTF_CHRG, ret); + return ret; + } ret = regmap_write(info->regmap, AXP20X_V_HTF_CHRG, CHRG_VHTFC_45C); - if (ret < 0) - dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n", + if (ret < 0) { + dev_err(&info->pdev->dev, "register(%x) write error(%d)\n", AXP20X_V_HTF_CHRG, ret); + return ret; + } /* Do not turn-off charger o/p after charge cycle ends */ ret = regmap_update_bits(info->regmap, AXP20X_CHRG_CTRL2, CNTL2_CHG_OUT_TURNON, 1); - if (ret < 0) - dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n", + if (ret < 0) { + dev_err(&info->pdev->dev, "register(%x) write error(%d)\n", AXP20X_CHRG_CTRL2, ret); + return ret; + } /* Enable interrupts */ ret = regmap_update_bits(info->regmap, AXP20X_IRQ2_EN, BAT_IRQ_CFG_BAT_MASK, 1); - if (ret < 0) - dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n", + if (ret < 0) { + dev_err(&info->pdev->dev, "register(%x) write error(%d)\n", AXP20X_IRQ2_EN, ret); + return ret; + } ret = regmap_update_bits(info->regmap, AXP20X_IRQ3_EN, TEMP_IRQ_CFG_MASK, 1); - if (ret < 0) - dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n", + if (ret < 0) { + dev_err(&info->pdev->dev, "register(%x) write error(%d)\n", AXP20X_IRQ3_EN, ret); + return ret; + } /* Setup ending condition for charging to be 10% of I(chrg) */ ret = regmap_update_bits(info->regmap, AXP20X_CHRG_CTRL1, CHRG_CCCV_ITERM_20P, 0); - if (ret < 0) - dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n", + if (ret < 0) { + dev_err(&info->pdev->dev, "register(%x) write error(%d)\n", AXP20X_CHRG_CTRL1, ret); + return ret; + } /* Disable OCV-SOC curve calibration */ ret = regmap_update_bits(info->regmap, AXP20X_CC_CTRL, FG_CNTL_OCV_ADJ_EN, 0); - if (ret < 0) - dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n", + if (ret < 0) { + dev_err(&info->pdev->dev, "register(%x) write error(%d)\n", AXP20X_CC_CTRL, ret); + return ret; + } /* Init charging current and voltage */ info->max_cc = info->pdata->max_cc; @@ -796,15 +810,21 @@ static void charger_init_hw_regs(struct axp288_chrg_info *info) cv = min(info->pdata->def_cv, info->max_cv); ret = axp288_charger_set_cc(info, cc); - if (ret < 0) - dev_warn(&info->pdev->dev, + if (ret < 0) { + dev_err(&info->pdev->dev, "error(%d) in setting CC\n", ret); + return ret; + } ret = axp288_charger_set_cv(info, cv); - if (ret < 0) - dev_warn(&info->pdev->dev, + if (ret < 0) { + dev_err(&info->pdev->dev, "error(%d) in setting CV\n", ret); + return ret; + } } + + return 0; } static int axp288_charger_probe(struct platform_device *pdev) @@ -916,7 +936,9 @@ static int axp288_charger_probe(struct platform_device *pdev) } } - charger_init_hw_regs(info); + ret = charger_init_hw_regs(info); + if (ret) + goto intr_reg_failed; return 0; -- cgit v1.2.3 From eac53b3664f592713655f5de59dc44bdd0cfc0bd Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 21 Dec 2016 15:36:47 +0100 Subject: power: supply: axp288_charger: Drop platform_data dependency When the axp288_charger driver was originally merged, it was merged with a dependency on some other driver providing platform data for it. However the battery-data-framework which should provide that data never got merged, so the axp288_charger as merged upstream has never worked, its probe method simply always returns -ENODEV. This commit removes the dependency on the platform_data instead reading back the charging current and charging voltage that the firmware has set and using those values as the maximum values the user may set. Signed-off-by: Hans de Goede Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp288_charger.c | 88 ++++++++++++----------------------- include/linux/mfd/axp20x.h | 7 --- 2 files changed, 30 insertions(+), 65 deletions(-) diff --git a/drivers/power/supply/axp288_charger.c b/drivers/power/supply/axp288_charger.c index f1e3b0ec3b82..76f7d292a2ea 100644 --- a/drivers/power/supply/axp288_charger.c +++ b/drivers/power/supply/axp288_charger.c @@ -143,7 +143,6 @@ enum { struct axp288_chrg_info { struct platform_device *pdev; - struct axp20x_chrg_pdata *pdata; struct regmap *regmap; struct regmap_irq_chip_data *regmap_irqc; int irq[CHRG_INTR_END]; @@ -769,60 +768,42 @@ static int charger_init_hw_regs(struct axp288_chrg_info *info) return ret; } - /* Init charging current and voltage */ - info->max_cc = info->pdata->max_cc; - info->max_cv = info->pdata->max_cv; - /* Read current charge voltage and current limit */ ret = regmap_read(info->regmap, AXP20X_CHRG_CTRL1, &val); if (ret < 0) { - /* Assume default if cannot read */ - info->cc = info->pdata->def_cc; - info->cv = info->pdata->def_cv; - } else { - /* Determine charge voltage */ - cv = (val & CHRG_CCCV_CV_MASK) >> CHRG_CCCV_CV_BIT_POS; - switch (cv) { - case CHRG_CCCV_CV_4100MV: - info->cv = CV_4100MV; - break; - case CHRG_CCCV_CV_4150MV: - info->cv = CV_4150MV; - break; - case CHRG_CCCV_CV_4200MV: - info->cv = CV_4200MV; - break; - case CHRG_CCCV_CV_4350MV: - info->cv = CV_4350MV; - break; - default: - info->cv = INT_MAX; - break; - } - - /* Determine charge current limit */ - cc = (ret & CHRG_CCCV_CC_MASK) >> CHRG_CCCV_CC_BIT_POS; - cc = (cc * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET; - info->cc = cc; + dev_err(&info->pdev->dev, "register(%x) read error(%d)\n", + AXP20X_CHRG_CTRL1, ret); + return ret; + } - /* Program default charging voltage and current */ - cc = min(info->pdata->def_cc, info->max_cc); - cv = min(info->pdata->def_cv, info->max_cv); + /* Determine charge voltage */ + cv = (val & CHRG_CCCV_CV_MASK) >> CHRG_CCCV_CV_BIT_POS; + switch (cv) { + case CHRG_CCCV_CV_4100MV: + info->cv = CV_4100MV; + break; + case CHRG_CCCV_CV_4150MV: + info->cv = CV_4150MV; + break; + case CHRG_CCCV_CV_4200MV: + info->cv = CV_4200MV; + break; + case CHRG_CCCV_CV_4350MV: + info->cv = CV_4350MV; + break; + } - ret = axp288_charger_set_cc(info, cc); - if (ret < 0) { - dev_err(&info->pdev->dev, - "error(%d) in setting CC\n", ret); - return ret; - } + /* Determine charge current limit */ + cc = (ret & CHRG_CCCV_CC_MASK) >> CHRG_CCCV_CC_BIT_POS; + cc = (cc * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET; + info->cc = cc; - ret = axp288_charger_set_cv(info, cv); - if (ret < 0) { - dev_err(&info->pdev->dev, - "error(%d) in setting CV\n", ret); - return ret; - } - } + /* + * Do not allow the user to configure higher settings then those + * set by the firmware + */ + info->max_cv = info->cv; + info->max_cc = info->cc; return 0; } @@ -841,15 +822,6 @@ static int axp288_charger_probe(struct platform_device *pdev) info->pdev = pdev; info->regmap = axp20x->regmap; info->regmap_irqc = axp20x->regmap_irqc; - info->pdata = pdev->dev.platform_data; - - if (!info->pdata) { - /* Try ACPI provided pdata via device properties */ - if (!device_property_present(&pdev->dev, - "axp288_charger_data\n")) - dev_err(&pdev->dev, "failed to get platform data\n"); - return -ENODEV; - } info->cable.edev = extcon_get_extcon_dev(AXP288_EXTCON_DEV_NAME); if (info->cable.edev == NULL) { diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h index a4860bc9b73d..e460fc42d63e 100644 --- a/include/linux/mfd/axp20x.h +++ b/include/linux/mfd/axp20x.h @@ -554,13 +554,6 @@ struct axp20x_fg_pdata { int thermistor_curve[MAX_THERM_CURVE_SIZE][2]; }; -struct axp20x_chrg_pdata { - int max_cc; - int max_cv; - int def_cc; - int def_cv; -}; - struct axp288_extcon_pdata { /* GPIO pin control to switch D+/D- lines b/w PMIC and SOC */ struct gpio_desc *gpio_mux_cntl; -- cgit v1.2.3 From 888f97435a856c2c5c6ca0b3337b68d595b5639e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 14 Dec 2016 17:38:53 +0100 Subject: power: supply: axp288_fuel_gauge: Drop platform_data dependency When the axp288_faul_gauge driver was originally merged, it was merged with a dependency on some other driver providing platform data for it. However the battery-data-framework which should provide that data never got merged, resulting in x86 tablets / laptops with an axp288 having no working battery monitor, as before this commit the driver would simply return -ENODEV if there is no platform data. This commit removes the dependency on the platform_data instead checking that the firmware has initialized the fuel-gauge and reading the info back from the pmic. What is missing from the read-back info is the table to map raw adc values to temperature, so this commit drops the temperature and temperature limits properties. The min voltage, charge design and model name info is also missing. Note that none of these are really important for userspace to have. All other functionality is preserved and actually made available by this commit. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=88471 Signed-off-by: Hans de Goede Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp288_fuel_gauge.c | 405 +++---------------------------- include/linux/mfd/axp20x.h | 22 -- 2 files changed, 33 insertions(+), 394 deletions(-) diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c index 539eb41504bb..326eb08beaa2 100644 --- a/drivers/power/supply/axp288_fuel_gauge.c +++ b/drivers/power/supply/axp288_fuel_gauge.c @@ -49,11 +49,6 @@ #define CHRG_CCCV_CV_4350MV 0x3 /* 4.35V */ #define CHRG_CCCV_CHG_EN (1 << 7) -#define CV_4100 4100 /* 4100mV */ -#define CV_4150 4150 /* 4150mV */ -#define CV_4200 4200 /* 4200mV */ -#define CV_4350 4350 /* 4350mV */ - #define TEMP_IRQ_CFG_QWBTU (1 << 0) #define TEMP_IRQ_CFG_WBTU (1 << 1) #define TEMP_IRQ_CFG_QWBTO (1 << 2) @@ -104,9 +99,7 @@ /* 1.1mV per LSB expressed in uV */ #define VOLTAGE_FROM_ADC(a) ((a * 11) / 10) -/* properties converted to tenths of degrees, uV, uA, uW */ -#define PROP_TEMP(a) ((a) * 10) -#define UNPROP_TEMP(a) ((a) / 10) +/* properties converted to uV, uA */ #define PROP_VOLT(a) ((a) * 1000) #define PROP_CURR(a) ((a) * 1000) @@ -122,13 +115,13 @@ enum { struct axp288_fg_info { struct platform_device *pdev; - struct axp20x_fg_pdata *pdata; struct regmap *regmap; struct regmap_irq_chip_data *regmap_irqc; int irq[AXP288_FG_INTR_NUM]; struct power_supply *bat; struct mutex lock; int status; + int max_volt; struct delayed_work status_monitor; struct dentry *debug_file; }; @@ -138,22 +131,14 @@ static enum power_supply_property fuel_gauge_props[] = { POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, - POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_VOLTAGE_OCV, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN, - POWER_SUPPLY_PROP_TEMP, - POWER_SUPPLY_PROP_TEMP_MAX, - POWER_SUPPLY_PROP_TEMP_MIN, - POWER_SUPPLY_PROP_TEMP_ALERT_MIN, - POWER_SUPPLY_PROP_TEMP_ALERT_MAX, POWER_SUPPLY_PROP_TECHNOLOGY, POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_NOW, - POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, - POWER_SUPPLY_PROP_MODEL_NAME, }; static int fuel_gauge_reg_readb(struct axp288_fg_info *info, int reg) @@ -417,102 +402,6 @@ current_read_fail: return ret; } -static int temp_to_adc(struct axp288_fg_info *info, int tval) -{ - int rntc = 0, i, ret, adc_val; - int rmin, rmax, tmin, tmax; - int tcsz = info->pdata->tcsz; - - /* get the Rntc resitance value for this temp */ - if (tval > info->pdata->thermistor_curve[0][1]) { - rntc = info->pdata->thermistor_curve[0][0]; - } else if (tval <= info->pdata->thermistor_curve[tcsz-1][1]) { - rntc = info->pdata->thermistor_curve[tcsz-1][0]; - } else { - for (i = 1; i < tcsz; i++) { - if (tval > info->pdata->thermistor_curve[i][1]) { - rmin = info->pdata->thermistor_curve[i-1][0]; - rmax = info->pdata->thermistor_curve[i][0]; - tmin = info->pdata->thermistor_curve[i-1][1]; - tmax = info->pdata->thermistor_curve[i][1]; - rntc = rmin + ((rmax - rmin) * - (tval - tmin) / (tmax - tmin)); - break; - } - } - } - - /* we need the current to calculate the proper adc voltage */ - ret = fuel_gauge_reg_readb(info, AXP20X_ADC_RATE); - if (ret < 0) { - dev_err(&info->pdev->dev, "%s:read err:%d\n", __func__, ret); - ret = 0x30; - } - - /* - * temperature is proportional to NTS thermistor resistance - * ADC_RATE[5-4] determines current, 00=20uA,01=40uA,10=60uA,11=80uA - * [12-bit ADC VAL] = R_NTC(Ω) * current / 800 - */ - adc_val = rntc * (20 + (20 * ((ret >> 4) & 0x3))) / 800; - - return adc_val; -} - -static int adc_to_temp(struct axp288_fg_info *info, int adc_val) -{ - int ret, r, i, tval = 0; - int rmin, rmax, tmin, tmax; - int tcsz = info->pdata->tcsz; - - ret = fuel_gauge_reg_readb(info, AXP20X_ADC_RATE); - if (ret < 0) { - dev_err(&info->pdev->dev, "%s:read err:%d\n", __func__, ret); - ret = 0x30; - } - - /* - * temperature is proportional to NTS thermistor resistance - * ADC_RATE[5-4] determines current, 00=20uA,01=40uA,10=60uA,11=80uA - * R_NTC(Ω) = [12-bit ADC VAL] * 800 / current - */ - r = adc_val * 800 / (20 + (20 * ((ret >> 4) & 0x3))); - - if (r < info->pdata->thermistor_curve[0][0]) { - tval = info->pdata->thermistor_curve[0][1]; - } else if (r >= info->pdata->thermistor_curve[tcsz-1][0]) { - tval = info->pdata->thermistor_curve[tcsz-1][1]; - } else { - for (i = 1; i < tcsz; i++) { - if (r < info->pdata->thermistor_curve[i][0]) { - rmin = info->pdata->thermistor_curve[i-1][0]; - rmax = info->pdata->thermistor_curve[i][0]; - tmin = info->pdata->thermistor_curve[i-1][1]; - tmax = info->pdata->thermistor_curve[i][1]; - tval = tmin + ((tmax - tmin) * - (r - rmin) / (rmax - rmin)); - break; - } - } - } - - return tval; -} - -static int fuel_gauge_get_btemp(struct axp288_fg_info *info, int *btemp) -{ - int ret, raw_val = 0; - - ret = pmic_read_adc_val("axp288-batt-temp", &raw_val, info); - if (ret < 0) - goto temp_read_fail; - - *btemp = adc_to_temp(info, raw_val); - -temp_read_fail: - return ret; -} - static int fuel_gauge_get_vocv(struct axp288_fg_info *info, int *vocv) { int ret, value; @@ -535,25 +424,14 @@ vocv_read_fail: static int fuel_gauge_battery_health(struct axp288_fg_info *info) { - int temp, vocv; - int ret, health = POWER_SUPPLY_HEALTH_UNKNOWN; - - ret = fuel_gauge_get_btemp(info, &temp); - if (ret < 0) - goto health_read_fail; + int ret, vocv, health = POWER_SUPPLY_HEALTH_UNKNOWN; ret = fuel_gauge_get_vocv(info, &vocv); if (ret < 0) goto health_read_fail; - if (vocv > info->pdata->max_volt) + if (vocv > info->max_volt) health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; - else if (temp > info->pdata->max_temp) - health = POWER_SUPPLY_HEALTH_OVERHEAT; - else if (temp < info->pdata->min_temp) - health = POWER_SUPPLY_HEALTH_COLD; - else if (vocv < info->pdata->min_volt) - health = POWER_SUPPLY_HEALTH_DEAD; else health = POWER_SUPPLY_HEALTH_GOOD; @@ -561,28 +439,6 @@ health_read_fail: return health; } -static int fuel_gauge_set_high_btemp_alert(struct axp288_fg_info *info) -{ - int ret, adc_val; - - /* program temperature threshold as 1/16 ADC value */ - adc_val = temp_to_adc(info, info->pdata->max_temp); - ret = fuel_gauge_reg_writeb(info, AXP20X_V_HTF_DISCHRG, adc_val >> 4); - - return ret; -} - -static int fuel_gauge_set_low_btemp_alert(struct axp288_fg_info *info) -{ - int ret, adc_val; - - /* program temperature threshold as 1/16 ADC value */ - adc_val = temp_to_adc(info, info->pdata->min_temp); - ret = fuel_gauge_reg_writeb(info, AXP20X_V_LTF_DISCHRG, adc_val >> 4); - - return ret; -} - static int fuel_gauge_get_property(struct power_supply *ps, enum power_supply_property prop, union power_supply_propval *val) @@ -643,20 +499,6 @@ static int fuel_gauge_get_property(struct power_supply *ps, goto fuel_gauge_read_err; val->intval = (ret & 0x0f); break; - case POWER_SUPPLY_PROP_TEMP: - ret = fuel_gauge_get_btemp(info, &value); - if (ret < 0) - goto fuel_gauge_read_err; - val->intval = PROP_TEMP(value); - break; - case POWER_SUPPLY_PROP_TEMP_MAX: - case POWER_SUPPLY_PROP_TEMP_ALERT_MAX: - val->intval = PROP_TEMP(info->pdata->max_temp); - break; - case POWER_SUPPLY_PROP_TEMP_MIN: - case POWER_SUPPLY_PROP_TEMP_ALERT_MIN: - val->intval = PROP_TEMP(info->pdata->min_temp); - break; case POWER_SUPPLY_PROP_TECHNOLOGY: val->intval = POWER_SUPPLY_TECHNOLOGY_LION; break; @@ -684,17 +526,8 @@ static int fuel_gauge_get_property(struct power_supply *ps, value |= (ret & FG_DES_CAP0_VAL_MASK); val->intval = value * FG_DES_CAP_RES_LSB; break; - case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: - val->intval = PROP_CURR(info->pdata->design_cap); - break; case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: - val->intval = PROP_VOLT(info->pdata->max_volt); - break; - case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: - val->intval = PROP_VOLT(info->pdata->min_volt); - break; - case POWER_SUPPLY_PROP_MODEL_NAME: - val->strval = info->pdata->battid; + val->intval = PROP_VOLT(info->max_volt); break; default: mutex_unlock(&info->lock); @@ -718,35 +551,6 @@ static int fuel_gauge_set_property(struct power_supply *ps, mutex_lock(&info->lock); switch (prop) { - case POWER_SUPPLY_PROP_STATUS: - info->status = val->intval; - break; - case POWER_SUPPLY_PROP_TEMP_MIN: - case POWER_SUPPLY_PROP_TEMP_ALERT_MIN: - if ((val->intval < PD_DEF_MIN_TEMP) || - (val->intval > PD_DEF_MAX_TEMP)) { - ret = -EINVAL; - break; - } - info->pdata->min_temp = UNPROP_TEMP(val->intval); - ret = fuel_gauge_set_low_btemp_alert(info); - if (ret < 0) - dev_err(&info->pdev->dev, - "temp alert min set fail:%d\n", ret); - break; - case POWER_SUPPLY_PROP_TEMP_MAX: - case POWER_SUPPLY_PROP_TEMP_ALERT_MAX: - if ((val->intval < PD_DEF_MIN_TEMP) || - (val->intval > PD_DEF_MAX_TEMP)) { - ret = -EINVAL; - break; - } - info->pdata->max_temp = UNPROP_TEMP(val->intval); - ret = fuel_gauge_set_high_btemp_alert(info); - if (ret < 0) - dev_err(&info->pdev->dev, - "temp alert max set fail:%d\n", ret); - break; case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN: if ((val->intval < 0) || (val->intval > 15)) { ret = -EINVAL; @@ -774,11 +578,6 @@ static int fuel_gauge_property_is_writeable(struct power_supply *psy, int ret; switch (psp) { - case POWER_SUPPLY_PROP_STATUS: - case POWER_SUPPLY_PROP_TEMP_MIN: - case POWER_SUPPLY_PROP_TEMP_ALERT_MIN: - case POWER_SUPPLY_PROP_TEMP_MAX: - case POWER_SUPPLY_PROP_TEMP_ALERT_MAX: case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN: ret = 1; break; @@ -863,158 +662,6 @@ static const struct power_supply_desc fuel_gauge_desc = { .external_power_changed = fuel_gauge_external_power_changed, }; -static int fuel_gauge_set_lowbatt_thresholds(struct axp288_fg_info *info) -{ - int ret; - u8 reg_val; - - ret = fuel_gauge_reg_readb(info, AXP20X_FG_RES); - if (ret < 0) { - dev_err(&info->pdev->dev, "%s:read err:%d\n", __func__, ret); - return ret; - } - ret = (ret & FG_REP_CAP_VAL_MASK); - - if (ret > FG_LOW_CAP_WARN_THR) - reg_val = FG_LOW_CAP_WARN_THR; - else if (ret > FG_LOW_CAP_CRIT_THR) - reg_val = FG_LOW_CAP_CRIT_THR; - else - reg_val = FG_LOW_CAP_SHDN_THR; - - reg_val |= FG_LOW_CAP_THR1_VAL; - ret = fuel_gauge_reg_writeb(info, AXP288_FG_LOW_CAP_REG, reg_val); - if (ret < 0) - dev_err(&info->pdev->dev, "%s:write err:%d\n", __func__, ret); - - return ret; -} - -static int fuel_gauge_program_vbatt_full(struct axp288_fg_info *info) -{ - int ret; - u8 val; - - ret = fuel_gauge_reg_readb(info, AXP20X_CHRG_CTRL1); - if (ret < 0) - goto fg_prog_ocv_fail; - else - val = (ret & ~CHRG_CCCV_CV_MASK); - - switch (info->pdata->max_volt) { - case CV_4100: - val |= (CHRG_CCCV_CV_4100MV << CHRG_CCCV_CV_BIT_POS); - break; - case CV_4150: - val |= (CHRG_CCCV_CV_4150MV << CHRG_CCCV_CV_BIT_POS); - break; - case CV_4200: - val |= (CHRG_CCCV_CV_4200MV << CHRG_CCCV_CV_BIT_POS); - break; - case CV_4350: - val |= (CHRG_CCCV_CV_4350MV << CHRG_CCCV_CV_BIT_POS); - break; - default: - val |= (CHRG_CCCV_CV_4200MV << CHRG_CCCV_CV_BIT_POS); - break; - } - - ret = fuel_gauge_reg_writeb(info, AXP20X_CHRG_CTRL1, val); -fg_prog_ocv_fail: - return ret; -} - -static int fuel_gauge_program_design_cap(struct axp288_fg_info *info) -{ - int ret; - - ret = fuel_gauge_reg_writeb(info, - AXP288_FG_DES_CAP1_REG, info->pdata->cap1); - if (ret < 0) - goto fg_prog_descap_fail; - - ret = fuel_gauge_reg_writeb(info, - AXP288_FG_DES_CAP0_REG, info->pdata->cap0); - -fg_prog_descap_fail: - return ret; -} - -static int fuel_gauge_program_ocv_curve(struct axp288_fg_info *info) -{ - int ret = 0, i; - - for (i = 0; i < OCV_CURVE_SIZE; i++) { - ret = fuel_gauge_reg_writeb(info, - AXP288_FG_OCV_CURVE_REG + i, info->pdata->ocv_curve[i]); - if (ret < 0) - goto fg_prog_ocv_fail; - } - -fg_prog_ocv_fail: - return ret; -} - -static int fuel_gauge_program_rdc_vals(struct axp288_fg_info *info) -{ - int ret; - - ret = fuel_gauge_reg_writeb(info, - AXP288_FG_RDC1_REG, info->pdata->rdc1); - if (ret < 0) - goto fg_prog_ocv_fail; - - ret = fuel_gauge_reg_writeb(info, - AXP288_FG_RDC0_REG, info->pdata->rdc0); - -fg_prog_ocv_fail: - return ret; -} - -static void fuel_gauge_init_config_regs(struct axp288_fg_info *info) -{ - int ret; - - /* - * check if the config data is already - * programmed and if so just return. - */ - - ret = fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP1_REG); - if (ret < 0) { - dev_warn(&info->pdev->dev, "CAP1 reg read err!!\n"); - } else if (!(ret & FG_DES_CAP1_VALID)) { - dev_info(&info->pdev->dev, "FG data needs to be initialized\n"); - } else { - dev_info(&info->pdev->dev, "FG data is already initialized\n"); - return; - } - - ret = fuel_gauge_program_vbatt_full(info); - if (ret < 0) - dev_err(&info->pdev->dev, "set vbatt full fail:%d\n", ret); - - ret = fuel_gauge_program_design_cap(info); - if (ret < 0) - dev_err(&info->pdev->dev, "set design cap fail:%d\n", ret); - - ret = fuel_gauge_program_rdc_vals(info); - if (ret < 0) - dev_err(&info->pdev->dev, "set rdc fail:%d\n", ret); - - ret = fuel_gauge_program_ocv_curve(info); - if (ret < 0) - dev_err(&info->pdev->dev, "set ocv curve fail:%d\n", ret); - - ret = fuel_gauge_set_lowbatt_thresholds(info); - if (ret < 0) - dev_err(&info->pdev->dev, "lowbatt thr set fail:%d\n", ret); - - ret = fuel_gauge_reg_writeb(info, AXP20X_CC_CTRL, 0xef); - if (ret < 0) - dev_err(&info->pdev->dev, "gauge cntl set fail:%d\n", ret); -} - static void fuel_gauge_init_irq(struct axp288_fg_info *info) { int ret, i, pirq; @@ -1054,17 +701,8 @@ intr_failed: static void fuel_gauge_init_hw_regs(struct axp288_fg_info *info) { - int ret; unsigned int val; - ret = fuel_gauge_set_high_btemp_alert(info); - if (ret < 0) - dev_err(&info->pdev->dev, "high batt temp set fail:%d\n", ret); - - ret = fuel_gauge_set_low_btemp_alert(info); - if (ret < 0) - dev_err(&info->pdev->dev, "low batt temp set fail:%d\n", ret); - /* enable interrupts */ val = fuel_gauge_reg_readb(info, AXP20X_IRQ3_EN); val |= TEMP_IRQ_CFG_MASK; @@ -1090,15 +728,39 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev) info->regmap = axp20x->regmap; info->regmap_irqc = axp20x->regmap_irqc; info->status = POWER_SUPPLY_STATUS_UNKNOWN; - info->pdata = pdev->dev.platform_data; - if (!info->pdata) - return -ENODEV; platform_set_drvdata(pdev, info); mutex_init(&info->lock); INIT_DELAYED_WORK(&info->status_monitor, fuel_gauge_status_monitor); + ret = fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP1_REG); + if (ret < 0) + return ret; + + if (!(ret & FG_DES_CAP1_VALID)) { + dev_err(&pdev->dev, "axp288 not configured by firmware\n"); + return -ENODEV; + } + + ret = fuel_gauge_reg_readb(info, AXP20X_CHRG_CTRL1); + if (ret < 0) + return ret; + switch ((ret & CHRG_CCCV_CV_MASK) >> CHRG_CCCV_CV_BIT_POS) { + case CHRG_CCCV_CV_4100MV: + info->max_volt = 4100; + break; + case CHRG_CCCV_CV_4150MV: + info->max_volt = 4150; + break; + case CHRG_CCCV_CV_4200MV: + info->max_volt = 4200; + break; + case CHRG_CCCV_CV_4350MV: + info->max_volt = 4350; + break; + } + psy_cfg.drv_data = info; info->bat = power_supply_register(&pdev->dev, &fuel_gauge_desc, &psy_cfg); if (IS_ERR(info->bat)) { @@ -1108,12 +770,11 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev) } fuel_gauge_create_debugfs(info); - fuel_gauge_init_config_regs(info); fuel_gauge_init_irq(info); fuel_gauge_init_hw_regs(info); schedule_delayed_work(&info->status_monitor, STATUS_MON_DELAY_JIFFIES); - return ret; + return 0; } static const struct platform_device_id axp288_fg_id_table[] = { diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h index e460fc42d63e..812806d6319b 100644 --- a/include/linux/mfd/axp20x.h +++ b/include/linux/mfd/axp20x.h @@ -532,28 +532,6 @@ struct axp20x_dev { const struct regmap_irq_chip *regmap_irq_chip; }; -#define BATTID_LEN 64 -#define OCV_CURVE_SIZE 32 -#define MAX_THERM_CURVE_SIZE 25 -#define PD_DEF_MIN_TEMP 0 -#define PD_DEF_MAX_TEMP 55 - -struct axp20x_fg_pdata { - char battid[BATTID_LEN + 1]; - int design_cap; - int min_volt; - int max_volt; - int max_temp; - int min_temp; - int cap1; - int cap0; - int rdc1; - int rdc0; - int ocv_curve[OCV_CURVE_SIZE]; - int tcsz; - int thermistor_curve[MAX_THERM_CURVE_SIZE][2]; -}; - struct axp288_extcon_pdata { /* GPIO pin control to switch D+/D- lines b/w PMIC and SOC */ struct gpio_desc *gpio_mux_cntl; -- cgit v1.2.3