Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ed522b3 authored by Krzysztof Kozlowski's avatar Krzysztof Kozlowski Committed by Sebastian Reichel
Browse files

power_supply: max77693: 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 when getting 'online' and 'present'
   proprties 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: default avatarKrzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: default avatarSebastian Reichel <sre@kernel.org>
parent 213feb51
Loading
Loading
Loading
Loading
+55 −44
Original line number Diff line number Diff line
@@ -38,13 +38,14 @@ struct max77693_charger {
	u32 charge_input_threshold_volt;
};

static int max77693_get_charger_state(struct regmap *regmap)
static int max77693_get_charger_state(struct regmap *regmap, int *val)
{
	int state;
	int ret;
	unsigned int data;

	if (regmap_read(regmap, MAX77693_CHG_REG_CHG_DETAILS_01, &data) < 0)
		return POWER_SUPPLY_STATUS_UNKNOWN;
	ret = regmap_read(regmap, MAX77693_CHG_REG_CHG_DETAILS_01, &data);
	if (ret < 0)
		return ret;

	data &= CHG_DETAILS_01_CHG_MASK;
	data >>= CHG_DETAILS_01_CHG_SHIFT;
@@ -56,35 +57,36 @@ static int max77693_get_charger_state(struct regmap *regmap)
	case MAX77693_CHARGING_TOP_OFF:
	/* In high temp the charging current is reduced, but still charging */
	case MAX77693_CHARGING_HIGH_TEMP:
		state = POWER_SUPPLY_STATUS_CHARGING;
		*val = POWER_SUPPLY_STATUS_CHARGING;
		break;
	case MAX77693_CHARGING_DONE:
		state = POWER_SUPPLY_STATUS_FULL;
		*val = POWER_SUPPLY_STATUS_FULL;
		break;
	case MAX77693_CHARGING_TIMER_EXPIRED:
	case MAX77693_CHARGING_THERMISTOR_SUSPEND:
		state = POWER_SUPPLY_STATUS_NOT_CHARGING;
		*val = POWER_SUPPLY_STATUS_NOT_CHARGING;
		break;
	case MAX77693_CHARGING_OFF:
	case MAX77693_CHARGING_OVER_TEMP:
	case MAX77693_CHARGING_WATCHDOG_EXPIRED:
		state = POWER_SUPPLY_STATUS_DISCHARGING;
		*val = POWER_SUPPLY_STATUS_DISCHARGING;
		break;
	case MAX77693_CHARGING_RESERVED:
	default:
		state = POWER_SUPPLY_STATUS_UNKNOWN;
		*val = POWER_SUPPLY_STATUS_UNKNOWN;
	}

	return state;
	return 0;
}

static int max77693_get_charge_type(struct regmap *regmap)
static int max77693_get_charge_type(struct regmap *regmap, int *val)
{
	int state;
	int ret;
	unsigned int data;

	if (regmap_read(regmap, MAX77693_CHG_REG_CHG_DETAILS_01, &data) < 0)
		return POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
	ret = regmap_read(regmap, MAX77693_CHG_REG_CHG_DETAILS_01, &data);
	if (ret < 0)
		return ret;

	data &= CHG_DETAILS_01_CHG_MASK;
	data >>= CHG_DETAILS_01_CHG_SHIFT;
@@ -96,13 +98,13 @@ static int max77693_get_charge_type(struct regmap *regmap)
	 * 100 and 250 mA. It is higher than prequalification current.
	 */
	case MAX77693_CHARGING_TOP_OFF:
		state = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
		*val = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
		break;
	case MAX77693_CHARGING_FAST_CONST_CURRENT:
	case MAX77693_CHARGING_FAST_CONST_VOLTAGE:
	/* In high temp the charging current is reduced, but still charging */
	case MAX77693_CHARGING_HIGH_TEMP:
		state = POWER_SUPPLY_CHARGE_TYPE_FAST;
		*val = POWER_SUPPLY_CHARGE_TYPE_FAST;
		break;
	case MAX77693_CHARGING_DONE:
	case MAX77693_CHARGING_TIMER_EXPIRED:
@@ -110,14 +112,14 @@ static int max77693_get_charge_type(struct regmap *regmap)
	case MAX77693_CHARGING_OFF:
	case MAX77693_CHARGING_OVER_TEMP:
	case MAX77693_CHARGING_WATCHDOG_EXPIRED:
		state = POWER_SUPPLY_CHARGE_TYPE_NONE;
		*val = POWER_SUPPLY_CHARGE_TYPE_NONE;
		break;
	case MAX77693_CHARGING_RESERVED:
	default:
		state = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
		*val = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
	}

	return state;
	return 0;
}

