[PATCH 38/40] abx500-chargalg: Add charging current step interface
To prevent overheating, provide differnt steps of charging current interface to allow thermal mitigation. This will provide possibility to reduce gradually the charging current. Signed-off-by: Lee Jones --- drivers/power/abx500_chargalg.c | 231 ++- 1 file changed, 155 insertions(+), 76 deletions(-) diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c index 7e4bc01..9863e42 100644 --- a/drivers/power/abx500_chargalg.c +++ b/drivers/power/abx500_chargalg.c @@ -47,6 +47,9 @@ /* Plus margin for the low battery threshold */ #define BAT_PLUS_MARGIN(100) +#define CHARGALG_CURR_STEP_LOW 0 +#define CHARGALG_CURR_STEP_HIGH100 + #define to_abx500_chargalg_device_info(x) container_of((x), \ struct abx500_chargalg, chargalg_psy); @@ -80,6 +83,11 @@ struct abx500_chargalg_suspension_status { bool usb_suspended; }; +struct abx500_chargalg_current_step_status { + bool curr_step_change; + int curr_step; +}; + struct abx500_chargalg_battery_data { int temp; int volt; @@ -220,6 +228,7 @@ enum maxim_ret { * @batt_data: data of the battery * @susp_status: current charger suspension status * @bm:Platform specific battery management information + * @curr_status: Current step status for over-current protection * @parent:pointer to the struct abx500 * @chargalg_psy: structure that holds the battery properties exposed by * the charging algorithm @@ -245,6 +254,7 @@ struct abx500_chargalg { struct abx500_chargalg_battery_data batt_data; struct abx500_chargalg_suspension_status susp_status; struct ab8500 *parent; + struct abx500_chargalg_current_step_status curr_status; struct abx500_bm_data *bm; struct power_supply chargalg_psy; struct ux500_charger *ac_chg; @@ -268,6 +278,12 @@ static enum power_supply_property abx500_chargalg_props[] = { POWER_SUPPLY_PROP_HEALTH, }; +struct abx500_chargalg_sysfs_entry { + struct attribute attr; + ssize_t (*show)(struct abx500_chargalg *, char *); + ssize_t (*store)(struct abx500_chargalg *, const char *, size_t); +}; + /** * abx500_chargalg_safety_timer_expired() - Expiration of the safety timer * @timer: pointer to the hrtimer structure @@ -402,6 +418,22 @@ static int abx500_chargalg_check_charger_connection(struct abx500_chargalg *di) } /** + * abx500_chargalg_check_current_step_status() - Check charging current + * step status. + * @di:pointer to the abx500_chargalg structure + * + * This function will check if there is a change in the charging current step + * and change charge state accordingly. + */ +static void abx500_chargalg_check_current_step_status + (struct abx500_chargalg *di) +{ + if (di->curr_status.curr_step_change) + abx500_chargalg_state_to(di, STATE_NORMAL_INIT); + di->curr_status.curr_step_change = false; +} + +/** * abx500_chargalg_start_safety_timer() - Start charging safety timer * @di:pointer to the abx500_chargalg structure * @@ -1300,6 +1332,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) { int charger_status; int ret; + int curr_step_lvl; /* Collect data from all power_supply class devices */ class_for_each_device(power_supply_class, NULL, @@ -1310,6 +1343,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) abx500_chargalg_check_charger_voltage(di); charger_status = abx500_chargalg_check_charger_connection(di); + abx500_chargalg_check_current_step_status(di); if (is_ab8500(di->parent)) { ret = abx500_chargalg_check_charger_enable(di); @@ -1523,9 +1557,18 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) } } - abx500_chargalg_start_charging(di, - di->bm->bat_type[di->bm->batt_id].normal_vol_lvl, - di->bm->bat_type[di->bm->batt_id].normal_cur_lvl); + if (di->curr_status.curr_step == CHARGALG_CURR_STEP_LOW) + abx500_chargalg_stop_charging(di); + else { + curr_step_lvl = di->bm->bat_type[ + di->bm->batt_id].normal_cur_lvl + * di->curr_status.curr_step + / CHARGALG_CURR_STEP_HIGH; + abx500_chargalg_start_charging(di, + di->bm->bat_type[di->bm->batt_id] + .normal_vol_lvl, curr_step_lvl); + } + abx500_chargalg_state_to(di, STATE_NORMAL); abx500_chargalg_start_safety_timer(di); abx500_chargalg_stop_maintenance_timer(di); @@
[PATCH 38/40] abx500-chargalg: Add charging current step interface
To prevent overheating, provide differnt steps of charging current interface to allow thermal mitigation. This will provide possibility to reduce gradually the charging current. Signed-off-by: Lee Jones lee.jo...@linaro.org --- drivers/power/abx500_chargalg.c | 231 ++- 1 file changed, 155 insertions(+), 76 deletions(-) diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c index 7e4bc01..9863e42 100644 --- a/drivers/power/abx500_chargalg.c +++ b/drivers/power/abx500_chargalg.c @@ -47,6 +47,9 @@ /* Plus margin for the low battery threshold */ #define BAT_PLUS_MARGIN(100) +#define CHARGALG_CURR_STEP_LOW 0 +#define CHARGALG_CURR_STEP_HIGH100 + #define to_abx500_chargalg_device_info(x) container_of((x), \ struct abx500_chargalg, chargalg_psy); @@ -80,6 +83,11 @@ struct abx500_chargalg_suspension_status { bool usb_suspended; }; +struct abx500_chargalg_current_step_status { + bool curr_step_change; + int curr_step; +}; + struct abx500_chargalg_battery_data { int temp; int volt; @@ -220,6 +228,7 @@ enum maxim_ret { * @batt_data: data of the battery * @susp_status: current charger suspension status * @bm:Platform specific battery management information + * @curr_status: Current step status for over-current protection * @parent:pointer to the struct abx500 * @chargalg_psy: structure that holds the battery properties exposed by * the charging algorithm @@ -245,6 +254,7 @@ struct abx500_chargalg { struct abx500_chargalg_battery_data batt_data; struct abx500_chargalg_suspension_status susp_status; struct ab8500 *parent; + struct abx500_chargalg_current_step_status curr_status; struct abx500_bm_data *bm; struct power_supply chargalg_psy; struct ux500_charger *ac_chg; @@ -268,6 +278,12 @@ static enum power_supply_property abx500_chargalg_props[] = { POWER_SUPPLY_PROP_HEALTH, }; +struct abx500_chargalg_sysfs_entry { + struct attribute attr; + ssize_t (*show)(struct abx500_chargalg *, char *); + ssize_t (*store)(struct abx500_chargalg *, const char *, size_t); +}; + /** * abx500_chargalg_safety_timer_expired() - Expiration of the safety timer * @timer: pointer to the hrtimer structure @@ -402,6 +418,22 @@ static int abx500_chargalg_check_charger_connection(struct abx500_chargalg *di) } /** + * abx500_chargalg_check_current_step_status() - Check charging current + * step status. + * @di:pointer to the abx500_chargalg structure + * + * This function will check if there is a change in the charging current step + * and change charge state accordingly. + */ +static void abx500_chargalg_check_current_step_status + (struct abx500_chargalg *di) +{ + if (di-curr_status.curr_step_change) + abx500_chargalg_state_to(di, STATE_NORMAL_INIT); + di-curr_status.curr_step_change = false; +} + +/** * abx500_chargalg_start_safety_timer() - Start charging safety timer * @di:pointer to the abx500_chargalg structure * @@ -1300,6 +1332,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) { int charger_status; int ret; + int curr_step_lvl; /* Collect data from all power_supply class devices */ class_for_each_device(power_supply_class, NULL, @@ -1310,6 +1343,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) abx500_chargalg_check_charger_voltage(di); charger_status = abx500_chargalg_check_charger_connection(di); + abx500_chargalg_check_current_step_status(di); if (is_ab8500(di-parent)) { ret = abx500_chargalg_check_charger_enable(di); @@ -1523,9 +1557,18 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) } } - abx500_chargalg_start_charging(di, - di-bm-bat_type[di-bm-batt_id].normal_vol_lvl, - di-bm-bat_type[di-bm-batt_id].normal_cur_lvl); + if (di-curr_status.curr_step == CHARGALG_CURR_STEP_LOW) + abx500_chargalg_stop_charging(di); + else { + curr_step_lvl = di-bm-bat_type[ + di-bm-batt_id].normal_cur_lvl + * di-curr_status.curr_step + / CHARGALG_CURR_STEP_HIGH; + abx500_chargalg_start_charging(di, + di-bm-bat_type[di-bm-batt_id] + .normal_vol_lvl, curr_step_lvl); + } + abx500_chargalg_state_to(di, STATE_NORMAL); abx500_chargalg_start_safety_timer(di); abx500_chargalg_stop_maintenance_timer(di); @@