Loading drivers/power/supply/qcom/step-chg-jeita.c +74 −19 Original line number Diff line number Diff line Loading @@ -72,9 +72,11 @@ struct step_chg_info { struct votable *fcc_votable; struct votable *fv_votable; struct votable *usb_icl_votable; struct wakeup_source *step_chg_ws; struct power_supply *batt_psy; struct power_supply *bms_psy; struct power_supply *usb_psy; struct delayed_work status_change_work; struct delayed_work get_config_work; struct notifier_block nb; Loading Loading @@ -111,6 +113,17 @@ static bool is_bms_available(struct step_chg_info *chip) return true; } static bool is_usb_available(struct step_chg_info *chip) { if (!chip->usb_psy) chip->usb_psy = power_supply_get_by_name("usb"); if (!chip->usb_psy) return false; return true; } int read_range_data_from_node(struct device_node *node, const char *prop_str, struct range_data *ranges, u32 max_threshold, u32 max_value) Loading Loading @@ -484,6 +497,7 @@ static int handle_step_chg_config(struct step_chg_info *chip) return (STEP_CHG_HYSTERISIS_DELAY_US - elapsed_us + 1000); } #define JEITA_SUSPEND_HYST_UV 50000 static int handle_jeita(struct step_chg_info *chip) { union power_supply_propval pval = {0, }; Loading @@ -502,6 +516,8 @@ static int handle_jeita(struct step_chg_info *chip) vote(chip->fcc_votable, JEITA_VOTER, false, 0); if (chip->fv_votable) vote(chip->fv_votable, JEITA_VOTER, false, 0); if (chip->usb_icl_votable) vote(chip->usb_icl_votable, JEITA_VOTER, false, 0); return 0; } Loading @@ -523,12 +539,8 @@ static int handle_jeita(struct step_chg_info *chip) pval.intval, &chip->jeita_fcc_index, &fcc_ua); if (rc < 0) { /* remove the vote if no step-based fcc is found */ if (chip->fcc_votable) vote(chip->fcc_votable, JEITA_VOTER, false, 0); goto update_time; } if (rc < 0) fcc_ua = 0; if (!chip->fcc_votable) chip->fcc_votable = find_votable("FCC"); Loading @@ -536,7 +548,7 @@ static int handle_jeita(struct step_chg_info *chip) /* changing FCC is a must */ return -EINVAL; vote(chip->fcc_votable, JEITA_VOTER, true, fcc_ua); vote(chip->fcc_votable, JEITA_VOTER, fcc_ua ? true : false, fcc_ua); rc = get_val(chip->jeita_fv_config->fv_cfg, chip->jeita_fv_config->hysteresis, Loading @@ -544,21 +556,45 @@ static int handle_jeita(struct step_chg_info *chip) pval.intval, &chip->jeita_fv_index, &fv_uv); if (rc < 0) { /* remove the vote if no step-based fcc is found */ if (chip->fv_votable) vote(chip->fv_votable, JEITA_VOTER, false, 0); goto update_time; } if (rc < 0) fv_uv = 0; chip->fv_votable = find_votable("FV"); if (!chip->fv_votable) goto update_time; vote(chip->fv_votable, JEITA_VOTER, true, fv_uv); if (!chip->usb_icl_votable) chip->usb_icl_votable = find_votable("USB_ICL"); pr_debug("%s = %d FCC = %duA FV = %duV\n", chip->jeita_fcc_config->prop_name, pval.intval, fcc_ua, fv_uv); if (!chip->usb_icl_votable) goto set_jeita_fv; /* * If JEITA float voltage is same as max-vfloat of battery then * skip any further VBAT specific checks. */ rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_VOLTAGE_MAX, &pval); if (rc || (pval.intval == fv_uv)) { vote(chip->usb_icl_votable, JEITA_VOTER, false, 0); goto set_jeita_fv; } /* * Suspend USB input path if battery voltage is above * JEITA VFLOAT threshold. */ if (fv_uv > 0) { rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &pval); if (!rc && (pval.intval > fv_uv)) vote(chip->usb_icl_votable, JEITA_VOTER, true, 0); else if (pval.intval < (fv_uv - JEITA_SUSPEND_HYST_UV)) vote(chip->usb_icl_votable, JEITA_VOTER, false, 0); } set_jeita_fv: vote(chip->fv_votable, JEITA_VOTER, fv_uv ? true : false, fv_uv); update_time: chip->jeita_last_update_time = ktime_get(); Loading Loading @@ -610,11 +646,13 @@ static void status_change_work(struct work_struct *work) int reschedule_us; int reschedule_jeita_work_us = 0; int reschedule_step_work_us = 0; union power_supply_propval prop = {0, }; if (!is_batt_available(chip)) return; goto exit_work; handle_battery_insertion(chip); /* skip elapsed_us debounce for handling battery temperature */ rc = handle_jeita(chip); if (rc > 0) Loading @@ -628,12 +666,28 @@ static void status_change_work(struct work_struct *work) if (rc < 0) pr_err("Couldn't handle step rc = %d\n", rc); /* Remove stale votes on USB removal */ if (is_usb_available(chip)) { prop.intval = 0; power_supply_get_property(chip->usb_psy, POWER_SUPPLY_PROP_PRESENT, &prop); if (!prop.intval) { if (chip->usb_icl_votable) vote(chip->usb_icl_votable, JEITA_VOTER, false, 0); } } reschedule_us = min(reschedule_jeita_work_us, reschedule_step_work_us); if (reschedule_us == 0) __pm_relax(chip->step_chg_ws); goto exit_work; else schedule_delayed_work(&chip->status_change_work, usecs_to_jiffies(reschedule_us)); return; exit_work: __pm_relax(chip->step_chg_ws); } static int step_chg_notifier_call(struct notifier_block *nb, Loading @@ -645,7 +699,8 @@ static int step_chg_notifier_call(struct notifier_block *nb, if (ev != PSY_EVENT_PROP_CHANGED) return NOTIFY_OK; if ((strcmp(psy->desc->name, "battery") == 0)) { if ((strcmp(psy->desc->name, "battery") == 0) || (strcmp(psy->desc->name, "usb") == 0)) { __pm_stay_awake(chip->step_chg_ws); schedule_delayed_work(&chip->status_change_work, 0); } Loading Loading
drivers/power/supply/qcom/step-chg-jeita.c +74 −19 Original line number Diff line number Diff line Loading @@ -72,9 +72,11 @@ struct step_chg_info { struct votable *fcc_votable; struct votable *fv_votable; struct votable *usb_icl_votable; struct wakeup_source *step_chg_ws; struct power_supply *batt_psy; struct power_supply *bms_psy; struct power_supply *usb_psy; struct delayed_work status_change_work; struct delayed_work get_config_work; struct notifier_block nb; Loading Loading @@ -111,6 +113,17 @@ static bool is_bms_available(struct step_chg_info *chip) return true; } static bool is_usb_available(struct step_chg_info *chip) { if (!chip->usb_psy) chip->usb_psy = power_supply_get_by_name("usb"); if (!chip->usb_psy) return false; return true; } int read_range_data_from_node(struct device_node *node, const char *prop_str, struct range_data *ranges, u32 max_threshold, u32 max_value) Loading Loading @@ -484,6 +497,7 @@ static int handle_step_chg_config(struct step_chg_info *chip) return (STEP_CHG_HYSTERISIS_DELAY_US - elapsed_us + 1000); } #define JEITA_SUSPEND_HYST_UV 50000 static int handle_jeita(struct step_chg_info *chip) { union power_supply_propval pval = {0, }; Loading @@ -502,6 +516,8 @@ static int handle_jeita(struct step_chg_info *chip) vote(chip->fcc_votable, JEITA_VOTER, false, 0); if (chip->fv_votable) vote(chip->fv_votable, JEITA_VOTER, false, 0); if (chip->usb_icl_votable) vote(chip->usb_icl_votable, JEITA_VOTER, false, 0); return 0; } Loading @@ -523,12 +539,8 @@ static int handle_jeita(struct step_chg_info *chip) pval.intval, &chip->jeita_fcc_index, &fcc_ua); if (rc < 0) { /* remove the vote if no step-based fcc is found */ if (chip->fcc_votable) vote(chip->fcc_votable, JEITA_VOTER, false, 0); goto update_time; } if (rc < 0) fcc_ua = 0; if (!chip->fcc_votable) chip->fcc_votable = find_votable("FCC"); Loading @@ -536,7 +548,7 @@ static int handle_jeita(struct step_chg_info *chip) /* changing FCC is a must */ return -EINVAL; vote(chip->fcc_votable, JEITA_VOTER, true, fcc_ua); vote(chip->fcc_votable, JEITA_VOTER, fcc_ua ? true : false, fcc_ua); rc = get_val(chip->jeita_fv_config->fv_cfg, chip->jeita_fv_config->hysteresis, Loading @@ -544,21 +556,45 @@ static int handle_jeita(struct step_chg_info *chip) pval.intval, &chip->jeita_fv_index, &fv_uv); if (rc < 0) { /* remove the vote if no step-based fcc is found */ if (chip->fv_votable) vote(chip->fv_votable, JEITA_VOTER, false, 0); goto update_time; } if (rc < 0) fv_uv = 0; chip->fv_votable = find_votable("FV"); if (!chip->fv_votable) goto update_time; vote(chip->fv_votable, JEITA_VOTER, true, fv_uv); if (!chip->usb_icl_votable) chip->usb_icl_votable = find_votable("USB_ICL"); pr_debug("%s = %d FCC = %duA FV = %duV\n", chip->jeita_fcc_config->prop_name, pval.intval, fcc_ua, fv_uv); if (!chip->usb_icl_votable) goto set_jeita_fv; /* * If JEITA float voltage is same as max-vfloat of battery then * skip any further VBAT specific checks. */ rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_VOLTAGE_MAX, &pval); if (rc || (pval.intval == fv_uv)) { vote(chip->usb_icl_votable, JEITA_VOTER, false, 0); goto set_jeita_fv; } /* * Suspend USB input path if battery voltage is above * JEITA VFLOAT threshold. */ if (fv_uv > 0) { rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &pval); if (!rc && (pval.intval > fv_uv)) vote(chip->usb_icl_votable, JEITA_VOTER, true, 0); else if (pval.intval < (fv_uv - JEITA_SUSPEND_HYST_UV)) vote(chip->usb_icl_votable, JEITA_VOTER, false, 0); } set_jeita_fv: vote(chip->fv_votable, JEITA_VOTER, fv_uv ? true : false, fv_uv); update_time: chip->jeita_last_update_time = ktime_get(); Loading Loading @@ -610,11 +646,13 @@ static void status_change_work(struct work_struct *work) int reschedule_us; int reschedule_jeita_work_us = 0; int reschedule_step_work_us = 0; union power_supply_propval prop = {0, }; if (!is_batt_available(chip)) return; goto exit_work; handle_battery_insertion(chip); /* skip elapsed_us debounce for handling battery temperature */ rc = handle_jeita(chip); if (rc > 0) Loading @@ -628,12 +666,28 @@ static void status_change_work(struct work_struct *work) if (rc < 0) pr_err("Couldn't handle step rc = %d\n", rc); /* Remove stale votes on USB removal */ if (is_usb_available(chip)) { prop.intval = 0; power_supply_get_property(chip->usb_psy, POWER_SUPPLY_PROP_PRESENT, &prop); if (!prop.intval) { if (chip->usb_icl_votable) vote(chip->usb_icl_votable, JEITA_VOTER, false, 0); } } reschedule_us = min(reschedule_jeita_work_us, reschedule_step_work_us); if (reschedule_us == 0) __pm_relax(chip->step_chg_ws); goto exit_work; else schedule_delayed_work(&chip->status_change_work, usecs_to_jiffies(reschedule_us)); return; exit_work: __pm_relax(chip->step_chg_ws); } static int step_chg_notifier_call(struct notifier_block *nb, Loading @@ -645,7 +699,8 @@ static int step_chg_notifier_call(struct notifier_block *nb, if (ev != PSY_EVENT_PROP_CHANGED) return NOTIFY_OK; if ((strcmp(psy->desc->name, "battery") == 0)) { if ((strcmp(psy->desc->name, "battery") == 0) || (strcmp(psy->desc->name, "usb") == 0)) { __pm_stay_awake(chip->step_chg_ws); schedule_delayed_work(&chip->status_change_work, 0); } Loading