Snap for 12263504 from 64498b23ff04d2e104c4a64cb439cb57c4ab94a1 to android13-gs-pixel-5.10-24Q4-release
Change-Id: Ie134cb7c49cbcba42e5b7ba46193122418017ccb
Signed-off-by: Coastguard Worker <[email protected]>
diff --git a/google_battery.c b/google_battery.c
index 8ec9bce..619ec7a 100644
--- a/google_battery.c
+++ b/google_battery.c
@@ -547,7 +547,6 @@
/* FAN level */
struct gvotable_election *fan_level_votable;
- int fan_last_level;
/* stats */
int msc_state;
@@ -595,7 +594,6 @@
struct gbms_storage_device *history;
/* Fan control */
- int fan_level;
int fan_bt_limits[NB_FAN_BT_LIMITS];
/* AACR: Aged Adjusted Charging Rate */
@@ -1262,48 +1260,30 @@
return fan_level;
}
-static void fan_level_reset(const struct batt_drv *batt_drv)
+static bool vote_fan_level(struct gvotable_election *fan_level_votable, int level, bool enable)
{
+ int ret;
- if (batt_drv->fan_level_votable)
- gvotable_cast_int_vote(batt_drv->fan_level_votable,
- "MSC_BATT", 0, false);
-}
+ if (!fan_level_votable)
+ fan_level_votable = gvotable_election_get_handle(VOTABLE_FAN_LEVEL);
-static int fan_level_cb(struct gvotable_election *el,
- 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 (!fan_level_votable)
+ return false;
- if (!batt_drv)
- return 0;
-
- if (batt_drv->fan_last_level == lvl)
- return 0;
-
- pr_debug("FAN_LEVEL %d->%d reason=%s\n",
- batt_drv->fan_last_level, lvl, reason ? reason : "<>");
-
- 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);
+ ret = gvotable_cast_int_vote(fan_level_votable, "MSC_BATT", level, enable);
+ if (ret < 0) {
+ pr_err("MSC_FAN_LVL: enable:%d, level=%d ret=%d\n", enable, level, ret);
+ return false;
}
- return 0;
+ return true;
}
+
+static void fan_level_reset(struct batt_drv *batt_drv)
+{
+ vote_fan_level(batt_drv->fan_level_votable, 0, false);
+}
+
/* ------------------------------------------------------------------------- */
/*
@@ -4979,7 +4959,7 @@
/* call holding mutex_lock(&batt_drv->chg_lock); */
static int batt_chg_logic(struct batt_drv *batt_drv)
{
- int rc, err = 0;
+ int rc, level, err = 0;
bool jeita_stop;
bool changed = false;
const bool disable_votes = batt_drv->disable_votes;
@@ -5251,13 +5231,9 @@
}
/* Fan level can be updated only during power transfer */
- if (batt_drv->fan_level_votable) {
- int level = fan_calculate_level(batt_drv);
-
- gvotable_cast_int_vote(batt_drv->fan_level_votable,
- "MSC_BATT", level, true);
- pr_debug("MSC_FAN_LVL: level=%d\n", level);
- }
+ level = fan_calculate_level(batt_drv);
+ vote_fan_level(batt_drv->fan_level_votable, level, true);
+ pr_debug("MSC_FAN_LVL: level=%d\n", level);
if (!batt_drv->msc_interval_votable)
batt_drv->msc_interval_votable =
@@ -7066,48 +7042,6 @@
static const DEVICE_ATTR(constant_charge_voltage, 0444,
batt_show_constant_charge_voltage, NULL);
-static ssize_t fan_level_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 ret = 0;
- int level;
-
- ret = kstrtoint(buf, 0, &level);
- if (ret < 0)
- return ret;
-
- if ((level < FAN_LVL_UNKNOWN) || (level > FAN_LVL_ALARM))
- return -ERANGE;
-
- batt_drv->fan_level = level;
-
- /* always send a power supply event when forcing the value */
- if (batt_drv->psy)
- power_supply_changed(batt_drv->psy);
-
- return count;
-}
-
-static ssize_t fan_level_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);
- int result = 0;
-
- if (batt_drv->fan_level == -1 && batt_drv->fan_level_votable)
- result = gvotable_get_current_int_vote(
- batt_drv->fan_level_votable);
- else
- result = batt_drv->fan_level;
-
- return scnprintf(buf, PAGE_SIZE, "%d\n", result);
-}
-
-static const DEVICE_ATTR_RW(fan_level);
-
static ssize_t show_health_safety_margin(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -8421,9 +8355,6 @@
ret = device_create_file(&batt_drv->psy->dev, &dev_attr_constant_charge_voltage);
if (ret)
dev_err(&batt_drv->psy->dev, "Failed to create constant charge voltage\n");
- ret = device_create_file(&batt_drv->psy->dev, &dev_attr_fan_level);
- if (ret)
- dev_err(&batt_drv->psy->dev, "Failed to create fan level\n");
ret = device_create_file(&batt_drv->psy->dev, &dev_attr_health_safety_margin);
if (ret)
dev_err(&batt_drv->psy->dev, "Failed to create health safety margin\n");
@@ -8975,7 +8906,9 @@
/* TODO: google_battery caches cycle count, should use that */
cycle_cnt = GPSY_GET_PROP(batt_drv->fg_psy,
POWER_SUPPLY_PROP_CYCLE_COUNT);
- if (cycle_cnt < 0)
+
+ /* not update history if cycle count is not ready */
+ if (cycle_cnt <= 0)
return -EIO;
if (batt_drv->blf_collect_now) {
@@ -10749,23 +10682,6 @@
/* Fan levels limits from battery temperature */
batt_fan_bt_init(batt_drv);
- batt_drv->fan_level = -1;
- batt_drv->fan_last_level = -1;
- batt_drv->fan_level_votable =
- gvotable_create_int_election(NULL, gvotable_comparator_int_max,
- fan_level_cb, batt_drv);
- if (IS_ERR_OR_NULL(batt_drv->fan_level_votable)) {
- ret = PTR_ERR(batt_drv->fan_level_votable);
- dev_err(batt_drv->device, "Fail to create fan_level_votable\n");
- batt_drv->fan_level_votable = NULL;
- } else {
- gvotable_set_vote2str(batt_drv->fan_level_votable,
- gvotable_v2s_int);
- gvotable_election_set_name(batt_drv->fan_level_votable,
- VOTABLE_FAN_LEVEL);
- gvotable_cast_long_vote(batt_drv->fan_level_votable,
- "DEFAULT", FAN_LVL_UNKNOWN, true);
- }
/* charge speed interface: status and type */
batt_drv->csi_status_votable =
diff --git a/max1720x_battery.c b/max1720x_battery.c
index 5a0ca41..aae381e 100644
--- a/max1720x_battery.c
+++ b/max1720x_battery.c
@@ -941,10 +941,6 @@
version_now = max_m5_model_read_version(chip->model_data);
version_load = max_m5_fg_model_version(chip->model_data);
-
- if (!force && version_now == version_load)
- return -EEXIST;
-
gbms_logbuffer_devlog(chip->ce_log, chip->dev, LOGLEVEL_INFO, 0, LOGLEVEL_INFO,
"Schedule Load FG Model, ID=%d, ver:%d->%d cap_lsb:%d->%d",
chip->batt_id, version_now, version_load,
@@ -2390,6 +2386,49 @@
return 0;
}
+/* call holding chip->model_lock */
+static int max1720x_clear_por(struct max1720x_chip *chip)
+{
+ u16 data;
+ int ret;
+
+ ret = REGMAP_READ(&chip->regmap, MAX1720X_STATUS, &data);
+ if (ret < 0 || (data & MAX1720X_STATUS_POR) == 0)
+ return ret;
+
+ return regmap_update_bits(chip->regmap.regmap,
+ MAX1720X_STATUS,
+ MAX1720X_STATUS_POR,
+ 0x0);
+}
+
+/* call holding chip->model_lock */
+static void max1720x_check_por(struct max1720x_chip *chip)
+{
+ u16 data;
+ int ret;
+
+ ret = REGMAP_READ(&chip->regmap, MAX1720X_STATUS, &data);
+ if (ret < 0 || (data & MAX1720X_STATUS_POR) == 0)
+ return;
+
+ chip->por = true;
+ chip->cycle_reg_ok = false;
+ if (chip->fake_battery == 0) { /* no battery */
+ max1720x_clear_por(chip);
+ } else {
+ gbms_logbuffer_devlog(chip->ce_log, chip->dev, LOGLEVEL_INFO, 0, LOGLEVEL_INFO,
+ "POR is set(%04x), model reload:%d",
+ data, chip->model_reload);
+ /*
+ * trigger model load if not on-going, clear POR only when
+ * model loading done successfully
+ */
+ if (chip->model_reload != MAX_M5_LOAD_MODEL_REQUEST)
+ max1720x_model_reload(chip, false);
+ }
+}
+
static int max1720x_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
@@ -2493,6 +2532,7 @@
val->intval = rc;
break;
case POWER_SUPPLY_PROP_PRESENT:
+ /* gauge has no POR interrupt, keep polling here to catch POR */
if (chip->fake_battery != -1) {
val->intval = chip->fake_battery;
} else if (chip->gauge_type == -1) {
@@ -2507,16 +2547,11 @@
if (!val->intval)
break;
- /* chip->por prevent garbage in cycle count */
- chip->por = (data & MAX1720X_STATUS_POR) != 0;
- if (chip->por && chip->model_ok &&
- chip->model_reload != MAX_M5_LOAD_MODEL_REQUEST) {
- /* trigger reload model and clear of POR */
- mutex_unlock(&chip->model_lock);
- __pm_relax(chip->get_prop_ws);
- max1720x_fg_irq_thread_fn(-1, chip);
- return err;
- }
+ if (!chip->por)
+ max1720x_check_por(chip);
+ mutex_unlock(&chip->model_lock);
+ __pm_relax(chip->get_prop_ws);
+ return err;
}
break;
case POWER_SUPPLY_PROP_TEMP:
@@ -3127,29 +3162,6 @@
*/
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;
- chip->cycle_reg_ok = false;
- if (no_battery) {
- fg_status_clr &= ~MAX1720X_STATUS_POR;
- } else {
- gbms_logbuffer_devlog(chip->ce_log, chip->dev,
- LOGLEVEL_INFO, 0, LOGLEVEL_INFO,
- "POR is set(%04x), model reload:%d",
- fg_status, chip->model_reload);
- /*
- * trigger model load if not on-going, clear POR only when
- * model loading done successfully
- */
- if (chip->model_reload != MAX_M5_LOAD_MODEL_REQUEST)
- max1720x_model_reload(chip, false);
- }
- mutex_unlock(&chip->model_lock);
- }
-
if (fg_status & MAX1720X_STATUS_IMN)
pr_debug("IMN is set\n");
@@ -4624,24 +4636,6 @@
return 0;
}
-static int max1720x_clear_por(struct max1720x_chip *chip)
-{
- u16 data;
- int ret;
-
- ret = REGMAP_READ(&chip->regmap, MAX1720X_STATUS, &data);
- if (ret < 0)
- return ret;
-
- if ((data & MAX1720X_STATUS_POR) == 0)
- return 0;
-
- return regmap_update_bits(chip->regmap.regmap,
- MAX1720X_STATUS,
- MAX1720X_STATUS_POR,
- 0x0);
-}
-
/* read state from fg (if needed) and set the next update field */
static int max1720x_set_next_update(struct max1720x_chip *chip)
{
@@ -4760,6 +4754,7 @@
if (rc == 0) {
chip->model_reload = MAX_M5_LOAD_MODEL_IDLE;
chip->model_ok = true;
+ chip->por = false;
new_model = true;
/* saved new value in max1720x_set_next_update */
chip->model_next_update = reg_cycle > 0 ? reg_cycle - 1 : 0;
@@ -4767,8 +4762,6 @@
} else if (rc != -EAGAIN) {
chip->model_reload = MAX_M5_LOAD_MODEL_DISABLED;
chip->model_ok = false;
- } else if (chip->model_reload > MAX_M5_LOAD_MODEL_IDLE) {
- chip->model_reload += 1;
}
}
@@ -4779,6 +4772,7 @@
if (chip->model_reload >= MAX_M5_LOAD_MODEL_REQUEST) {
const unsigned long delay = msecs_to_jiffies(60 * 1000);
+ chip->model_reload += 1;
mod_delayed_work(system_wq, &chip->model_work, delay);
}
@@ -6085,10 +6079,12 @@
chip->init_complete = true;
chip->bhi_acim = 0;
- /*
- * Handle any IRQ that might have been set before init
- * NOTE: will clear the POR bit and trigger model load if needed
- */
+ /* Handle POR interrupt */
+ mutex_lock(&chip->model_lock);
+ max1720x_check_por(chip);
+ mutex_unlock(&chip->model_lock);
+
+ /* Handle other IRQs that might have been set before init */
max1720x_fg_irq_thread_fn(-1, chip);
max1720x_update_timer_base(chip);
diff --git a/max_m5.c b/max_m5.c
index 1345f76..4ad9afd 100644
--- a/max_m5.c
+++ b/max_m5.c
@@ -471,7 +471,7 @@
static int max_m5_update_gauge_custom_parameters(struct max_m5_data *m5_data)
{
struct max17x0x_regmap *regmap = m5_data->regmap;
- int ret, retries;
+ int ret, retries, temp;
u16 data;
/* write parameters (which include state) */
@@ -503,16 +503,6 @@
m5_data->cap_lsb = max_m5_period2caplsb(m5_data->parameters.taskperiod);
- /*
- * version could be in the DT: this will overwrite it if set.
- * Invalid version is not written out.
- */
- ret = max_m5_model_write_version(m5_data, m5_data->model_version);
- if (ret < 0) {
- dev_err(m5_data->dev, "cannot update version (%d)\n", ret);
- return ret;
- }
-
/* trigger load model */
ret = REGMAP_READ(regmap, MAX_M5_CONFIG2, &data);
if (ret == 0)
@@ -531,25 +521,37 @@
ret = REGMAP_READ(regmap, MAX_M5_CONFIG2, &data);
if (ret == 0 && !(data & MAX_M5_CONFIG2_LDMDL)) {
ret = REGMAP_READ(regmap, MAX_M5_REPCAP, &data);
- if (ret == 0 && data != 0) {
- int temp;
-
- temp = max_m5_model_read_version(m5_data);
- if (m5_data->model_version == MAX_M5_INVALID_VERSION) {
- dev_info(m5_data->dev, "No Model Version, Current %x\n",
- temp);
- } else if (temp != m5_data->model_version) {
- dev_info(m5_data->dev, "Model Version %x, Mismatch %x\n",
- m5_data->model_version, temp);
- return -EINVAL;
- }
-
- return 0;
- }
+ if (ret == 0 && data != 0)
+ break;
}
}
- return -ETIMEDOUT;
+ if (retries == 0)
+ return -ETIMEDOUT;
+
+ /*
+ * version could be in the DT: this will overwrite it if set.
+ * Invalid version is not written out.
+ */
+ ret = max_m5_model_write_version(m5_data, m5_data->model_version);
+ if (ret < 0) {
+ dev_err(m5_data->dev, "cannot update version (%d)\n", ret);
+ return ret;
+ }
+
+ temp = max_m5_model_read_version(m5_data);
+ if (m5_data->model_version == MAX_M5_INVALID_VERSION) {
+ dev_info(m5_data->dev, "No Model Version, Current %x\n", temp);
+ return -EINVAL;
+ }
+
+ if (temp != m5_data->model_version) {
+ dev_info(m5_data->dev, "Model Version %x, Mismatch %x\n",
+ m5_data->model_version, temp);
+ return -EINVAL;
+ }
+
+ return 0;
}
/* protected from mutex_lock(&chip->model_lock) */
diff --git a/p9221_charger.c b/p9221_charger.c
index 1a208f6..cfd687c 100644
--- a/p9221_charger.c
+++ b/p9221_charger.c
@@ -4808,6 +4808,47 @@
static DEVICE_ATTR_RO(fw_rev);
+static ssize_t fan_level_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct p9221_charger_data *charger = i2c_get_clientdata(client);
+ int result = 0;
+
+ if (charger->fan_level_votable)
+ result = gvotable_get_current_int_vote(charger->fan_level_votable);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", result);
+}
+
+static ssize_t fan_level_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct p9221_charger_data *charger = i2c_get_clientdata(client);
+ int ret = 0;
+ int level;
+
+ ret = kstrtoint(buf, 0, &level);
+ if (ret < 0)
+ return ret;
+
+ if ((level < FAN_LVL_UNKNOWN) || (level > FAN_LVL_ALARM))
+ return -ERANGE;
+
+ if (charger->fan_level_votable) {
+ ret = gvotable_cast_int_vote(charger->fan_level_votable, "MSC_USR", level, true);
+ if (ret < 0)
+ pr_err("MSC_FAN_LVL: fail to set level=%d(ret=%d)\n", level, ret);
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR_RW(fan_level);
+
static ssize_t p9382_show_rtx_boost(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -5347,6 +5388,7 @@
&dev_attr_mitigate_threshold.attr,
&dev_attr_wpc_ready.attr,
&dev_attr_qien.attr,
+ &dev_attr_fan_level.attr,
NULL
};
@@ -6799,6 +6841,31 @@
return 0;
}
+static int fan_level_cb(struct gvotable_election *el,
+ const char *reason, void *vote)
+{
+ struct p9221_charger_data *charger = gvotable_get_data(el);
+ int lvl = GVOTABLE_PTR_TO_INT(vote);
+
+ if (!charger)
+ return 0;
+
+ if (charger->fan_last_level == lvl)
+ return 0;
+
+ if (!charger->online)
+ return 0;
+
+ logbuffer_log(charger->log, "FAN_LEVEL %d->%d reason=%s",
+ charger->fan_last_level, lvl, reason ? reason : "<>");
+
+ charger->fan_last_level = lvl;
+
+ kobject_uevent(&charger->dev->kobj, KOBJ_CHANGE);
+
+ return 0;
+}
+
/*
* If able to read the chip_id register then we know we are online
*
@@ -7075,6 +7142,24 @@
if (!charger->chg_mode_votable)
dev_warn(&charger->client->dev, "Could not find %s votable\n", GBMS_MODE_VOTABLE);
+ charger->fan_level_votable =
+ gvotable_create_int_election(NULL, gvotable_comparator_int_max,
+ fan_level_cb, charger);
+ if (IS_ERR_OR_NULL(charger->fan_level_votable)) {
+ ret = PTR_ERR(charger->fan_level_votable);
+ dev_err(&client->dev, "Fail to create fan_level_votable\n");
+ charger->fan_level_votable = NULL;
+ } else {
+ gvotable_set_vote2str(charger->fan_level_votable,
+ gvotable_v2s_int);
+ gvotable_election_set_name(charger->fan_level_votable,
+ VOTABLE_FAN_LEVEL);
+ gvotable_cast_long_vote(charger->fan_level_votable,
+ "DEFAULT", FAN_LVL_UNKNOWN, true);
+ }
+
+ charger->fan_last_level = -1;
+
/* Ramping on BPP is optional */
if (charger->pdata->icl_ramp_delay_ms != -1) {
charger->icl_ramp_ua = P9221_DC_ICL_BPP_RAMP_DEFAULT_UA;
diff --git a/p9221_charger.h b/p9221_charger.h
index 3b72a69..d891d3f 100644
--- a/p9221_charger.h
+++ b/p9221_charger.h
@@ -719,6 +719,7 @@
struct gvotable_election *csi_status_votable;
struct gvotable_election *csi_type_votable;
struct gvotable_election *point_full_ui_soc_votable;
+ struct gvotable_election *fan_level_votable;
struct notifier_block nb;
struct mutex io_lock;
struct mutex cmd_lock;
@@ -844,6 +845,7 @@
bool hpp_hv;
int fod_mode;
enum p9xxx_chk_rp check_rp;
+ int fan_last_level;
#if IS_ENABLED(CONFIG_GPIOLIB)
struct gpio_chip gpio;