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/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)