google_eeprom: support for lotr updates

Bug: 203465508
Signed-off-by: AleX Pelosi <[email protected]>
Change-Id: I32e84dd2901131b300d76fd4fb87ec70c68af65d
Signed-off-by: Jack Wu <[email protected]>
diff --git a/gbms_storage.h b/gbms_storage.h
index 7157b16..2c1bd52 100644
--- a/gbms_storage.h
+++ b/gbms_storage.h
@@ -40,9 +40,19 @@
 /* Gauge Model State Restore */
 #define GBMS_GMSR_LEN	23
 
+/* TODO: link to the structure used to save this*/
+#define BATT_ONE_HIST_LEN	12
+/* TODO: this depends on the EEPROM size */
+#define BATT_TOTAL_HIST_LEN	924
+/* TODO: this depends on the EEPROM size */
+#define BATT_MAX_HIST_CNT	\
+		(BATT_TOTAL_HIST_LEN / BATT_ONE_HIST_LEN) // 77
+
 
 #define GBMS_CCBIN_BUCKET_COUNT	10
 
+/* Adds BPST and STRD */
+#define GBMS_LOTR_DEFAULT 0xff
 #define GBMS_LOTR_V1 1
 
 /*
@@ -55,9 +65,10 @@
 	GBMS_TAG_BCNT = 0x42434e54,
 	GBMS_TAG_BGCE = 0x42474345,
 	GBMS_TAG_BGPN = 0x4247504e,
-	GBMS_TAG_BPST = 0x42505354,
+	GBMS_TAG_BPST = 0x42505354, /* LOTRV1: health or spare */
 	GBMS_TAG_BRES = 0x42524553,
 	GBMS_TAG_BRID = 0x42524944,
+	GBMS_TAG_CELC = 0x43454C43,
 	GBMS_TAG_CLHI = 0x424C4849,
 	GBMS_TAG_CMPC = 0x434d5043,
 	GBMS_TAG_CNHS = 0x434E4853,
@@ -69,6 +80,8 @@
 	GBMS_TAG_HIST = 0x48495354,
 	GBMS_TAG_LOTR = 0x4C4F5452,
 	GBMS_TAG_MINF = 0x4d494e46,
+	GBMS_TAG_MXSN = 0x4d58534e,
+	GBMS_TAG_MXCN = 0x4d58434e,
 
 	/* User Space Read/Write scratch */
 	GBMS_TAG_RS32 = 0x52533332,
@@ -87,12 +100,10 @@
 
 	GBMS_TAG_RAVG = 0x52415647,
 	GBMS_TAG_RFCN = 0x5246434e,
-	GBMS_TAG_SNUM = 0x534e554d,
-	GBMS_TAG_MXSN = 0x4d58534e,
-	GBMS_TAG_MXCN = 0x4d58434e,
-
 	GBMS_TAG_SELC = 0x53454C43,
-	GBMS_TAG_CELC = 0x43454C43,
+	GBMS_TAG_SNUM = 0x534e554d,
+
+	GBMS_TAG_STRD = 0x53545244, /* LOTRV1: Swelling data */
 };
 
 /*
diff --git a/google_eeprom.c b/google_eeprom.c
index cb75ec3..20fec14 100644
--- a/google_eeprom.c
+++ b/google_eeprom.c
@@ -9,21 +9,19 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": %s " fmt, __func__
 
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/pm_runtime.h>
 #include <linux/nvmem-consumer.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include "gbms_storage.h"
 
-#define BATT_TOTAL_HIST_LEN	924
-#define BATT_ONE_HIST_LEN	12
-#define BATT_MAX_HIST_CNT	\
-		(BATT_TOTAL_HIST_LEN / BATT_ONE_HIST_LEN) // 77
-
-#define BATT_EEPROM_TAG_BRID_OFFSET	0x17
-#define BATT_EEPROM_TAG_BRID_LEN	1
 #define BATT_EEPROM_TAG_MINF_OFFSET	0x00
 #define BATT_EEPROM_TAG_MINF_LEN	GBMS_MINF_LEN
+#define BATT_EEPROM_TAG_BGPN_OFFSET	0x03
+#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_DINF_OFFSET	0x1E
 #define BATT_EEPROM_TAG_DINF_LEN	GBMS_DINF_LEN
 #define BATT_EEPROM_TAG_BCNT_OFFSET	0x2E
@@ -38,10 +36,9 @@
 #define BATT_EEPROM_TAG_SELC_LEN	1
 #define BATT_EEPROM_TAG_CELC_OFFSET	0x5D
 #define BATT_EEPROM_TAG_CELC_LEN	1
+
 #define BATT_EEPROM_TAG_HIST_OFFSET	0x5E
 #define BATT_EEPROM_TAG_HIST_LEN	BATT_ONE_HIST_LEN
-#define BATT_EEPROM_TAG_BGPN_OFFSET	0x03
-#define BATT_EEPROM_TAG_BGPN_LEN	GBMS_BGPN_LEN
 
 static struct gbms_storage_desc *gbee_desc;
 
@@ -303,22 +300,78 @@
 	.write_data = gbee_storage_write_data,
 };
 
-/* LOTR in a fixed position */
-static int gbms_lotr_update(struct nvmem_device *nvmem, int lotr)
+/* TODO: factor history mechanics out of google battery? */
+static int gbms_hist_move(struct nvmem_device *nvmem, int from, int to, int len)
 {
-	int ret, lotr_ver = 0;
+	u8 *buff, *p;
+	int index, ret;
+
+	buff = kzalloc(len, GFP_KERNEL);
+	if (!buff)
+		return -ENOMEM;
+
+	/* move only the entries that are used */
+	p = buff;
+	for (index = 0; index < BATT_MAX_HIST_CNT; index++) {
+		ret = nvmem_device_read(nvmem, from, BATT_ONE_HIST_LEN, p);
+		if (ret < 0) {
+			pr_err("%s: cannot read history data (%d)\n", __func__, ret);
+			goto exit;
+		}
+
+		/* verify 1st byte for tempco */
+		if (*p == 0xff)
+			break;
+		/* move to next history entry */
+		from += BATT_ONE_HIST_LEN;
+		p += BATT_ONE_HIST_LEN;
+	}
+
+	ret = nvmem_device_write(nvmem, to, (BATT_ONE_HIST_LEN * index), buff);
+	if (ret < 0)
+		pr_err("%s: cannot write history data (%d)\n", __func__, ret);
+
+exit:
+	kfree(buff);
+	return ret;
+}
+
+/* LOTR is in a fixed position, move  */
+static int gbms_lotr_update(struct nvmem_device *nvmem, int lotr_to)
+{
+	int ret, lotr_from = 0;
+	static u8 init_data[5]= { 0 };
 
 	ret = nvmem_device_read(nvmem, BATT_EEPROM_TAG_LOTR_OFFSET,
-				BATT_EEPROM_TAG_LOTR_LEN, &lotr_ver);
-	if (ret < 0 || lotr_ver == lotr)
+				BATT_EEPROM_TAG_LOTR_LEN, &lotr_from);
+	if (ret < 0 || lotr_from == lotr_to)
 		return ret;
 
