Init the google-modules/bms codebase

Porting driver/power/supply/google/* from
s-dev-gs-pixel-4.19 branch. The last commit ID is
c030bdb806ef12bfed9d3f33ed0a783cbff269d5

Bug: 160835098
Change-Id: I14a6204dcd9cefa3aecad825e8dfeb8d8c97e61e
Signed-off-by: Ken Tsou <[email protected]>
diff --git a/google_eeprom.c b/google_eeprom.c
new file mode 100644
index 0000000..7a0c897
--- /dev/null
+++ b/google_eeprom.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2018 Google, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/pm_runtime.h>
+#include <linux/nvmem-consumer.h>
+#include "google_bms.h"
+
+#define BATT_TOTAL_HIST_LEN	928
+#define BATT_ONE_HIST_LEN	28
+#define BATT_MAX_HIST_CNT	\
+		(BATT_TOTAL_HIST_LEN / BATT_ONE_HIST_LEN) // 33.14
+
+#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_DINF_OFFSET	0x20
+#define BATT_EEPROM_TAG_DINF_LEN	GBMS_DINF_LEN
+#define BATT_EEPROM_TAG_BCNT_OFFSET	0x40
+#define BATT_EEPROM_TAG_BCNT_LEN	(GBMS_CCBIN_BUCKET_COUNT * 2)
+#define BATT_EEPROM_TAG_GMSR_OFFSET	0x54
+#define BATT_EEPROM_TAG_GMSR_LEN	GBMS_GMSR_LEN
+#define BATT_EEPROM_TAG_HIST_OFFSET	0x6A
+#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 int gbee_storage_info(gbms_tag_t tag, size_t *addr, size_t *count,
+			    void *ptr)
+{
+	int ret = 0;
+
+	switch (tag) {
+	case GBMS_TAG_MINF:
+		*addr = BATT_EEPROM_TAG_MINF_OFFSET;
+		*count = BATT_EEPROM_TAG_MINF_LEN;
+		break;
+	case GBMS_TAG_DINF:
+		*addr = BATT_EEPROM_TAG_DINF_OFFSET;
+		*count = BATT_EEPROM_TAG_DINF_LEN;
+		break;
+	case GBMS_TAG_HIST:
+		*addr = BATT_EEPROM_TAG_HIST_OFFSET;
+		*count = BATT_EEPROM_TAG_HIST_LEN;
+		break;
+	case GBMS_TAG_SNUM:
+	case GBMS_TAG_BGPN:
+		*addr = BATT_EEPROM_TAG_BGPN_OFFSET;
+		*count = BATT_EEPROM_TAG_BGPN_LEN;
+		break;
+	case GBMS_TAG_GMSR:
+		*addr = BATT_EEPROM_TAG_GMSR_OFFSET;
+		*count = BATT_EEPROM_TAG_GMSR_LEN;
+		break;
+	case GBMS_TAG_BCNT:
+		*addr = BATT_EEPROM_TAG_BCNT_OFFSET;
+		*count = BATT_EEPROM_TAG_BCNT_LEN;
+		break;
+	default:
+		ret = -ENOENT;
+		break;
+	}
+
+	return ret;
+}
+
+static int gbee_storage_iter(int index, gbms_tag_t *tag, void *ptr)
+{
+	static gbms_tag_t keys[] = { GBMS_TAG_BGPN, GBMS_TAG_MINF,
+				     GBMS_TAG_DINF, GBMS_TAG_HIST,
+				     GBMS_TAG_BRID, GBMS_TAG_SNUM,
+				     GBMS_TAG_GMSR, GBMS_TAG_BCNT };
+	const int count = ARRAY_SIZE(keys);
+
+	if (index < 0 || index >= count)
+		return -ENOENT;
+
+	*tag = keys[index];
+	return 0;
+}
+
+static int gbee_storage_read(gbms_tag_t tag, void *buff, size_t size,
+			    void *ptr)
+{
+	struct nvmem_device *nvmem = ptr;
+	size_t offset = 0, len = 0;
+	int ret;
+
+	if (tag == GBMS_TAG_BRID) {
+		u8 temp;
+
+		if (size != sizeof(u32))
+			return -ENOMEM;
+
+		ret = nvmem_device_read(nvmem, BATT_EEPROM_TAG_BRID_OFFSET,
+					1, &temp);
+		pr_err("cannot read nvram %d\n", ret);
+		if (ret < 0)
+			return ret;
+
+		((u32*)buff)[0] = temp;
+		return len;
+	}
+
+	ret = gbee_storage_info(tag, &offset, &len, ptr);
+	if (ret < 0)
+		return ret;
+	if (!len)
+		return -ENOENT;
+	if (len > size)
+		return -ENOMEM;
+
+	ret = nvmem_device_read(nvmem, offset, len, buff);
+	if (ret == 0)
+		ret = len;
+
+	return ret;
+}
+
+static int gbee_storage_write(gbms_tag_t tag, const void *buff, size_t size,
+			      void *ptr)
+{
+	struct nvmem_device *nvmem = ptr;
+	size_t offset = 0, len = 0;
+	int ret;
+
+	if ((tag != GBMS_TAG_DINF) && (tag != GBMS_TAG_GMSR) &&
+	    (tag != GBMS_TAG_BCNT))
+		return -ENOENT;
+
+	ret = gbee_storage_info(tag, &offset, &len, ptr);
+	if (ret < 0)
+		return ret;
+	if (size > len)
+		return -ENOMEM;
+
+	ret = nvmem_device_write(nvmem, offset, size, (void *)buff);
+	if (ret == 0)
+		ret = size;
+
+	return ret;
+}
+
+static int gbee_storage_read_data(gbms_tag_t tag, void *data, size_t count,
+				  int idx, void *ptr)
+{
+	struct nvmem_device *nvmem = ptr;
+	size_t offset = 0, len = 0;
+	int ret;
+
+	switch (tag) {
+	case GBMS_TAG_HIST:
+		ret = gbee_storage_info(tag, &offset, &len, ptr);
+		break;
+	default:
+		ret = -ENOENT;
+		break;
+	}
+
+	if (ret < 0)
+		return ret;
+
+	if (!data || !count) {
+		if (idx == GBMS_STORAGE_INDEX_INVALID)
+			return 0;
+		else
+			return BATT_MAX_HIST_CNT;
+	}
+
+	if (idx < 0)
+		return -EINVAL;
+
+	/* index == 0 is ok here */
+	if (idx >= BATT_MAX_HIST_CNT)
+		return -ENODATA;
+
+	if (len > count)
+		return -EINVAL;
+
+	offset += len * idx;
+
+	ret = nvmem_device_read(nvmem, offset, len, data);
+	if (ret == 0)
+		ret = len;
+
+	return ret;
+}
+
+static int gbee_storage_write_data(gbms_tag_t tag, const void *data,
+				   size_t count, int idx, void *ptr)
+{
+	struct nvmem_device *nvmem = ptr;
+	size_t offset = 0, len = 0;
+	int ret;
+
+	switch (tag) {
+	case GBMS_TAG_HIST:
+		ret = gbee_storage_info(tag, &offset, &len, ptr);
+		break;
+	default:
+		ret = -ENOENT;
+		break;
+	}
+
+	if (ret < 0)
+		return ret;
+
+	if (idx < 0 || !data || !count)
+		return -EINVAL;
+
+	/* index == 0 is ok here */
+	if (idx >= BATT_MAX_HIST_CNT)
+		return -ENODATA;
+
+	if (count > len)
+		return -EINVAL;
+
+	offset += len * idx;
+
+	ret = nvmem_device_write(nvmem, offset, len, (void *)data);
+	if (ret == 0)
+		ret = len;
+
+	return ret;
+}
+
+
+static struct gbms_storage_desc gbee_storage_dsc = {
+	.info = gbee_storage_info,
+	.iter = gbee_storage_iter,
+	.read = gbee_storage_read,
+	.write = gbee_storage_write,
+	.read_data = gbee_storage_read_data,
+	.write_data = gbee_storage_write_data,
+};
+
+/*
+ * Caller will use something like of_nvmem_device_get() to retrieve the
+ * nvmem_device instance.
+ * TODO: map nvram cells to tags
+ */
+int gbee_register_device(const char *name, struct nvmem_device *nvram)
+{
+	return gbms_storage_register(&gbee_storage_dsc, name, nvram);
+}
+
+void gbee_destroy_device(void)
+{
+
+}