Loading Documentation/devicetree/bindings/power/supply/qcom/smb1390-charger.txt +6 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,12 @@ Charger specific properties: Definition: For details about IIO bindings see: Documentation/devicetree/bindings/iio/iio-bindings.txt - qcom,max-cutoff-soc Usage: optional Value type: <u32> Definition: SOC beyond which SMB1390 is kept disabled. If this value is not specified then default value is 85%. ================================================ Second Level Nodes - SMB1390 Charger Peripherals ================================================ Loading drivers/power/supply/qcom/smb1390-charger.c +85 −12 Original line number Diff line number Diff line Loading @@ -87,9 +87,11 @@ #define ILIM_VOTER "ILIM_VOTER" #define FCC_VOTER "FCC_VOTER" #define ICL_VOTER "ICL_VOTER" #define TAPER_END_VOTER "TAPER_END_VOTER" #define WIRELESS_VOTER "WIRELESS_VOTER" #define SRC_VOTER "SRC_VOTER" #define SWITCHER_TOGGLE_VOTER "SWITCHER_TOGGLE_VOTER" #define SOC_LEVEL_VOTER "SOC_LEVEL_VOTER" enum { SWITCHER_OFF_WINDOW_IRQ = 0, Loading Loading @@ -126,6 +128,7 @@ struct smb1390 { struct votable *disable_votable; struct votable *ilim_votable; struct votable *fcc_votable; struct votable *fv_votable; struct votable *cp_awake_votable; /* power supplies */ Loading @@ -138,6 +141,8 @@ struct smb1390 { bool taper_work_running; struct smb1390_iio iio; int irq_status; int taper_entry_fv; u32 max_cutoff_soc; }; struct smb_irq { Loading Loading @@ -207,6 +212,14 @@ static bool is_psy_voter_available(struct smb1390 *chip) } } if (!chip->fv_votable) { chip->fv_votable = find_votable("FV"); if (!chip->fv_votable) { pr_debug("Couldn't find FV votable\n"); return false; } } return true; } Loading @@ -220,6 +233,28 @@ static void cp_toggle_switcher(struct smb1390 *chip) vote(chip->disable_votable, SWITCHER_TOGGLE_VOTER, false, 0); } static int smb1390_is_batt_soc_valid(struct smb1390 *chip) { int rc; union power_supply_propval pval = {0, }; if (!chip->batt_psy) goto out; rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_CAPACITY, &pval); if (rc < 0) { pr_err("Couldn't get CAPACITY rc=%d\n", rc); goto out; } if (pval.intval >= chip->max_cutoff_soc) return false; out: return true; } static irqreturn_t default_irq_handler(int irq, void *data) { struct smb1390 *chip = data; Loading Loading @@ -550,6 +585,9 @@ static void smb1390_status_change_work(struct work_struct *work) if (!is_psy_voter_available(chip)) goto out; vote(chip->disable_votable, SOC_LEVEL_VOTER, smb1390_is_batt_soc_valid(chip) ? false : true, 0); rc = power_supply_get_property(chip->usb_psy, POWER_SUPPLY_PROP_SMB_EN_MODE, &pval); if (rc < 0) { Loading Loading @@ -596,6 +634,14 @@ static void smb1390_status_change_work(struct work_struct *work) vote(chip->ilim_votable, FCC_VOTER, true, get_effective_result(chip->fcc_votable) / 2); /* * Remove SMB1390 Taper condition disable vote if float voltage * increased in comparison to voltage at which it entered taper. */ if (chip->taper_entry_fv < get_effective_result(chip->fv_votable)) vote(chip->disable_votable, TAPER_END_VOTER, false, 0); /* * all votes that would result in disabling the charge pump have * been cast; ensure the charhe pump is still enabled before Loading @@ -622,10 +668,12 @@ static void smb1390_status_change_work(struct work_struct *work) } } else { vote(chip->disable_votable, SRC_VOTER, true, 0); vote(chip->disable_votable, TAPER_END_VOTER, false, 0); max_fcc_ma = get_client_vote(chip->fcc_votable, BATT_PROFILE_VOTER); vote(chip->fcc_votable, CP_VOTER, max_fcc_ma > 0 ? true : false, max_fcc_ma); vote(chip->disable_votable, SOC_LEVEL_VOTER, true, 0); } out: Loading @@ -642,17 +690,8 @@ static void smb1390_taper_work(struct work_struct *work) if (!is_psy_voter_available(chip)) goto out; do { fcc_uA = get_effective_result(chip->fcc_votable); if (fcc_uA < 2000000) break; fcc_uA = get_client_vote(chip->fcc_votable, CP_VOTER) - 100000; pr_debug("taper work reducing FCC to %duA\n", fcc_uA); vote(chip->fcc_votable, CP_VOTER, true, fcc_uA); msleep(500); chip->taper_entry_fv = get_effective_result(chip->fv_votable); while (true) { rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_CHARGE_TYPE, &pval); if (rc < 0) { Loading @@ -660,10 +699,36 @@ static void smb1390_taper_work(struct work_struct *work) goto out; } } while (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER); if (get_effective_result(chip->fv_votable) > chip->taper_entry_fv) { pr_debug("Float voltage increased. Exiting taper\n"); goto out; } else { chip->taper_entry_fv = get_effective_result(chip->fv_votable); } if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER) { fcc_uA = get_client_vote(chip->fcc_votable, CP_VOTER) - 100000; pr_debug("taper work reducing FCC to %duA\n", fcc_uA); vote(chip->fcc_votable, CP_VOTER, true, fcc_uA); if (fcc_uA < 2000000) { vote(chip->disable_votable, TAPER_END_VOTER, true, 0); goto out; } } else { pr_debug("In fast charging. Wait for next taper\n"); } msleep(500); } out: pr_debug("taper work exit\n"); vote(chip->fcc_votable, CP_VOTER, false, 0); chip->taper_work_running = false; } Loading @@ -687,6 +752,10 @@ static int smb1390_parse_dt(struct smb1390 *chip) } } chip->max_cutoff_soc = 85; /* 85% */ of_property_read_u32(chip->dev->of_node, "qcom,max-cutoff-soc", &chip->max_cutoff_soc); return rc; } Loading Loading @@ -732,6 +801,9 @@ static int smb1390_init_hw(struct smb1390 *chip) * traditional parallel charging if present */ vote(chip->disable_votable, USER_VOTER, true, 0); /* keep charge pump disabled if SOC is above threshold */ vote(chip->disable_votable, SOC_LEVEL_VOTER, smb1390_is_batt_soc_valid(chip) ? false : true, 0); /* * Improve ILIM accuracy: Loading Loading @@ -915,6 +987,7 @@ static int smb1390_remove(struct platform_device *pdev) /* explicitly disable charging */ vote(chip->disable_votable, USER_VOTER, true, 0); vote(chip->disable_votable, SOC_LEVEL_VOTER, true, 0); cancel_work(&chip->taper_work); cancel_work(&chip->status_change_work); wakeup_source_unregister(chip->cp_ws); Loading Loading
Documentation/devicetree/bindings/power/supply/qcom/smb1390-charger.txt +6 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,12 @@ Charger specific properties: Definition: For details about IIO bindings see: Documentation/devicetree/bindings/iio/iio-bindings.txt - qcom,max-cutoff-soc Usage: optional Value type: <u32> Definition: SOC beyond which SMB1390 is kept disabled. If this value is not specified then default value is 85%. ================================================ Second Level Nodes - SMB1390 Charger Peripherals ================================================ Loading
drivers/power/supply/qcom/smb1390-charger.c +85 −12 Original line number Diff line number Diff line Loading @@ -87,9 +87,11 @@ #define ILIM_VOTER "ILIM_VOTER" #define FCC_VOTER "FCC_VOTER" #define ICL_VOTER "ICL_VOTER" #define TAPER_END_VOTER "TAPER_END_VOTER" #define WIRELESS_VOTER "WIRELESS_VOTER" #define SRC_VOTER "SRC_VOTER" #define SWITCHER_TOGGLE_VOTER "SWITCHER_TOGGLE_VOTER" #define SOC_LEVEL_VOTER "SOC_LEVEL_VOTER" enum { SWITCHER_OFF_WINDOW_IRQ = 0, Loading Loading @@ -126,6 +128,7 @@ struct smb1390 { struct votable *disable_votable; struct votable *ilim_votable; struct votable *fcc_votable; struct votable *fv_votable; struct votable *cp_awake_votable; /* power supplies */ Loading @@ -138,6 +141,8 @@ struct smb1390 { bool taper_work_running; struct smb1390_iio iio; int irq_status; int taper_entry_fv; u32 max_cutoff_soc; }; struct smb_irq { Loading Loading @@ -207,6 +212,14 @@ static bool is_psy_voter_available(struct smb1390 *chip) } } if (!chip->fv_votable) { chip->fv_votable = find_votable("FV"); if (!chip->fv_votable) { pr_debug("Couldn't find FV votable\n"); return false; } } return true; } Loading @@ -220,6 +233,28 @@ static void cp_toggle_switcher(struct smb1390 *chip) vote(chip->disable_votable, SWITCHER_TOGGLE_VOTER, false, 0); } static int smb1390_is_batt_soc_valid(struct smb1390 *chip) { int rc; union power_supply_propval pval = {0, }; if (!chip->batt_psy) goto out; rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_CAPACITY, &pval); if (rc < 0) { pr_err("Couldn't get CAPACITY rc=%d\n", rc); goto out; } if (pval.intval >= chip->max_cutoff_soc) return false; out: return true; } static irqreturn_t default_irq_handler(int irq, void *data) { struct smb1390 *chip = data; Loading Loading @@ -550,6 +585,9 @@ static void smb1390_status_change_work(struct work_struct *work) if (!is_psy_voter_available(chip)) goto out; vote(chip->disable_votable, SOC_LEVEL_VOTER, smb1390_is_batt_soc_valid(chip) ? false : true, 0); rc = power_supply_get_property(chip->usb_psy, POWER_SUPPLY_PROP_SMB_EN_MODE, &pval); if (rc < 0) { Loading Loading @@ -596,6 +634,14 @@ static void smb1390_status_change_work(struct work_struct *work) vote(chip->ilim_votable, FCC_VOTER, true, get_effective_result(chip->fcc_votable) / 2); /* * Remove SMB1390 Taper condition disable vote if float voltage * increased in comparison to voltage at which it entered taper. */ if (chip->taper_entry_fv < get_effective_result(chip->fv_votable)) vote(chip->disable_votable, TAPER_END_VOTER, false, 0); /* * all votes that would result in disabling the charge pump have * been cast; ensure the charhe pump is still enabled before Loading @@ -622,10 +668,12 @@ static void smb1390_status_change_work(struct work_struct *work) } } else { vote(chip->disable_votable, SRC_VOTER, true, 0); vote(chip->disable_votable, TAPER_END_VOTER, false, 0); max_fcc_ma = get_client_vote(chip->fcc_votable, BATT_PROFILE_VOTER); vote(chip->fcc_votable, CP_VOTER, max_fcc_ma > 0 ? true : false, max_fcc_ma); vote(chip->disable_votable, SOC_LEVEL_VOTER, true, 0); } out: Loading @@ -642,17 +690,8 @@ static void smb1390_taper_work(struct work_struct *work) if (!is_psy_voter_available(chip)) goto out; do { fcc_uA = get_effective_result(chip->fcc_votable); if (fcc_uA < 2000000) break; fcc_uA = get_client_vote(chip->fcc_votable, CP_VOTER) - 100000; pr_debug("taper work reducing FCC to %duA\n", fcc_uA); vote(chip->fcc_votable, CP_VOTER, true, fcc_uA); msleep(500); chip->taper_entry_fv = get_effective_result(chip->fv_votable); while (true) { rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_CHARGE_TYPE, &pval); if (rc < 0) { Loading @@ -660,10 +699,36 @@ static void smb1390_taper_work(struct work_struct *work) goto out; } } while (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER); if (get_effective_result(chip->fv_votable) > chip->taper_entry_fv) { pr_debug("Float voltage increased. Exiting taper\n"); goto out; } else { chip->taper_entry_fv = get_effective_result(chip->fv_votable); } if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER) { fcc_uA = get_client_vote(chip->fcc_votable, CP_VOTER) - 100000; pr_debug("taper work reducing FCC to %duA\n", fcc_uA); vote(chip->fcc_votable, CP_VOTER, true, fcc_uA); if (fcc_uA < 2000000) { vote(chip->disable_votable, TAPER_END_VOTER, true, 0); goto out; } } else { pr_debug("In fast charging. Wait for next taper\n"); } msleep(500); } out: pr_debug("taper work exit\n"); vote(chip->fcc_votable, CP_VOTER, false, 0); chip->taper_work_running = false; } Loading @@ -687,6 +752,10 @@ static int smb1390_parse_dt(struct smb1390 *chip) } } chip->max_cutoff_soc = 85; /* 85% */ of_property_read_u32(chip->dev->of_node, "qcom,max-cutoff-soc", &chip->max_cutoff_soc); return rc; } Loading Loading @@ -732,6 +801,9 @@ static int smb1390_init_hw(struct smb1390 *chip) * traditional parallel charging if present */ vote(chip->disable_votable, USER_VOTER, true, 0); /* keep charge pump disabled if SOC is above threshold */ vote(chip->disable_votable, SOC_LEVEL_VOTER, smb1390_is_batt_soc_valid(chip) ? false : true, 0); /* * Improve ILIM accuracy: Loading Loading @@ -915,6 +987,7 @@ static int smb1390_remove(struct platform_device *pdev) /* explicitly disable charging */ vote(chip->disable_votable, USER_VOTER, true, 0); vote(chip->disable_votable, SOC_LEVEL_VOTER, true, 0); cancel_work(&chip->taper_work); cancel_work(&chip->status_change_work); wakeup_source_unregister(chip->cp_ws); Loading