AACR: sync AACR feature
2e583480c google_bms: initial cccm_limits before update charge table
191127850 google_bms: AACR feature implement
23314e6b5 google_battery: AACR feature implement
68183e861 google_battery: add chg_raw_profile for logging
c10eb8b86 AACR: nodes for server side configuration
Bug: 205900652
Bug: 205900551
Signed-off-by: Jenny Ho <hsiufangho@google.com>
Change-Id: Ia65e6f5f867fe633cbff5cc0565942b87df5d95b
diff --git a/drivers/power/supply/google/google_battery.c b/drivers/power/supply/google/google_battery.c
index f01dbae..c486daa 100644
--- a/drivers/power/supply/google/google_battery.c
+++ b/drivers/power/supply/google/google_battery.c
@@ -58,6 +58,11 @@
#define MSC_ERROR_UPDATE_INTERVAL 5000
#define MSC_DEFAULT_UPDATE_INTERVAL 30000
+
+/* AACR default slope is disabled by default */
+#define AACR_START_CYCLE_DEFAULT 100
+#define AACR_MAX_CYCLE_DEFAULT 0 /* disabled */
+
/* qual time is 0 minutes of charge or 0% increase in SOC */
#define DEFAULT_CHG_STATS_MIN_QUAL_TIME 0
#define DEFAULT_CHG_STATS_MIN_DELTA_SOC 0
@@ -236,6 +241,15 @@
u16 checksum; // 0x1A
};
+enum batt_aacr_state {
+ BATT_AACR_UNKNOWN = -3,
+ BATT_AACR_INVALID_CAP = -2,
+ BATT_AACR_UNDER_CYCLES = -1,
+ BATT_AACR_DISABLED = 0,
+ BATT_AACR_ENABLED = 1,
+ BATT_AACR_MAX,
+};
+
/* battery driver state */
struct batt_drv {
struct device *device;
@@ -294,7 +308,7 @@
struct batt_chg_health chg_health;
/* MSC charging */
- u32 battery_capacity;
+ u32 battery_capacity; /* in mAh */
struct gbms_chg_profile chg_profile;
union gbms_charger_state chg_state;
@@ -351,6 +365,11 @@
/* Battery pack info for Suez*/
char batt_pack_info[GBMS_MINF_LEN];
bool pack_info_ready;
+
+ /* AACR: Aged Adjusted Charging Rate */
+ enum batt_aacr_state aacr_state;
+ int aacr_cycle_grace;
+ int aacr_cycle_max;
};
static int batt_chg_tier_stats_cstr(char *buff, int size,
@@ -1140,8 +1159,7 @@
cev_stats_init(ce_data, &batt_drv->chg_profile);
batt_drv->ce_data.adapter_details.v = ad.v;
- vin = GPSY_GET_PROP(batt_drv->fg_psy,
- POWER_SUPPLY_PROP_VOLTAGE_NOW);
+ vin = GPSY_GET_PROP(batt_drv->fg_psy, POWER_SUPPLY_PROP_VOLTAGE_NOW);
ce_data->charging_stats.voltage_in = (vin < 0) ? -1 : vin / 1000;
ce_data->charging_stats.ssoc_in =
ssoc_get_capacity(&batt_drv->ssoc_state);
@@ -1594,7 +1612,7 @@
ce_data->adapter_details.ad_voltage * 100,
ce_data->adapter_details.ad_amperage * 100);
- logbuffer_log(log, "S: %hu,%hu, %hu,%hu %hu,%hu %ld,%ld",
+ logbuffer_log(log, "S: %hu,%hu, %hu,%hu %hu,%hu %ld,%ld, %u",
ce_data->charging_stats.ssoc_in,
ce_data->charging_stats.voltage_in,
ce_data->charging_stats.ssoc_out,
@@ -1602,7 +1620,8 @@
ce_data->charging_stats.cc_in,
ce_data->charging_stats.cc_out,
ce_data->first_update,
- ce_data->last_update);
+ ce_data->last_update,
+ ce_data->chg_profile->capacity_ma);
for (i = 0; i < GBMS_STATS_TIER_COUNT; i++) {
const int soc_next = batt_chg_stats_soc_next(ce_data, i);
@@ -2533,6 +2552,101 @@
return cc_max;
}
+/* same as design when under the grace period */
+static u32 aacr_get_reference_capacity(const struct batt_drv *batt_drv,
+ int cycle_count)
+{
+ const int design_capacity = batt_drv->battery_capacity;
+ const int aacr_cycle_grace = batt_drv->aacr_cycle_grace;
+ const int aacr_cycle_max = batt_drv->aacr_cycle_max;
+ int fade10;
+
+ fade10 = gbms_aacr_fade10(&batt_drv->chg_profile, cycle_count);
+ if (fade10 >= 0) {
+ /* use interpolation between known points */
+ } else if (aacr_cycle_max && (cycle_count > aacr_cycle_grace)) {
+ /* or use slope from ->aacr_cycle_grace for 20% @
+ * ->aacr_cycle_max
+ */
+ fade10 = (200 * (cycle_count - aacr_cycle_grace)) /
+ (aacr_cycle_max - aacr_cycle_grace);
+
+ pr_debug("%s: aacr_cycle_max=%d, cycle_count=%d fade10=%d\n",
+ __func__, aacr_cycle_max, cycle_count, fade10);
+ } else {
+ fade10 = 0;
+ }
+
+ return design_capacity - (design_capacity * fade10 / 1000);
+}
+
+/* 80% of design_capacity min, design_capacity in grace, aacr or negative */
+static int aacr_get_capacity_at_cycle(const struct batt_drv *batt_drv,
+ int cycle_count)
+{
+ const int design_capacity = batt_drv->battery_capacity; /* mAh */
+ const int min_capacity = (batt_drv->battery_capacity * 80) / 100;
+ int reference_capacity, full_cap_nom, full_capacity;
+ struct power_supply *fg_psy = batt_drv->fg_psy;
+ int aacr_capacity;
+
+ /* batt_drv->cycle_count might be negative */
+ if (cycle_count <= batt_drv->aacr_cycle_grace)
+ return design_capacity;
+
+ /* peg at 80% of design when over limit (if set) */
+ if (batt_drv->aacr_cycle_max &&
+ (cycle_count >= batt_drv->aacr_cycle_max))
+ return min_capacity;
+
+ reference_capacity = aacr_get_reference_capacity(batt_drv, cycle_count);
+ if (reference_capacity <= 0)
+ return design_capacity;
+
+ /* full_cap_nom in uAh, need to scale to mAh */
+ full_cap_nom = GPSY_GET_PROP(fg_psy, POWER_SUPPLY_PROP_CHARGE_FULL);
+ if (full_cap_nom < 0)
+ return full_cap_nom;
+
+ full_capacity = min(min(full_cap_nom / 1000, design_capacity),
+ reference_capacity);
+ aacr_capacity = max(full_capacity, min_capacity);
+ aacr_capacity = (aacr_capacity / 50) * 50; /* 50mAh, ~1% capacity */
+
+ pr_debug("%s: design=%d reference=%d full_cap_nom=%d, full=%d aacr=%d\n",
+ __func__, design_capacity, reference_capacity, full_cap_nom,
+ full_capacity, aacr_capacity);
+
+ return aacr_capacity;
+}
+
+/* design_capacity when not enabled, never a negative value */
+static u32 aacr_get_capacity(struct batt_drv *batt_drv)
+{
+ int capacity = batt_drv->battery_capacity;
+
+ if (batt_drv->aacr_state == BATT_AACR_DISABLED)
+ goto exit_done;
+
+ if (batt_drv->cycle_count <= batt_drv->aacr_cycle_grace) {
+ batt_drv->aacr_state = BATT_AACR_UNDER_CYCLES;
+ } else {
+ int aacr_capacity;
+
+ aacr_capacity = aacr_get_capacity_at_cycle(batt_drv,
+ batt_drv->cycle_count);
+ if (aacr_capacity < 0) {
+ batt_drv->aacr_state = BATT_AACR_INVALID_CAP;
+ } else {
+ batt_drv->aacr_state = BATT_AACR_ENABLED;
+ capacity = aacr_capacity;
+ }
+ }
+
+exit_done:
+ return (u32)capacity;
+}
+
/* TODO: factor msc_logic_irdop from the logic about tier switch */
static int msc_logic(struct batt_drv *batt_drv)
{
@@ -2584,7 +2698,9 @@
msc_state = MSC_SEED;
- /* seed voltage only on connect, book 0 time */
+ /* seed voltage and charging table only on connect,
+ * book 0 time
+ */
if (batt_drv->vbatt_idx == -1)
vbatt_idx = gbms_msc_voltage_idx(profile, vbatt);
@@ -2799,6 +2915,18 @@
ce_data->bd_clear_trickle = true;
}
+static void google_battery_dump_profile(const struct gbms_chg_profile *profile)
+{
+ char *buff;
+
+ buff = kzalloc(GBMS_CHG_ALG_BUF, GFP_KERNEL);
+ if (buff) {
+ gbms_dump_chg_profile(buff, GBMS_CHG_ALG_BUF, profile);
+ pr_info("%s", buff);
+ kfree(buff);
+ }
+}
+
/* called holding chg_lock */
static int batt_chg_logic(struct batt_drv *batt_drv)
{
@@ -2857,7 +2985,9 @@
/* here when connected to power supply */
if (batt_drv->ssoc_state.buck_enabled <= 0) {
+ struct device_node *node = batt_drv->device->of_node;
const qnum_t ssoc_delta = ssoc_get_delta(batt_drv);
+ u32 capacity;
/*
* FIX: BatteryDefenderUI needs use a different curve because
@@ -2872,6 +3002,13 @@
if (batt_drv->res_state.estimate_filter)
batt_res_state_set(&batt_drv->res_state, true);
+ capacity = aacr_get_capacity(batt_drv);
+ if (capacity != batt_drv->chg_profile.capacity_ma) {
+ gbms_init_chg_table(&batt_drv->chg_profile, node,
+ capacity);
+ google_battery_dump_profile(&batt_drv->chg_profile);
+ }
+
batt_chg_stats_start(batt_drv);
err = GPSY_SET_PROP(batt_drv->fg_psy,
POWER_SUPPLY_PROP_BATT_CE_CTRL,
@@ -3026,8 +3163,8 @@
/* charge profile not in battery */
static int batt_init_chg_profile(struct batt_drv *batt_drv)
{
- struct device_node *node = batt_drv->device->of_node;
struct gbms_chg_profile *profile = &batt_drv->chg_profile;
+ struct device_node *node = batt_drv->device->of_node;
int ret = 0;
/* handle retry */
@@ -3037,6 +3174,7 @@
return -EINVAL;
}
+ /* this is in mAh */
ret = of_property_read_u32(node, "google,chg-battery-capacity",
&batt_drv->battery_capacity);
if (ret < 0)
@@ -3052,7 +3190,7 @@
if (batt_drv->batt_present) {
fc = GPSY_GET_PROP(fg_psy,
- POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN);
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN);
if (fc == -EAGAIN)
return -EPROBE_DEFER;
if (fc > 0) {
@@ -3072,12 +3210,17 @@
if (ret < 0)
pr_warn("battery not present, no default capacity, zero charge table\n");
else
- pr_warn("battery not present, using default capacity:\n");
+ pr_warn("battery not present, using default capacity\n");
}
}
+ /* aacr tables enable AACR by default UNLESS explicitly disabled */
+ ret = of_property_read_bool(node, "google,aacr-disable");
+ if (!ret && profile->aacr_nb_limits)
+ batt_drv->aacr_state = BATT_AACR_ENABLED;
+
/* NOTE: with NG charger tolerance is applied from "charger" */
- gbms_init_chg_table(&batt_drv->chg_profile, batt_drv->battery_capacity);
+ gbms_init_chg_table(profile, node, aacr_get_capacity(batt_drv));
return 0;
}
@@ -3497,6 +3640,77 @@
debug_chg_health_set_stage, "%u\n");
#endif
+/* debug variable */
+static int raw_profile_cycles;
+
+static ssize_t debug_get_chg_raw_profile(struct file *filp,
+ char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct batt_drv *batt_drv = (struct batt_drv *)filp->private_data;
+ char *tmp;
+ int len;
+
+ tmp = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+
+ if (raw_profile_cycles) {
+ struct gbms_chg_profile profile;
+ int count;
+
+ len = gbms_init_chg_profile(&profile,
+ batt_drv->device->of_node);
+ if (len < 0)
+ goto exit_done;
+
+ /* len is the capacity */
+ len = aacr_get_capacity_at_cycle(batt_drv, raw_profile_cycles);
+ if (len <= 0) {
+ gbms_free_chg_profile(&profile);
+ goto exit_done;
+ }
+
+ count = scnprintf(tmp, PAGE_SIZE, "AACR Profile at %d cycles\n",
+ raw_profile_cycles);
+ gbms_init_chg_table(&profile, batt_drv->device->of_node, len);
+ gbms_dump_chg_profile(&tmp[count], PAGE_SIZE - count, &profile);
+ gbms_free_chg_profile(&profile);
+ } else {
+ gbms_dump_chg_profile(tmp, PAGE_SIZE, &batt_drv->chg_profile);
+ }
+
+ len = simple_read_from_buffer(buf, count, ppos, tmp, strlen(tmp));
+
+exit_done:
+ kfree(tmp);
+ return len;
+}
+
+static ssize_t debug_set_chg_raw_profile(struct file *filp,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ int ret = 0, val;
+ char buf[8];
+
+ ret = simple_write_to_buffer(buf, sizeof(buf), ppos, user_buf, count);
+ if (!ret)
+ return -EFAULT;
+
+ buf[ret] = '\0';
+ ret = kstrtoint(buf, 0, &val);
+ if (ret < 0)
+ return ret;
+
+ raw_profile_cycles = val;
+ return count;
+}
+
+BATTERY_DEBUG_ATTRIBUTE(debug_chg_raw_profile_fops,
+ debug_get_chg_raw_profile,
+ debug_set_chg_raw_profile);
+
/* ------------------------------------------------------------------------- */
static ssize_t charge_stats_actual_store(struct device *dev,
struct device_attribute *attr,
@@ -4266,6 +4480,93 @@
static DEVICE_ATTR_RW(health_safety_margin);
+static ssize_t aacr_state_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->aacr_state);
+}
+
+static ssize_t aacr_state_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 state, ret = 0;
+
+ ret = kstrtoint(buf, 0, &state);
+ if (ret < 0)
+ return ret;
+
+ if ((state != BATT_AACR_DISABLED) && (state != BATT_AACR_ENABLED))
+ return -ERANGE;
+
+ if (batt_drv->aacr_state == state)
+ return count;
+
+ batt_drv->aacr_state = state;
+ return count;
+}
+
+static DEVICE_ATTR_RW(aacr_state);
+
+static ssize_t aacr_cycle_grace_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->aacr_cycle_grace);
+}
+
+static ssize_t aacr_cycle_grace_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 = 0;
+
+ ret = kstrtoint(buf, 0, &value);
+ if (ret < 0)
+ return ret;
+
+ batt_drv->aacr_cycle_grace = value;
+ return count;
+}
+
+static DEVICE_ATTR_RW(aacr_cycle_grace);
+
+static ssize_t aacr_cycle_max_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->aacr_cycle_max);
+}
+
+static ssize_t aacr_cycle_max_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 = 0;
+
+ ret = kstrtoint(buf, 0, &value);
+ if (ret < 0)
+ return ret;
+
+ batt_drv->aacr_cycle_max = value;
+ return count;
+}
+
+static DEVICE_ATTR_RW(aacr_cycle_max);
+
static struct attribute *batt_attrs[] = {
&dev_attr_charge_stats.attr,
&dev_attr_charge_stats_actual.attr,
@@ -4286,6 +4587,9 @@
&dev_attr_bd_trickle_reset_sec.attr,
&dev_attr_bd_clear.attr,
&dev_attr_health_safety_margin.attr,
+ &dev_attr_aacr_state.attr,
+ &dev_attr_aacr_cycle_grace.attr,
+ &dev_attr_aacr_cycle_max.attr,
NULL,
};
@@ -4338,6 +4642,10 @@
batt_drv, &debug_chg_health_rest_rate_fops);
debugfs_create_file("chg_health_stage", 0600, de,
batt_drv, &debug_chg_health_stage_fops);
+
+ /* charging table */
+ debugfs_create_file("chg_raw_profile", 0644, de,
+ batt_drv, &debug_chg_raw_profile_fops);
}
#endif
@@ -5493,6 +5801,7 @@
dump_ssoc_state(&batt_drv->ssoc_state, batt_drv->ssoc_log);
+ /* chg_profile will use cycle_count when aacr is enabled */
ret = batt_init_chg_profile(batt_drv);
if (ret == -EPROBE_DEFER)
goto retry_init_work;
@@ -5500,7 +5809,7 @@
if (ret < 0) {
pr_err("charging profile disabled, ret=%d\n", ret);
} else if (batt_drv->battery_capacity) {
- gbms_dump_chg_profile(&batt_drv->chg_profile);
+ google_battery_dump_profile(&batt_drv->chg_profile);
}
cev_stats_init(&batt_drv->ce_data, &batt_drv->chg_profile);
@@ -5743,6 +6052,12 @@
} else {
thermal_zone_device_update(batt_drv->tz_dev, THERMAL_DEVICE_UP);
}
+
+ /* AACR server side */
+ batt_drv->aacr_cycle_grace = AACR_START_CYCLE_DEFAULT;
+ batt_drv->aacr_cycle_max = AACR_MAX_CYCLE_DEFAULT;
+ batt_drv->aacr_state = BATT_AACR_DISABLED;
+
/* give time to fg driver to start */
schedule_delayed_work(&batt_drv->init_work,
msecs_to_jiffies(BATT_DELAY_INIT_MS));
diff --git a/drivers/power/supply/google/google_bms.c b/drivers/power/supply/google/google_bms.c
index 57de959..4e6fdfc 100644
--- a/drivers/power/supply/google/google_bms.c
+++ b/drivers/power/supply/google/google_bms.c
@@ -82,14 +82,23 @@
* NOTE: the call covert C rates to chanrge currents IN PLACE, ie you cannot
* call this twice.
*/
-void gbms_init_chg_table(struct gbms_chg_profile *profile, u32 capacity_ma)
+void gbms_init_chg_table(struct gbms_chg_profile *profile,
+ struct device_node *node, u32 capacity_ma)
{
u32 ccm;
- int vi, ti;
+ int vi, ti, ret;
const int fv_uv_step = profile->fv_uv_resolution;
+ u32 cccm_array_size = (profile->temp_nb_limits - 1)
+ * profile->volt_nb_limits;
profile->capacity_ma = capacity_ma;
+ ret = of_property_read_u32_array(node, "google,chg-cc-limits",
+ (u32 *)profile->cccm_limits,
+ cccm_array_size);
+ if (ret < 0)
+ pr_warn("unable to get default cccm_limits.\n");
+
/* chg-battery-capacity is in mAh, chg-cc-limits relative to 100 */
for (ti = 0; ti < profile->temp_nb_limits - 1; ti++) {
for (vi = 0; vi < profile->volt_nb_limits; vi++) {
@@ -159,6 +168,85 @@
return 0;
}
+static int gbms_read_aacr_limits(struct gbms_chg_profile *profile,
+ struct device_node *node)
+{
+ int ret = 0, cycle_nb_limits = 0, fade10_nb_limits = 0;
+
+ ret = of_property_count_elems_of_size(node,
+ "google,aacr-ref-cycles",
+ sizeof(u32));
+ if (ret < 0)
+ goto no_data;
+
+ cycle_nb_limits = ret;
+
+ ret = of_property_count_elems_of_size(node,
+ "google,aacr-ref-fade10",
+ sizeof(u32));
+ if (ret < 0)
+ goto no_data;
+
+ fade10_nb_limits = ret;
+
+ if (cycle_nb_limits != fade10_nb_limits ||
+ cycle_nb_limits > GBMS_AACR_DATA_MAX ||
+ cycle_nb_limits == 0) {
+ gbms_warn(profile,
+ "aacr not enable, cycle_nb:%d, fade10_nb:%d, max:%d",
+ cycle_nb_limits, fade10_nb_limits,
+ GBMS_AACR_DATA_MAX);
+ profile->aacr_nb_limits = 0;
+ return -ERANGE;
+ }
+
+ ret = of_property_read_u32_array(node, "google,aacr-ref-cycles",
+ (u32 *)profile->reference_cycles,
+ cycle_nb_limits);
+ if (ret < 0)
+ return ret;
+
+ ret = of_property_read_u32_array(node, "google,aacr-ref-fade10",
+ (u32 *)profile->reference_fade10,
+ fade10_nb_limits);
+ if (ret < 0)
+ return ret;
+
+ profile->aacr_nb_limits = cycle_nb_limits;
+
+ return 0;
+
+no_data:
+ profile->aacr_nb_limits = 0;
+ return ret;
+}
+
+/* return pct amount of capacity fade at cycles or negative if not enabled */
+int gbms_aacr_fade10(const struct gbms_chg_profile *profile, int cycles)
+{
+ int cycle_s = 0, fade_s = 0;
+ int idx, cycle_f, fade_f;
+
+ if (profile->aacr_nb_limits == 0 || cycles < 0)
+ return -EINVAL;
+
+ for (idx = 0; idx < profile->aacr_nb_limits; idx++)
+ if (cycles < profile->reference_cycles[idx])
+ break;
+
+ /* Interpolation */
+ cycle_f = profile->reference_cycles[idx];
+ fade_f = profile->reference_fade10[idx];
+ if (idx > 0) {
+ cycle_s = profile->reference_cycles[idx - 1];
+ fade_s = profile->reference_fade10[idx - 1];
+ }
+
+ return (cycles - cycle_s) * (fade_f - fade_s) / (cycle_f - cycle_s)
+ + fade_s;
+}
+EXPORT_SYMBOL_GPL(gbms_aacr_fade10);
+
int gbms_init_chg_profile_internal(struct gbms_chg_profile *profile,
struct device_node *node,
const char *owner_name)
@@ -172,6 +260,11 @@
if (ret < 0)
return ret;
+ /* TODO: dump the AACR table if supported */
+ ret = gbms_read_aacr_limits(profile, node);
+ if (ret == 0)
+ gbms_info(profile, "AACR: supported\n");
+
cccm_array_size = (profile->temp_nb_limits - 1)
* profile->volt_nb_limits;
mem_size = sizeof(s32) * cccm_array_size;
@@ -276,23 +369,22 @@
}
/* NOTE: I should really pass the scale */
-void gbms_dump_raw_profile(const struct gbms_chg_profile *profile, int scale)
+void gbms_dump_raw_profile(char *buff, size_t len,
+ const struct gbms_chg_profile *profile, int scale)
{
const int tscale = (scale == 1) ? 1 : 10;
- /* with scale == 1 voltage takes 7 bytes, add 7 bytes of temperature */
- char buff[GBMS_CHG_VOLT_NB_LIMITS_MAX * 9 + 7];
- int ti, vi, count, len = sizeof(buff);
+ int ti, vi, count = 0;
- gbms_info(profile, "Profile constant charge limits:\n");
- count = 0;
+ count += scnprintf(buff + count, len - count,
+ "Profile constant charge limits:\n");
+ count += scnprintf(buff + count, len - count, "|T \\ V");
for (vi = 0; vi < profile->volt_nb_limits; vi++) {
count += scnprintf(buff + count, len - count, " %4d",
profile->volt_limits[vi] / scale);
}
- gbms_info(profile, "|T \\ V%s\n", buff);
+ count += scnprintf(buff + count, len - count, "\n");
for (ti = 0; ti < profile->temp_nb_limits - 1; ti++) {
- count = 0;
count += scnprintf(buff + count, len - count, "|%2d:%2d",
profile->temp_limits[ti] / tscale,
profile->temp_limits[ti + 1] / tscale);
@@ -301,7 +393,7 @@
GBMS_CCCM_LIMITS(profile, ti, vi)
/ scale);
}
- gbms_info(profile, "%s\n", buff);
+ count += scnprintf(buff + count, len - count, "\n");
}
}
diff --git a/drivers/power/supply/google/google_bms.h b/drivers/power/supply/google/google_bms.h
index d574041..fa5247f5 100644
--- a/drivers/power/supply/google/google_bms.h
+++ b/drivers/power/supply/google/google_bms.h
@@ -17,6 +17,7 @@
#ifndef __GOOGLE_BMS_H_
#define __GOOGLE_BMS_H_
+#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/power_supply.h>
#include "qmath.h"
@@ -26,6 +27,8 @@
#define GBMS_CHG_TEMP_NB_LIMITS_MAX 10
#define GBMS_CHG_VOLT_NB_LIMITS_MAX 6
+#define GBMS_CHG_ALG_BUF 500
+#define GBMS_AACR_DATA_MAX 10
struct gbms_chg_profile {
const char *owner_name;
@@ -53,6 +56,11 @@
u32 fv_uv_resolution;
/* experimental */
u32 cv_otv_margin;
+
+ /* AACR feature */
+ u32 reference_cycles[GBMS_AACR_DATA_MAX];
+ u32 reference_fade10[GBMS_AACR_DATA_MAX];
+ u32 aacr_nb_limits;
};
#define WLC_BPP_THRESHOLD_UV 700000
@@ -359,12 +367,15 @@
#define gbms_init_chg_profile(p, n) \
gbms_init_chg_profile_internal(p, n, KBUILD_MODNAME)
-void gbms_init_chg_table(struct gbms_chg_profile *profile, u32 capacity);
+void gbms_init_chg_table(struct gbms_chg_profile *profile,
+ struct device_node *node, u32 capacity);
void gbms_free_chg_profile(struct gbms_chg_profile *profile);
-void gbms_dump_raw_profile(const struct gbms_chg_profile *profile, int scale);
-#define gbms_dump_chg_profile(profile) gbms_dump_raw_profile(profile, 1000)
+void gbms_dump_raw_profile(char *buff, size_t len,
+ const struct gbms_chg_profile *profile, int scale);
+#define gbms_dump_chg_profile(buff, len, profile) \
+ gbms_dump_raw_profile(buff, len, profile, 1000)
/* newgen charging: charge profile */
int gbms_msc_temp_idx(const struct gbms_chg_profile *profile, int temp);
@@ -379,6 +390,9 @@
struct power_supply *chg_psy,
struct power_supply *wlc_psy);
+/* calculate aacr reference capacity */
+int gbms_aacr_fade10(const struct gbms_chg_profile *profile, int cycles);
+
/* debug/print */
const char *gbms_chg_type_s(int chg_type);
const char *gbms_chg_status_s(int chg_status);