Merge android13-gs-pixel-5.10-tm-qpr3 into android13-gs-pixel-5.10-udc
Bug: 255246572
Change-Id: I9ff696ac5ec7f5eb3a4a8289ad84d53e576171f4
Signed-off-by: Joey Lin <[email protected]>
diff --git a/gbms_storage.h b/gbms_storage.h
index b3753b2..7eb82c7 100644
--- a/gbms_storage.h
+++ b/gbms_storage.h
@@ -59,6 +59,7 @@
enum gbms_tags {
GBMS_TAG_ACIM = 0x4143494d, /* Activation Impedance */
+ GBMS_TAG_AYMD = 0x41594d44,
GBMS_TAG_BCNT = 0x42434e54,
GBMS_TAG_BGCE = 0x42474345,
GBMS_TAG_BGPN = 0x4247504e,
@@ -80,12 +81,14 @@
GBMS_TAG_MINF = 0x4d494e46,
GBMS_TAG_MXSN = 0x4d58534e,
GBMS_TAG_MXCN = 0x4d58434e,
+ GBMS_TAG_MYMD = 0x4d594d44,
GBMS_TAG_THAS = 0x54484153,
/* User Space Read/Write scratch */
GBMS_TAG_RS32 = 0x52533332,
GBMS_TAG_RSBM = 0x5253424d,
GBMS_TAG_RSBR = 0x52534252,
+ GBMS_TAG_SUFG = 0x53554647, /* shutdown by user_request flag */
/* Reboot scratch */
GBMS_TAG_RRS0 = 0x52525330,
diff --git a/google_battery.c b/google_battery.c
index 6489ce3..dd3e5a8 100644
--- a/google_battery.c
+++ b/google_battery.c
@@ -352,6 +352,8 @@
int bhi_debug_imp_index;
int bhi_debug_sd_index;
int bhi_debug_health_index;
+ /* algo BHI_ALGO_INDI capacity threshold */
+ int bhi_indi_cap;
/* current battery state */
struct bhi_data bhi_data;
@@ -549,6 +551,9 @@
/* battery pack status */
struct batt_bpst bpst_state;
+ /* shutdown flag */
+ int boot_to_os_attempts;
+
/* battery critical level */
int batt_critical_voltage;
};
@@ -1115,28 +1120,32 @@
const char *reason, void *vote)
{
struct batt_drv *batt_drv = gvotable_get_data(el);
+ const int last_lvl = batt_drv->fan_last_level;
int lvl = GVOTABLE_PTR_TO_INT(vote);
if (!batt_drv)
return 0;
- if (batt_drv->fan_last_level != lvl) {
- pr_debug("FAN_LEVEL %d->%d reason=%s\n",
- batt_drv->fan_last_level, lvl, reason ? reason : "<>");
+ if (batt_drv->fan_last_level == lvl)
+ return 0;
- if (!chg_state_is_disconnected(&batt_drv->chg_state)) {
- logbuffer_log(batt_drv->ttf_stats.ttf_log,
- "FAN_LEVEL %d->%d reason=%s",
- batt_drv->fan_last_level, lvl,
- reason ? reason : "<>");
+ pr_debug("FAN_LEVEL %d->%d reason=%s\n",
+ batt_drv->fan_last_level, lvl, reason ? reason : "<>");
- batt_drv->fan_last_level = lvl;
- if (batt_drv->psy)
- power_supply_changed(batt_drv->psy);
- } else {
- /* Disconnected */
- batt_drv->fan_last_level = lvl;
- }
+ batt_drv->fan_last_level = lvl;
+
+ if (!chg_state_is_disconnected(&batt_drv->chg_state)) {
+
+ logbuffer_log(batt_drv->ttf_stats.ttf_log,
+ "FAN_LEVEL %d->%d reason=%s",
+ last_lvl, lvl,
+ reason ? reason : "<>");
+
+ /*
+ * Send the uevent by kobject API to distinguish the uevent sent by
+ * power_supply_changed() since fan_level is not a standard power_supply_property
+ */
+ kobject_uevent(&batt_drv->device->kobj, KOBJ_CHANGE);
}
return 0;
@@ -3234,17 +3243,18 @@
/* BHI -------------------------------------------------------------------- */
-#define ONE_YEAR_HRS (24 * 365)
-#define BHI_INDI_CAP 85
+#define ONE_YEAR_HRS (24 * 365)
+#define BHI_INDI_CAP_DEFAULT 85
static int bhi_individual_conditions_index(const struct health_data *health_data)
{
const struct bhi_data *bhi_data = &health_data->bhi_data;
const int cur_impedance = batt_ravg_value(&bhi_data->res_state);
const int age_impedance_max = bhi_data->act_impedance * 2;
const int cur_capacity_pct = 100 - bhi_data->capacity_fade;
+ const int bhi_indi_cap = health_data->bhi_indi_cap;
if (health_data->bhi_data.battery_age >= ONE_YEAR_HRS ||
- cur_impedance >= age_impedance_max || cur_capacity_pct <= BHI_INDI_CAP)
+ cur_impedance >= age_impedance_max || cur_capacity_pct <= bhi_indi_cap)
return health_data->need_rep_threshold * 100;
return BHI_ALGO_FULL_HEALTH;
@@ -6507,11 +6517,42 @@
struct power_supply *psy = container_of(dev, struct power_supply, dev);
struct batt_drv *batt_drv = power_supply_get_drvdata(psy);
- return scnprintf(buf, PAGE_SIZE, "%d\n", batt_drv->health_data.bhi_algo);
+ return scnprintf(buf, PAGE_SIZE, "%d\n", batt_drv->health_data.bhi_indi_cap);
}
static const DEVICE_ATTR_RW(health_algo);
+static ssize_t health_indi_cap_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct power_supply *psy = container_of(dev, struct power_supply, dev);
+ struct batt_drv *batt_drv = power_supply_get_drvdata(psy);
+ int value, ret;
+
+ ret = kstrtoint(buf, 0, &value);
+ if (ret < 0)
+ return ret;
+
+ if (value > 100 || value < 0)
+ return count;
+
+ batt_drv->health_data.bhi_indi_cap = value;
+
+ return count;
+}
+
+static ssize_t health_indi_cap_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct power_supply *psy = container_of(dev, struct power_supply, dev);
+ struct batt_drv *batt_drv = power_supply_get_drvdata(psy);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", batt_drv->health_data.bhi_indi_cap);
+}
+
+static const DEVICE_ATTR_RW(health_indi_cap);
+
/* CSI --------------------------------------------------------------------- */
static ssize_t charging_speed_store(struct device *dev,
@@ -6920,6 +6961,9 @@
ret = device_create_file(&batt_drv->psy->dev, &dev_attr_health_algo);
if (ret)
dev_err(&batt_drv->psy->dev, "Failed to create health algo\n");
+ ret = device_create_file(&batt_drv->psy->dev, &dev_attr_health_indi_cap);
+ if (ret)
+ dev_err(&batt_drv->psy->dev, "Failed to create health individual capacity\n");
/* csi */
ret = device_create_file(&batt_drv->psy->dev, &dev_attr_charging_speed);
@@ -7030,6 +7074,9 @@
&batt_drv->health_data.bhi_data.res_state.ravg_soc_high);
debugfs_create_file("ravg", 0400, de, batt_drv, &debug_ravg_fops);
+ /* shutdown flag */
+ debugfs_create_u32("boot_to_os_attempts", 0660, de, &batt_drv->boot_to_os_attempts);
+
return 0;
}
@@ -7393,9 +7440,9 @@
idx = cycle_cnt / batt_drv->hist_delta_cycle_cnt;
- /* check if the cycle_cnt is valid */
+ /* save in last when over max cycles */
if (idx >= batt_drv->hist_data_max_cnt)
- return -ENOENT;
+ idx = batt_drv->hist_data_max_cnt - 1;
ret = batt_hist_data_collect(batt_drv->hist_data, idx);
if (ret < 0)
@@ -7447,6 +7494,38 @@
return 0;
}
+#define BOOT_TO_OS_ATTEMPTS 3
+
+static int batt_init_shutdown_flag(struct batt_drv *batt_drv)
+{
+ u8 data;
+ int ret;
+
+ ret = gbms_storage_read(GBMS_TAG_SUFG, &data, sizeof(data));
+ if (ret < 0)
+ return -EIO;
+
+ batt_drv->boot_to_os_attempts = data;
+
+ /* reset battery shutdown flag */
+ data = 0;
+ ret = gbms_storage_write(GBMS_TAG_SUFG, &data, sizeof(data));
+
+ return (ret < 0) ? -EIO : 0;
+}
+
+static int batt_set_shutdown_flag(struct batt_drv *batt_drv)
+{
+ u8 data = batt_drv->boot_to_os_attempts;
+ int ret;
+
+ if (data == 0)
+ data = BOOT_TO_OS_ATTEMPTS;
+
+ ret = gbms_storage_write(GBMS_TAG_SUFG, &data, sizeof(data));
+
+ return (ret < 0) ? -EIO : 0;
+}
/*
* poll the battery, run SOC%, dead battery, critical.
@@ -7534,6 +7613,13 @@
__func__, batt_drv->capacity_level,
level);
+ /* set battery critical shutdown */
+ if (level == POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL) {
+ ret = batt_set_shutdown_flag(batt_drv);
+ if (ret < 0)
+ pr_warn("failed to write shutdown flag, ret=%d\n", ret);
+ }
+
batt_drv->capacity_level = level;
notify_psy_changed = true;
}
@@ -8330,6 +8416,12 @@
if (ret < 0)
health_data->cycle_count_need_rep_threshold = BHI_CC_NEED_REP_THRESHOLD_DEFAULT;
+ /* algorithm BHI_ALGO_INDI capacity threshold */
+ ret = of_property_read_u32(batt_drv->device->of_node, "google,bhi-indi-cap",
+ &health_data->bhi_indi_cap);
+ if (ret < 0)
+ health_data->bhi_indi_cap = BHI_INDI_CAP_DEFAULT;
+
/* design is the value used to build the charge table */
health_data->bhi_data.capacity_design = batt_drv->battery_capacity;
@@ -8402,6 +8494,7 @@
batt_drv->hold_taper_ws = false;
batt_drv->fake_temp = 0;
batt_drv->fake_battery_present = -1;
+ batt_drv->boot_to_os_attempts = 0;
batt_reset_chg_drv_state(batt_drv);
mutex_init(&batt_drv->chg_lock);
@@ -8487,6 +8580,11 @@
if (ret < 0)
pr_err("bpst profile disabled, ret=%d\n", ret);
+ /* init shutdown flag */
+ ret = batt_init_shutdown_flag(batt_drv);
+ if (ret < 0)
+ pr_err("failed to init shutdown flag, ret=%d\n", ret);
+
/* cycle count is cached: read here bc SSOC, chg_profile might use it */
batt_update_cycle_count(batt_drv);
diff --git a/google_eeprom.c b/google_eeprom.c
index 75b2755..6260ba1 100644
--- a/google_eeprom.c
+++ b/google_eeprom.c
@@ -22,6 +22,8 @@
#define BATT_EEPROM_TAG_BGPN_LEN GBMS_BGPN_LEN
#define BATT_EEPROM_TAG_BRID_OFFSET 0x17
#define BATT_EEPROM_TAG_BRID_LEN 1
+#define BATT_EEPROM_TAG_MYMD_OFFSET 0x1A
+#define BATT_EEPROM_TAG_MYMD_LEN 4
#define BATT_EEPROM_TAG_STRD_OFFSET 0x1E
#define BATT_EEPROM_TAG_STRD_LEN 12
#define BATT_EEPROM_TAG_RSOC_OFFSET 0x2A
@@ -48,6 +50,8 @@
#define BATT_EEPROM_TAG_EXTRA_START (BATT_EEPROM_TAG_HIST_OFFSET + BATT_TOTAL_HIST_LEN)
// 0x3E2 is the first free with 75 history entries
+#define BATT_EEPROM_TAG_AYMD_OFFSET 0x3E4
+#define BATT_EEPROM_TAG_AYMD_LEN 4
#define BATT_EEPROM_TAG_GCFE_OFFSET 0x3E8
#define BATT_EEPROM_TAG_GCFE_LEN 2
#define BATT_EEPROM_TAG_RAVG_OFFSET 0x3EA
@@ -147,6 +151,14 @@
*addr = BATT_EEPROM_TAG_THAS_OFFSET;
*count = BATT_EEPROM_TAG_THAS_LEN;
break;
+ case GBMS_TAG_AYMD:
+ *addr = BATT_EEPROM_TAG_AYMD_OFFSET;
+ *count = BATT_EEPROM_TAG_AYMD_LEN;
+ break;
+ case GBMS_TAG_MYMD:
+ *addr = BATT_EEPROM_TAG_MYMD_OFFSET;
+ *count = BATT_EEPROM_TAG_MYMD_LEN;
+ break;
default:
ret = -ENOENT;
break;
@@ -166,7 +178,8 @@
GBMS_TAG_STRD, GBMS_TAG_RSOC,
GBMS_TAG_ACIM, GBMS_TAG_GCFE,
GBMS_TAG_RAVG, GBMS_TAG_RFCN,
- GBMS_TAG_THAS};
+ GBMS_TAG_THAS, GBMS_TAG_AYMD,
+ GBMS_TAG_MYMD};
const int count = ARRAY_SIZE(keys);
if (index < 0 || index >= count)
@@ -229,6 +242,7 @@
case GBMS_TAG_RAVG:
case GBMS_TAG_RFCN:
case GBMS_TAG_THAS:
+ case GBMS_TAG_AYMD:
return true;
default:
return false;
diff --git a/max1720x_battery.c b/max1720x_battery.c
index 5d17030..d29dddc 100644
--- a/max1720x_battery.c
+++ b/max1720x_battery.c
@@ -129,6 +129,8 @@
#define BHI_CAP_FCN_COUNT 3
+#define DEFAULT_STATUS_CHARGE_MA 100
+
#pragma pack(1)
struct max17x0x_eeprom_history {
u16 tempco;
@@ -259,6 +261,9 @@
int bhi_acim;
struct max1720x_rc_switch rc_switch;
+
+ /* battery current criteria for report status charge */
+ u32 status_charge_threshold_ma;
};
#define MAX1720_EMPTY_VOLTAGE(profile, temp, cycle) \
@@ -1245,10 +1250,14 @@
return -EIO;
current_avg = -reg_to_micro_amp(data, chip->RSense);
- err = REGMAP_READ(&chip->regmap, MAX1720X_ICHGTERM, &data);
- if (err)
- return -EIO;
- ichgterm = reg_to_micro_amp(data, chip->RSense);
+ if (chip->status_charge_threshold_ma) {
+ ichgterm = chip->status_charge_threshold_ma * 1000;
+ } else {
+ err = REGMAP_READ(&chip->regmap, MAX1720X_ICHGTERM, &data);
+ if (err)
+ return -EIO;
+ ichgterm = reg_to_micro_amp(data, chip->RSense);
+ }
err = REGMAP_READ(&chip->regmap, MAX1720X_FULLSOCTHR, &data);
if (err)
@@ -2109,6 +2118,7 @@
static int max1720x_get_fade_rate(struct max1720x_chip *chip)
{
struct max17x0x_eeprom_history hist = { 0 };
+ int bhi_fcn_count = chip->bhi_fcn_count;
int ret, ratio, i, fcn_sum = 0;
u16 hist_idx;
@@ -2120,10 +2130,20 @@
dev_info(chip->dev, "%s: hist_idx=%d\n", __func__, hist_idx);
- if (hist_idx < chip->bhi_fcn_count)
- return -ENODATA;
+ /* no fade for new battery (less than 30 cycles) */
+ if (hist_idx < bhi_fcn_count)
+ return 0;
- for (i = chip->bhi_fcn_count; i ; i--, hist_idx--) {
+ while (hist_idx >= BATT_MAX_HIST_CNT && bhi_fcn_count > 1) {
+ hist_idx--;
+ bhi_fcn_count--;
+ if (bhi_fcn_count == 1) {
+ hist_idx = BATT_MAX_HIST_CNT - 1;
+ break;
+ }
+ }
+
+ for (i = bhi_fcn_count; i ; i--, hist_idx--) {
ret = gbms_storage_read_data(GBMS_TAG_HIST, &hist,
sizeof(hist), hist_idx);
@@ -2138,7 +2158,7 @@
}
/* convert from max17x0x_eeprom_history to percent */
- ratio = fcn_sum / (chip->bhi_fcn_count * 8);
+ ratio = fcn_sum / (bhi_fcn_count * 8);
if (ratio > 100)
ratio = 100;
@@ -2831,15 +2851,21 @@
fg_status_clr = fg_status;
if (fg_status & MAX1720X_STATUS_POR) {
+ const bool no_battery = chip->fake_battery == 0;
+
mutex_lock(&chip->model_lock);
chip->por = true;
- dev_warn(chip->dev, "POR is set(%04x), model reload:%d\n",
- fg_status, chip->model_reload);
- /* trigger model load if not on-going */
- if (chip->model_reload != MAX_M5_LOAD_MODEL_REQUEST) {
- err = max1720x_model_reload(chip, true);
- if (err < 0)
- fg_status_clr &= ~MAX1720X_STATUS_POR;
+ if (no_battery) {
+ fg_status_clr &= ~MAX1720X_STATUS_POR;
+ } else {
+ dev_warn(chip->dev, "POR is set(%04x), model reload:%d\n",
+ fg_status, chip->model_reload);
+ /* trigger model load if not on-going */
+ if (chip->model_reload != MAX_M5_LOAD_MODEL_REQUEST) {
+ err = max1720x_model_reload(chip, true);
+ if (err < 0)
+ fg_status_clr &= ~MAX1720X_STATUS_POR;
+ }
}
mutex_unlock(&chip->model_lock);
}
@@ -3507,11 +3533,15 @@
/* Model reload will be disabled if the node is not found */
static int max1720x_init_model(struct max1720x_chip *chip)
{
+ const bool no_battery = chip->fake_battery == 0;
void *model_data;
if (chip->gauge_type != MAX_M5_GAUGE_TYPE)
return 0;
+ if (no_battery)
+ return 0;
+
/* ->batt_id negative for no lookup */
if (chip->batt_id >= 0) {
chip->batt_node = max1720x_find_batt_node(chip);
@@ -4671,6 +4701,9 @@
{
int ret;
+ if (!chip->model_data)
+ return 0;
+
if (!max_m5_fg_model_check_version(chip->model_data)) {
if (max_m5_needs_reset_model_data(chip->model_data)) {
ret = max_m5_reset_state_data(chip->model_data);
@@ -5832,6 +5865,7 @@
const char *psy_name = NULL;
char monitor_name[32];
int ret = 0;
+ u32 data32;
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
@@ -5848,6 +5882,15 @@
if (chip->gauge_type < 0)
chip->gauge_type = -1;
+ ret = of_property_read_u32(dev->of_node, "maxim,status-charge-threshold-ma",
+ &data32);
+ if (ret == 0)
+ chip->status_charge_threshold_ma = data32;
+ else if (chip->gauge_type == MAX_M5_GAUGE_TYPE)
+ chip->status_charge_threshold_ma = DEFAULT_STATUS_CHARGE_MA;
+ else
+ chip->status_charge_threshold_ma = 0;
+
/* needs chip->primary and (optional) chip->secondary */
ret = max17x0x_regmap_init(chip);
if (ret < 0) {
diff --git a/max77759_maxq.c b/max77759_maxq.c
index a613ac1..583ac4e 100644
--- a/max77759_maxq.c
+++ b/max77759_maxq.c
@@ -66,7 +66,9 @@
#define RSBM_ADDR 0
#define RSBR_ADDR 4
+#define SUFG_ADDR 8
#define RS_TAG_LENGTH 4
+#define SU_TAG_LENGTH 1
#define RS_TAG_OFFSET_ADDR 0
#define RS_TAG_OFFSET_LENGTH 1
#define RS_TAG_OFFSET_DATA 2
@@ -314,42 +316,54 @@
static int maxq_rs_read(struct max77759_maxq *maxq, gbms_tag_t tag, u8 *data)
{
- int ret;
+ int ret, len;
u8 buff[OPCODE_USER_SPACE_R_RES_LEN];
- if (tag == GBMS_TAG_RSBM)
+ if (tag == GBMS_TAG_RSBM) {
buff[RS_TAG_OFFSET_ADDR] = RSBM_ADDR;
- else if (tag == GBMS_TAG_RSBR)
+ len = RS_TAG_LENGTH;
+ } else if (tag == GBMS_TAG_RSBR) {
buff[RS_TAG_OFFSET_ADDR] = RSBM_ADDR;
- else
+ len = RS_TAG_LENGTH;
+ } else if (tag == GBMS_TAG_SUFG) {
+ buff[RS_TAG_OFFSET_ADDR] = SUFG_ADDR;
+ len = SU_TAG_LENGTH;
+ } else {
return -EINVAL;
+ }
- buff[RS_TAG_OFFSET_LENGTH] = RS_TAG_LENGTH;
+ buff[RS_TAG_OFFSET_LENGTH] = len;
ret = maxq_user_space_read(maxq, buff);
if (ret < 0)
return ret;
- memcpy(data, buff, RS_TAG_LENGTH);
+ memcpy(data, buff, len);
return ret;
}
static int maxq_rs_write(struct max77759_maxq *maxq, gbms_tag_t tag, u8 *data)
{
- int ret;
+ int ret, len;
u8 buff[OPCODE_USER_SPACE_W_REQ_LEN];
- if (tag == GBMS_TAG_RSBM)
+ if (tag == GBMS_TAG_RSBM) {
buff[RS_TAG_OFFSET_ADDR] = RSBM_ADDR;
- else if (tag == GBMS_TAG_RSBR)
+ len = RS_TAG_LENGTH;
+ } else if (tag == GBMS_TAG_RSBR) {
buff[RS_TAG_OFFSET_ADDR] = RSBR_ADDR;
- else
+ len = RS_TAG_LENGTH;
+ } else if (tag == GBMS_TAG_SUFG) {
+ buff[RS_TAG_OFFSET_ADDR] = SUFG_ADDR;
+ len = SU_TAG_LENGTH;
+ } else {
return -EINVAL;
+ }
- buff[RS_TAG_OFFSET_LENGTH] = RS_TAG_LENGTH;
+ buff[RS_TAG_OFFSET_LENGTH] = len;
- memcpy(&buff[RS_TAG_OFFSET_DATA], data, RS_TAG_LENGTH);
+ memcpy(&buff[RS_TAG_OFFSET_DATA], data, len);
ret = maxq_user_space_write(maxq, buff);
@@ -374,6 +388,11 @@
return -EINVAL;
ret = maxq_rs_read(maxq, tag, buff);
break;
+ case GBMS_TAG_SUFG:
+ if (size && size > SU_TAG_LENGTH)
+ return -EINVAL;
+ ret = maxq_rs_read(maxq, tag, buff);
+ break;
default:
ret = -ENOENT;
break;
@@ -400,6 +419,11 @@
return -EINVAL;
ret = maxq_rs_write(maxq, tag, (void *)buff);
break;
+ case GBMS_TAG_SUFG:
+ if (size && size > SU_TAG_LENGTH)
+ return -EINVAL;
+ ret = maxq_rs_write(maxq, tag, (void *)buff);
+ break;
default:
ret = -ENOENT;
break;
diff --git a/p9221_charger.c b/p9221_charger.c
index e81a05d..bd691c7 100644
--- a/p9221_charger.c
+++ b/p9221_charger.c
@@ -27,7 +27,7 @@
#include <linux/debugfs.h>
#define P9221R5_OVER_CHECK_NUM 3
-
+#define MFG_CHK_COUNT_MAX 30
#define OVC_LIMIT 1
#define OVC_THRESHOLD 1400000
#define OVC_BACKOFF_LIMIT 900000
@@ -658,19 +658,56 @@
#define EPP_MODE_REQ_PWR 15
#define EPP_MODE_REQ_VOUT 12000
+#define WLC_VOUT_RAMP_DOWN_MV 15300
+#define WLC_VOUT_CFG_STEP 40 /* b/194346461 ramp down VOUT */
static int p9xxx_set_bypass_mode(struct p9221_charger_data *charger)
{
const int req_pwr = EPP_MODE_REQ_PWR;
+ const int vout_target = WLC_VOUT_RAMP_DOWN_MV;
int i, count, ret;
u8 cdmode, currpwr;
u32 vout_mv;
+ if (!charger->online)
+ return 0;
+
/* Check it's in Cap Div mode */
ret = charger->reg_read_8(charger, P9412_CDMODE_STS_REG, &cdmode);
if (ret || (cdmode & CDMODE_BYPASS_MODE))
return ret;
dev_info(&charger->client->dev, "cdmode_reg=%02x\n", cdmode);
+ usleep_range(500 * USEC_PER_MSEC, 510 * USEC_PER_MSEC);
+ /* Ramp down WLC Vout to 15.3V */
+ while (true) {
+ ret = charger->chip_get_vout(charger, &vout_mv);
+ if (ret < 0 || vout_mv == 0) {
+ dev_err(&charger->client->dev, "%s: invalid vout %d\n", __func__, ret);
+ return ret;
+ }
+
+ if (vout_mv < vout_target) {
+ dev_info(&charger->client->dev, "%s: underflow vout=%d, (target=%d)\n",
+ __func__, vout_mv, vout_target);
+ break;
+ }
+
+ vout_mv -= WLC_VOUT_CFG_STEP;
+
+ ret = charger->chip_set_vout_max(charger, vout_mv);
+ if (ret < 0) {
+ dev_err(&charger->client->dev, "%s: cannot set vout %d\n", __func__, ret);
+ return ret;
+ } else {
+ dev_info(&charger->client->dev, "%s: vout set to %d\n", __func__, vout_mv);
+ usleep_range(250 * USEC_PER_MSEC, 260 * USEC_PER_MSEC);
+ }
+ }
+
+ if (!charger->online)
+ return 0;
+
+ usleep_range(500 * USEC_PER_MSEC, 510 * USEC_PER_MSEC);
for (count = 0; count < 3; count++) {
/* Change the Requested Power to 15W */
ret = charger->reg_write_8(charger, P9412_PROP_REQ_PWR_REG, req_pwr * 2);
@@ -727,8 +764,12 @@
const int extben_gpio = charger->pdata->ext_ben_gpio;
int ret;
+ if (!charger->pdata->has_wlc_dc)
+ return -EOPNOTSUPP;
+
charger->wlc_dc_enabled = false;
+ usleep_range(500 * USEC_PER_MSEC, 510 * USEC_PER_MSEC);
p9xxx_gpio_set_value(charger, dc_sw_gpio, 0);
p9xxx_gpio_set_value(charger, extben_gpio, 0);
@@ -1397,7 +1438,7 @@
* Check 10 times if alignment_capble is still 0.
*/
- if ((charger->mfg_check_count < 10) ||
+ if ((charger->mfg_check_count < MFG_CHK_COUNT_MAX) ||
(charger->alignment_capable == ALIGN_MFG_PASSED)) {
/* release the align_ws before return*/
@@ -1414,7 +1455,8 @@
/* release the align_ws */
__pm_relax(charger->align_ws);
- dev_info(&charger->client->dev, "align_work ended\n");
+ dev_info(&charger->client->dev, "align_work ended(mfg_check_count=%d)\n",
+ charger->mfg_check_count);
}
static const char *p9221_get_tx_id_str(struct p9221_charger_data *charger)
@@ -2227,6 +2269,23 @@
return ret;
}
+static int p9xxx_check_alignment(struct p9221_charger_data *charger)
+{
+ int ret = 0;
+
+ if (charger->alignment == 100) {
+ dev_dbg(&charger->client->dev, "Alignment check OK\n");
+ } else if (charger->alignment == -1 && charger->mfg_check_count < MFG_CHK_COUNT_MAX) {
+ ret = -EAGAIN;
+ dev_dbg(&charger->client->dev, "Alignment checking\n");
+ } else {
+ ret = -EOPNOTSUPP;
+ dev_err(&charger->client->dev, "Misalignment!\n");
+ }
+
+ return ret;
+}
+
/* < 0 error, 0 = no changes, > 1 changed */
static int p9221_set_psy_online(struct p9221_charger_data *charger, int online)
{
@@ -2305,15 +2364,20 @@
return -EOPNOTSUPP;
}
+ /* AUTH is passed remove the DC_ICL limit */
+ p9221_set_auth_dc_icl(charger, false);
+ mutex_unlock(&charger->auth_lock);
+
+ /* Check alignment before enabling proprietary mode */
+ ret = p9xxx_check_alignment(charger);
+ if (ret < 0)
+ return ret;
+
ret = p9221_set_hpp_dc_icl(charger, true);
if (ret < 0)
dev_warn(&charger->client->dev, "Cannot enable HPP_ICL (%d)\n", ret);
mdelay(10);
- /* AUTH is passed remove the DC_ICL limit */
- p9221_set_auth_dc_icl(charger, false);
- mutex_unlock(&charger->auth_lock);
-
/*
* run ->chip_prop_mode_en() if proprietary mode or cap divider
* mode isn't enabled (i.e. with p9412_prop_mode_enable())
@@ -2410,8 +2474,20 @@
return;
}
- threshold = charger->mitigate_threshold > 0 ? charger->mitigate_threshold :
- charger->pdata->power_mitigate_threshold;
+ if (!charger->csi_type_votable)
+ charger->csi_type_votable = gvotable_election_get_handle(VOTABLE_CSI_TYPE);
+
+ if (charger->mitigate_threshold > 0)
+ threshold = charger->mitigate_threshold;
+ else if (charger->csi_type_votable &&
+ charger->pdata->power_mitigate_threshold > 0 &&
+ gvotable_get_current_int_vote(charger->csi_type_votable) == CSI_TYPE_Adaptive)
+ threshold = charger->last_capacity - 1; /* Run dream defend when AC trigger */
+ else
+ threshold = charger->pdata->power_mitigate_threshold;
+
+ pr_debug("dream_defend soc:%d threshold:%d\n", charger->last_capacity, threshold);
+
if (!threshold)
return;
diff --git a/p9221_charger.h b/p9221_charger.h
index 4a15eb2..dee1be6 100644
--- a/p9221_charger.h
+++ b/p9221_charger.h
@@ -710,6 +710,7 @@
struct gvotable_election *chg_mode_votable;
struct gvotable_election *wlc_disable_votable;
struct gvotable_election *csi_status_votable;
+ struct gvotable_election *csi_type_votable;
struct notifier_block nb;
struct mutex io_lock;
struct mutex cmd_lock;
diff --git a/pca9468_charger.c b/pca9468_charger.c
index 72a564a..a3fc6f6 100644
--- a/pca9468_charger.c
+++ b/pca9468_charger.c
@@ -5014,7 +5014,7 @@
pca9468_chg->pdata = pdata;
pca9468_chg->charging_state = DC_STATE_NO_CHARGING;
pca9468_chg->wlc_ramp_out_iin = true;
- pca9468_chg->wlc_ramp_out_vout_target = 15300000; /* 15.3V as default */
+ pca9468_chg->wlc_ramp_out_vout_target = 0; /* use Vbatt*4 as default */
pca9468_chg->wlc_ramp_out_delay = 250; /* 250 ms default */
/* Create a work queue for the direct charger */