提交 dd18a663 编写于 作者: K Krzysztof Kozlowski 提交者: Sebastian Reichel

power_supply: max14577: Properly handle error conditions

Re-work and fix handling of errors when retrieving power supply
properties:

1. Return errno values directly from get_property() instead of
   storing 'unknown' as intval for given property.

2. Handle regmap_read() errors and return errno code. Previously the
   regmap_read() return code was ignored so an uninitialized value from
   the stack could be used for calculating the property.
Signed-off-by: NKrzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: NSebastian Reichel <sre@kernel.org>
上级 7524741f
...@@ -54,10 +54,10 @@ static enum max14577_muic_charger_type maxim_get_charger_type( ...@@ -54,10 +54,10 @@ static enum max14577_muic_charger_type maxim_get_charger_type(
} }
} }
static int max14577_get_charger_state(struct max14577_charger *chg) static int max14577_get_charger_state(struct max14577_charger *chg, int *val)
{ {
struct regmap *rmap = chg->max14577->regmap; struct regmap *rmap = chg->max14577->regmap;
int state = POWER_SUPPLY_STATUS_DISCHARGING; int ret;
u8 reg_data; u8 reg_data;
/* /*
...@@ -71,22 +71,32 @@ static int max14577_get_charger_state(struct max14577_charger *chg) ...@@ -71,22 +71,32 @@ static int max14577_get_charger_state(struct max14577_charger *chg)
* - handle properly dead-battery charging (respect timer) * - handle properly dead-battery charging (respect timer)
* - handle timers (fast-charge and prequal) /MBCCHGERR/ * - handle timers (fast-charge and prequal) /MBCCHGERR/
*/ */
max14577_read_reg(rmap, MAX14577_CHG_REG_CHG_CTRL2, &reg_data); ret = max14577_read_reg(rmap, MAX14577_CHG_REG_CHG_CTRL2, &reg_data);
if ((reg_data & CHGCTRL2_MBCHOSTEN_MASK) == 0) if (ret < 0)
goto state_set; goto out;
if ((reg_data & CHGCTRL2_MBCHOSTEN_MASK) == 0) {
*val = POWER_SUPPLY_STATUS_DISCHARGING;
goto out;
}
ret = max14577_read_reg(rmap, MAX14577_CHG_REG_STATUS3, &reg_data);
if (ret < 0)
goto out;
max14577_read_reg(rmap, MAX14577_CHG_REG_STATUS3, &reg_data);
if (reg_data & STATUS3_CGMBC_MASK) { if (reg_data & STATUS3_CGMBC_MASK) {
/* Charger or USB-cable is connected */ /* Charger or USB-cable is connected */
if (reg_data & STATUS3_EOC_MASK) if (reg_data & STATUS3_EOC_MASK)
state = POWER_SUPPLY_STATUS_FULL; *val = POWER_SUPPLY_STATUS_FULL;
else else
state = POWER_SUPPLY_STATUS_CHARGING; *val = POWER_SUPPLY_STATUS_CHARGING;
goto state_set; goto out;
} }
state_set: *val = POWER_SUPPLY_STATUS_DISCHARGING;
return state;
out:
return ret;
} }
/* /*
...@@ -94,8 +104,10 @@ static int max14577_get_charger_state(struct max14577_charger *chg) ...@@ -94,8 +104,10 @@ static int max14577_get_charger_state(struct max14577_charger *chg)
* - POWER_SUPPLY_CHARGE_TYPE_NONE * - POWER_SUPPLY_CHARGE_TYPE_NONE
* - POWER_SUPPLY_CHARGE_TYPE_FAST * - POWER_SUPPLY_CHARGE_TYPE_FAST
*/ */
static int max14577_get_charge_type(struct max14577_charger *chg) static int max14577_get_charge_type(struct max14577_charger *chg, int *val)
{ {
int ret, charging;
/* /*
* TODO: CHARGE_TYPE_TRICKLE (VCHGR_RC or EOC)? * TODO: CHARGE_TYPE_TRICKLE (VCHGR_RC or EOC)?
* As spec says: * As spec says:
...@@ -104,18 +116,29 @@ static int max14577_get_charge_type(struct max14577_charger *chg) ...@@ -104,18 +116,29 @@ static int max14577_get_charge_type(struct max14577_charger *chg)
* top-off timer starts. The device continues to trickle * top-off timer starts. The device continues to trickle
* charge the battery until the top-off timer runs out." * charge the battery until the top-off timer runs out."
*/ */
if (max14577_get_charger_state(chg) == POWER_SUPPLY_STATUS_CHARGING) ret = max14577_get_charger_state(chg, &charging);
return POWER_SUPPLY_CHARGE_TYPE_FAST; if (ret < 0)
return POWER_SUPPLY_CHARGE_TYPE_NONE; return ret;
if (charging == POWER_SUPPLY_STATUS_CHARGING)
*val = POWER_SUPPLY_CHARGE_TYPE_FAST;
else
*val = POWER_SUPPLY_CHARGE_TYPE_NONE;
return 0;
} }
static int max14577_get_online(struct max14577_charger *chg) static int max14577_get_online(struct max14577_charger *chg, int *val)
{ {
struct regmap *rmap = chg->max14577->regmap; struct regmap *rmap = chg->max14577->regmap;
u8 reg_data; u8 reg_data;
int ret;
enum max14577_muic_charger_type chg_type; enum max14577_muic_charger_type chg_type;
max14577_read_reg(rmap, MAX14577_MUIC_REG_STATUS2, &reg_data); ret = max14577_read_reg(rmap, MAX14577_MUIC_REG_STATUS2, &reg_data);
if (ret < 0)
return ret;
reg_data = ((reg_data & STATUS2_CHGTYP_MASK) >> STATUS2_CHGTYP_SHIFT); reg_data = ((reg_data & STATUS2_CHGTYP_MASK) >> STATUS2_CHGTYP_SHIFT);
chg_type = maxim_get_charger_type(chg->max14577->dev_type, reg_data); chg_type = maxim_get_charger_type(chg->max14577->dev_type, reg_data);
switch (chg_type) { switch (chg_type) {
...@@ -125,14 +148,17 @@ static int max14577_get_online(struct max14577_charger *chg) ...@@ -125,14 +148,17 @@ static int max14577_get_online(struct max14577_charger *chg)
case MAX14577_CHARGER_TYPE_SPECIAL_1A: case MAX14577_CHARGER_TYPE_SPECIAL_1A:
case MAX14577_CHARGER_TYPE_DEAD_BATTERY: case MAX14577_CHARGER_TYPE_DEAD_BATTERY:
case MAX77836_CHARGER_TYPE_SPECIAL_BIAS: case MAX77836_CHARGER_TYPE_SPECIAL_BIAS:
return 1; *val = 1;
break;
case MAX14577_CHARGER_TYPE_NONE: case MAX14577_CHARGER_TYPE_NONE:
case MAX14577_CHARGER_TYPE_DOWNSTREAM_PORT: case MAX14577_CHARGER_TYPE_DOWNSTREAM_PORT:
case MAX14577_CHARGER_TYPE_RESERVED: case MAX14577_CHARGER_TYPE_RESERVED:
case MAX77836_CHARGER_TYPE_RESERVED: case MAX77836_CHARGER_TYPE_RESERVED:
default: default:
return 0; *val = 0;
} }
return 0;
} }
/* /*
...@@ -141,29 +167,38 @@ static int max14577_get_online(struct max14577_charger *chg) ...@@ -141,29 +167,38 @@ static int max14577_get_online(struct max14577_charger *chg)
* - POWER_SUPPLY_HEALTH_OVERVOLTAGE * - POWER_SUPPLY_HEALTH_OVERVOLTAGE
* - POWER_SUPPLY_HEALTH_GOOD * - POWER_SUPPLY_HEALTH_GOOD
*/ */
static int max14577_get_battery_health(struct max14577_charger *chg) static int max14577_get_battery_health(struct max14577_charger *chg, int *val)
{ {
struct regmap *rmap = chg->max14577->regmap; struct regmap *rmap = chg->max14577->regmap;
int state = POWER_SUPPLY_HEALTH_GOOD; int ret;
u8 reg_data; u8 reg_data;
enum max14577_muic_charger_type chg_type; enum max14577_muic_charger_type chg_type;
max14577_read_reg(rmap, MAX14577_MUIC_REG_STATUS2, &reg_data); ret = max14577_read_reg(rmap, MAX14577_MUIC_REG_STATUS2, &reg_data);
if (ret < 0)
goto out;
reg_data = ((reg_data & STATUS2_CHGTYP_MASK) >> STATUS2_CHGTYP_SHIFT); reg_data = ((reg_data & STATUS2_CHGTYP_MASK) >> STATUS2_CHGTYP_SHIFT);
chg_type = maxim_get_charger_type(chg->max14577->dev_type, reg_data); chg_type = maxim_get_charger_type(chg->max14577->dev_type, reg_data);
if (chg_type == MAX14577_CHARGER_TYPE_DEAD_BATTERY) { if (chg_type == MAX14577_CHARGER_TYPE_DEAD_BATTERY) {
state = POWER_SUPPLY_HEALTH_DEAD; *val = POWER_SUPPLY_HEALTH_DEAD;
goto state_set; goto out;
} }
max14577_read_reg(rmap, MAX14577_CHG_REG_STATUS3, &reg_data); ret = max14577_read_reg(rmap, MAX14577_CHG_REG_STATUS3, &reg_data);
if (ret < 0)
goto out;
if (reg_data & STATUS3_OVP_MASK) { if (reg_data & STATUS3_OVP_MASK) {
state = POWER_SUPPLY_HEALTH_OVERVOLTAGE; *val = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
goto state_set; goto out;
} }
state_set: /* Not dead, not overvoltage */
return state; *val = POWER_SUPPLY_HEALTH_GOOD;
out:
return ret;
} }
/* /*
...@@ -171,9 +206,11 @@ static int max14577_get_battery_health(struct max14577_charger *chg) ...@@ -171,9 +206,11 @@ static int max14577_get_battery_health(struct max14577_charger *chg)
* The max14577 chip doesn't report any status of battery presence. * The max14577 chip doesn't report any status of battery presence.
* Lets assume that it will always be used with some battery. * Lets assume that it will always be used with some battery.
*/ */
static int max14577_get_present(struct max14577_charger *chg) static int max14577_get_present(struct max14577_charger *chg, int *val)
{ {
return 1; *val = 1;
return 0;
} }
static int max14577_set_fast_charge_timer(struct max14577_charger *chg, static int max14577_set_fast_charge_timer(struct max14577_charger *chg,
...@@ -391,19 +428,19 @@ static int max14577_charger_get_property(struct power_supply *psy, ...@@ -391,19 +428,19 @@ static int max14577_charger_get_property(struct power_supply *psy,
switch (psp) { switch (psp) {
case POWER_SUPPLY_PROP_STATUS: case POWER_SUPPLY_PROP_STATUS:
val->intval = max14577_get_charger_state(chg); ret = max14577_get_charger_state(chg, &val->intval);
break; break;
case POWER_SUPPLY_PROP_CHARGE_TYPE: case POWER_SUPPLY_PROP_CHARGE_TYPE:
val->intval = max14577_get_charge_type(chg); ret = max14577_get_charge_type(chg, &val->intval);
break; break;
case POWER_SUPPLY_PROP_HEALTH: case POWER_SUPPLY_PROP_HEALTH:
val->intval = max14577_get_battery_health(chg); ret = max14577_get_battery_health(chg, &val->intval);
break; break;
case POWER_SUPPLY_PROP_PRESENT: case POWER_SUPPLY_PROP_PRESENT:
val->intval = max14577_get_present(chg); ret = max14577_get_present(chg, &val->intval);
break; break;
case POWER_SUPPLY_PROP_ONLINE: case POWER_SUPPLY_PROP_ONLINE:
val->intval = max14577_get_online(chg); ret = max14577_get_online(chg, &val->intval);
break; break;
case POWER_SUPPLY_PROP_MODEL_NAME: case POWER_SUPPLY_PROP_MODEL_NAME:
BUILD_BUG_ON(ARRAY_SIZE(model_names) != MAXIM_DEVICE_TYPE_NUM); BUILD_BUG_ON(ARRAY_SIZE(model_names) != MAXIM_DEVICE_TYPE_NUM);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
新手
引导
客服 返回
顶部