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: Krzysztof Kozlowski <k.kozlowski@samsung.com> Signed-off-by: Sebastian Reichel <sre@kernel.org>
This commit is contained in:
parent
7524741f83
commit
dd18a66346
1 changed files with 73 additions and 36 deletions
|
@ -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)
|
||||||
* - 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, ®_data);
|
ret = max14577_read_reg(rmap, MAX14577_CHG_REG_CHG_CTRL2, ®_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, ®_data);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
max14577_read_reg(rmap, MAX14577_CHG_REG_STATUS3, ®_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 @@ state_set:
|
||||||
* - 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)
|
||||||
* 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, ®_data);
|
ret = max14577_read_reg(rmap, MAX14577_MUIC_REG_STATUS2, ®_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)
|
||||||
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)
|
||||||
* - 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, ®_data);
|
ret = max14577_read_reg(rmap, MAX14577_MUIC_REG_STATUS2, ®_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, ®_data);
|
ret = max14577_read_reg(rmap, MAX14577_CHG_REG_STATUS3, ®_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 @@ state_set:
|
||||||
* 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,
|
||||||
|
|
||||||
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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue