summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenny Ho <hsiufangho@google.com>2024-03-14 04:40:18 +0800
committerJenny Ho <hsiufangho@google.com>2024-03-19 00:50:30 +0000
commit3a3b2f9442decdfe4c1cffbbe4571d98ab6da676 (patch)
treecd03b35fc4a9447fcce3e820f4ebc745818f679f
parent67f700d5136444b9d064eb4a5dac1367a0fb939c (diff)
downloadbms-android-gs-shusky-5.15-android15-dp.tar.gz
google_battery: create charge_to_limit for LotXandroid-15-beta-1_r0.7android-gs-shusky-5.15-android15-dp
implement feature for charge to limited battery soc Bug: 322254381 Change-Id: I158bbc77ce9a69ff78066d63c3b09810da0d6914 Merged-In: I158bbc77ce9a69ff78066d63c3b09810da0d6914 Signed-off-by: Jenny Ho <hsiufangho@google.com>
-rw-r--r--Documentation/ABI/testing/sysfs-class-power12
-rw-r--r--google_battery.c131
2 files changed, 119 insertions, 24 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-power b/Documentation/ABI/testing/sysfs-class-power
index 04d0edd..5aa0e50 100644
--- a/Documentation/ABI/testing/sysfs-class-power
+++ b/Documentation/ABI/testing/sysfs-class-power
@@ -6,4 +6,14 @@ Description:
each learning event. Write 0 to clear the events.
Access: Read/Write
- Valid values: Represented as string \ No newline at end of file
+ Valid values: Represented as string
+
+What: /sys/class/power_supply/battery/charge_to_limit
+Date: Mar 2024
+Contact: hsiufangho@google.com
+Description:
+ Read/Write charge to limit SOC(state of charge)
+ Write 0 to disable this feature.
+
+ Access: Read/Write
+ Valid values: Represented as int \ No newline at end of file
diff --git a/google_battery.c b/google_battery.c
index 21e27d9..c47a5f8 100644
--- a/google_battery.c
+++ b/google_battery.c
@@ -1729,6 +1729,11 @@ static void bat_log_ttf_change(ktime_t estimate, int max_ratio, struct batt_drv
batt_drv->ttf_est = estimate;
}
+static bool batt_charge_to_limit_enable(const struct batt_chg_health *chg_health)
+{
+ return chg_health->rest_rate == 0 && chg_health->always_on_soc > 0;
+}
+
/*
* msc_logic_health() sync ce_data->ce_health to batt_drv->chg_health
* . return -EINVAL when the device is not connected to power -ERANGE when
@@ -1744,7 +1749,7 @@ static int batt_ttf_estimate(ktime_t *res, struct batt_drv *batt_drv)
qnum_t raw_full = ssoc_point_full - qnum_rconst(SOC_ROUND_BASE);
qnum_t soc_raw = ssoc_get_real_raw(&batt_drv->ssoc_state);
ktime_t estimate = 0;
- int rc = 0, max_ratio = 0;
+ int rc = 0, max_ratio = 0, ssoc_full = SSOC_FULL;
if (batt_drv->ssoc_state.buck_enabled != 1)
return -EINVAL;
@@ -1754,8 +1759,14 @@ static int batt_ttf_estimate(ktime_t *res, struct batt_drv *batt_drv)
goto done;
}
- /* TTF is 0 when UI shows 100% */
- if (ssoc_get_capacity(&batt_drv->ssoc_state) == SSOC_FULL) {
+ /* charge to limit enable */
+ if (batt_charge_to_limit_enable(&batt_drv->chg_health)) {
+ ssoc_full = batt_drv->chg_health.always_on_soc;
+ raw_full = qnum_fromint(ssoc_full) - qnum_rconst(SOC_ROUND_BASE);
+ }
+
+ /* TTF is 0 when over ssoc_full */
+ if (ssoc_get_capacity(&batt_drv->ssoc_state) >= ssoc_full) {
estimate = 0;
goto done;
}
@@ -6813,6 +6824,38 @@ static ssize_t chg_health_charge_limit_set(struct device *dev,
static DEVICE_ATTR(charge_limit, 0660, chg_health_charge_limit_get,
chg_health_charge_limit_set);
+static void batt_init_chg_health(struct batt_drv *batt_drv)
+{
+ int ret;
+
+ ret = of_property_read_u32(batt_drv->device->of_node,
+ "google,chg-rest-soc",
+ &batt_drv->chg_health.rest_soc);
+ if (ret < 0)
+ batt_drv->chg_health.rest_soc = -1;
+
+ ret = of_property_read_u32(batt_drv->device->of_node,
+ "google,chg-rest-rate",
+ &batt_drv->chg_health.rest_rate);
+ if (ret < 0)
+ batt_drv->chg_health.rest_rate = 0;
+
+ ret = of_property_read_u32(batt_drv->device->of_node,
+ "google,chg-rest-rate-before-trigger",
+ &batt_drv->chg_health.rest_rate_before_trigger);
+ if (ret < 0)
+ batt_drv->chg_health.rest_rate_before_trigger = HEALTH_CHG_RATE_BEFORE_TRIGGER;
+
+ batt_set_health_charge_limit(batt_drv, -1);
+
+ gbms_logbuffer_prlog(batt_drv->ttf_stats.ttf_log, LOGLEVEL_INFO, 0, LOGLEVEL_DEBUG,
+ "MSC_HEALTH: %s: rest_soc=%d, aon_soc=%d, rest_rate/before=%d/%d",
+ __func__, batt_drv->chg_health.rest_soc,
+ batt_drv->chg_health.always_on_soc,
+ batt_drv->chg_health.rest_rate,
+ batt_drv->chg_health.rest_rate_before_trigger);
+}
+
static ssize_t batt_show_chg_deadline(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -7199,6 +7242,63 @@ static ssize_t batt_show_ac_soc(struct device *dev,
static const DEVICE_ATTR(ac_soc, 0444, batt_show_ac_soc, NULL);
+static ssize_t charge_to_limit_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);
+ bool is_enable = batt_drv->chg_health.rest_rate == 0 &&
+ batt_drv->chg_health.always_on_soc > 0;
+ int charge_to_limit;
+ int ret = 0;
+
+ ret = kstrtoint(buf, 0, &charge_to_limit);
+ if (ret < 0)
+ return ret;
+
+ /* disable charge to limit, restore original setting */
+ if (is_enable && charge_to_limit == 0) {
+ batt_init_chg_health(batt_drv);
+ return count;
+ }
+
+ /* invalid value, do nothing */
+ if (charge_to_limit <= 0 || charge_to_limit > 99)
+ return count;
+
+
+ if (batt_drv->chg_health.rest_rate == 0 &&
+ batt_drv->chg_health.always_on_soc == charge_to_limit)
+ return count;
+
+ gbms_logbuffer_prlog(batt_drv->ttf_stats.ttf_log, LOGLEVEL_INFO, 0, LOGLEVEL_DEBUG,
+ "MSC_HEALTH: %s: set aon_soc=%d->%d", __func__,
+ batt_drv->chg_health.always_on_soc, charge_to_limit);
+
+ /* will set cc_max = 0 */
+ batt_drv->chg_health.rest_rate = 0;
+ batt_set_health_charge_limit(batt_drv, charge_to_limit);
+
+ return count;
+}
+
+static ssize_t charge_to_limit_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);
+ const bool is_enable = batt_charge_to_limit_enable(&batt_drv->chg_health);
+ int result = 0;
+
+ if (is_enable)
+ result = batt_drv->chg_health.always_on_soc;
+ else
+ result = 0;
+
+ return sysfs_emit(buf, "%d\n", result);
+}
+
+static const DEVICE_ATTR_RW(charge_to_limit);
static ssize_t batt_show_charger_state(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -8540,6 +8640,10 @@ static int batt_init_fs(struct batt_drv *batt_drv)
if (ret != 0)
dev_err(&batt_drv->psy->dev, "Failed to create chg_deadline_dryrun\n");
+ ret = device_create_file(&batt_drv->psy->dev, &dev_attr_charge_to_limit);
+ if (ret != 0)
+ dev_err(&batt_drv->psy->dev, "Failed to create charge_to_limit\n");
+
/* time to full */
ret = device_create_file(&batt_drv->psy->dev, &dev_attr_ttf_stats);
if (ret)
@@ -10480,7 +10584,6 @@ static struct gbms_storage_desc batt_prop_dsc = {
.read = batt_prop_read,
};
-
static void google_battery_init_work(struct work_struct *work)
{
struct batt_drv *batt_drv = container_of(work, struct batt_drv,
@@ -10694,25 +10797,7 @@ static void google_battery_init_work(struct work_struct *work)
batt_res_dump_logs(&batt_drv->health_data.bhi_data.res_state);
/* health based charging, triggers */
- batt_drv->chg_health.always_on_soc = -1;
-
- ret = of_property_read_u32(batt_drv->device->of_node,
- "google,chg-rest-soc",
- &batt_drv->chg_health.rest_soc);
- if (ret < 0)
- batt_drv->chg_health.rest_soc = -1;
-
- ret = of_property_read_u32(batt_drv->device->of_node,
- "google,chg-rest-rate",
- &batt_drv->chg_health.rest_rate);
- if (ret < 0)
- batt_drv->chg_health.rest_rate = 0;
-
- ret = of_property_read_u32(batt_drv->device->of_node,
- "google,chg-rest-rate-before-trigger",
- &batt_drv->chg_health.rest_rate_before_trigger);
- if (ret < 0)
- batt_drv->chg_health.rest_rate_before_trigger = HEALTH_CHG_RATE_BEFORE_TRIGGER;
+ batt_init_chg_health(batt_drv);
/* override setting google,battery-roundtrip = 0 in device tree */
batt_drv->disable_votes =