summaryrefslogtreecommitdiffstats
path: root/drivers/power
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/supply/act8945a_charger.c86
1 files changed, 70 insertions, 16 deletions
diff --git a/drivers/power/supply/act8945a_charger.c b/drivers/power/supply/act8945a_charger.c
index af006680dd5c..a6bbaff5483e 100644
--- a/drivers/power/supply/act8945a_charger.c
+++ b/drivers/power/supply/act8945a_charger.c
@@ -94,16 +94,24 @@ static int act8945a_get_charger_state(struct regmap *regmap, int *val)
state &= APCH_STATE_CSTATE;
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)
*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
*val = POWER_SUPPLY_STATUS_NOT_CHARGING;
- } else if ((state == APCH_STATE_CSTATE_FAST) ||
- (state == APCH_STATE_CSTATE_PRE)) {
- *val = POWER_SUPPLY_STATUS_CHARGING;
- } else {
- *val = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ break;
}
return 0;
@@ -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)
{
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);
if (ret < 0)
@@ -129,9 +141,15 @@ static int act8945a_get_charge_type(struct regmap *regmap, int *val)
*val = POWER_SUPPLY_CHARGE_TYPE_FAST;
break;
case APCH_STATE_CSTATE_EOC:
+ *val = POWER_SUPPLY_CHARGE_TYPE_NONE;
+ break;
case APCH_STATE_CSTATE_DISABLED:
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;
@@ -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)
{
int ret;
- unsigned int status;
+ unsigned int status, state, config;
ret = regmap_read(regmap, ACT8945A_APCH_STATUS, &status);
if (ret < 0)
return ret;
- if (!(status & APCH_STATUS_TEMPDAT))
- *val = POWER_SUPPLY_HEALTH_OVERHEAT;
- else if (!(status & APCH_STATUS_INDAT))
- *val = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
- else if (status & APCH_STATUS_TIMRDAT)
- *val = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
- else
+ ret = regmap_read(regmap, ACT8945A_APCH_CFG, &config);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_read(regmap, ACT8945A_APCH_STATE, &state);
+ if (ret < 0)
+ 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;
+ break;
+ }
return 0;
}
@@ -224,7 +267,9 @@ static int act8945a_charger_config(struct device *dev,
u32 pre_time_out;
u32 input_voltage_threshold;
int chglev_pin;
+ int ret;
+ unsigned int tmp;
unsigned int value = 0;
if (!np) {
@@ -232,6 +277,15 @@ static int act8945a_charger_config(struct device *dev,
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,
"active-semi,chglev-gpios", 0, &flags);