Commit 1f0ba406 authored by Wenyou Yang's avatar Wenyou Yang Committed by Sebastian Reichel

power: supply: act8945a_charger: Improve state handling

When get the property, first check the charger state machine,
then check the status bit to decide what value is assigned to
the corresponding property.

Retain the SUSCHG bit of REG 0x71 when configure the timers to
avoid losting the charger suspending info after boot.
Signed-off-by: default avatarWenyou Yang <wenyou.yang@atmel.com>
Signed-off-by: default avatarFengguang Wu <fengguang.wu@intel.com>
Signed-off-by: default avatarSebastian Reichel <sre@kernel.org>
parent 6b021fc9
...@@ -94,16 +94,24 @@ static int act8945a_get_charger_state(struct regmap *regmap, int *val) ...@@ -94,16 +94,24 @@ static int act8945a_get_charger_state(struct regmap *regmap, int *val)
state &= APCH_STATE_CSTATE; state &= APCH_STATE_CSTATE;
state >>= APCH_STATE_CSTATE_SHIFT; state >>= APCH_STATE_CSTATE_SHIFT;
if (state == APCH_STATE_CSTATE_EOC) { switch (state) {
case APCH_STATE_CSTATE_PRE:
case APCH_STATE_CSTATE_FAST:
*val = POWER_SUPPLY_STATUS_CHARGING;
break;
case APCH_STATE_CSTATE_EOC:
if (status & APCH_STATUS_CHGDAT) if (status & APCH_STATUS_CHGDAT)
*val = POWER_SUPPLY_STATUS_FULL; *val = POWER_SUPPLY_STATUS_FULL;
else
*val = POWER_SUPPLY_STATUS_CHARGING;
break;
case APCH_STATE_CSTATE_DISABLED:
default:
if (!(status & APCH_STATUS_INDAT))
*val = POWER_SUPPLY_STATUS_DISCHARGING;
else else
*val = POWER_SUPPLY_STATUS_NOT_CHARGING; *val = POWER_SUPPLY_STATUS_NOT_CHARGING;
} else if ((state == APCH_STATE_CSTATE_FAST) || break;
(state == APCH_STATE_CSTATE_PRE)) {
*val = POWER_SUPPLY_STATUS_CHARGING;
} else {
*val = POWER_SUPPLY_STATUS_NOT_CHARGING;
} }
return 0; return 0;
...@@ -112,7 +120,11 @@ static int act8945a_get_charger_state(struct regmap *regmap, int *val) ...@@ -112,7 +120,11 @@ static int act8945a_get_charger_state(struct regmap *regmap, int *val)
static int act8945a_get_charge_type(struct regmap *regmap, int *val) static int act8945a_get_charge_type(struct regmap *regmap, int *val)
{ {
int ret; int ret;
unsigned int state; unsigned int status, state;
ret = regmap_read(regmap, ACT8945A_APCH_STATUS, &status);
if (ret < 0)
return ret;
ret = regmap_read(regmap, ACT8945A_APCH_STATE, &state); ret = regmap_read(regmap, ACT8945A_APCH_STATE, &state);
if (ret < 0) if (ret < 0)
...@@ -129,9 +141,15 @@ static int act8945a_get_charge_type(struct regmap *regmap, int *val) ...@@ -129,9 +141,15 @@ static int act8945a_get_charge_type(struct regmap *regmap, int *val)
*val = POWER_SUPPLY_CHARGE_TYPE_FAST; *val = POWER_SUPPLY_CHARGE_TYPE_FAST;
break; break;
case APCH_STATE_CSTATE_EOC: case APCH_STATE_CSTATE_EOC:
*val = POWER_SUPPLY_CHARGE_TYPE_NONE;
break;
case APCH_STATE_CSTATE_DISABLED: case APCH_STATE_CSTATE_DISABLED:
default: default:
*val = POWER_SUPPLY_CHARGE_TYPE_NONE; if (!(status & APCH_STATUS_INDAT))
*val = POWER_SUPPLY_CHARGE_TYPE_NONE;
else
*val = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
break;
} }
return 0; return 0;
...@@ -140,20 +158,45 @@ static int act8945a_get_charge_type(struct regmap *regmap, int *val) ...@@ -140,20 +158,45 @@ static int act8945a_get_charge_type(struct regmap *regmap, int *val)
static int act8945a_get_battery_health(struct regmap *regmap, int *val) static int act8945a_get_battery_health(struct regmap *regmap, int *val)
{ {
int ret; int ret;
unsigned int status; unsigned int status, state, config;
ret = regmap_read(regmap, ACT8945A_APCH_STATUS, &status); ret = regmap_read(regmap, ACT8945A_APCH_STATUS, &status);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (!(status & APCH_STATUS_TEMPDAT)) ret = regmap_read(regmap, ACT8945A_APCH_CFG, &config);
*val = POWER_SUPPLY_HEALTH_OVERHEAT; if (ret < 0)
else if (!(status & APCH_STATUS_INDAT)) return ret;
*val = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
else if (status & APCH_STATUS_TIMRDAT) ret = regmap_read(regmap, ACT8945A_APCH_STATE, &state);
*val = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE; if (ret < 0)
else return ret;
state &= APCH_STATE_CSTATE;
state >>= APCH_STATE_CSTATE_SHIFT;
switch (state) {
case APCH_STATE_CSTATE_DISABLED:
if (config & APCH_CFG_SUSCHG) {
*val = POWER_SUPPLY_HEALTH_UNKNOWN;
} else if (status & APCH_STATUS_INDAT) {
if (!(status & APCH_STATUS_TEMPDAT))
*val = POWER_SUPPLY_HEALTH_OVERHEAT;
else if (status & APCH_STATUS_TIMRDAT)
*val = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
else
*val = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
} else {
*val = POWER_SUPPLY_HEALTH_GOOD;
}
break;
case APCH_STATE_CSTATE_PRE:
case APCH_STATE_CSTATE_FAST:
case APCH_STATE_CSTATE_EOC:
default:
*val = POWER_SUPPLY_HEALTH_GOOD; *val = POWER_SUPPLY_HEALTH_GOOD;
break;
}
return 0; return 0;
} }
...@@ -224,7 +267,9 @@ static int act8945a_charger_config(struct device *dev, ...@@ -224,7 +267,9 @@ static int act8945a_charger_config(struct device *dev,
u32 pre_time_out; u32 pre_time_out;
u32 input_voltage_threshold; u32 input_voltage_threshold;
int chglev_pin; int chglev_pin;
int ret;
unsigned int tmp;
unsigned int value = 0; unsigned int value = 0;
if (!np) { if (!np) {
...@@ -232,6 +277,15 @@ static int act8945a_charger_config(struct device *dev, ...@@ -232,6 +277,15 @@ static int act8945a_charger_config(struct device *dev,
return -EINVAL; return -EINVAL;
} }
ret = regmap_read(regmap, ACT8945A_APCH_CFG, &tmp);
if (ret)
return ret;
if (tmp & APCH_CFG_SUSCHG) {
value |= APCH_CFG_SUSCHG;
dev_info(dev, "have been suspended\n");
}
chglev_pin = of_get_named_gpio_flags(np, chglev_pin = of_get_named_gpio_flags(np,
"active-semi,chglev-gpios", 0, &flags); "active-semi,chglev-gpios", 0, &flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment