google_battery: save swelling data into eeprom STRD

Restore and Save data through gbms_tag GBMS_TAG_STRD

Bug: 205000635
Signed-off-by: Jenny Ho <[email protected]>
Change-Id: Id7d6e92a058ae116514592aef6f975c5a1aa6c6d
diff --git a/google_battery.c b/google_battery.c
index 2be0b6e..2cf14ba 100644
--- a/google_battery.c
+++ b/google_battery.c
@@ -231,11 +231,27 @@
 };
 
 #define BATT_TEMP_RECORD_THR 3
+/* discharge saved after charge */
+#define SD_CHG_START 0
+#define SD_DISCHG_START BATT_TEMP_RECORD_THR
+#define BATT_SD_SAVE_SIZE (BATT_TEMP_RECORD_THR * 2)
+#define BATT_SD_MAX_HOURS 15120 // 90 weeks
 struct swelling_data {
 	/* Time in different temperature */
 	bool is_enable;
 	u32 temp_thr[BATT_TEMP_RECORD_THR];
 	u32 soc_thr[BATT_TEMP_RECORD_THR];
+	/*
+	 * cumulative time array format:
+	 * | saved  | 0                | 1                | 2                |
+	 * |--------| Charge           | Charge           | Charge           |
+	 * | Content| > 30degC & > 90% | > 35degC & > 90% | > 40degC & > 95% |
+	 *
+	 * | saved  | 3                | 4                | 5                |
+	 * |--------| Discharge        | Discharge        | Discharge        |
+	 * | Content| > 30degC & > 90% | > 35degC & > 90% | > 40degC & > 95% |
+	 */
+	u16 saved[BATT_SD_SAVE_SIZE];
 	ktime_t chg[BATT_TEMP_RECORD_THR];
 	ktime_t dischg[BATT_TEMP_RECORD_THR];
 	ktime_t last_update;
@@ -5611,6 +5627,40 @@
 	return 0;
 }
 
+/* save data in hours */
+#define SAVE_UNIT 3600
+static void gbatt_save_sd(struct swelling_data *sd)
+{
+	u16 sd_saved[BATT_SD_SAVE_SIZE];
+	bool update_save_data = false;
+	int i, j, ret = 0;
+
+	/* Change seconds to hours */
+	for (i = 0; i < BATT_TEMP_RECORD_THR; i++) {
+		j = i + SD_DISCHG_START;
+
+		sd_saved[i] = sd->chg[i] / SAVE_UNIT < BATT_SD_MAX_HOURS ?
+			      sd->chg[i] / SAVE_UNIT : BATT_SD_MAX_HOURS;
+
+		sd_saved[j] = sd->dischg[i] / SAVE_UNIT < BATT_SD_MAX_HOURS ?
+			      sd->dischg[i] / SAVE_UNIT : BATT_SD_MAX_HOURS;
+
+		if (sd_saved[i] > sd->saved[i] ||
+		    sd_saved[j] > sd->saved[j]) {
+			sd->saved[i] = sd_saved[i];
+			sd->saved[j] = sd_saved[j];
+			update_save_data = true;
+		}
+	}
+
+	if (!update_save_data)
+		return;
+
+	ret = gbms_storage_write(GBMS_TAG_STRD, &sd->saved, sizeof(sd->saved));
+	if (ret < 0)
+		pr_warn("Failed to save swelling data, ret=%d\n", ret);
+}
+
 static void gbatt_record_over_temp(struct batt_drv *batt_drv)
 {
 	struct swelling_data *sd = &batt_drv->sd;
@@ -5621,10 +5671,18 @@
 	const int temp = batt_drv->batt_temp;
 	const int soc = ssoc_get_real(ssoc_state);
 	const ktime_t now = get_boot_sec();
-	ktime_t elap = now - sd->last_update;
+	const ktime_t elap = now - sd->last_update;
+	bool update_data = false;
 	int i;
 
 	for (i = 0; i < BATT_TEMP_RECORD_THR; i++) {
+		/*
+		 *  thresholds table:
+		 *  | i        | 0      | 1      | 2      |
+		 *  |----------|--------|--------|--------|
+		 *  | temp_thr | 30degC | 35degC | 40degC |
+		 *  | soc_thr  | 90%    | 90%    | 95%    |
+		 */
 		if (temp < sd->temp_thr[i] || soc < sd->soc_thr[i])
 			continue;
 
@@ -5632,8 +5690,13 @@
 			sd->chg[i] += elap;
 		else
 			sd->dischg[i] += elap;
+
+		update_data = true;
 	}
 
+	if (update_data)
+		gbatt_save_sd(&batt_drv->sd);
+
 	sd->last_update = now;
 }
 
@@ -6369,6 +6432,34 @@
 		 batt_drv->blf_state, cnt);
 }
 
+static int batt_init_sd(struct swelling_data *sd)
+{
+	int ret = 0, i, j;
+
+	if (!sd->is_enable)
+		return 0;
+
+	ret = gbms_storage_read(GBMS_TAG_STRD, &sd->saved,
+				sizeof(sd->saved));
+	if (ret < 0)
+		return ret;
+
+	if (sd->saved[SD_CHG_START] == 0xFFFF) {
+		/* Empty EEPROM, initial sd_saved */
+		for (i = 0; i < BATT_SD_SAVE_SIZE; i++)
+			sd->saved[i] = 0;
+	} else {
+		/* Available data, restore */
+		for (i = 0; i < BATT_TEMP_RECORD_THR; i++) {
+			j = i + SD_DISCHG_START;
+			sd->chg[i] = sd->saved[i] * SAVE_UNIT;
+			sd->dischg[i] = sd->saved[j] * SAVE_UNIT;
+		}
+	}
+
+	return ret;
+}
+
 static void google_battery_init_work(struct work_struct *work)
 {
 	struct batt_drv *batt_drv = container_of(work, struct batt_drv,
@@ -6457,6 +6548,12 @@
 			batt_drv->sd.is_enable = true;
 	}
 
+	ret = batt_init_sd(&batt_drv->sd);
+	if (ret < 0) {
+		pr_err("Unable to read swelling data, ret=%d\n", ret);
+		batt_drv->sd.is_enable = false;
+	}
+
 	/* cycle count is cached: read here bc SSOC, chg_profile might use it */
 	batt_update_cycle_count(batt_drv);