diff options
-rw-r--r-- | Documentation/devicetree/bindings/power/reset/atmel,sama5d2-shdwc.yaml | 5 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.yaml | 1 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/power/supply/x-powers,axp20x-battery-power-supply.yaml | 20 | ||||
-rw-r--r-- | drivers/mfd/axp20x.c | 1 | ||||
-rw-r--r-- | drivers/power/supply/axp20x_battery.c | 21 | ||||
-rw-r--r-- | drivers/power/supply/axp20x_usb_power.c | 2 | ||||
-rw-r--r-- | drivers/power/supply/bq27xxx_battery.c | 55 | ||||
-rw-r--r-- | drivers/power/supply/max1720x_battery.c | 49 | ||||
-rw-r--r-- | include/linux/mfd/axp20x.h | 1 | ||||
-rw-r--r-- | include/linux/power/bq27xxx_battery.h | 1 |
10 files changed, 147 insertions, 9 deletions
diff --git a/Documentation/devicetree/bindings/power/reset/atmel,sama5d2-shdwc.yaml b/Documentation/devicetree/bindings/power/reset/atmel,sama5d2-shdwc.yaml index 0735ceb7c103..9c34249b2d6d 100644 --- a/Documentation/devicetree/bindings/power/reset/atmel,sama5d2-shdwc.yaml +++ b/Documentation/devicetree/bindings/power/reset/atmel,sama5d2-shdwc.yaml @@ -17,6 +17,11 @@ properties: compatible: oneOf: - items: + - enum: + - microchip,sama7d65-shdwc + - const: microchip,sama7g5-shdwc + - const: syscon + - items: - const: microchip,sama7g5-shdwc - const: syscon - enum: diff --git a/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.yaml b/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.yaml index 799831636194..079ad977b907 100644 --- a/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.yaml +++ b/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.yaml @@ -46,7 +46,6 @@ properties: required: - compatible - - interrupts additionalProperties: false diff --git a/Documentation/devicetree/bindings/power/supply/x-powers,axp20x-battery-power-supply.yaml b/Documentation/devicetree/bindings/power/supply/x-powers,axp20x-battery-power-supply.yaml index 5ccd375eb294..3504c76a01d8 100644 --- a/Documentation/devicetree/bindings/power/supply/x-powers,axp20x-battery-power-supply.yaml +++ b/Documentation/devicetree/bindings/power/supply/x-powers,axp20x-battery-power-supply.yaml @@ -14,9 +14,6 @@ maintainers: - Chen-Yu Tsai <wens@csie.org> - Sebastian Reichel <sre@kernel.org> -allOf: - - $ref: power-supply.yaml# - properties: compatible: oneOf: @@ -35,7 +32,24 @@ properties: this gauge. $ref: /schemas/types.yaml#/definitions/phandle + x-powers,no-thermistor: + type: boolean + description: Indicates that no thermistor is connected to the TS pin + required: - compatible +allOf: + - $ref: power-supply.yaml# + - if: + not: + properties: + compatible: + contains: + enum: + - x-powers,axp717-battery-power-supply + then: + properties: + x-powers,no-thermistor: false + additionalProperties: false diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index cff56deba24f..e9914e8a29a3 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -224,6 +224,7 @@ static const struct regmap_range axp717_writeable_ranges[] = { regmap_reg_range(AXP717_VSYS_V_POWEROFF, AXP717_VSYS_V_POWEROFF), regmap_reg_range(AXP717_IRQ0_EN, AXP717_IRQ4_EN), regmap_reg_range(AXP717_IRQ0_STATE, AXP717_IRQ4_STATE), + regmap_reg_range(AXP717_TS_PIN_CFG, AXP717_TS_PIN_CFG), regmap_reg_range(AXP717_ICC_CHG_SET, AXP717_CV_CHG_SET), regmap_reg_range(AXP717_DCDC_OUTPUT_CONTROL, AXP717_CPUSLDO_CONTROL), regmap_reg_range(AXP717_ADC_CH_EN_CONTROL, AXP717_ADC_CH_EN_CONTROL), diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c index fa27195f074e..010ac6e67b16 100644 --- a/drivers/power/supply/axp20x_battery.c +++ b/drivers/power/supply/axp20x_battery.c @@ -89,6 +89,8 @@ #define AXP717_BAT_CC_MIN_UA 0 #define AXP717_BAT_CC_MAX_UA 3008000 +#define AXP717_TS_PIN_DISABLE BIT(4) + struct axp20x_batt_ps; struct axp_data { @@ -117,6 +119,7 @@ struct axp20x_batt_ps { /* Maximum constant charge current */ unsigned int max_ccc; const struct axp_data *data; + bool ts_disable; }; static int axp20x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt, @@ -985,6 +988,24 @@ static void axp717_set_battery_info(struct platform_device *pdev, int ccc = info->constant_charge_current_max_ua; int val; + axp_batt->ts_disable = (device_property_read_bool(axp_batt->dev, + "x-powers,no-thermistor")); + + /* + * Under rare conditions an incorrectly programmed efuse for + * the temp sensor on the PMIC may trigger a fault condition. + * Allow users to hard-code if the ts pin is not used to work + * around this problem. Note that this requires the battery + * be correctly defined in the device tree with a monitored + * battery node. + */ + if (axp_batt->ts_disable) { + regmap_update_bits(axp_batt->regmap, + AXP717_TS_PIN_CFG, + AXP717_TS_PIN_DISABLE, + AXP717_TS_PIN_DISABLE); + } + if (vmin > 0 && axp717_set_voltage_min_design(axp_batt, vmin)) dev_err(&pdev->dev, "couldn't set voltage_min_design\n"); diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c index 9722912268fe..1c30851054ae 100644 --- a/drivers/power/supply/axp20x_usb_power.c +++ b/drivers/power/supply/axp20x_usb_power.c @@ -492,7 +492,7 @@ static int axp717_usb_power_set_input_current_limit(struct axp20x_usb_power *pow if (power->max_input_cur && (intval > power->max_input_cur)) { dev_warn(power->dev, - "reqested current %d clamped to max current %d\n", + "requested current %d clamped to max current %d\n", intval, power->max_input_cur); intval = power->max_input_cur; } diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c index 90a5bccfc6b9..6a1e4b6875d2 100644 --- a/drivers/power/supply/bq27xxx_battery.c +++ b/drivers/power/supply/bq27xxx_battery.c @@ -124,6 +124,7 @@ enum bq27xxx_reg_index { BQ27XXX_DM_DATA, /* Block Data */ BQ27XXX_DM_CKSUM, /* Block Data Checksum */ BQ27XXX_REG_SEDVF, /* End-of-discharge Voltage */ + BQ27XXX_REG_PKCFG, /* Pack Configuration */ BQ27XXX_REG_MAX, /* sentinel */ }; @@ -161,6 +162,7 @@ static u8 [BQ27XXX_DM_DATA] = INVALID_REG_ADDR, [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR, [BQ27XXX_REG_SEDVF] = 0x77, + [BQ27XXX_REG_PKCFG] = 0x7C, }, bq27010_regs[BQ27XXX_REG_MAX] = { [BQ27XXX_REG_CTRL] = 0x00, @@ -187,6 +189,7 @@ static u8 [BQ27XXX_DM_DATA] = INVALID_REG_ADDR, [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR, [BQ27XXX_REG_SEDVF] = 0x77, + [BQ27XXX_REG_PKCFG] = 0x7C, }, bq2750x_regs[BQ27XXX_REG_MAX] = { [BQ27XXX_REG_CTRL] = 0x00, @@ -583,6 +586,7 @@ static enum power_supply_property bq27000_props[] = { POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_MANUFACTURER, POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, }; static enum power_supply_property bq27010_props[] = { @@ -604,6 +608,7 @@ static enum power_supply_property bq27010_props[] = { POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_MANUFACTURER, POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, }; #define bq2750x_props bq27510g3_props @@ -1918,7 +1923,6 @@ static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di) cache.flags = -1; /* read error */ if (cache.flags >= 0) { cache.capacity = bq27xxx_battery_read_soc(di); - di->cache.flags = cache.flags; /* * On gauges with signed current reporting the current must be @@ -2045,6 +2049,35 @@ static int bq27xxx_battery_voltage(struct bq27xxx_device_info *di, } /* + * Return the design maximum battery Voltage in microvolts, or < 0 if something + * fails. The programmed value of the maximum battery voltage is determined by + * QV0 and QV1 (bits 5 and 6) in the Pack Configuration register. + */ +static int bq27xxx_battery_read_dmax_volt(struct bq27xxx_device_info *di, + union power_supply_propval *val) +{ + int reg_val, qv; + + if (di->voltage_max_design > 0) { + val->intval = di->voltage_max_design; + return 0; + } + + reg_val = bq27xxx_read(di, BQ27XXX_REG_PKCFG, true); + if (reg_val < 0) { + dev_err(di->dev, "error reading design max voltage\n"); + return reg_val; + } + + qv = (reg_val >> 5) & 0x3; + val->intval = 3968000 + 48000 * qv; + + di->voltage_max_design = val->intval; + + return 0; +} + +/* * Return the design minimum battery Voltage in microvolts * Or < 0 if something fails. */ @@ -2115,6 +2148,10 @@ static int bq27xxx_battery_get_property(struct power_supply *psy, break; case POWER_SUPPLY_PROP_CAPACITY: ret = bq27xxx_simple_value(di->cache.capacity, val); + /* If 0 is reported, it is expected that EDVF is also set */ + if (!ret && di->opts & BQ27XXX_O_ZERO && + !(di->cache.flags & BQ27000_FLAG_EDVF)) + return -EINVAL; break; case POWER_SUPPLY_PROP_CAPACITY_LEVEL: ret = bq27xxx_battery_capacity_level(di, val); @@ -2138,10 +2175,15 @@ static int bq27xxx_battery_get_property(struct power_supply *psy, val->intval = POWER_SUPPLY_TECHNOLOGY_LION; break; case POWER_SUPPLY_PROP_CHARGE_NOW: - if (di->regs[BQ27XXX_REG_NAC] != INVALID_REG_ADDR) + if (di->regs[BQ27XXX_REG_NAC] != INVALID_REG_ADDR) { ret = bq27xxx_battery_read_nac(di, val); - else + /* If 0 is reported, it is expected that EDVF is also set */ + if (!ret && di->opts & BQ27XXX_O_ZERO && + !(di->cache.flags & BQ27000_FLAG_EDVF)) + return -EINVAL; + } else { ret = bq27xxx_battery_read_rc(di, val); + } break; case POWER_SUPPLY_PROP_CHARGE_FULL: ret = bq27xxx_battery_read_fcc(di, val); @@ -2158,11 +2200,18 @@ static int bq27xxx_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: ret = bq27xxx_battery_read_dmin_volt(di, val); break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + ret = bq27xxx_battery_read_dmax_volt(di, val); + break; case POWER_SUPPLY_PROP_CYCLE_COUNT: ret = bq27xxx_battery_read_cyct(di, val); break; case POWER_SUPPLY_PROP_ENERGY_NOW: ret = bq27xxx_battery_read_energy(di, val); + /* If 0 is reported, it is expected that EDVF is also set */ + if (!ret && di->opts & BQ27XXX_O_ZERO && + !(di->cache.flags & BQ27000_FLAG_EDVF)) + return -EINVAL; break; case POWER_SUPPLY_PROP_POWER_AVG: ret = bq27xxx_battery_pwr_avg(di, val); diff --git a/drivers/power/supply/max1720x_battery.c b/drivers/power/supply/max1720x_battery.c index 11580e414713..c1eaf3f7a782 100644 --- a/drivers/power/supply/max1720x_battery.c +++ b/drivers/power/supply/max1720x_battery.c @@ -29,6 +29,11 @@ /* ModelGauge m5 */ #define MAX172XX_STATUS 0x00 /* Status */ #define MAX172XX_STATUS_BAT_ABSENT BIT(3) /* Battery absent */ +#define MAX172XX_STATUS_IMX BIT(6) /* Maximum Current Alert Threshold Exceeded */ +#define MAX172XX_STATUS_VMN BIT(8) /* Minimum Voltage Alert Threshold Exceeded */ +#define MAX172XX_STATUS_TMN BIT(9) /* Minimum Temperature Alert Threshold Exceeded */ +#define MAX172XX_STATUS_VMX BIT(12) /* Maximum Voltage Alert Threshold Exceeded */ +#define MAX172XX_STATUS_TMX BIT(13) /* Maximum Temperature Alert Threshold Exceeded */ #define MAX172XX_REPCAP 0x05 /* Average capacity */ #define MAX172XX_REPSOC 0x06 /* Percentage of charge */ #define MAX172XX_TEMP 0x08 /* Temperature */ @@ -250,6 +255,7 @@ static const struct nvmem_cell_info max1720x_nvmem_cells[] = { }; static const enum power_supply_property max1720x_battery_props[] = { + POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_VOLTAGE_NOW, @@ -302,7 +308,7 @@ static int max172xx_temperature_to_ps(unsigned int reg) /* * Calculating current registers resolution: * - * RSense stored in 10^-5 Ohm, so mesaurment voltage must be + * RSense stored in 10^-5 Ohm, so measurement voltage must be * in 10^-11 Volts for get current in uA. * 16 bit current reg fullscale +/-51.2mV is 102400 uV. * So: 102400 / 65535 * 10^5 = 156252 @@ -314,6 +320,43 @@ static int max172xx_current_to_voltage(unsigned int reg) return val * 156252; } +static int max172xx_battery_health(struct max1720x_device_info *info, + unsigned int *health) +{ + unsigned int status; + int ret; + + ret = regmap_read(info->regmap, MAX172XX_STATUS, &status); + if (ret < 0) + return ret; + + if (status & MAX172XX_STATUS_VMN) + *health = POWER_SUPPLY_HEALTH_DEAD; + else if (status & MAX172XX_STATUS_VMX) + *health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; + else if (status & MAX172XX_STATUS_TMN) + *health = POWER_SUPPLY_HEALTH_COLD; + else if (status & MAX172XX_STATUS_TMX) + *health = POWER_SUPPLY_HEALTH_OVERHEAT; + else if (status & MAX172XX_STATUS_IMX) + *health = POWER_SUPPLY_HEALTH_OVERCURRENT; + else + *health = POWER_SUPPLY_HEALTH_GOOD; + + /* Clear events which are not self-clearing to detect next events */ + if (status > 0 && status != MAX172XX_STATUS_IMX) { + ret = regmap_set_bits(info->regmap, MAX172XX_STATUS, + MAX172XX_STATUS_VMN | + MAX172XX_STATUS_VMX | + MAX172XX_STATUS_TMN | + MAX172XX_STATUS_TMX); + if (ret < 0) + return ret; + } + + return 0; +} + static int max1720x_battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -323,6 +366,10 @@ static int max1720x_battery_get_property(struct power_supply *psy, int ret = 0; switch (psp) { + case POWER_SUPPLY_PROP_HEALTH: + ret = max172xx_battery_health(info, ®_val); + val->intval = reg_val; + break; case POWER_SUPPLY_PROP_PRESENT: /* * POWER_SUPPLY_PROP_PRESENT will always readable via diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h index c3df0e615fbf..3c5aecf1d4b5 100644 --- a/include/linux/mfd/axp20x.h +++ b/include/linux/mfd/axp20x.h @@ -137,6 +137,7 @@ enum axp20x_variants { #define AXP717_IRQ2_STATE 0x4a #define AXP717_IRQ3_STATE 0x4b #define AXP717_IRQ4_STATE 0x4c +#define AXP717_TS_PIN_CFG 0x50 #define AXP717_ICC_CHG_SET 0x62 #define AXP717_ITERM_CHG_SET 0x63 #define AXP717_CV_CHG_SET 0x64 diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h index 6b190639b08e..d56e1276aafe 100644 --- a/include/linux/power/bq27xxx_battery.h +++ b/include/linux/power/bq27xxx_battery.h @@ -62,6 +62,7 @@ struct bq27xxx_device_info { struct bq27xxx_reg_cache cache; int charge_design_full; int voltage_min_design; + int voltage_max_design; bool removed; unsigned long last_update; union power_supply_propval last_status; |