Snap for 10302501 from ca21ebe25218a5e2e1b64e2125baa78f532f02d2 to android13-gs-pixel-5.10-release
Change-Id: I1661460e73edcc955078237141a573c71f81b517
diff --git a/gbms_storage.c b/gbms_storage.c
index 2c4f2e0..d1a44f4 100644
--- a/gbms_storage.c
+++ b/gbms_storage.c
@@ -1118,7 +1118,7 @@
GBEE_STATUS_OK,
};
-#define GBEE_POLL_RETRIES 5
+#define GBEE_POLL_RETRIES 15
#define GBEE_POLL_INTERVAL_MS 200
/* only one battery eeprom for now */
diff --git a/google_battery.c b/google_battery.c
index 8e3d412..d6ce2b9 100644
--- a/google_battery.c
+++ b/google_battery.c
@@ -187,6 +187,9 @@
/* Save/Restore fake capacity */
bool save_soc_available;
u16 save_soc;
+
+ /* adjust SOC */
+ int point_full_ui_soc;
};
struct gbatt_ccbin_data {
@@ -322,7 +325,7 @@
int battery_age; /* from the FG, time in field */
/* capacity metrics */
- int capacity_design; /* from the FG or from charge table */
+ int pack_capacity; /* mAh, from the FG or from charge table */
int capacity_fade; /* from the FG */
/* impedance */
@@ -430,6 +433,8 @@
uint16_t cc_in;
uint16_t cc_out;
ktime_t thermal_severity[CSI_THERMAL_SEVERITY_MAX];
+ int thermal_lvl_max;
+ int thermal_lvl_min;
};
#define TEMP_SAMPLE_SIZE 5
@@ -528,6 +533,7 @@
struct gvotable_election *fcc_votable;
struct gvotable_election *fv_votable;
struct gvotable_election *temp_dryrun_votable;
+ struct gvotable_election *point_full_ui_soc_votable;
/* FAN level */
struct gvotable_election *fan_level_votable;
@@ -624,6 +630,7 @@
/* irdrop for DC */
bool dc_irdrop;
+ int batt_id;
};
static int gbatt_get_temp(struct batt_drv *batt_drv, int *temp);
@@ -875,6 +882,9 @@
/* splice only when real is within the curve range */
curve[1].real = real;
curve[1].ui = ui;
+
+ if (curve[1].real > curve[UICURVE_MAX - 1].real)
+ curve[UICURVE_MAX - 1].real = ssoc_point_full;
}
static void ssoc_uicurve_dup(struct ssoc_uicurve *dst,
@@ -884,6 +894,22 @@
memcpy(dst, curve, sizeof(*dst)*UICURVE_MAX);
}
+/* "optimized" to work on 3 element curves */
+static void ssoc_uicurve_splice_full(struct ssoc_uicurve *curve,
+ qnum_t real,qnum_t ui)
+{
+ /*
+ * for case: curve:[15.00 15.00][99.00 99.00][98.00 100.00]
+ * the calculation in ssoc_uicurve_map causes minus value
+ */
+ if (curve[1].real > real)
+ return;
+
+ curve[UICURVE_MAX - 1].real = real;
+ curve[UICURVE_MAX - 1].ui = ui;
+}
+
+
/* ------------------------------------------------------------------------- */
@@ -1069,6 +1095,7 @@
* QC could need:
* QG_CC_SOC, QG_Raw_SOC, QG_Bat_SOC, QG_Sys_SOC, QG_Mon_SOC
*/
+#define DISABLE_POINT_FULL_UI_SOC (-1)
static int ssoc_work(struct batt_ssoc_state *ssoc_state,
struct power_supply *fg_psy)
{
@@ -2575,10 +2602,12 @@
res = 0;
gbms_logbuffer_prlog(batt_drv->ttf_stats.ttf_log, LOGLEVEL_INFO, 0, LOGLEVEL_DEBUG,
- "ssoc=%d temp=%d CSI[min=%d max=%d avg=%d type=%d status=%d TTF[cc=%d time=%lld %lld:%lld:%lld (est=%lld max_ratio=%d)]",
- csi_stats->ssoc, batt_drv->batt_temp, csi_stats->csi_speed_min,
- csi_stats->csi_speed_max, csi_speed_avg,
+ "ssoc=%d temp=%d CSI[speed=%d,%d,%d type=%d status=%d lvl=%d,%d"
+ " TTF[cc=%d time=%lld %lld:%lld:%lld (est=%lld max_ratio=%d)]",
+ csi_stats->ssoc, batt_drv->batt_temp, csi_speed_avg,
+ csi_stats->csi_speed_min, csi_stats->csi_speed_max,
csi_stats->csi_current_type, csi_stats->csi_current_status,
+ csi_stats->thermal_lvl_min, csi_stats->thermal_lvl_max,
cc / 1000, right_now, res / 3600, (res % 3600) / 60,
(res % 3600) % 60, res, max_ratio);
@@ -2592,6 +2621,12 @@
csi_stats->csi_speed_min = current_speed;
csi_stats->csi_speed_max = current_speed;
+ /* ssoc == -1 on disconnect */
+ if (ssoc == -1) {
+ csi_stats->thermal_lvl_min = 0;
+ csi_stats->thermal_lvl_max = 0;
+ }
+
csi_stats->csi_time_sum = 0;
csi_stats->speed_sum = 0;
csi_stats->last_update = right_now;
@@ -2774,14 +2809,15 @@
gvotable_cast_long_vote(batt_drv->csi_status_votable, "CSI_STATUS_DSG",
CSI_STATUS_NotCharging,
- !is_disconnected && batt_drv->msc_state == MSC_DSG);
+ !is_disconnected && batt_drv->msc_state == MSC_DSG &&
+ !batt_drv->chg_done);
gvotable_cast_long_vote(batt_drv->csi_status_votable, "CSI_STATUS_100",
CSI_STATUS_Charging,
- !is_disconnected && batt_drv->chg_done);
+ !is_disconnected && batt_drv->batt_full && !batt_drv->chg_done);
gvotable_cast_long_vote(batt_drv->csi_status_votable, "CSI_STATUS_CHG",
- CSI_STATUS_Charging, !is_disconnected);
+ CSI_STATUS_Charging, !is_disconnected);
}
#define CSI_CHG_SPEED_MAX 100
@@ -2849,12 +2885,37 @@
return chg_speed;
}
+static void batt_update_thermal_lvl(struct batt_drv *batt_drv)
+{
+ struct csi_stats *csi_stats = &batt_drv->csi_stats;
+ int thermal_level = 0;
+
+ if (chg_state_is_disconnected(&batt_drv->chg_state))
+ return;
+
+ if (!batt_drv->thermal_level_votable)
+ batt_drv->thermal_level_votable = gvotable_election_get_handle(VOTABLE_THERMAL_LVL);
+ if (batt_drv->thermal_level_votable)
+ thermal_level = gvotable_get_current_int_vote(batt_drv->thermal_level_votable);
+
+ if (thermal_level < 0)
+ return;
+
+ if (csi_stats->thermal_lvl_max == 0 && csi_stats->thermal_lvl_min == 0)
+ csi_stats->thermal_lvl_max = csi_stats->thermal_lvl_min = thermal_level;
+ else if (thermal_level > csi_stats->thermal_lvl_max)
+ csi_stats->thermal_lvl_max = thermal_level;
+ else if (thermal_level < csi_stats->thermal_lvl_min)
+ csi_stats->thermal_lvl_min = thermal_level;
+}
+
static void batt_update_csi_info(struct batt_drv *batt_drv)
{
int charging_speed;
batt_update_csi_type(batt_drv);
batt_update_csi_status(batt_drv);
+ batt_update_thermal_lvl(batt_drv);
charging_speed = batt_calc_charging_speed(batt_drv);
if (batt_drv->csi_current_speed != charging_speed) {
@@ -3694,10 +3755,17 @@
static int bhi_cap_data_update(struct bhi_data *bhi_data, struct batt_drv *batt_drv)
{
struct power_supply *fg_psy = batt_drv->fg_psy;
+ const int fade_rate = GPSY_GET_PROP(fg_psy, GBMS_PROP_CAPACITY_FADE_RATE);
+ const int designcap = GPSY_GET_PROP(fg_psy, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN);
int cap_fade;
/* GBMS_PROP_CAPACITY_FADE_RATE is in percent */
- cap_fade = GPSY_GET_PROP(fg_psy, GBMS_PROP_CAPACITY_FADE_RATE);
+ if (fade_rate < 0 || designcap < 0)
+ return -ENODATA;
+ if (bhi_data->pack_capacity <= 0)
+ return -EINVAL;
+
+ cap_fade = fade_rate * designcap / (bhi_data->pack_capacity * 1000);
if (cap_fade < 0)
return -ENODATA;
if (cap_fade > 100)
@@ -3718,7 +3786,7 @@
*/
static int bhi_health_get_capacity(int algo, const struct bhi_data *bhi_data)
{
- return bhi_data->capacity_design * (100 - bhi_data->capacity_fade) / 100;
+ return bhi_data->pack_capacity * (100 - bhi_data->capacity_fade) / 100;
}
/* The limit for capacity is 80% of design */
@@ -3734,7 +3802,7 @@
if (health_data->bhi_debug_cap_index)
return health_data->bhi_debug_cap_index;
- if (!bhi_data->capacity_design)
+ if (!bhi_data->pack_capacity)
return -ENODATA;
capacity_health = bhi_health_get_capacity(algo, bhi_data);
@@ -3752,12 +3820,12 @@
* ret = gbms_storage_read(GBMS_TAG_GCFE, &gcap sizeof(gcap));
*/
- index = (capacity_health * BHI_ALGO_FULL_HEALTH) / bhi_data->capacity_design;
+ index = (capacity_health * BHI_ALGO_FULL_HEALTH) / bhi_data->pack_capacity;
if (index > BHI_ALGO_FULL_HEALTH)
index = BHI_ALGO_FULL_HEALTH;
- pr_debug("%s: algo=%d index=%d ch=%d, ca=%d, cd=%d, fr=%d\n", __func__,
- algo, index, capacity_health, capacity_aacr, bhi_data->capacity_design,
+ pr_debug("%s: algo=%d index=%d ch=%d, ca=%d, pc=%d, fr=%d\n", __func__,
+ algo, index, capacity_health, capacity_aacr, bhi_data->pack_capacity,
bhi_data->capacity_fade);
return index;
@@ -7360,13 +7428,27 @@
struct power_supply *psy = container_of(dev, struct power_supply, dev);
struct batt_drv *batt_drv = power_supply_get_drvdata(psy);
struct bhi_data *bhi_data = &batt_drv->health_data.bhi_data;
- int cnt = sscanf(buf, "%hu,%hu,%hu,%hu,%hu,%hu,%hu,%hu",
- &bhi_data->trend[0], &bhi_data->trend[1], &bhi_data->trend[2],
- &bhi_data->trend[3], &bhi_data->trend[4], &bhi_data->trend[5],
- &bhi_data->trend[6], &bhi_data->trend[7]);
+ u16 trend[BHI_TREND_POINTS_SIZE];
+ const int buf_len = strlen(buf);
+ int cnt = 0, len = 0;
+ u16 batt_id;
- if (cnt != BHI_TREND_POINTS_SIZE)
- return -ERANGE;
+ do {
+ cnt = sscanf(&buf[len], "%hu,%hu,%hu,%hu,%hu,%hu,%hu,%hu,%hu", &batt_id,
+ &trend[0], &trend[1], &trend[2], &trend[3],
+ &trend[4], &trend[5], &trend[6], &trend[7]);
+
+ if (cnt != BHI_TREND_POINTS_SIZE + 1)
+ return -ERANGE;
+
+ if ((int)batt_id == batt_drv->batt_id) {
+ memcpy(&bhi_data->trend, trend, sizeof(trend));
+ break;
+ }
+
+ while (buf[len] != '\n' && len < buf_len)
+ len++;
+ } while (len++ < buf_len);
return count;
}
@@ -7394,13 +7476,27 @@
struct power_supply *psy = container_of(dev, struct power_supply, dev);
struct batt_drv *batt_drv = power_supply_get_drvdata(psy);
struct bhi_data *bhi_data = &batt_drv->health_data.bhi_data;
- int cnt = sscanf(buf, "%hu,%hu,%hu,%hu,%hu,%hu,%hu,%hu",
- &bhi_data->l_bound[0], &bhi_data->l_bound[1], &bhi_data->l_bound[2],
- &bhi_data->l_bound[3], &bhi_data->l_bound[4], &bhi_data->l_bound[5],
- &bhi_data->l_bound[6], &bhi_data->l_bound[7]);
+ u16 l_bound[BHI_TREND_POINTS_SIZE];
+ const int buf_len = strlen(buf);
+ int cnt = 0, len = 0;
+ u16 batt_id;
- if (cnt != BHI_TREND_POINTS_SIZE)
- return -ERANGE;
+ do {
+ cnt = sscanf(&buf[len], "%hu,%hu,%hu,%hu,%hu,%hu,%hu,%hu,%hu", &batt_id,
+ &l_bound[0], &l_bound[1], &l_bound[2], &l_bound[3],
+ &l_bound[4], &l_bound[5], &l_bound[6], &l_bound[7]);
+
+ if (cnt != BHI_TREND_POINTS_SIZE + 1)
+ return -ERANGE;
+
+ if ((int)batt_id == batt_drv->batt_id) {
+ memcpy(&bhi_data->l_bound, l_bound, sizeof(l_bound));
+ break;
+ }
+
+ while (buf[len] != '\n' && len < buf_len)
+ len++;
+ } while (len++ < buf_len);
return count;
}
@@ -8605,6 +8701,35 @@
return (ret < 0) ? -EIO : 0;
}
+static int point_full_ui_soc_cb(struct gvotable_election *el,
+ const char *reason, void *vote)
+{
+ struct batt_drv *batt_drv = gvotable_get_data(el);
+ struct batt_ssoc_state *ssoc_state = &batt_drv->ssoc_state;
+ int ssoc = ssoc_get_capacity(ssoc_state);
+ int soc = GVOTABLE_PTR_TO_INT(vote);
+
+ if (ssoc_state->point_full_ui_soc == soc)
+ return 0;
+
+ dev_info(batt_drv->device, "update point_full_ui_soc: %d -> %d\n",
+ ssoc_state->point_full_ui_soc, soc);
+
+ ssoc_state->point_full_ui_soc = soc;
+
+ if (ssoc_state->point_full_ui_soc != DISABLE_POINT_FULL_UI_SOC &&
+ ssoc < SSOC_FULL && ssoc_state->buck_enabled == 1) {
+ struct ssoc_uicurve *curve = ssoc_state->ssoc_curve;
+ const qnum_t full = qnum_fromint(ssoc_state->point_full_ui_soc);
+
+ ssoc_uicurve_splice_full(curve, full, ssoc_point_full);
+ dump_ssoc_state(&batt_drv->ssoc_state, batt_drv->ssoc_log);
+ ssoc_state->point_full_ui_soc = DISABLE_POINT_FULL_UI_SOC;
+ }
+
+ return 0;
+}
+
/*
* poll the battery, run SOC%, dead battery, critical.
* scheduled from psy_changed and from timer
@@ -9528,7 +9653,10 @@
health_data->bhi_cycle_grace = 0;
/* design is the value used to build the charge table */
- health_data->bhi_data.capacity_design = batt_drv->battery_capacity;
+ health_data->bhi_data.pack_capacity = batt_drv->battery_capacity;
+
+ /* need battery id to get right trend points */
+ batt_drv->batt_id = GPSY_GET_PROP(batt_drv->fg_psy, GBMS_PROP_BATT_ID);
/* debug data initialization */
health_data->bhi_debug_cycle_count = 0;
@@ -10117,6 +10245,19 @@
gvotable_set_vote2str(batt_drv->csi_type_votable, gvotable_v2s_int);
gvotable_election_set_name(batt_drv->csi_type_votable, VOTABLE_CSI_TYPE);
+ batt_drv->point_full_ui_soc_votable =
+ gvotable_create_int_election(NULL, gvotable_comparator_int_min,
+ point_full_ui_soc_cb, batt_drv);
+ if (IS_ERR_OR_NULL(batt_drv->point_full_ui_soc_votable)) {
+ ret = PTR_ERR(batt_drv->point_full_ui_soc_votable);
+ dev_err(batt_drv->device, "Fail to create point_full_ui_soc_votable\n");
+ batt_drv->point_full_ui_soc_votable = NULL;
+ } else {
+ gvotable_set_vote2str(batt_drv->point_full_ui_soc_votable, gvotable_v2s_int);
+ gvotable_set_default(batt_drv->point_full_ui_soc_votable, (void *)DISABLE_POINT_FULL_UI_SOC);
+ gvotable_election_set_name(batt_drv->point_full_ui_soc_votable, VOTABLE_CHARGING_UISOC);
+ }
+
/* AACR server side */
batt_drv->aacr_cycle_grace = AACR_START_CYCLE_DEFAULT;
batt_drv->aacr_cycle_max = AACR_MAX_CYCLE_DEFAULT;
@@ -10184,11 +10325,13 @@
gvotable_destroy_election(batt_drv->fan_level_votable);
gvotable_destroy_election(batt_drv->csi_status_votable);
gvotable_destroy_election(batt_drv->csi_type_votable);
+ gvotable_destroy_election(batt_drv->point_full_ui_soc_votable);
batt_drv->fan_level_votable = NULL;
batt_drv->csi_status_votable = NULL;
batt_drv->csi_type_votable = NULL;
batt_drv->charging_policy_votable = NULL;
+ batt_drv->point_full_ui_soc_votable = NULL;
return 0;
}
diff --git a/google_bms.h b/google_bms.h
index 2a943ba..bb41cc8 100644
--- a/google_bms.h
+++ b/google_bms.h
@@ -470,6 +470,7 @@
#define VOTABLE_CSI_TYPE "CSI_TYPE"
#define VOTABLE_CHARGING_POLICY "CHARGING_POLICY"
+#define VOTABLE_CHARGING_UISOC "CHARGING_UISOC"
#define VOTABLE_DC_CHG_AVAIL "DC_AVAIL"
#define REASON_DC_DRV "DC_DRV"
diff --git a/max1720x_battery.c b/max1720x_battery.c
index 75f6608..7d94796 100644
--- a/max1720x_battery.c
+++ b/max1720x_battery.c
@@ -5719,8 +5719,6 @@
chip->init_complete = true;
chip->bhi_acim = 0;
- max17x0x_init_sysfs(chip);
-
/*
* Handle any IRQ that might have been set before init
* NOTE: will clear the POR bit and trigger model load if needed
@@ -6108,6 +6106,8 @@
reg = max17x0x_find_by_tag(&chip->regmap, MAX17X0X_TAG_vfsoc);
chip->reg_prop_capacity_raw = (reg) ? reg->reg : MAX1720X_REPSOC;
+ max17x0x_init_sysfs(chip);
+
INIT_DELAYED_WORK(&chip->cap_estimate.settle_timer,
batt_ce_capacityfiltered_work);
INIT_DELAYED_WORK(&chip->init_work, max1720x_init_work);
diff --git a/max77759_charger.c b/max77759_charger.c
index e3bcf66..e3998d5 100644
--- a/max77759_charger.c
+++ b/max77759_charger.c
@@ -55,6 +55,9 @@
#define CHGR_DTLS_OFF_JEITA 0x0c
#define CHGR_DTLS_OFF_TEMP 0x0d
+#define CHGR_CHG_CNFG_12_VREG_4P6V 0x1
+#define CHGR_CHG_CNFG_12_VREG_4P7V 0x2
+
static inline int max77759_reg_read(struct regmap *regmap, uint8_t reg,
uint8_t *val)
{
@@ -1856,6 +1859,37 @@
return 0;
}
+static int max77759_higher_headroom_enable(struct max77759_chgr_data *data, bool flag)
+{
+ int ret = 0;
+ u8 reg, reg_rd, val = flag ? CHGR_CHG_CNFG_12_VREG_4P7V : CHGR_CHG_CNFG_12_VREG_4P6V;
+
+ ret = max77759_reg_read(data->regmap, MAX77759_CHG_CNFG_12, ®);
+ if (ret < 0)
+ return ret;
+
+ reg_rd = reg;
+ ret = max77759_chg_prot(data->regmap, false);
+ if (ret < 0)
+ return ret;
+
+ reg = _chg_cnfg_12_vchgin_reg_set(reg, val);
+ ret = max77759_reg_write(data->regmap, MAX77759_CHG_CNFG_12, reg);
+ if (ret)
+ goto done;;
+
+ dev_dbg(data->dev, "%s: val: %#02x, reg: %#02x -> %#02x\n", __func__, val, reg_rd, reg);
+
+ ret = max77759_reg_read(data->regmap, MAX77759_CHG_CNFG_12, ®);
+ if (ret)
+ goto done;
+
+done:
+ ret = max77759_chg_prot(data->regmap, true);
+ if (ret < 0)
+ dev_err(data->dev, "%s: error enabling prot (%d)\n", __func__, ret);
+ return ret < 0 ? ret : 0;
+}
static int max77759_chg_is_valid(struct max77759_chgr_data *data)
{
@@ -2180,6 +2214,10 @@
ret = max77759_set_regulation_voltage(data, pval->intval);
pr_debug("%s: charge_voltage=%d (%d)\n",
__func__, pval->intval, ret);
+ if (ret)
+ break;
+ if (max77759_is_online(data) && pval->intval >= data->chg_term_voltage * 1000)
+ ret = max77759_higher_headroom_enable(data, true);
break;
/* called from google_cpm when switching chargers */
case GBMS_PROP_CHARGING_ENABLED:
@@ -2791,6 +2829,10 @@
pr_debug("%s: INSEL insel_auto_clear=%d (%d)\n", __func__,
data->insel_clear, data->insel_clear ? ret : 0);
atomic_inc(&data->insel_cnt);
+
+ ret = max77759_higher_headroom_enable(data, false); /* reset on plug/unplug */
+ if (ret)
+ return IRQ_NONE;
}
#if IS_ENABLED(CONFIG_GOOGLE_BCL)
diff --git a/max_m5.c b/max_m5.c
index 4532e8c..062bd6c 100644
--- a/max_m5.c
+++ b/max_m5.c
@@ -687,6 +687,14 @@
cp->qresidual10 = m5_data->model_save.qresidual10;
cp->qresidual20 = m5_data->model_save.qresidual20;
cp->qresidual30 = m5_data->model_save.qresidual30;
+ /* b/278492168 restore dpacc with fullcapnom for taskperiod=351ms */
+ if (cp->taskperiod == 0x2d00 && cp->dpacc == 0x3200)
+ cp->dqacc = cp->fullcapnom >> 2;
+ else if (cp->taskperiod == 0x2d00 && cp->dpacc == 0x0c80)
+ cp->dqacc = cp->fullcapnom >> 4;
+ else
+ dev_warn(m5_data->dev, "taskperiod:%#x, dpacc:%#x, dqacc:%#x\n",
+ cp->taskperiod, cp->dpacc, cp->dqacc);
m5_data->cycles = m5_data->model_save.cycles;
m5_data->cv_mixcap = m5_data->model_save.cv_mixcap;
diff --git a/p9221_charger.c b/p9221_charger.c
index c6744b8..ead5797 100644
--- a/p9221_charger.c
+++ b/p9221_charger.c
@@ -596,6 +596,22 @@
sysfs_notify(&charger->dev->kobj, NULL, "rxdone");
}
+#define FORCE_FULL_SOC 98
+static void p9xxx_ll_adjust_soc(struct p9221_charger_data *charger, int soc)
+{
+ if (!charger->point_full_ui_soc_votable) {
+ charger->point_full_ui_soc_votable =
+ gvotable_election_get_handle(VOTABLE_CHARGING_UISOC);
+ if (!charger->point_full_ui_soc_votable) {
+ dev_err(&charger->client->dev, "Could not get votable: CHARGING_UISOC\n");
+ return;
+ }
+ }
+
+ gvotable_cast_long_vote(charger->point_full_ui_soc_votable, LL_BPP_CEP_VOTER,
+ FORCE_FULL_SOC, charger->ll_bpp_cep == 1 && soc >= FORCE_FULL_SOC);
+}
+
/*
* Put the default ICL back to BPP, reset OCP voter
* @pre charger && charger->dc_icl_votable && charger->client->dev
@@ -604,6 +620,8 @@
{
int ret, ocp_icl;
+ p9xxx_ll_adjust_soc(charger, FORCE_FULL_SOC);
+
if (!charger->dc_icl_votable) {
dev_err(&charger->client->dev,
"Could not vote DC_ICL - no votable\n");
@@ -2013,9 +2031,8 @@
val->intval = p9221_get_psy_online(charger);
break;
case POWER_SUPPLY_PROP_SERIAL_NUMBER:
+ /* val->strval == NULL means NODATA */
val->strval = p9221_get_tx_id_str(charger);
- if (val->strval == NULL)
- return -ENODATA;
break;
case POWER_SUPPLY_PROP_CAPACITY:
/* Zero may be returned on transition to wireless "online", as
@@ -2037,8 +2054,10 @@
val->intval = rc ? : charger->wlc_dc_current_now;
} else {
- if (!charger->dc_icl_votable)
- return -EAGAIN;
+ if (!charger->dc_icl_votable) {
+ val->intval = -EAGAIN;
+ break;
+ }
val->intval = gvotable_get_current_int_vote(
charger->dc_icl_votable);
}
@@ -2575,6 +2594,9 @@
if (capacity > 98)
icl_ua = 300000;
+ if (capacity >= FORCE_FULL_SOC)
+ p9xxx_ll_adjust_soc(charger, capacity);
+
gvotable_cast_int_vote(charger->dc_icl_votable,
DD_VOTER, icl_ua, icl_ua > 0);
@@ -6591,6 +6613,8 @@
pdata->ll_vout_not_set = of_property_read_bool(node, "google,ll-bpp-vout-not-set");
+ pdata->disable_repeat_eop = of_property_read_bool(node, "google,disable-repeat-eop");
+
return 0;
}
diff --git a/p9221_charger.h b/p9221_charger.h
index 34b110c..030af07 100644
--- a/p9221_charger.h
+++ b/p9221_charger.h
@@ -665,6 +665,7 @@
bool light_load;
bool disable_align;
bool ll_vout_not_set;
+ bool disable_repeat_eop;
};
struct p9221_charger_ints_bit {
@@ -715,6 +716,7 @@
struct gvotable_election *wlc_disable_votable;
struct gvotable_election *csi_status_votable;
struct gvotable_election *csi_type_votable;
+ struct gvotable_election *point_full_ui_soc_votable;
struct notifier_block nb;
struct mutex io_lock;
struct mutex cmd_lock;
diff --git a/p9221_chip.c b/p9221_chip.c
index 58105c6..e1d876c 100644
--- a/p9221_chip.c
+++ b/p9221_chip.c
@@ -958,6 +958,41 @@
}
/* send eop */
+/* send multiple times to make sure it works */
+#define EOP_RESTART_COUNT 2
+#define P9222_EOP_REPEAT_COUNT 4
+static int p9222_send_repeat_eop(struct p9221_charger_data *chgr, u8 reason)
+{
+ int count, ret = 0;
+ u8 val, ept_reason;
+
+ for (count = 0; count < P9222_EOP_REPEAT_COUNT; count++) {
+ ept_reason = (count < EOP_RESTART_COUNT) ? P9221_EOP_RESTART_POWER : reason;
+
+ ret = chgr->reg_write_8(chgr, P9222RE_EPT_REG, ept_reason);
+ if (ret == 0)
+ ret = chgr->chip_set_cmd(chgr, P9221R5_COM_SENDEPT);
+ if (ret < 0) {
+ dev_err(&chgr->client->dev, "fail send eop_%d (%d)\n", count, ret);
+ return ret;
+ }
+ mdelay(500);
+
+ /* Check Tx is offline due to EPT command works */
+ ret = chgr->reg_read_8(chgr, P9221_STATUS_REG, &val);
+ if (ret < 0) {
+ dev_info(&chgr->client->dev,
+ "WLC chip offline, count=%d, ret=%d\n", count, ret);
+ break;
+ }
+ }
+
+ dev_info(&chgr->client->dev,
+ "send 3xEOP command success(reason=%02x)\n", reason);
+
+ return 0;
+}
+
static int p9221_send_eop(struct p9221_charger_data *chgr, u8 reason)
{
int ret;
@@ -982,11 +1017,16 @@
mutex_lock(&chgr->cmd_lock);
- ret = chgr->reg_write_8(chgr, P9222RE_EPT_REG, reason);
- if (ret == 0)
- ret = chgr->chip_set_cmd(chgr, P9221R5_COM_SENDEPT);
+ if (chgr->pdata->disable_repeat_eop) {
+ ret = chgr->reg_write_8(chgr, P9222RE_EPT_REG, reason);
+ if (ret == 0)
+ ret = chgr->chip_set_cmd(chgr, P9221R5_COM_SENDEPT);
+ } else {
+ ret = p9222_send_repeat_eop(chgr, reason);
+ }
mutex_unlock(&chgr->cmd_lock);
+
return ret;
}