Loading Documentation/devicetree/bindings/batterydata/batterydata.txt +18 −5 Original line number Original line Diff line number Diff line Loading @@ -120,12 +120,25 @@ Profile data node optional properties: The threshold values in range should be in ascending The threshold values in range should be in ascending and shouldn't overlap. It support 8 ranges at max. and shouldn't overlap. It support 8 ranges at max. - qcom,jeita-soft-thresholds: A tuple entry to specify ADC code for battery's soft JEITA - qcom,jeita-soft-thresholds: A tuple entry to specify ADC code for battery's soft JEITA threshold. threshold. <SOFT_COLD_ADC_CODE, SOFT_HOT_ADC_CODE>. <SOFT_COLD_ADC_CODE, SOFT_HOT_ADC_CODE>. - qcom,jeita-hard-thresholds: A tuple entry to specify ADC code for battery's hard JEITA - qcom,jeita-hard-thresholds: A tuple entry to specify ADC code for battery's hard JEITA threshold. threshold. <HARD_COLD_ADC_CODE, HARD_HOT_ADC_CODE>. <HARD_COLD_ADC_CODE, HARD_HOT_ADC_CODE>. - qcom,jeita-soft-hys-thresholds: A tuple entry to specify ADC code for battery's soft JEITA threshold with hysteresis adjustment. <SOFT_COLD_ADC_CODE, SOFT_HOT_ADC_CODE>. These "hysteresis" values should be specified if "qcom,jeita-soft-thresholds" are specified. Without which SW JEITA compensation won't function properly. - qcom,jeita-soft-fcc-ua: A tuple entry to specify the values of Fast charging current (in uA) that needs to be applied during soft JEITA conditions (cool/warm). Element 0 - FCC value for soft cool. Element 1 - FCC value for soft warm. - qcom,jeita-soft-fv-uv: A tuple entry to specify the values of Float voltage (in uV) that needs to be applied during soft JEITA conditions (cool/warm). Element 0 - FV value for soft cool. Element 1 - FV value for soft warm. Profile data node required subnodes: Profile data node required subnodes: - qcom,fcc-temp-lut : An 1-dimensional lookup table node that encodes - qcom,fcc-temp-lut : An 1-dimensional lookup table node that encodes temperature to fcc lookup. The units for this lookup temperature to fcc lookup. The units for this lookup Loading arch/arm64/boot/dts/qcom/fg-gen4-batterydata-alium-3600mah.dtsi +9 −1 Original line number Original line Diff line number Diff line Loading @@ -16,7 +16,7 @@ qcom,alium_860_89032_0000_3600mah_averaged_masterslave_sep24th2018 { qcom,max-voltage-uv = <4350000>; qcom,max-voltage-uv = <4350000>; qcom,fastchg-current-ma = <5400>; qcom,fastchg-current-ma = <5400>; qcom,jeita-fcc-ranges = <0 100 2500000 qcom,jeita-fcc-ranges = <0 100 2500000 110 400 5400000 110 400 3600000 410 450 2500000>; 410 450 2500000>; qcom,jeita-fv-ranges = <0 100 4250000 qcom,jeita-fv-ranges = <0 100 4250000 110 400 4350000 110 400 4350000 Loading @@ -24,6 +24,14 @@ qcom,alium_860_89032_0000_3600mah_averaged_masterslave_sep24th2018 { qcom,step-chg-ranges = <3600000 3800000 5400000 qcom,step-chg-ranges = <3600000 3800000 5400000 3801000 4300000 3600000 3801000 4300000 3600000 4301000 4350000 2500000>; 4301000 4350000 2500000>; /* COLD = 0 DegC, HOT = 45 DegC */ qcom,jeita-hard-thresholds = <0x58cd 0x20b8>; /* COOL = 10 DegC, WARM = 40 DegC */ qcom,jeita-soft-thresholds = <0x4ccc 0x25e3>; /* COLD hys = 13 DegC, WARM hys = 37 DegC */ qcom,jeita-soft-hys-thresholds = <0x48d4 0x2943>; qcom,jeita-soft-fcc-ua = <2500000 2500000>; qcom,jeita-soft-fv-uv = <4250000 4250000>; qcom,ocv-based-step-chg; qcom,ocv-based-step-chg; qcom,batt-id-kohm = <107>; qcom,batt-id-kohm = <107>; qcom,battery-beta = <4250>; qcom,battery-beta = <4250>; Loading arch/arm64/boot/dts/qcom/fg-gen4-batterydata-mlp466076-3250mah.dtsi +4 −0 Original line number Original line Diff line number Diff line Loading @@ -19,12 +19,16 @@ qcom,mlp466076_3250mah_averaged_masterslave_sept24th2018 { qcom,jeita-hard-thresholds = <0x5840 0x1810>; qcom,jeita-hard-thresholds = <0x5840 0x1810>; /* COOL = 15 DegC, WARM = 45 DegC */ /* COOL = 15 DegC, WARM = 45 DegC */ qcom,jeita-soft-thresholds = <0x45f3 0x20c4>; qcom,jeita-soft-thresholds = <0x45f3 0x20c4>; /* COOL hys = 18 DegC, WARM hys = 42 DegC */ qcom,jeita-soft-hys-thresholds = <0x4206 0x23c0>; qcom,jeita-fcc-ranges = <0 150 650000 qcom,jeita-fcc-ranges = <0 150 650000 151 450 4875000 151 450 4875000 451 550 1625000>; 451 550 1625000>; qcom,jeita-fv-ranges = <0 150 4150000 qcom,jeita-fv-ranges = <0 150 4150000 151 450 4400000 151 450 4400000 451 550 4150000>; 451 550 4150000>; qcom,jeita-soft-fcc-ua = <650000 1625000>; qcom,jeita-soft-fv-uv = <4150000 4150000>; qcom,batt-id-kohm = <133>; qcom,batt-id-kohm = <133>; qcom,battery-beta = <4250>; qcom,battery-beta = <4250>; qcom,therm-room-temp = <100000>; qcom,therm-room-temp = <100000>; Loading drivers/power/supply/qcom/qpnp-smb5.c +4 −14 Original line number Original line Diff line number Diff line Loading @@ -1378,13 +1378,6 @@ static int smb5_batt_set_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED: case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED: chg->step_chg_enabled = !!val->intval; chg->step_chg_enabled = !!val->intval; break; break; case POWER_SUPPLY_PROP_SW_JEITA_ENABLED: if (chg->sw_jeita_enabled != (!!val->intval)) { rc = smblib_disable_hw_jeita(chg, !!val->intval); if (rc == 0) chg->sw_jeita_enabled = !!val->intval; } break; case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: chg->batt_profile_fcc_ua = val->intval; chg->batt_profile_fcc_ua = val->intval; vote(chg->fcc_votable, BATT_PROFILE_VOTER, true, val->intval); vote(chg->fcc_votable, BATT_PROFILE_VOTER, true, val->intval); Loading Loading @@ -1458,7 +1451,6 @@ static int smb5_batt_prop_is_writeable(struct power_supply *psy, case POWER_SUPPLY_PROP_RERUN_AICL: case POWER_SUPPLY_PROP_RERUN_AICL: case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED: case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED: case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED: case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED: case POWER_SUPPLY_PROP_SW_JEITA_ENABLED: case POWER_SUPPLY_PROP_DIE_HEALTH: case POWER_SUPPLY_PROP_DIE_HEALTH: return 1; return 1; default: default: Loading Loading @@ -2119,13 +2111,11 @@ static int smb5_init_hw(struct smb5 *chip) } } } } if (chg->sw_jeita_enabled) { rc = smblib_disable_hw_jeita(chg, true); rc = smblib_disable_hw_jeita(chg, true); if (rc < 0) { if (rc < 0) { dev_err(chg->dev, "Couldn't set hw jeita rc=%d\n", rc); dev_err(chg->dev, "Couldn't set hw jeita rc=%d\n", rc); return rc; return rc; } } } rc = smblib_masked_write(chg, DCDC_ENG_SDCDC_CFG5_REG, rc = smblib_masked_write(chg, DCDC_ENG_SDCDC_CFG5_REG, ENG_SDCDC_BAT_HPWR_MASK, BOOST_MODE_THRESH_3P6_V); ENG_SDCDC_BAT_HPWR_MASK, BOOST_MODE_THRESH_3P6_V); Loading drivers/power/supply/qcom/smb5-lib.c +216 −78 Original line number Original line Diff line number Diff line Loading @@ -915,7 +915,7 @@ static int smblib_notifier_call(struct notifier_block *nb, schedule_work(&chg->bms_update_work); schedule_work(&chg->bms_update_work); } } if (!chg->jeita_configured) if (chg->jeita_configured == JEITA_CFG_NONE) schedule_work(&chg->jeita_update_work); schedule_work(&chg->jeita_update_work); if (chg->sec_pl_present && !chg->pl.psy if (chg->sec_pl_present && !chg->pl.psy Loading Loading @@ -2270,6 +2270,7 @@ int smblib_disable_hw_jeita(struct smb_charger *chg, bool disable) rc); rc); return rc; return rc; } } return 0; return 0; } } Loading Loading @@ -3689,49 +3690,153 @@ int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg, return rc; return rc; } } static int smblib_recover_from_soft_jeita(struct smb_charger *chg) #define JEITA_SOFT 0 #define JEITA_HARD 1 static int smblib_update_jeita(struct smb_charger *chg, u32 *thresholds, int type) { { u8 stat1, stat7; int rc; int rc; u16 temp, base; base = CHGR_JEITA_THRESHOLD_BASE_REG(type); rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat1); temp = thresholds[1] & 0xFFFF; temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8); rc = smblib_batch_write(chg, base, (u8 *)&temp, 2); if (rc < 0) { if (rc < 0) { smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n", smblib_err(chg, rc); "Couldn't configure Jeita %s hot threshold rc=%d\n", (type == JEITA_SOFT) ? "Soft" : "Hard", rc); return rc; return rc; } } rc = smblib_read(chg, BATTERY_CHARGER_STATUS_7_REG, &stat7); temp = thresholds[0] & 0xFFFF; temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8); rc = smblib_batch_write(chg, base + 2, (u8 *)&temp, 2); if (rc < 0) { if (rc < 0) { smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_2 rc=%d\n", smblib_err(chg, rc); "Couldn't configure Jeita %s cold threshold rc=%d\n", (type == JEITA_SOFT) ? "Soft" : "Hard", rc); return rc; return rc; } } if ((chg->jeita_status && !(stat7 & BAT_TEMP_STATUS_SOFT_LIMIT_MASK) && smblib_dbg(chg, PR_MISC, "%s Jeita threshold configured\n", ((stat1 & BATTERY_CHARGER_STATUS_MASK) == TERMINATE_CHARGE))) { (type == JEITA_SOFT) ? "Soft" : "Hard"); /* * We are moving from JEITA soft -> Normal and charging return 0; * is terminated } */ rc = smblib_write(chg, CHARGING_ENABLE_CMD_REG, 0); static int smblib_charge_inhibit_en(struct smb_charger *chg, bool enable) if (rc < 0) { { smblib_err(chg, "Couldn't disable charging rc=%d\n", int rc; rc); rc = smblib_masked_write(chg, CHGR_CFG2_REG, CHARGER_INHIBIT_BIT, enable ? CHARGER_INHIBIT_BIT : 0); return rc; return rc; } } rc = smblib_write(chg, CHARGING_ENABLE_CMD_REG, CHARGING_ENABLE_CMD_BIT); static int smblib_soft_jeita_arb_wa(struct smb_charger *chg) { union power_supply_propval pval; int rc = 0; bool soft_jeita; rc = smblib_get_prop_batt_health(chg, &pval); if (rc < 0) { if (rc < 0) { smblib_err(chg, "Couldn't enable charging rc=%d\n", smblib_err(chg, "Couldn't get battery health rc=%d\n", rc); rc); return rc; return rc; } } } chg->jeita_status = stat7 & BAT_TEMP_STATUS_SOFT_LIMIT_MASK; /* Do nothing on entering hard JEITA condition */ if (pval.intval == POWER_SUPPLY_HEALTH_COLD || pval.intval == POWER_SUPPLY_HEALTH_HOT) return 0; if (chg->jeita_soft_fcc[0] < 0 || chg->jeita_soft_fcc[1] < 0 || chg->jeita_soft_fv[0] < 0 || chg->jeita_soft_fv[1] < 0) return 0; soft_jeita = (pval.intval == POWER_SUPPLY_HEALTH_COOL) || (pval.intval == POWER_SUPPLY_HEALTH_WARM); /* Do nothing on entering soft JEITA from hard JEITA */ if (chg->jeita_arb_flag && soft_jeita) return 0; /* Do nothing, initial to health condition */ if (!chg->jeita_arb_flag && !soft_jeita) return 0; return 0; if (!chg->cp_disable_votable) chg->cp_disable_votable = find_votable("CP_DISABLE"); /* Entering soft JEITA from normal state */ if (!chg->jeita_arb_flag && soft_jeita) { vote(chg->chg_disable_votable, JEITA_ARB_VOTER, true, 0); /* Disable parallel charging */ if (chg->pl_disable_votable) vote(chg->pl_disable_votable, JEITA_ARB_VOTER, true, 0); if (chg->cp_disable_votable) vote(chg->cp_disable_votable, JEITA_ARB_VOTER, true, 0); rc = smblib_charge_inhibit_en(chg, true); if (rc < 0) smblib_err(chg, "Couldn't enable charge inhibit rc=%d\n", rc); rc = smblib_update_jeita(chg, chg->jeita_soft_hys_thlds, JEITA_SOFT); if (rc < 0) smblib_err(chg, "Couldn't configure Jeita soft threshold rc=%d\n", rc); if (pval.intval == POWER_SUPPLY_HEALTH_COOL) { vote(chg->fcc_votable, JEITA_ARB_VOTER, true, chg->jeita_soft_fcc[0]); vote(chg->fv_votable, JEITA_ARB_VOTER, true, chg->jeita_soft_fv[0]); } else { vote(chg->fcc_votable, JEITA_ARB_VOTER, true, chg->jeita_soft_fcc[1]); vote(chg->fv_votable, JEITA_ARB_VOTER, true, chg->jeita_soft_fv[1]); } vote(chg->chg_disable_votable, JEITA_ARB_VOTER, false, 0); chg->jeita_arb_flag = true; } else if (chg->jeita_arb_flag && !soft_jeita) { /* Exit to health state from soft JEITA */ vote(chg->chg_disable_votable, JEITA_ARB_VOTER, true, 0); rc = smblib_charge_inhibit_en(chg, false); if (rc < 0) smblib_err(chg, "Couldn't disable charge inhibit rc=%d\n", rc); rc = smblib_update_jeita(chg, chg->jeita_soft_thlds, JEITA_SOFT); if (rc < 0) smblib_err(chg, "Couldn't configure Jeita soft threshold rc=%d\n", rc); vote(chg->fcc_votable, JEITA_ARB_VOTER, false, 0); vote(chg->fv_votable, JEITA_ARB_VOTER, false, 0); if (chg->pl_disable_votable) vote(chg->pl_disable_votable, JEITA_ARB_VOTER, false, 0); if (chg->cp_disable_votable) vote(chg->cp_disable_votable, JEITA_ARB_VOTER, false, 0); vote(chg->chg_disable_votable, JEITA_ARB_VOTER, false, 0); chg->jeita_arb_flag = false; } smblib_dbg(chg, PR_MISC, "JEITA ARB status %d, soft JEITA status %d\n", chg->jeita_arb_flag, soft_jeita); return rc; } } /************************ /************************ Loading Loading @@ -3889,15 +3994,18 @@ irqreturn_t batt_temp_changed_irq_handler(int irq, void *data) struct smb_charger *chg = irq_data->parent_data; struct smb_charger *chg = irq_data->parent_data; int rc; int rc; rc = smblib_recover_from_soft_jeita(chg); smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name); if (chg->jeita_configured != JEITA_CFG_COMPLETE) return IRQ_HANDLED; rc = smblib_soft_jeita_arb_wa(chg); if (rc < 0) { if (rc < 0) { smblib_err(chg, "Couldn't recover chg from soft jeita rc=%d\n", smblib_err(chg, "Couldn't fix soft jeita arb rc=%d\n", rc); rc); return IRQ_HANDLED; return IRQ_HANDLED; } } rerun_election(chg->fcc_votable); power_supply_changed(chg->batt_psy); return IRQ_HANDLED; return IRQ_HANDLED; } } Loading Loading @@ -4975,7 +5083,7 @@ irqreturn_t wdog_bark_irq_handler(int irq, void *data) if (rc < 0) if (rc < 0) smblib_err(chg, "Couldn't pet the dog rc=%d\n", rc); smblib_err(chg, "Couldn't pet the dog rc=%d\n", rc); if (chg->step_chg_enabled || chg->sw_jeita_enabled) if (chg->step_chg_enabled) power_supply_changed(chg->batt_psy); power_supply_changed(chg->batt_psy); return IRQ_HANDLED; return IRQ_HANDLED; Loading Loading @@ -5220,42 +5328,6 @@ static void smblib_thermal_regulation_work(struct work_struct *work) rc); rc); } } #define JEITA_SOFT 0 #define JEITA_HARD 1 static int smblib_update_jeita(struct smb_charger *chg, u32 *thresholds, int type) { int rc; u16 temp, base; base = CHGR_JEITA_THRESHOLD_BASE_REG(type); temp = thresholds[1] & 0xFFFF; temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8); rc = smblib_batch_write(chg, base, (u8 *)&temp, 2); if (rc < 0) { smblib_err(chg, "Couldn't configure Jeita %s hot threshold rc=%d\n", (type == JEITA_SOFT) ? "Soft" : "Hard", rc); return rc; } temp = thresholds[0] & 0xFFFF; temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8); rc = smblib_batch_write(chg, base + 2, (u8 *)&temp, 2); if (rc < 0) { smblib_err(chg, "Couldn't configure Jeita %s cold threshold rc=%d\n", (type == JEITA_SOFT) ? "Soft" : "Hard", rc); return rc; } smblib_dbg(chg, PR_MISC, "%s Jeita threshold configured\n", (type == JEITA_SOFT) ? "Soft" : "Hard"); return 0; } static void jeita_update_work(struct work_struct *work) static void jeita_update_work(struct work_struct *work) { { struct smb_charger *chg = container_of(work, struct smb_charger, struct smb_charger *chg = container_of(work, struct smb_charger, Loading @@ -5263,8 +5335,8 @@ static void jeita_update_work(struct work_struct *work) struct device_node *node = chg->dev->of_node; struct device_node *node = chg->dev->of_node; struct device_node *batt_node, *pnode; struct device_node *batt_node, *pnode; union power_supply_propval val; union power_supply_propval val; int rc; int rc, tmp[2], max_fcc_ma, max_fv_uv; u32 jeita_thresholds[2]; u32 jeita_hard_thresholds[2]; batt_node = of_find_node_by_name(node, "qcom,battery-data"); batt_node = of_find_node_by_name(node, "qcom,battery-data"); if (!batt_node) { if (!batt_node) { Loading Loading @@ -5297,9 +5369,10 @@ static void jeita_update_work(struct work_struct *work) } } rc = of_property_read_u32_array(pnode, "qcom,jeita-hard-thresholds", rc = of_property_read_u32_array(pnode, "qcom,jeita-hard-thresholds", jeita_thresholds, 2); jeita_hard_thresholds, 2); if (!rc) { if (!rc) { rc = smblib_update_jeita(chg, jeita_thresholds, JEITA_HARD); rc = smblib_update_jeita(chg, jeita_hard_thresholds, JEITA_HARD); if (rc < 0) { if (rc < 0) { smblib_err(chg, "Couldn't configure Hard Jeita rc=%d\n", smblib_err(chg, "Couldn't configure Hard Jeita rc=%d\n", rc); rc); Loading @@ -5308,18 +5381,83 @@ static void jeita_update_work(struct work_struct *work) } } rc = of_property_read_u32_array(pnode, "qcom,jeita-soft-thresholds", rc = of_property_read_u32_array(pnode, "qcom,jeita-soft-thresholds", jeita_thresholds, 2); chg->jeita_soft_thlds, 2); if (!rc) { if (!rc) { rc = smblib_update_jeita(chg, jeita_thresholds, JEITA_SOFT); rc = smblib_update_jeita(chg, chg->jeita_soft_thlds, JEITA_SOFT); if (rc < 0) { if (rc < 0) { smblib_err(chg, "Couldn't configure Soft Jeita rc=%d\n", smblib_err(chg, "Couldn't configure Soft Jeita rc=%d\n", rc); rc); goto out; goto out; } } rc = of_property_read_u32_array(pnode, "qcom,jeita-soft-hys-thresholds", chg->jeita_soft_hys_thlds, 2); if (rc < 0) { smblib_err(chg, "Couldn't get Soft Jeita hysteresis thresholds rc=%d\n", rc); goto out; } } chg->jeita_soft_fcc[0] = chg->jeita_soft_fcc[1] = -EINVAL; chg->jeita_soft_fv[0] = chg->jeita_soft_fv[1] = -EINVAL; max_fcc_ma = max_fv_uv = -EINVAL; of_property_read_u32(pnode, "qcom,fastchg-current-ma", &max_fcc_ma); of_property_read_u32(pnode, "qcom,max-voltage-uv", &max_fv_uv); if (max_fcc_ma <= 0 || max_fv_uv <= 0) { smblib_err(chg, "Incorrect fastchg-current-ma or max-voltage-uv\n"); goto out; } rc = of_property_read_u32_array(pnode, "qcom,jeita-soft-fcc-ua", tmp, 2); if (rc < 0) { smblib_err(chg, "Couldn't get fcc values for soft JEITA rc=%d\n", rc); goto out; } max_fcc_ma *= 1000; if (tmp[0] > max_fcc_ma || tmp[1] > max_fcc_ma) { smblib_err(chg, "Incorrect FCC value [%d %d] max: %d\n", tmp[0], tmp[1], max_fcc_ma); goto out; } chg->jeita_soft_fcc[0] = tmp[0]; chg->jeita_soft_fcc[1] = tmp[1]; rc = of_property_read_u32_array(pnode, "qcom,jeita-soft-fv-uv", tmp, 2); if (rc < 0) { smblib_err(chg, "Couldn't get fv values for soft JEITA rc=%d\n", rc); goto out; } } if (tmp[0] > max_fv_uv || tmp[1] > max_fv_uv) { smblib_err(chg, "Incorrect FV value [%d %d] max: %d\n", tmp[0], tmp[1], max_fv_uv); goto out; } chg->jeita_soft_fv[0] = tmp[0]; chg->jeita_soft_fv[1] = tmp[1]; rc = smblib_soft_jeita_arb_wa(chg); if (rc < 0) { smblib_err(chg, "Couldn't fix soft jeita arb rc=%d\n", rc); goto out; } chg->jeita_configured = JEITA_CFG_COMPLETE; return; out: out: chg->jeita_configured = true; chg->jeita_configured = JEITA_CFG_FAILURE; } } static void smblib_lpd_ra_open_work(struct work_struct *work) static void smblib_lpd_ra_open_work(struct work_struct *work) Loading Loading
Documentation/devicetree/bindings/batterydata/batterydata.txt +18 −5 Original line number Original line Diff line number Diff line Loading @@ -120,12 +120,25 @@ Profile data node optional properties: The threshold values in range should be in ascending The threshold values in range should be in ascending and shouldn't overlap. It support 8 ranges at max. and shouldn't overlap. It support 8 ranges at max. - qcom,jeita-soft-thresholds: A tuple entry to specify ADC code for battery's soft JEITA - qcom,jeita-soft-thresholds: A tuple entry to specify ADC code for battery's soft JEITA threshold. threshold. <SOFT_COLD_ADC_CODE, SOFT_HOT_ADC_CODE>. <SOFT_COLD_ADC_CODE, SOFT_HOT_ADC_CODE>. - qcom,jeita-hard-thresholds: A tuple entry to specify ADC code for battery's hard JEITA - qcom,jeita-hard-thresholds: A tuple entry to specify ADC code for battery's hard JEITA threshold. threshold. <HARD_COLD_ADC_CODE, HARD_HOT_ADC_CODE>. <HARD_COLD_ADC_CODE, HARD_HOT_ADC_CODE>. - qcom,jeita-soft-hys-thresholds: A tuple entry to specify ADC code for battery's soft JEITA threshold with hysteresis adjustment. <SOFT_COLD_ADC_CODE, SOFT_HOT_ADC_CODE>. These "hysteresis" values should be specified if "qcom,jeita-soft-thresholds" are specified. Without which SW JEITA compensation won't function properly. - qcom,jeita-soft-fcc-ua: A tuple entry to specify the values of Fast charging current (in uA) that needs to be applied during soft JEITA conditions (cool/warm). Element 0 - FCC value for soft cool. Element 1 - FCC value for soft warm. - qcom,jeita-soft-fv-uv: A tuple entry to specify the values of Float voltage (in uV) that needs to be applied during soft JEITA conditions (cool/warm). Element 0 - FV value for soft cool. Element 1 - FV value for soft warm. Profile data node required subnodes: Profile data node required subnodes: - qcom,fcc-temp-lut : An 1-dimensional lookup table node that encodes - qcom,fcc-temp-lut : An 1-dimensional lookup table node that encodes temperature to fcc lookup. The units for this lookup temperature to fcc lookup. The units for this lookup Loading
arch/arm64/boot/dts/qcom/fg-gen4-batterydata-alium-3600mah.dtsi +9 −1 Original line number Original line Diff line number Diff line Loading @@ -16,7 +16,7 @@ qcom,alium_860_89032_0000_3600mah_averaged_masterslave_sep24th2018 { qcom,max-voltage-uv = <4350000>; qcom,max-voltage-uv = <4350000>; qcom,fastchg-current-ma = <5400>; qcom,fastchg-current-ma = <5400>; qcom,jeita-fcc-ranges = <0 100 2500000 qcom,jeita-fcc-ranges = <0 100 2500000 110 400 5400000 110 400 3600000 410 450 2500000>; 410 450 2500000>; qcom,jeita-fv-ranges = <0 100 4250000 qcom,jeita-fv-ranges = <0 100 4250000 110 400 4350000 110 400 4350000 Loading @@ -24,6 +24,14 @@ qcom,alium_860_89032_0000_3600mah_averaged_masterslave_sep24th2018 { qcom,step-chg-ranges = <3600000 3800000 5400000 qcom,step-chg-ranges = <3600000 3800000 5400000 3801000 4300000 3600000 3801000 4300000 3600000 4301000 4350000 2500000>; 4301000 4350000 2500000>; /* COLD = 0 DegC, HOT = 45 DegC */ qcom,jeita-hard-thresholds = <0x58cd 0x20b8>; /* COOL = 10 DegC, WARM = 40 DegC */ qcom,jeita-soft-thresholds = <0x4ccc 0x25e3>; /* COLD hys = 13 DegC, WARM hys = 37 DegC */ qcom,jeita-soft-hys-thresholds = <0x48d4 0x2943>; qcom,jeita-soft-fcc-ua = <2500000 2500000>; qcom,jeita-soft-fv-uv = <4250000 4250000>; qcom,ocv-based-step-chg; qcom,ocv-based-step-chg; qcom,batt-id-kohm = <107>; qcom,batt-id-kohm = <107>; qcom,battery-beta = <4250>; qcom,battery-beta = <4250>; Loading
arch/arm64/boot/dts/qcom/fg-gen4-batterydata-mlp466076-3250mah.dtsi +4 −0 Original line number Original line Diff line number Diff line Loading @@ -19,12 +19,16 @@ qcom,mlp466076_3250mah_averaged_masterslave_sept24th2018 { qcom,jeita-hard-thresholds = <0x5840 0x1810>; qcom,jeita-hard-thresholds = <0x5840 0x1810>; /* COOL = 15 DegC, WARM = 45 DegC */ /* COOL = 15 DegC, WARM = 45 DegC */ qcom,jeita-soft-thresholds = <0x45f3 0x20c4>; qcom,jeita-soft-thresholds = <0x45f3 0x20c4>; /* COOL hys = 18 DegC, WARM hys = 42 DegC */ qcom,jeita-soft-hys-thresholds = <0x4206 0x23c0>; qcom,jeita-fcc-ranges = <0 150 650000 qcom,jeita-fcc-ranges = <0 150 650000 151 450 4875000 151 450 4875000 451 550 1625000>; 451 550 1625000>; qcom,jeita-fv-ranges = <0 150 4150000 qcom,jeita-fv-ranges = <0 150 4150000 151 450 4400000 151 450 4400000 451 550 4150000>; 451 550 4150000>; qcom,jeita-soft-fcc-ua = <650000 1625000>; qcom,jeita-soft-fv-uv = <4150000 4150000>; qcom,batt-id-kohm = <133>; qcom,batt-id-kohm = <133>; qcom,battery-beta = <4250>; qcom,battery-beta = <4250>; qcom,therm-room-temp = <100000>; qcom,therm-room-temp = <100000>; Loading
drivers/power/supply/qcom/qpnp-smb5.c +4 −14 Original line number Original line Diff line number Diff line Loading @@ -1378,13 +1378,6 @@ static int smb5_batt_set_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED: case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED: chg->step_chg_enabled = !!val->intval; chg->step_chg_enabled = !!val->intval; break; break; case POWER_SUPPLY_PROP_SW_JEITA_ENABLED: if (chg->sw_jeita_enabled != (!!val->intval)) { rc = smblib_disable_hw_jeita(chg, !!val->intval); if (rc == 0) chg->sw_jeita_enabled = !!val->intval; } break; case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: chg->batt_profile_fcc_ua = val->intval; chg->batt_profile_fcc_ua = val->intval; vote(chg->fcc_votable, BATT_PROFILE_VOTER, true, val->intval); vote(chg->fcc_votable, BATT_PROFILE_VOTER, true, val->intval); Loading Loading @@ -1458,7 +1451,6 @@ static int smb5_batt_prop_is_writeable(struct power_supply *psy, case POWER_SUPPLY_PROP_RERUN_AICL: case POWER_SUPPLY_PROP_RERUN_AICL: case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED: case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED: case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED: case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED: case POWER_SUPPLY_PROP_SW_JEITA_ENABLED: case POWER_SUPPLY_PROP_DIE_HEALTH: case POWER_SUPPLY_PROP_DIE_HEALTH: return 1; return 1; default: default: Loading Loading @@ -2119,13 +2111,11 @@ static int smb5_init_hw(struct smb5 *chip) } } } } if (chg->sw_jeita_enabled) { rc = smblib_disable_hw_jeita(chg, true); rc = smblib_disable_hw_jeita(chg, true); if (rc < 0) { if (rc < 0) { dev_err(chg->dev, "Couldn't set hw jeita rc=%d\n", rc); dev_err(chg->dev, "Couldn't set hw jeita rc=%d\n", rc); return rc; return rc; } } } rc = smblib_masked_write(chg, DCDC_ENG_SDCDC_CFG5_REG, rc = smblib_masked_write(chg, DCDC_ENG_SDCDC_CFG5_REG, ENG_SDCDC_BAT_HPWR_MASK, BOOST_MODE_THRESH_3P6_V); ENG_SDCDC_BAT_HPWR_MASK, BOOST_MODE_THRESH_3P6_V); Loading
drivers/power/supply/qcom/smb5-lib.c +216 −78 Original line number Original line Diff line number Diff line Loading @@ -915,7 +915,7 @@ static int smblib_notifier_call(struct notifier_block *nb, schedule_work(&chg->bms_update_work); schedule_work(&chg->bms_update_work); } } if (!chg->jeita_configured) if (chg->jeita_configured == JEITA_CFG_NONE) schedule_work(&chg->jeita_update_work); schedule_work(&chg->jeita_update_work); if (chg->sec_pl_present && !chg->pl.psy if (chg->sec_pl_present && !chg->pl.psy Loading Loading @@ -2270,6 +2270,7 @@ int smblib_disable_hw_jeita(struct smb_charger *chg, bool disable) rc); rc); return rc; return rc; } } return 0; return 0; } } Loading Loading @@ -3689,49 +3690,153 @@ int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg, return rc; return rc; } } static int smblib_recover_from_soft_jeita(struct smb_charger *chg) #define JEITA_SOFT 0 #define JEITA_HARD 1 static int smblib_update_jeita(struct smb_charger *chg, u32 *thresholds, int type) { { u8 stat1, stat7; int rc; int rc; u16 temp, base; base = CHGR_JEITA_THRESHOLD_BASE_REG(type); rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat1); temp = thresholds[1] & 0xFFFF; temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8); rc = smblib_batch_write(chg, base, (u8 *)&temp, 2); if (rc < 0) { if (rc < 0) { smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n", smblib_err(chg, rc); "Couldn't configure Jeita %s hot threshold rc=%d\n", (type == JEITA_SOFT) ? "Soft" : "Hard", rc); return rc; return rc; } } rc = smblib_read(chg, BATTERY_CHARGER_STATUS_7_REG, &stat7); temp = thresholds[0] & 0xFFFF; temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8); rc = smblib_batch_write(chg, base + 2, (u8 *)&temp, 2); if (rc < 0) { if (rc < 0) { smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_2 rc=%d\n", smblib_err(chg, rc); "Couldn't configure Jeita %s cold threshold rc=%d\n", (type == JEITA_SOFT) ? "Soft" : "Hard", rc); return rc; return rc; } } if ((chg->jeita_status && !(stat7 & BAT_TEMP_STATUS_SOFT_LIMIT_MASK) && smblib_dbg(chg, PR_MISC, "%s Jeita threshold configured\n", ((stat1 & BATTERY_CHARGER_STATUS_MASK) == TERMINATE_CHARGE))) { (type == JEITA_SOFT) ? "Soft" : "Hard"); /* * We are moving from JEITA soft -> Normal and charging return 0; * is terminated } */ rc = smblib_write(chg, CHARGING_ENABLE_CMD_REG, 0); static int smblib_charge_inhibit_en(struct smb_charger *chg, bool enable) if (rc < 0) { { smblib_err(chg, "Couldn't disable charging rc=%d\n", int rc; rc); rc = smblib_masked_write(chg, CHGR_CFG2_REG, CHARGER_INHIBIT_BIT, enable ? CHARGER_INHIBIT_BIT : 0); return rc; return rc; } } rc = smblib_write(chg, CHARGING_ENABLE_CMD_REG, CHARGING_ENABLE_CMD_BIT); static int smblib_soft_jeita_arb_wa(struct smb_charger *chg) { union power_supply_propval pval; int rc = 0; bool soft_jeita; rc = smblib_get_prop_batt_health(chg, &pval); if (rc < 0) { if (rc < 0) { smblib_err(chg, "Couldn't enable charging rc=%d\n", smblib_err(chg, "Couldn't get battery health rc=%d\n", rc); rc); return rc; return rc; } } } chg->jeita_status = stat7 & BAT_TEMP_STATUS_SOFT_LIMIT_MASK; /* Do nothing on entering hard JEITA condition */ if (pval.intval == POWER_SUPPLY_HEALTH_COLD || pval.intval == POWER_SUPPLY_HEALTH_HOT) return 0; if (chg->jeita_soft_fcc[0] < 0 || chg->jeita_soft_fcc[1] < 0 || chg->jeita_soft_fv[0] < 0 || chg->jeita_soft_fv[1] < 0) return 0; soft_jeita = (pval.intval == POWER_SUPPLY_HEALTH_COOL) || (pval.intval == POWER_SUPPLY_HEALTH_WARM); /* Do nothing on entering soft JEITA from hard JEITA */ if (chg->jeita_arb_flag && soft_jeita) return 0; /* Do nothing, initial to health condition */ if (!chg->jeita_arb_flag && !soft_jeita) return 0; return 0; if (!chg->cp_disable_votable) chg->cp_disable_votable = find_votable("CP_DISABLE"); /* Entering soft JEITA from normal state */ if (!chg->jeita_arb_flag && soft_jeita) { vote(chg->chg_disable_votable, JEITA_ARB_VOTER, true, 0); /* Disable parallel charging */ if (chg->pl_disable_votable) vote(chg->pl_disable_votable, JEITA_ARB_VOTER, true, 0); if (chg->cp_disable_votable) vote(chg->cp_disable_votable, JEITA_ARB_VOTER, true, 0); rc = smblib_charge_inhibit_en(chg, true); if (rc < 0) smblib_err(chg, "Couldn't enable charge inhibit rc=%d\n", rc); rc = smblib_update_jeita(chg, chg->jeita_soft_hys_thlds, JEITA_SOFT); if (rc < 0) smblib_err(chg, "Couldn't configure Jeita soft threshold rc=%d\n", rc); if (pval.intval == POWER_SUPPLY_HEALTH_COOL) { vote(chg->fcc_votable, JEITA_ARB_VOTER, true, chg->jeita_soft_fcc[0]); vote(chg->fv_votable, JEITA_ARB_VOTER, true, chg->jeita_soft_fv[0]); } else { vote(chg->fcc_votable, JEITA_ARB_VOTER, true, chg->jeita_soft_fcc[1]); vote(chg->fv_votable, JEITA_ARB_VOTER, true, chg->jeita_soft_fv[1]); } vote(chg->chg_disable_votable, JEITA_ARB_VOTER, false, 0); chg->jeita_arb_flag = true; } else if (chg->jeita_arb_flag && !soft_jeita) { /* Exit to health state from soft JEITA */ vote(chg->chg_disable_votable, JEITA_ARB_VOTER, true, 0); rc = smblib_charge_inhibit_en(chg, false); if (rc < 0) smblib_err(chg, "Couldn't disable charge inhibit rc=%d\n", rc); rc = smblib_update_jeita(chg, chg->jeita_soft_thlds, JEITA_SOFT); if (rc < 0) smblib_err(chg, "Couldn't configure Jeita soft threshold rc=%d\n", rc); vote(chg->fcc_votable, JEITA_ARB_VOTER, false, 0); vote(chg->fv_votable, JEITA_ARB_VOTER, false, 0); if (chg->pl_disable_votable) vote(chg->pl_disable_votable, JEITA_ARB_VOTER, false, 0); if (chg->cp_disable_votable) vote(chg->cp_disable_votable, JEITA_ARB_VOTER, false, 0); vote(chg->chg_disable_votable, JEITA_ARB_VOTER, false, 0); chg->jeita_arb_flag = false; } smblib_dbg(chg, PR_MISC, "JEITA ARB status %d, soft JEITA status %d\n", chg->jeita_arb_flag, soft_jeita); return rc; } } /************************ /************************ Loading Loading @@ -3889,15 +3994,18 @@ irqreturn_t batt_temp_changed_irq_handler(int irq, void *data) struct smb_charger *chg = irq_data->parent_data; struct smb_charger *chg = irq_data->parent_data; int rc; int rc; rc = smblib_recover_from_soft_jeita(chg); smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name); if (chg->jeita_configured != JEITA_CFG_COMPLETE) return IRQ_HANDLED; rc = smblib_soft_jeita_arb_wa(chg); if (rc < 0) { if (rc < 0) { smblib_err(chg, "Couldn't recover chg from soft jeita rc=%d\n", smblib_err(chg, "Couldn't fix soft jeita arb rc=%d\n", rc); rc); return IRQ_HANDLED; return IRQ_HANDLED; } } rerun_election(chg->fcc_votable); power_supply_changed(chg->batt_psy); return IRQ_HANDLED; return IRQ_HANDLED; } } Loading Loading @@ -4975,7 +5083,7 @@ irqreturn_t wdog_bark_irq_handler(int irq, void *data) if (rc < 0) if (rc < 0) smblib_err(chg, "Couldn't pet the dog rc=%d\n", rc); smblib_err(chg, "Couldn't pet the dog rc=%d\n", rc); if (chg->step_chg_enabled || chg->sw_jeita_enabled) if (chg->step_chg_enabled) power_supply_changed(chg->batt_psy); power_supply_changed(chg->batt_psy); return IRQ_HANDLED; return IRQ_HANDLED; Loading Loading @@ -5220,42 +5328,6 @@ static void smblib_thermal_regulation_work(struct work_struct *work) rc); rc); } } #define JEITA_SOFT 0 #define JEITA_HARD 1 static int smblib_update_jeita(struct smb_charger *chg, u32 *thresholds, int type) { int rc; u16 temp, base; base = CHGR_JEITA_THRESHOLD_BASE_REG(type); temp = thresholds[1] & 0xFFFF; temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8); rc = smblib_batch_write(chg, base, (u8 *)&temp, 2); if (rc < 0) { smblib_err(chg, "Couldn't configure Jeita %s hot threshold rc=%d\n", (type == JEITA_SOFT) ? "Soft" : "Hard", rc); return rc; } temp = thresholds[0] & 0xFFFF; temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8); rc = smblib_batch_write(chg, base + 2, (u8 *)&temp, 2); if (rc < 0) { smblib_err(chg, "Couldn't configure Jeita %s cold threshold rc=%d\n", (type == JEITA_SOFT) ? "Soft" : "Hard", rc); return rc; } smblib_dbg(chg, PR_MISC, "%s Jeita threshold configured\n", (type == JEITA_SOFT) ? "Soft" : "Hard"); return 0; } static void jeita_update_work(struct work_struct *work) static void jeita_update_work(struct work_struct *work) { { struct smb_charger *chg = container_of(work, struct smb_charger, struct smb_charger *chg = container_of(work, struct smb_charger, Loading @@ -5263,8 +5335,8 @@ static void jeita_update_work(struct work_struct *work) struct device_node *node = chg->dev->of_node; struct device_node *node = chg->dev->of_node; struct device_node *batt_node, *pnode; struct device_node *batt_node, *pnode; union power_supply_propval val; union power_supply_propval val; int rc; int rc, tmp[2], max_fcc_ma, max_fv_uv; u32 jeita_thresholds[2]; u32 jeita_hard_thresholds[2]; batt_node = of_find_node_by_name(node, "qcom,battery-data"); batt_node = of_find_node_by_name(node, "qcom,battery-data"); if (!batt_node) { if (!batt_node) { Loading Loading @@ -5297,9 +5369,10 @@ static void jeita_update_work(struct work_struct *work) } } rc = of_property_read_u32_array(pnode, "qcom,jeita-hard-thresholds", rc = of_property_read_u32_array(pnode, "qcom,jeita-hard-thresholds", jeita_thresholds, 2); jeita_hard_thresholds, 2); if (!rc) { if (!rc) { rc = smblib_update_jeita(chg, jeita_thresholds, JEITA_HARD); rc = smblib_update_jeita(chg, jeita_hard_thresholds, JEITA_HARD); if (rc < 0) { if (rc < 0) { smblib_err(chg, "Couldn't configure Hard Jeita rc=%d\n", smblib_err(chg, "Couldn't configure Hard Jeita rc=%d\n", rc); rc); Loading @@ -5308,18 +5381,83 @@ static void jeita_update_work(struct work_struct *work) } } rc = of_property_read_u32_array(pnode, "qcom,jeita-soft-thresholds", rc = of_property_read_u32_array(pnode, "qcom,jeita-soft-thresholds", jeita_thresholds, 2); chg->jeita_soft_thlds, 2); if (!rc) { if (!rc) { rc = smblib_update_jeita(chg, jeita_thresholds, JEITA_SOFT); rc = smblib_update_jeita(chg, chg->jeita_soft_thlds, JEITA_SOFT); if (rc < 0) { if (rc < 0) { smblib_err(chg, "Couldn't configure Soft Jeita rc=%d\n", smblib_err(chg, "Couldn't configure Soft Jeita rc=%d\n", rc); rc); goto out; goto out; } } rc = of_property_read_u32_array(pnode, "qcom,jeita-soft-hys-thresholds", chg->jeita_soft_hys_thlds, 2); if (rc < 0) { smblib_err(chg, "Couldn't get Soft Jeita hysteresis thresholds rc=%d\n", rc); goto out; } } chg->jeita_soft_fcc[0] = chg->jeita_soft_fcc[1] = -EINVAL; chg->jeita_soft_fv[0] = chg->jeita_soft_fv[1] = -EINVAL; max_fcc_ma = max_fv_uv = -EINVAL; of_property_read_u32(pnode, "qcom,fastchg-current-ma", &max_fcc_ma); of_property_read_u32(pnode, "qcom,max-voltage-uv", &max_fv_uv); if (max_fcc_ma <= 0 || max_fv_uv <= 0) { smblib_err(chg, "Incorrect fastchg-current-ma or max-voltage-uv\n"); goto out; } rc = of_property_read_u32_array(pnode, "qcom,jeita-soft-fcc-ua", tmp, 2); if (rc < 0) { smblib_err(chg, "Couldn't get fcc values for soft JEITA rc=%d\n", rc); goto out; } max_fcc_ma *= 1000; if (tmp[0] > max_fcc_ma || tmp[1] > max_fcc_ma) { smblib_err(chg, "Incorrect FCC value [%d %d] max: %d\n", tmp[0], tmp[1], max_fcc_ma); goto out; } chg->jeita_soft_fcc[0] = tmp[0]; chg->jeita_soft_fcc[1] = tmp[1]; rc = of_property_read_u32_array(pnode, "qcom,jeita-soft-fv-uv", tmp, 2); if (rc < 0) { smblib_err(chg, "Couldn't get fv values for soft JEITA rc=%d\n", rc); goto out; } } if (tmp[0] > max_fv_uv || tmp[1] > max_fv_uv) { smblib_err(chg, "Incorrect FV value [%d %d] max: %d\n", tmp[0], tmp[1], max_fv_uv); goto out; } chg->jeita_soft_fv[0] = tmp[0]; chg->jeita_soft_fv[1] = tmp[1]; rc = smblib_soft_jeita_arb_wa(chg); if (rc < 0) { smblib_err(chg, "Couldn't fix soft jeita arb rc=%d\n", rc); goto out; } chg->jeita_configured = JEITA_CFG_COMPLETE; return; out: out: chg->jeita_configured = true; chg->jeita_configured = JEITA_CFG_FAILURE; } } static void smblib_lpd_ra_open_work(struct work_struct *work) static void smblib_lpd_ra_open_work(struct work_struct *work) Loading