/*
@@ -129,69 +131,78 @@ static int max77693_get_charge_type(struct regmap *regmap)
 *  - POWER_SUPPLY_HEALTH_UNKNOWN
 *  - POWER_SUPPLY_HEALTH_UNSPEC_FAILURE
 */
static int max77693_get_battery_health(struct regmap *regmap)
static int max77693_get_battery_health(struct regmap *regmap, int *val)
{
	int state;
	int ret;
	unsigned int data;

	if (regmap_read(regmap, MAX77693_CHG_REG_CHG_DETAILS_01, &data) < 0)
		return POWER_SUPPLY_HEALTH_UNKNOWN;
	ret = regmap_read(regmap, MAX77693_CHG_REG_CHG_DETAILS_01, &data);
	if (ret < 0)
		return ret;

	data &= CHG_DETAILS_01_BAT_MASK;
	data >>= CHG_DETAILS_01_BAT_SHIFT;

	switch (data) {
	case MAX77693_BATTERY_NOBAT:
		state = POWER_SUPPLY_HEALTH_DEAD;
		*val = POWER_SUPPLY_HEALTH_DEAD;
		break;
	case MAX77693_BATTERY_PREQUALIFICATION:
	case MAX77693_BATTERY_GOOD:
	case MAX77693_BATTERY_LOWVOLTAGE:
		state = POWER_SUPPLY_HEALTH_GOOD;
		*val = POWER_SUPPLY_HEALTH_GOOD;
		break;
	case MAX77693_BATTERY_TIMER_EXPIRED:
		/*
		 * Took longer to charge than expected, charging suspended.
		 * Damaged battery?
		 */
		state = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
		*val = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
		break;
	case MAX77693_BATTERY_OVERVOLTAGE:
		state = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
		*val = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
		break;
	case MAX77693_BATTERY_OVERCURRENT:
		state = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
		*val = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
		break;
	case MAX77693_BATTERY_RESERVED:
	default:
		state = POWER_SUPPLY_HEALTH_UNKNOWN;
		*val = POWER_SUPPLY_HEALTH_UNKNOWN;
		break;
	}

	return state;
	return 0;
}

static int max77693_get_present(struct regmap *regmap)
static int max77693_get_present(struct regmap *regmap, int *val)
{
	unsigned int data;
	int ret;

	/*
	 * Read CHG_INT_OK register. High DETBAT bit here should be
	 * equal to value 0x0 in CHG_DETAILS_01/BAT field.
	 */
	regmap_read(regmap, MAX77693_CHG_REG_CHG_INT_OK, &data);
	if (data & CHG_INT_OK_DETBAT_MASK)
	ret = regmap_read(regmap, MAX77693_CHG_REG_CHG_INT_OK, &data);
	if (ret < 0)
		return ret;

	*val = (data & CHG_INT_OK_DETBAT_MASK) ? 0 : 1;

	return 0;
	return 1;
}

static int max77693_get_online(struct regmap *regmap)
static int max77693_get_online(struct regmap *regmap, int *val)
{
	unsigned int data;
	int ret;

	ret = regmap_read(regmap, MAX77693_CHG_REG_CHG_INT_OK, &data);
	if (ret < 0)
		return ret;

	*val = (data & CHG_INT_OK_CHGIN_MASK) ? 1 : 0;

	regmap_read(regmap, MAX77693_CHG_REG_CHG_INT_OK, &data);
	if (data & CHG_INT_OK_CHGIN_MASK)
		return 1;
	return 0;
}

@@ -217,19 +228,19 @@ static int max77693_charger_get_property(struct power_supply *psy,

	switch (psp) {
	case POWER_SUPPLY_PROP_STATUS:
		val->intval = max77693_get_charger_state(regmap);
		ret = max77693_get_charger_state(regmap, &val->intval);
		break;
	case POWER_SUPPLY_PROP_CHARGE_TYPE:
		val->intval = max77693_get_charge_type(regmap);
		ret = max77693_get_charge_type(regmap, &val->intval);
		break;
	case POWER_SUPPLY_PROP_HEALTH:
		val->intval = max77693_get_battery_health(regmap);
		ret = max77693_get_battery_health(regmap, &val->intval);
		break;
	case POWER_SUPPLY_PROP_PRESENT:
		val->intval = max77693_get_present(regmap);
		ret = max77693_get_present(regmap, &val->intval);
		break;
	case POWER_SUPPLY_PROP_ONLINE:
		val->intval = max77693_get_online(regmap);
		ret = max77693_get_online(regmap, &val->intval);
		break;
	case POWER_SUPPLY_PROP_MODEL_NAME:
		val->strval = max77693_charger_model;