P22: Enable dynamic IR drop
Enable dynamic irdrop on P22 and merge other logging changes from P23.
Check bug for testing details on C10.
Bug: 261736557
Change-Id: I63feedc0917d78471e3eebc431fbe14cb35ee60d
Signed-off-by: Ken Yang <[email protected]>
diff --git a/google_battery.c b/google_battery.c
index f116e78..bd852a5 100644
--- a/google_battery.c
+++ b/google_battery.c
@@ -620,6 +620,10 @@
/* charging policy */
struct gvotable_election *charging_policy_votable;
int charging_policy;
+
+ /* irdrop for DC */
+ bool dc_irdrop;
+
};
static int gbatt_get_temp(struct batt_drv *batt_drv, int *temp);
@@ -2962,9 +2966,14 @@
int vchg = batt_drv->chg_state.f.vchrg;
int msc_state = MSC_NONE;
bool match_enable;
+ bool no_back_down = false;
- if (batt_drv->chg_state.f.flags & GBMS_CS_FLAG_NOCOMP)
- vchg = 0;
+ if (batt_drv->chg_state.f.flags & GBMS_CS_FLAG_DIRECT_CHG) {
+ if (batt_drv->dc_irdrop)
+ no_back_down = true;
+ else
+ vchg = 0;
+ }
match_enable = vchg != 0;
if ((vbatt - vtier) > otv_margin) {
@@ -2978,9 +2987,12 @@
* switching voltage tiers if the current is right).
* NOTE: lowering voltage might cause a small drop in
* current (we should remain under next tier)
+ * TODO: the fv_uv_resolution might be different in
+ * main charger and CP (should separate them)
*/
*fv_uv = gbms_msc_round_fv_uv(profile, vtier,
- *fv_uv - profile->fv_uv_resolution);
+ *fv_uv - profile->fv_uv_resolution,
+ no_back_down ? cc_max : 0);
if (*fv_uv < vtier)
*fv_uv = vtier;
@@ -3008,10 +3020,12 @@
} else {
/* simple pullback */
msc_state = MSC_PULLBACK;
+ if (no_back_down)
+ *fv_uv = batt_drv->fv_uv;
batt_prlog(BATT_PRLOG_ALWAYS,
- "MSC_PULLBACK vt=%d vb=%d ibatt=%d fv_uv=%d->%d\n",
+ "MSC_PULLBACK vt=%d vb=%d ibatt=%d fv_uv=%d->%d no_back=%d\n",
vtier, vbatt, ibatt,
- batt_drv->fv_uv, *fv_uv);
+ batt_drv->fv_uv, *fv_uv, no_back_down);
}
/*
@@ -3028,28 +3042,35 @@
* data might not be consistent (b/110318684)
* NOTE: could add PID loop for management of thermals
*/
- const int vchrg_ua = vchg * 1000;
+ const int vchrg_uv = vchg * 1000;
+ const int pre_fv = *fv_uv;
msc_state = MSC_FAST;
/* invalid or 0 vchg disable IDROP compensation */
- if (vchrg_ua <= 0) {
+ if (vchrg_uv <= 0) {
/* could keep it steady instead */
*fv_uv = vtier;
- } else if (vchrg_ua > vbatt) {
- *fv_uv = gbms_msc_round_fv_uv(profile, vtier,
- vtier + (vchrg_ua - vbatt));
+ } else if (vchrg_uv > vbatt) {
+ const int cc_max = GBMS_CCCM_LIMITS(profile, temp_idx, *vbatt_idx);
+
+ *fv_uv = gbms_msc_round_fv_uv(profile, vtier, vtier + (vchrg_uv - vbatt),
+ no_back_down ? cc_max : 0);
}
+ /* not allow to reduce fv in DC to avoid the VSWITCH */
+ if (no_back_down && (pre_fv > *fv_uv))
+ *fv_uv = pre_fv;
+
/* no tier switch in fast charge (TODO unless close to tier) */
if (batt_drv->checked_cv_cnt == 0)
batt_drv->checked_cv_cnt = 1;
batt_prlog(BATT_PRLOG_ALWAYS,
- "MSC_FAST vt=%d vb=%d ib=%d fv_uv=%d->%d vchrg=%d cv_cnt=%d\n",
+ "MSC_FAST vt=%d vb=%d ib=%d fv_uv=%d->%d vchrg=%d cv_cnt=%d no_back=%d\n",
vtier, vbatt, ibatt, batt_drv->fv_uv, *fv_uv,
batt_drv->chg_state.f.vchrg,
- batt_drv->checked_cv_cnt);
+ batt_drv->checked_cv_cnt, no_back_down);
} else if (chg_type == POWER_SUPPLY_CHARGE_TYPE_TRICKLE) {
/*
@@ -3135,9 +3156,12 @@
* TAPER_RAISE: under tier vlim, raise one click &
* debounce taper (see above handling of STEADY)
*/
+ const int cc_max = GBMS_CCCM_LIMITS(profile, temp_idx, *vbatt_idx);
+
msc_state = MSC_RAISE;
*fv_uv = gbms_msc_round_fv_uv(profile, vtier,
- *fv_uv + profile->fv_uv_resolution);
+ *fv_uv + profile->fv_uv_resolution,
+ no_back_down ? cc_max : 0);
*update_interval = profile->cv_update_interval;
/* debounce next taper voltage adjustment */
@@ -4385,7 +4409,7 @@
batt_drv->vbatt_idx != vbatt_idx ||
batt_drv->fv_uv != fv_uv;
batt_prlog(batt_prlog_level(changed),
- "MSC_LOGIC temp_idx:%d->%d, vbatt_idx:%d->%d, fv=%d->%d, ui=%d->%d cv_cnt=%d ov_cnt=%d\n",
+ "MSC_LOGIC temp_idx:%d->%d, vbatt_idx:%d->%d, fv=%d->%d, cc_max=%d, ui=%d cv_cnt=%d ov_cnt=%d\n",
batt_drv->temp_idx, temp_idx, batt_drv->vbatt_idx, vbatt_idx,
batt_drv->fv_uv, fv_uv, batt_drv->cc_max, update_interval,
batt_drv->checked_cv_cnt, batt_drv->checked_ov_cnt);
@@ -9831,6 +9855,10 @@
if (ret < 0)
batt_drv->health_data.bhi_data.first_usage_date = 0;
+ batt_drv->dc_irdrop = of_property_read_bool(node, "google,dc-irdrop");
+ if (batt_drv->dc_irdrop)
+ pr_info("dc irdrop is enabled\n");
+
/* single battery disconnect */
(void)batt_bpst_init_debugfs(batt_drv);
diff --git a/google_bms.c b/google_bms.c
index 9f87c54..11b1332 100644
--- a/google_bms.c
+++ b/google_bms.c
@@ -38,6 +38,7 @@
#define GBMS_DEFAULT_FV_UV_RESOLUTION 25000
#define GBMS_DEFAULT_FV_UV_MARGIN_DPCT 1020
+#define GBMS_DEFAULT_FV_DC_RATIO 20
#define GBMS_DEFAULT_CV_DEBOUNCE_CNT 3
#define GBMS_DEFAULT_CV_UPDATE_INTERVAL 2000
#define GBMS_DEFAULT_CV_TIER_OV_CNT 10
@@ -341,6 +342,11 @@
if (ret < 0)
profile->fv_uv_margin_dpct = GBMS_DEFAULT_FV_UV_MARGIN_DPCT;
+ ret = of_property_read_u32(node, "google,fv-dc-ratio",
+ &profile->fv_dc_ratio);
+ if (ret < 0)
+ profile->fv_dc_ratio = GBMS_DEFAULT_FV_DC_RATIO;
+
/* debounce tier switch */
ret = of_property_read_u32(node, "google,cv-debounce-cnt",
&profile->cv_debounce_cnt);
@@ -415,21 +421,37 @@
}
EXPORT_SYMBOL_GPL(gbms_dump_raw_profile);
+/*
+ * When charging in DC, the fv_max will be (FV + cc_max * fv_dc_ratio).
+ * DC can be detected by cc_ua non-zero.
+ * The gap between Vchg and Vbat is caused by the ibat and the impedance.
+ * The fv_dc_ratio is used to simulate the impedance to get the proper fv, so
+ * the vbat will not over the otv threshold.
+ */
int gbms_msc_round_fv_uv(const struct gbms_chg_profile *profile,
- int vtier, int fv_uv)
+ int vtier, int fv_uv, int cc_ua)
{
int result;
- const unsigned int fv_uv_max = (vtier / 1000)
- * profile->fv_uv_margin_dpct;
+ const unsigned int fv_uv_max = (vtier / 1000) * profile->fv_uv_margin_dpct;
+ const unsigned int dc_fv_uv_max = vtier + (cc_ua / 1000) * profile->fv_dc_ratio;
+ const unsigned int last_fv = profile->volt_limits[profile->volt_nb_limits - 1];
+ unsigned int fv_max;
- if (fv_uv_max != 0 && fv_uv > fv_uv_max)
- fv_uv = fv_uv_max;
+ if (cc_ua == 0)
+ fv_max = fv_uv_max;
+ else if (dc_fv_uv_max >= last_fv)
+ fv_max = last_fv - profile->fv_uv_resolution;
+ else
+ fv_max = dc_fv_uv_max;
+
+ if (fv_max != 0 && fv_uv > fv_max)
+ fv_uv = fv_max;
result = fv_uv - (fv_uv % profile->fv_uv_resolution);
- if (fv_uv_max != 0)
+ if (fv_max != 0)
gbms_info(profile, "MSC_ROUND: fv_uv=%d vtier=%d fv_uv_max=%d -> %d\n",
- fv_uv, vtier, fv_uv_max, result);
+ fv_uv, vtier, fv_max, result);
return result;
}
diff --git a/google_bms.h b/google_bms.h
index 91a4410..2a943ba 100644
--- a/google_bms.h
+++ b/google_bms.h
@@ -49,6 +49,7 @@
/* behavior */
u32 fv_uv_margin_dpct;
+ u32 fv_dc_ratio;
u32 cv_range_accuracy;
u32 cv_debounce_cnt;
u32 cv_update_interval;
@@ -402,7 +403,7 @@
#define GBMS_CS_FLAG_CV BIT(3)
#define GBMS_CS_FLAG_ILIM BIT(4)
#define GBMS_CS_FLAG_CCLVL BIT(5)
-#define GBMS_CS_FLAG_NOCOMP BIT(6)
+#define GBMS_CS_FLAG_DIRECT_CHG BIT(6)
union gbms_charger_state {
uint64_t v;
@@ -433,7 +434,7 @@
int gbms_msc_temp_idx(const struct gbms_chg_profile *profile, int temp);
int gbms_msc_voltage_idx(const struct gbms_chg_profile *profile, int vbatt);
int gbms_msc_round_fv_uv(const struct gbms_chg_profile *profile,
- int vtier, int fv_uv);
+ int vtier, int fv_uv, int cc_ua);
/* newgen charging: charger flags */
uint8_t gbms_gen_chg_flags(int chg_status, int chg_type);
diff --git a/pca9468_charger.c b/pca9468_charger.c
index b225398..183ddb9 100644
--- a/pca9468_charger.c
+++ b/pca9468_charger.c
@@ -128,6 +128,8 @@
#define PCA9468_SC_CLK_DITHER_RATE_DEF 0 /* 25kHz */
#define PCA9468_SC_CLK_DITHER_LIMIT_DEF 0xF /* 10% */
+#define PCA9468_TIER_SWITCH_DELTA 25000 /* uV */
+
/* INT1 Register Buffer */
enum {
REG_INT1,
@@ -1040,11 +1042,11 @@
static int pca9468_apply_irdrop(struct pca9468_charger *pca9468, int fv_uv)
{
const int delta_limit = pca9468_irdrop_limit(pca9468, fv_uv);
- int ret, vbat, pca_vbat = 0, delta = 0;
+ int ret = -1, vbat, pca_vbat = 0, delta = 0;
const bool adaptive = false;
/* use classic irdrop */
- if (pca9468->irdrop_comp_ok)
+ if (!pca9468->pdata->pca_irdrop)
goto error_done;
ret = pca9468_get_batt_info(pca9468, BATT_VOLTAGE, &vbat);
@@ -1613,7 +1615,7 @@
{
const int iin_high = pca9468->iin_cc + pca9468->pdata->iin_cc_comp_offset;
const int iin_low = pca9468->iin_cc - pca9468->pdata->iin_cc_comp_offset;
- const ibat_limit = (pca9468->cc_max * FCC_POWER_INCREASE_THRESHOLD) / 100;
+ const int ibat_limit = (pca9468->cc_max * FCC_POWER_INCREASE_THRESHOLD) / 100;
int rc, ibat, icn = -EINVAL, iin = -EINVAL;
bool ovc_flag;
@@ -2385,24 +2387,31 @@
if (fv_uv < 0)
return fv_uv;
+ if (pca9468->fv_uv == fv_uv)
+ goto error_done;
+
/* actually change the hardware */
ret = pca9468_set_vfloat(pca9468, fv_uv);
if (ret < 0)
goto error_done;
- /* Restart the process (TODO: optimize this) */
- ret = pca9468_reset_dcmode(pca9468);
- if (ret < 0) {
- pr_err("%s: cannot reset dcmode (%d)\n", __func__, ret);
- } else {
- dev_info(pca9468->dev, "%s: charging_state=%u->%u\n", __func__,
- pca9468->charging_state, DC_STATE_ADJUST_CC);
+ /* Restart the process if tier switch happened (either direction) */
+ if (abs(fv_uv - pca9468->fv_uv) > PCA9468_TIER_SWITCH_DELTA) {
+ ret = pca9468_reset_dcmode(pca9468);
+ if (ret < 0) {
+ pr_err("%s: cannot reset dcmode (%d)\n", __func__, ret);
+ } else {
+ dev_info(pca9468->dev, "%s: charging_state=%u->%u\n", __func__,
+ pca9468->charging_state, DC_STATE_ADJUST_CC);
- pca9468->charging_state = DC_STATE_ADJUST_CC;
- pca9468->timer_id = TIMER_PDMSG_SEND;
- pca9468->timer_period = 0;
+ pca9468->charging_state = DC_STATE_ADJUST_CC;
+ pca9468->timer_id = TIMER_PDMSG_SEND;
+ pca9468->timer_period = 0;
+ }
}
+ pca9468->fv_uv = fv_uv;
+
error_done:
logbuffer_prlog(pca9468, LOGLEVEL_INFO,
"%s: new_vfloat=%d, fv_uv=%d ret=%d", __func__,
@@ -2424,19 +2433,17 @@
}
mutex_lock(&pca9468->lock);
- if (pca9468->fv_uv == vfloat)
+ if (pca9468->new_vfloat == vfloat)
goto done;
- /* this is what is requested */
- pca9468->fv_uv = vfloat;
-
/* use fv_uv at start in pca9468_preset_config() */
if (pca9468->charging_state == DC_STATE_NO_CHARGING ||
pca9468->charging_state == DC_STATE_CHECK_VBAT) {
- // pca9468->pdata->v_float = vfloat;
+ pca9468->fv_uv = vfloat;
} else {
/* applied in pca9468_apply_new_vfloat() from CC or in CV loop */
pca9468->new_vfloat = vfloat;
+ pr_debug("%s: new_vfloat=%d\n", __func__, pca9468->new_vfloat);
/* might want to tickle the cycle */
}
@@ -2670,6 +2677,7 @@
switch(ccmode) {
case STS_MODE_IIN_LOOP:
+ pca9468->chg_data.iin_loop_count++;
case STS_MODE_CHG_LOOP: /* CHG_LOOP does't exist */
apply_ircomp = true;
@@ -2757,7 +2765,7 @@
goto error;
}
- if (!pca9468->irdrop_comp_ok && apply_ircomp) {
+ if (pca9468->pdata->pca_irdrop && apply_ircomp) {
int rc;
rc = pca9468_comp_irdrop(pca9468);
@@ -2801,7 +2809,7 @@
/* 2:1 Direct Charging CC MODE control */
static int pca9468_charge_ccmode(struct pca9468_charger *pca9468)
{
- int ccmode, vin_vol, iin, ret = 0;
+ int ccmode = -1, vin_vol, iin, ret = 0;
bool apply_ircomp = false;
pr_debug("%s: ======START======= \n", __func__);
@@ -2886,6 +2894,7 @@
break;
case STS_MODE_IIN_LOOP:
+ pca9468->chg_data.iin_loop_count++;
case STS_MODE_CHG_LOOP:
iin = pca9468_read_adc(pca9468, ADCCH_IIN);
if (iin < 0)
@@ -2933,7 +2942,7 @@
break;
}
- if (!pca9468->irdrop_comp_ok && apply_ircomp) {
+ if (pca9468->pdata->pca_irdrop && apply_ircomp) {
int rc;
rc = pca9468_comp_irdrop(pca9468);
@@ -2985,8 +2994,9 @@
}
switch(cvmode) {
- case STS_MODE_CHG_LOOP:
case STS_MODE_IIN_LOOP:
+ pca9468->chg_data.iin_loop_count++;
+ case STS_MODE_CHG_LOOP:
if (pca9468->ta_type == TA_TYPE_WIRELESS) {
/* Decrease RX voltage (100mV) */
@@ -3180,8 +3190,9 @@
pca9468->timer_period = PCA9468_CVMODE_CHECK_T;
} break;
- case STS_MODE_CHG_LOOP:
case STS_MODE_IIN_LOOP:
+ pca9468->chg_data.iin_loop_count++;
+ case STS_MODE_CHG_LOOP:
/* Check the TA type */
if (pca9468->ta_type == TA_TYPE_WIRELESS) {
/* Decrease RX Voltage (100mV) */
@@ -4288,7 +4299,6 @@
/* Start Direct Charging on Index */
pca9468->dc_start_time = get_boot_sec();
p9468_chg_stats_init(&pca9468->chg_data);
- pca9468->irdrop_comp_ok = false;
pca9468->pps_index = index;
dev_info(pca9468->dev, "%s: charging_state=%u->%u\n", __func__,
@@ -4465,8 +4475,6 @@
ret = pca9468_get_chg_chgr_state(pca9468, &chg_state);
if (ret < 0)
return ret;
- if (pca9468->irdrop_comp_ok)
- chg_state.f.flags &= ~GBMS_CS_FLAG_NOCOMP;
gbms_propval_int64val(val) = chg_state.v;
break;
@@ -4696,6 +4704,9 @@
pdata->irdrop_limits[1] = PCA9468_IRDROP_LIMIT_TIER2;
pdata->irdrop_limits[2] = PCA9468_IRDROP_LIMIT_TIER3;
}
+ pdata->pca_irdrop = of_property_read_bool(np_pca9468, "google,pca-irdrop");
+ if (pdata->pca_irdrop)
+ pr_info("%s: google,pca-irdrop is set, run irdrop in pca\n", __func__);
/* Spread Spectrum settings */
ret = of_property_read_u32(np_pca9468, "pca9468,sc-clk-dither-rate",
@@ -4905,10 +4916,11 @@
chg_data->receiver_state[3],
chg_data->receiver_state[4]);
len += scnprintf(&buff[len], max_size - len,
- "N: ovc=%d,ovc_ibatt=%d,ovc_delta=%d rcp=%d,stby=%d\n",
+ "N: ovc=%d,ovc_ibatt=%d,ovc_delta=%d rcp=%d,stby=%d, iin_loop=%d\n",
chg_data->ovc_count, chg_data->ovc_max_ibatt, chg_data->ovc_max_delta,
chg_data->rcp_count,
- chg_data->stby_count);
+ chg_data->stby_count,
+ chg_data->iin_loop_count);
len += scnprintf(&buff[len], max_size - len,
"C: nc=%d,pre=%d,ca=%d,cc=%d,cv=%d,adj=%d\n",
chg_data->nc_count,
@@ -5003,8 +5015,6 @@
&debug_adc_chan_ops);
debugfs_create_file("pps_index", 0644, chip->debug_root, chip,
&debug_pps_index_ops);
- debugfs_create_bool("irdrop_comp", 0644, chip->debug_root,
- &chip->irdrop_comp_ok);
return 0;
}
diff --git a/pca9468_charger.h b/pca9468_charger.h
index 21dbcd3..d72d2fd 100644
--- a/pca9468_charger.h
+++ b/pca9468_charger.h
@@ -43,6 +43,7 @@
/* irdrop */
unsigned int irdrop_limits[3];
int irdrop_limit_cnt;
+ bool pca_irdrop;
/* Spread Spectrum settings */
unsigned int sc_clk_dither_rate;
@@ -104,6 +105,7 @@
unsigned int cv_count;
unsigned int adj_count;
unsigned int stby_count;
+ unsigned int iin_loop_count;
};
#define p9468_chg_stats_valid(chg_data) ((chg_data)->valid)
@@ -179,7 +181,6 @@
* @debug_adc_channel: ADC channel to read
* @init_done: true when initialization is complete
* @dc_start_time: start time (sec since boot) of the DC session
- * @irdrop_comp_ok: when true clear GBMS_CS_FLAG_NOCOMP in flags
*/
struct pca9468_charger {
struct wakeup_source *monitor_wake_lock;
diff --git a/pca9468_gbms_pps.c b/pca9468_gbms_pps.c
index 98c0bab..0145ea0 100644
--- a/pca9468_gbms_pps.c
+++ b/pca9468_gbms_pps.c
@@ -600,7 +600,7 @@
chg_state->f.chg_type = pca9468_get_charge_type(pca9468);
chg_state->f.flags = gbms_gen_chg_flags(chg_state->f.chg_status,
chg_state->f.chg_type);
- chg_state->f.flags |= GBMS_CS_FLAG_NOCOMP;
+ chg_state->f.flags |= GBMS_CS_FLAG_DIRECT_CHG;
vchrg = pca9468_read_adc(pca9468, ADCCH_VBAT);
if (vchrg > 0)