From c454984ac3b064d97ff9dba7950a63a976c6bcc8 Mon Sep 17 00:00:00 2001 From: xuwt2 Date: Wed, 25 Sep 2019 11:37:34 +0800 Subject: [PATCH] mmi_parallel_charger: enhance the stability of sm work Under certain condition, the PD adapter would be instability, and the sm work who responsible for the entire charging policy might exited abnormally. improve the synchronous processing. Change-Id: I87bb51a4b69178f9eb40d6519328975203027c7e Signed-off-by: xuwt2 Reviewed-on: https://gerrit.mot.com/1427554 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Jichao Zou Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1893556 Reviewed-by: Xiangpo Zhao Reviewed-by: Wei Xu --- .../mmi_parallel_charger/mmi_charger_core.c | 78 ++++++++++++++++--- .../mmi_parallel_charger/mmi_charger_core.h | 2 +- .../mmi_parallel_charger/mmi_charger_policy.h | 1 + .../mmi_charger_pump_policy.c | 49 +++++++----- 4 files changed, 100 insertions(+), 30 deletions(-) diff --git a/drivers/power/mmi_parallel_charger/mmi_charger_core.c b/drivers/power/mmi_parallel_charger/mmi_charger_core.c index 3c6017b15c34..71b9fd2904ef 100644 --- a/drivers/power/mmi_parallel_charger/mmi_charger_core.c +++ b/drivers/power/mmi_parallel_charger/mmi_charger_core.c @@ -629,7 +629,7 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr) cancel_delayed_work(&chip->heartbeat_work); schedule_delayed_work(&chip->heartbeat_work, - msecs_to_jiffies(0)); + msecs_to_jiffies(1000)); } @@ -838,12 +838,13 @@ static DEVICE_ATTR(force_max_chrg_temp, 0644, static void kick_sm(struct mmi_charger_manager *chip, int ms) { - if (!delayed_work_pending(&chip->mmi_chrg_sm_work)) { - + if (!chip->sm_work_running) { mmi_chrg_dbg(chip, PR_INTERRUPT, - "lunch mmi chrg sm work\n"); + "launch mmi chrg sm work\n"); + mmi_chrg_policy_clear(chip); schedule_delayed_work(&chip->mmi_chrg_sm_work, msecs_to_jiffies(ms)); + chip->sm_work_running = true; } else mmi_chrg_dbg(chip, PR_INTERRUPT, "mmi chrg sm work already existed\n"); @@ -851,9 +852,11 @@ static void kick_sm(struct mmi_charger_manager *chip, int ms) static void cancel_sm(struct mmi_charger_manager *chip) { - mmi_chrg_dbg(chip, PR_INTERRUPT, "flush and cancel mmi chrg sm work\n"); + cancel_delayed_work_sync(&chip->mmi_chrg_sm_work); flush_delayed_work(&chip->mmi_chrg_sm_work); - cancel_delayed_work(&chip->mmi_chrg_sm_work); + chip->sm_work_running = false; + mmi_chrg_dbg(chip, PR_INTERRUPT, + "cancel sync and flush mmi chrg sm work\n"); } void clear_chg_manager(struct mmi_charger_manager *chip) @@ -968,10 +971,11 @@ static void mmi_heartbeat_work(struct work_struct *work) { struct mmi_charger_manager *chip = container_of(work, struct mmi_charger_manager, heartbeat_work.work); - int hb_resch_time = 0, ret = 0; + int hb_resch_time = 0, ret = 0, i = 0; char *chrg_rate_string = NULL; char *envp[2]; union power_supply_propval val; + bool pd_active; mmi_chrg_info(chip, "MMI: Heartbeat!\n"); /* Have not been resumed so wait another 100 ms */ @@ -1006,7 +1010,6 @@ static void mmi_heartbeat_work(struct work_struct *work) mmi_chrg_rate_check(chip); hb_resch_time = HEARTBEAT_DELAY_MS; - if (chip->vbus_present) alarm_start_relative(&chip->heartbeat_alarm, ns_to_ktime(SMBCHG_HEARTBEAT_INTRVAL_NS)); @@ -1034,9 +1037,66 @@ static void mmi_heartbeat_work(struct work_struct *work) __pm_relax(&chip->mmi_hb_wake_source); + ret = power_supply_get_property(chip->usb_psy, + POWER_SUPPLY_PROP_PD_ACTIVE, &val); + if (ret) { + mmi_chrg_err(chip, "Unable to read PD ACTIVE: %d\n", ret); + goto schedule_work; + } + pd_active = val.intval; + + if (!chip->pd_handle) { + chip->pd_handle = devm_usbpd_get_by_phandle(chip->dev, + "qcom,usbpd-phandle"); + if (IS_ERR_OR_NULL(chip->pd_handle)) { + mmi_chrg_err(chip, "Error getting the pd phandle %ld\n", + PTR_ERR(chip->pd_handle)); + chip->pd_handle = NULL; + goto schedule_work; + } + } + + if (!chip->sm_work_running && chip->vbus_present + && pd_active) { + usbpd_get_pdo_info(chip->pd_handle, chip->mmi_pdo_info); + mmi_chrg_info(chip, "check all effective pdo info\n"); + for (i = 0; i < PD_MAX_PDO_NUM; i++) { + if ((chip->mmi_pdo_info[i].type == + PD_SRC_PDO_TYPE_AUGMENTED) + && chip->mmi_pdo_info[i].uv_max >= PUMP_CHARGER_PPS_MIN_VOLT + && chip->mmi_pdo_info[i].ua >= TYPEC_MIDDLE_CURRENT_UA) { + chip->mmi_pd_pdo_idx = chip->mmi_pdo_info[i].pdo_pos; + mmi_chrg_info(chip, + "pd charger support pps, pdo %d, " + "volt %d, curr %d \n", + chip->mmi_pd_pdo_idx, + chip->mmi_pdo_info[i].uv_max, + chip->mmi_pdo_info[i].ua); + chip->pd_pps_support = true; + + if (chip->mmi_pdo_info[i].uv_max < + chip->pd_volt_max) { + chip->pd_volt_max = + chip->mmi_pdo_info[i].uv_max; + } + if (chip->mmi_pdo_info[i].ua < + chip->pd_curr_max) { + chip->pd_curr_max = + chip->mmi_pdo_info[i].ua; + } + break; + } + } + + if (chip->pd_pps_support) { + mmi_chrg_info(chip, "MMI: Heartbeat!, launch sm work\n"); + kick_sm(chip, 100); + } + } + +schedule_work: schedule_delayed_work(&chip->heartbeat_work, msecs_to_jiffies(hb_resch_time)); - } static void psy_changed_work_func(struct work_struct *work) diff --git a/drivers/power/mmi_parallel_charger/mmi_charger_core.h b/drivers/power/mmi_parallel_charger/mmi_charger_core.h index 6cd51f01292a..b0933e3ac2be 100644 --- a/drivers/power/mmi_parallel_charger/mmi_charger_core.h +++ b/drivers/power/mmi_parallel_charger/mmi_charger_core.h @@ -200,7 +200,7 @@ struct mmi_charger_manager { struct delayed_work heartbeat_work; /*cycle trig heartbeat work*/ struct completion sm_completion; struct work_struct psy_changed_work; /*the change notification of power supply*/ - + bool sm_work_running; int num_temp_zones; struct mmi_chrg_temp_zone *temp_zones; /*the temperature zone of charging*/ enum mmi_chrg_temp_zones pres_temp_zone; /*the present zone idx*/ diff --git a/drivers/power/mmi_parallel_charger/mmi_charger_policy.h b/drivers/power/mmi_parallel_charger/mmi_charger_policy.h index 41426a86e60a..b24392e75166 100644 --- a/drivers/power/mmi_parallel_charger/mmi_charger_policy.h +++ b/drivers/power/mmi_parallel_charger/mmi_charger_policy.h @@ -30,4 +30,5 @@ extern int mmi_chrg_policy_init(struct mmi_charger_manager *chip, struct mmi_chrg_dts_info *chrg_dts, int chrg_cnt); +extern void mmi_chrg_policy_clear(struct mmi_charger_manager *chip); #endif diff --git a/drivers/power/mmi_parallel_charger/mmi_charger_pump_policy.c b/drivers/power/mmi_parallel_charger/mmi_charger_pump_policy.c index 07ad01706b94..e5cc2975730e 100644 --- a/drivers/power/mmi_parallel_charger/mmi_charger_pump_policy.c +++ b/drivers/power/mmi_parallel_charger/mmi_charger_pump_policy.c @@ -171,6 +171,7 @@ static void clear_chrg_dev_error_cnt(struct mmi_charger_manager *chip, struct mm for (i = 0; i < chrg_num; i++) { if (is_charger_exist(dev_ops[i].dev_name)) { chrg_dev = chrg_list->chrg_dev[i]; + chrg_dev->charger_error.chrg_err_type = 0; chrg_dev->charger_error.bus_ucp_err_cnt = 0; chrg_dev->charger_error.bus_ocp_err_cnt = 0; } @@ -285,6 +286,20 @@ static void chrg_policy_error_recovery(struct mmi_charger_manager *chip, #define PPS_SELECT_PDO_RETRY_COUNT 3 #define DISABLE_CHRG_LIMIT -1 #define CP_CHRG_SOC_LIMIT 90 + +void mmi_chrg_policy_clear(struct mmi_charger_manager *chip) { + chrg_dev_init(chip, &g_chrg_list); + clear_chrg_dev_error_cnt(chip, &g_chrg_list);; + clear_chg_manager(chip); + sm_state = PM_STATE_DISCONNECT; + chip->pps_volt_comp = PPS_INIT_VOLT_COMP; + quit_slave_chrg_cnt = 0; + chrg_cc_power_tunning_cnt = 0; + chrg_cv_taper_tunning_cnt = 0; + chrg_cv_delta_volt = 0; + return; +} + static void mmi_chrg_sm_work_func(struct work_struct *work) { struct mmi_charger_manager *chip = container_of(work, @@ -405,6 +420,12 @@ static void mmi_chrg_sm_work_func(struct work_struct *work) "Enter into COOLING LOOP !\n", batt_temp, chrg_step->temp_c); chip->thermal_cooling = true; + } else { + mmi_chrg_info(chip, "battery temp %d, temp thre %d " + "Restart select chrg step and temp zone !\n", + batt_temp, chrg_step->temp_c); + mmi_find_chrg_step(chip, chip->pres_temp_zone, vbatt_volt); + mmi_chrg_sm_move_state(chip, PM_STATE_ENTRY); } } @@ -659,17 +680,16 @@ static void mmi_chrg_sm_work_func(struct work_struct *work) } break; case PM_STATE_PPS_TUNNING_CURR: + heartbeat_dely_ms = HEARTBEAT_NEXT_STATE_MS; if (chrg_list->cp_master && !chrg_list->chrg_dev[CP_MASTER]->charger_enabled) { mmi_chrg_info(chip,"CP MASTER was disabled, Enter into " "SW directly\n"); mmi_chrg_sm_move_state(chip, PM_STATE_SW_ENTRY); - heartbeat_dely_ms = HEARTBEAT_NEXT_STATE_MS; }else if (vbatt_volt > chrg_step->chrg_step_cv_volt) { chip->pd_request_curr -= chip->pps_curr_steps; mmi_chrg_sm_move_state(chip, PM_STATE_CP_CC_LOOP); - heartbeat_dely_ms = HEARTBEAT_NEXT_STATE_MS; mmi_chrg_info(chip,"Duing the curr going up process, " "the chrg step was changed," "stop increase pps curr and Enter into " @@ -678,7 +698,6 @@ static void mmi_chrg_sm_work_func(struct work_struct *work) if (mmi_get_pps_result_history(chip) != NO_ERROR) { mmi_chrg_sm_move_state(chip, PM_STATE_CP_CC_LOOP); - heartbeat_dely_ms = HEARTBEAT_NEXT_STATE_MS; mmi_chrg_info(chip,"Too many pdo request failed," " Enter into CC stage directly!\n"); } @@ -695,10 +714,10 @@ static void mmi_chrg_sm_work_func(struct work_struct *work) } else { mmi_chrg_info(chip,"Enter into tunning pps volt\n"); mmi_chrg_sm_move_state(chip, PM_STATE_PPS_TUNNING_VOLT); - heartbeat_dely_ms = HEARTBEAT_NEXT_STATE_MS; } break; case PM_STATE_PPS_TUNNING_VOLT: + heartbeat_dely_ms = HEARTBEAT_NEXT_STATE_MS; if (chrg_list->cp_slave && chrg_list->cp_clave_later && !chrg_list->chrg_dev[CP_SLAVE]->charger_enabled) { @@ -711,12 +730,10 @@ static void mmi_chrg_sm_work_func(struct work_struct *work) mmi_chrg_info(chip,"CP MASTER was disabled, " "Enter into SW directly\n"); mmi_chrg_sm_move_state(chip, PM_STATE_SW_ENTRY); - heartbeat_dely_ms = HEARTBEAT_NEXT_STATE_MS; } else if (vbatt_volt > chrg_step->chrg_step_cv_volt) { chip->pd_request_volt -= chip->pps_volt_steps; mmi_chrg_sm_move_state(chip, PM_STATE_CP_CC_LOOP); - heartbeat_dely_ms = HEARTBEAT_NEXT_STATE_MS; mmi_chrg_info(chip,"Duing the volt going up process, " "the chrg step was changed," "stop increase pps volt and" @@ -725,7 +742,6 @@ static void mmi_chrg_sm_work_func(struct work_struct *work) if (mmi_get_pps_result_history(chip) != NO_ERROR) { mmi_chrg_sm_move_state(chip, PM_STATE_CP_CC_LOOP); - heartbeat_dely_ms = HEARTBEAT_NEXT_STATE_MS; mmi_chrg_info(chip,"Too many pdo request failed," " Enter into CC stage directly!\n"); } @@ -744,7 +760,6 @@ static void mmi_chrg_sm_work_func(struct work_struct *work) } else { mmi_chrg_info(chip,"Enter into CC loop stage !\n"); mmi_chrg_sm_move_state(chip, PM_STATE_CP_CC_LOOP); - heartbeat_dely_ms = HEARTBEAT_NEXT_STATE_MS; } break; case PM_STATE_CP_CC_LOOP: @@ -791,7 +806,6 @@ static void mmi_chrg_sm_work_func(struct work_struct *work) goto schedule; } - if (!chip->thermal_cooling && !chip->thermal_mitigation_doing) { if (ibatt_curr < chrg_step->chrg_step_cc_curr @@ -1031,6 +1045,7 @@ static void mmi_chrg_sm_work_func(struct work_struct *work) heartbeat_dely_ms = HEARTBEAT_NEXT_STATE_MS; break; case PM_STATE_RECOVERY_SW: + heartbeat_dely_ms = HEARTBEAT_SHORT_DELAY_MS; if (chrg_list->chrg_dev[PMIC_SW]->charger_limited) { mmi_set_charing_current(chrg_list->chrg_dev[PMIC_SW], chrg_list->chrg_dev[PMIC_SW]->input_curr_setted); @@ -1357,21 +1372,15 @@ schedule: chip->pd_request_curr_prev = chip->pd_target_curr; } - if (heartbeat_dely_ms >= 0) { + if (heartbeat_dely_ms > 0) { if (chip->pps_result < 0) - heartbeat_dely_ms = 0; + heartbeat_dely_ms = HEARTBEAT_NEXT_STATE_MS; + mmi_chrg_err(chip, "schedule work timer %d\n", heartbeat_dely_ms); schedule_delayed_work(&chip->mmi_chrg_sm_work, msecs_to_jiffies(heartbeat_dely_ms)); } else { - chrg_dev_init(chip, &g_chrg_list); - clear_chrg_dev_error_cnt(chip, &g_chrg_list); - clear_chg_manager(chip); - sm_state = PM_STATE_DISCONNECT; - chip->pps_volt_comp = PPS_INIT_VOLT_COMP; - quit_slave_chrg_cnt = 0; - chrg_cc_power_tunning_cnt = 0; - chrg_cv_taper_tunning_cnt = 0; - chrg_cv_delta_volt = 0; + mmi_chrg_policy_clear(chip); + chip->sm_work_running = false; mmi_chrg_err(chip, "exit sm work\n"); }