From a13fb8dcf5c2d8f5032d2e36c037a05bae4d022e Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Thu, 2 Apr 2020 17:52:28 -0700 Subject: [PATCH] power: supply: qti-battery-charger: Handle incorrect thermal levels Currently, when "qcom,thermal-levels" is specified and the values are not in descending order, an error is returned which fails the driver probe thereby causing battery/USB power supply not available. Same problem can happen when charger firmware returns a lower value for BATT_CHG_CTRL_LIM_MAX than the maximum value specified under "qcom,thermal-levels" property. Without a battery power supply, user would not know the battery charging status. To avoid this, just return 0 after printing an error. This would only affect the user by disallowing a change to the POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT property under battery power supply. Change-Id: I216d4d370e71ec5003adbee2600191e36a45e870 Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qti_battery_charger.c | 44 +++++++++++++++------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/drivers/power/supply/qti_battery_charger.c b/drivers/power/supply/qti_battery_charger.c index 6110b9f78e76..e711f43146e8 100644 --- a/drivers/power/supply/qti_battery_charger.c +++ b/drivers/power/supply/qti_battery_charger.c @@ -683,6 +683,11 @@ static int battery_psy_set_charge_current(struct battery_chg_dev *bcdev, if (!bcdev->num_thermal_levels) return 0; + if (bcdev->num_thermal_levels < 0) { + pr_err("Incorrect num_thermal_levels\n"); + return -EINVAL; + } + if (val < 0 || val > bcdev->num_thermal_levels) return -EINVAL; @@ -976,6 +981,7 @@ static int battery_chg_parse_dt(struct battery_chg_dev *bcdev) struct device_node *node = bcdev->dev->of_node; struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_BATTERY]; int i, rc, len; + u32 prev, val; rc = of_property_count_elems_of_size(node, "qcom,thermal-mitigation", sizeof(u32)); @@ -983,6 +989,28 @@ static int battery_chg_parse_dt(struct battery_chg_dev *bcdev) return 0; len = rc; + + rc = read_property_id(bcdev, pst, BATT_CHG_CTRL_LIM_MAX); + if (rc < 0) + return rc; + + prev = pst->prop[BATT_CHG_CTRL_LIM_MAX]; + + for (i = 0; i < len; i++) { + rc = of_property_read_u32_index(node, "qcom,thermal-mitigation", + i, &val); + if (rc < 0) + return rc; + + if (val > prev) { + pr_err("Thermal levels should be in descending order\n"); + bcdev->num_thermal_levels = -EINVAL; + return 0; + } + + prev = val; + } + bcdev->thermal_levels = devm_kcalloc(bcdev->dev, len + 1, sizeof(*bcdev->thermal_levels), GFP_KERNEL); @@ -993,6 +1021,9 @@ static int battery_chg_parse_dt(struct battery_chg_dev *bcdev) * Element 0 is for normal charging current. Elements from index 1 * onwards is for thermal mitigation charging currents. */ + + bcdev->thermal_levels[0] = pst->prop[BATT_CHG_CTRL_LIM_MAX]; + rc = of_property_read_u32_array(node, "qcom,thermal-mitigation", &bcdev->thermal_levels[1], len); if (rc < 0) { @@ -1000,19 +1031,6 @@ static int battery_chg_parse_dt(struct battery_chg_dev *bcdev) return rc; } - rc = read_property_id(bcdev, pst, BATT_CHG_CTRL_LIM_MAX); - if (rc < 0) - return rc; - - bcdev->thermal_levels[0] = pst->prop[BATT_CHG_CTRL_LIM_MAX]; - - for (i = 1; i <= len; i++) { - if (bcdev->thermal_levels[i] > bcdev->thermal_levels[i - 1]) { - pr_err("Thermal levels should be in descending order\n"); - return -EINVAL; - } - } - bcdev->num_thermal_levels = len; return 0;