-	/* TODO: convert one layout to the other */
-	/* eg: zero history when moving from 0xff to 0x01 */
+	if (lotr_to != GBMS_LOTR_V1 || lotr_from != GBMS_LOTR_DEFAULT)
+		return 0;
+
+	ret = gbms_hist_move(nvmem, 0x5E, 0x64, BATT_TOTAL_HIST_LEN);
+	if (ret < 0) {
+		pr_err("%s: cannot move history\n", __func__);
+		return ret;
+		/* TODO: flag this in BPST? */
+	}
+
+	ret = nvmem_device_write(nvmem, 0x5E, sizeof(init_data), init_data);
+	if (ret != sizeof(init_data)) {
+		pr_err("%s: cannot init new fields\n", __func__);
+		return ret < 0 ? ret : -EINVAL;
+	}
+
+	/* TODO: how do we handle backporting? */
 
 	/* now write lotr to the right place */
-	return nvmem_device_write(nvmem, BATT_EEPROM_TAG_LOTR_OFFSET,
-				  BATT_EEPROM_TAG_LOTR_LEN, &lotr_ver);
+	ret = nvmem_device_write(nvmem, BATT_EEPROM_TAG_LOTR_OFFSET,
+				BATT_EEPROM_TAG_LOTR_LEN, &lotr_to);
+	if (ret == BATT_EEPROM_TAG_LOTR_LEN)
+		pr_info("%s: lotr migrated %d->%d\n", __func__, lotr_from, lotr_to);
+
+	return ret;
 }
 
 static struct gbms_storage_desc *gbms_lotr_2_dsc(int lotr_ver)
diff --git a/google_eeprom_01.c b/google_eeprom_01.c
index a833feb..c96fdf9 100644
--- a/google_eeprom_01.c
+++ b/google_eeprom_01.c
@@ -15,17 +15,18 @@
 #include <linux/delay.h>
 #include "gbms_storage.h"
 
-#define BATT_TOTAL_HIST_LEN	924
-#define BATT_ONE_HIST_LEN	12
-#define BATT_MAX_HIST_CNT	\
-		(BATT_TOTAL_HIST_LEN / BATT_ONE_HIST_LEN) // 77
-
+/* battery health */
 #define BATT_EEPROM_TAG_BPST_OFFSET	0x5E
 #define BATT_EEPROM_TAG_BPST_LEN	1
+/* swelling data */
+#define BATT_EEPROM_TAG_STRD_OFFSET	0x5F
+#define BATT_EEPROM_TAG_STRD_LEN	4
+
+/* */
 #define BATT_EEPROM_TAG_HIST_OFFSET	0x64
 #define BATT_EEPROM_TAG_HIST_LEN	BATT_ONE_HIST_LEN
 
-/* add GBMS_TAG_BPST a target specific entry */
+/* Add GBMS_TAG_BPST and GBMS_TAG_STRD move down history */
 int gbee_storage01_info(gbms_tag_t tag, size_t *addr, size_t *count, void *ptr)
 {
 	int ret = 0;
@@ -35,6 +36,10 @@
 		*addr = BATT_EEPROM_TAG_BPST_OFFSET;
 		*count = BATT_EEPROM_TAG_BPST_LEN;
 		break;
+	case GBMS_TAG_STRD:
+		*addr = BATT_EEPROM_TAG_STRD_OFFSET;
+		*count = BATT_EEPROM_TAG_STRD_LEN;
+		break;
 	case GBMS_TAG_HIST:
 		*addr = BATT_EEPROM_TAG_HIST_OFFSET;
 		*count = BATT_EEPROM_TAG_HIST_LEN;
@@ -56,7 +61,7 @@
 					   GBMS_TAG_GMSR, GBMS_TAG_BCNT,
 					   GBMS_TAG_CNHS, GBMS_TAG_SELC,
 					   GBMS_TAG_CELC, GBMS_TAG_LOTR,
-					   GBMS_TAG_BPST };
+					   GBMS_TAG_BPST, GBMS_TAG_STRD };
 	const int max = ARRAY_SIZE(keys);
 
 	if (index < 0 || index >= max)