From a51c738a2af8107e391114d73ae5c79c383b2732 Mon Sep 17 00:00:00 2001 From: Jonghwa Lee Date: Tue, 22 Oct 2013 17:35:58 +0900 Subject: [PATCH] charger-manager : Add default battery temperature checking funtion. During the charger manager driver's probing time, it can't succeed if there's no pre-defined .temperature_out_of_range callback function. But if fuel gauge supports battery temperature measurement, we can use it directly. That's what cm_default_get_temp() function does. With flag measure_batter_temp ON, we normally use cm_default_get_temp() for .temperature_out_of_range callback funtion. The TEMP_AMBIENT property is only used for pre-defined one. Signed-off-by: Jonghwa Lee --- drivers/power/charger-manager.c | 97 ++++++++++++++++++++++++++++------- include/linux/power/charger-manager.h | 11 +++- 2 files changed, 89 insertions(+), 19 deletions(-) diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c index 1e2201f..108c00c 100644 --- a/drivers/power/charger-manager.c +++ b/drivers/power/charger-manager.c @@ -552,7 +552,7 @@ static int check_charging_duration(struct charger_manager *cm) static bool _cm_monitor(struct charger_manager *cm) { struct charger_desc *desc = cm->desc; - int temp = desc->temperature_out_of_range(&cm->last_temp_mC); + int temp = desc->temperature_out_of_range(cm); dev_dbg(cm->dev, "monitoring (%2.2d.%3.3dC)\n", cm->last_temp_mC / 1000, cm->last_temp_mC % 1000); @@ -804,18 +804,19 @@ static int charger_get_property(struct power_supply *psy, POWER_SUPPLY_PROP_CURRENT_NOW, val); break; case POWER_SUPPLY_PROP_TEMP: - /* in thenth of centigrade */ + /* in tenth of centigrade */ if (cm->last_temp_mC == INT_MIN) - desc->temperature_out_of_range(&cm->last_temp_mC); - val->intval = cm->last_temp_mC / 100; + desc->temperature_out_of_range(cm); + + val->intval = cm->last_temp_mC; if (!desc->measure_battery_temp) ret = -ENODEV; break; case POWER_SUPPLY_PROP_TEMP_AMBIENT: - /* in thenth of centigrade */ + /* in tenth of centigrade */ if (cm->last_temp_mC == INT_MIN) - desc->temperature_out_of_range(&cm->last_temp_mC); - val->intval = cm->last_temp_mC / 100; + desc->temperature_out_of_range(cm); + val->intval = cm->last_temp_mC; if (desc->measure_battery_temp) ret = -ENODEV; break; @@ -1461,16 +1462,75 @@ err: return ret; } +/* Every temperature units are in milli centigrade */ +#define CM_DEFAULT_TEMP_ALERT_DIFF 10000 +#define CM_DEFAULT_TEMP_ALERT_MAX 127000 +#define CM_DEFAULT_TEMP_ALERT_MIN (-127000) + +static int cm_default_get_temp(struct charger_manager *cm) +{ + struct charger_desc *desc = cm->desc; + union power_supply_propval val; + static int temp_alert_min = 0; + static int temp_alert_max = 0; + static int temp_alert_diff = 0; + static int last_temp_status = 0; + int ret; + + if (!temp_alert_min && !temp_alert_max) { + /* Initialize minimum temperature for alert */ + ret = cm->fuel_gauge->get_property(cm->fuel_gauge, + POWER_SUPPLY_PROP_TEMP_ALERT_MIN, + &val); + temp_alert_min = ret ? desc->temp_alert_min : + min(desc->temp_alert_min, val.intval); + if (!temp_alert_min) + temp_alert_min = CM_DEFAULT_TEMP_ALERT_MIN; + + /* Initialize maximum temperature for alert */ + ret = cm->fuel_gauge->get_property(cm->fuel_gauge, + POWER_SUPPLY_PROP_TEMP_ALERT_MAX, + &val); + temp_alert_max = ret ? desc->temp_alert_max : + min(desc->temp_alert_max, val.intval); + if (!temp_alert_max) + temp_alert_max = CM_DEFAULT_TEMP_ALERT_MAX; + + temp_alert_diff = desc->temp_alert_diff ? + : CM_DEFAULT_TEMP_ALERT_DIFF; + } + + /* Get battery temperature */ + ret = cm->fuel_gauge->get_property(cm->fuel_gauge, + POWER_SUPPLY_PROP_TEMP, + &val); + if (ret) { + cm->last_temp_mC = INT_MIN; + return 0; + } + + cm->last_temp_mC = val.intval; + + if (cm->last_temp_mC > temp_alert_max || (last_temp_status && + cm->last_temp_mC + temp_alert_diff > temp_alert_max)) { + /* OVERHEAT */ + last_temp_status = 1; + } else if (cm->last_temp_mC < temp_alert_min || (last_temp_status && + cm->last_temp_mC < temp_alert_min + temp_alert_diff)) { + /* Too COLD */ + last_temp_status = -1; + } else { + last_temp_status = 0; + } + + return last_temp_status; +} + /* * Charger driver platform data * To do : Should be transferred to DT. */ -static int thermistor_ck(int *mC) -{ - return 0; -} - static char *charger_stats[] = { #if defined(CONFIG_CHARGER_MAX77693) "max77693-charger", @@ -1537,7 +1597,6 @@ static struct charger_desc cm_drv_data = { .charger_regulators = regulators, .num_charger_regulators = ARRAY_SIZE(regulators), - .temperature_out_of_range = thermistor_ck, .measure_battery_temp = true, .charging_max_duration_ms = (6 * 60 * 60 * 1000), /* 6hr */ @@ -1674,11 +1733,6 @@ static int charger_manager_probe(struct platform_device *pdev) return -EINVAL; } - if (!desc->temperature_out_of_range) { - dev_err(&pdev->dev, "there is no temperature_out_of_range\n"); - return -EINVAL; - } - if (!desc->charging_max_duration_ms || !desc->discharging_max_duration_ms) { dev_info(&pdev->dev, "Cannot limit charging duration " @@ -1723,7 +1777,14 @@ static int charger_manager_probe(struct platform_device *pdev) if (desc->measure_battery_temp) { cm_chg_add_property(POWER_SUPPLY_PROP_TEMP); + desc->temperature_out_of_range = cm_default_get_temp; } else { + if (!desc->temperature_out_of_range) { + dev_err(&pdev->dev, + "%s : No battery thermometer exists\n", + __func__); + return -EINVAL; + } cm_chg_add_property(POWER_SUPPLY_PROP_TEMP_AMBIENT); } diff --git a/include/linux/power/charger-manager.h b/include/linux/power/charger-manager.h index 0e86840..20886197 100644 --- a/include/linux/power/charger-manager.h +++ b/include/linux/power/charger-manager.h @@ -148,6 +148,8 @@ struct charger_regulator { struct charger_manager *cm; }; +struct charger_manager; + /** * struct charger_desc * @psy_name: the name of power-supply-class for charger manager @@ -173,6 +175,9 @@ struct charger_regulator { * @num_charger_regulator: the number of entries in charger_regulators * @charger_regulators: array of charger regulators * @psy_fuel_gauge: the name of power-supply for fuel gauge + * @temp_alert_min : Minimum battery temperature to be allowed. + * @temp_alert_max : Maximum battery temperature to be allowed. + * @temp_alert_diff : Temperature diffential to restart charging. * @temperature_out_of_range: * Determine whether the status is overheat or cold or normal. * return_value > 0: overheat @@ -210,7 +215,11 @@ struct charger_desc { char *psy_fuel_gauge; - int (*temperature_out_of_range)(int *mC); + int temp_alert_min; + int temp_alert_max; + int temp_alert_diff; + + int (*temperature_out_of_range)(struct charger_manager *); bool measure_battery_temp; u64 charging_max_duration_ms; -- 2.7.4