km: qrio: add access functions for ebootcount

The EBOOTCNT is a reserved persistent static memory area in QRIO,
and similar to BOOTCNT is intended to be used as boot counter location.

Comparable to BOOTCNT that is reserved for u-boot main bootcount
infrastructure, EBOOTCNT is intended to be used for pg-wcom board
specific purposes (e.g implementing early boot counter for fail-safe
u-boot update).

Signed-off-by: Aleksandar Gerasimovski <aleksandar.gerasimovski@hitachienergy.com>
Reviewed-by: Priyanka Jain <priyanka.jain@nxp.com>
diff --git a/board/keymile/common/common.h b/board/keymile/common/common.h
index 15a3c37..fc14728 100644
--- a/board/keymile/common/common.h
+++ b/board/keymile/common/common.h
@@ -133,6 +133,9 @@
 
 int set_km_env(void);
 
+ulong early_bootcount_load(void);
+void early_bootcount_store(ulong ebootcount);
+
 #define DELAY_ABORT_SEQ		62  /* @200kHz 9 clocks = 44us, 62us is ok */
 #define DELAY_HALF_PERIOD	(500 / (CONFIG_SYS_I2C_SPEED / 1000))
 
diff --git a/board/keymile/common/qrio.c b/board/keymile/common/qrio.c
index 89a9726..5401bdd 100644
--- a/board/keymile/common/qrio.c
+++ b/board/keymile/common/qrio.c
@@ -270,6 +270,44 @@
 	out_8(qrio_base + RSTCFG_OFF, rstcfg);
 }
 
+/* Early bootcount memory area is avilable starting from QRIO3 Rev.2 */
+#define QRIO3_ID		0x71
+#define QRIO3_REV		0x02
+#define EBOOTCNT_OFF		0x28
+
+ulong early_bootcount_load(void)
+{
+	void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE;
+	u16 id_rev = in_be16(qrio_base + ID_REV_OFF);
+	u8 id = (id_rev >> 8) & 0xff;
+	u8 rev = id_rev & 0xff;
+	u32 ebootcount = 0;
+
+	if (id == QRIO3_ID && rev >= QRIO3_REV) {
+		ebootcount = in_be32(qrio_base + EBOOTCNT_OFF);
+	} else {
+		printf("QRIO: warning: early bootcount not supported, ");
+		printf("id = %u, rev = %u\n", id, rev);
+	}
+
+	return ebootcount;
+}
+
+void early_bootcount_store(ulong ebootcount)
+{
+	void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE;
+	u16 id_rev = in_be16(qrio_base + ID_REV_OFF);
+	u8 id = (id_rev >> 8) & 0xff;
+	u8 rev = id_rev & 0xff;
+
+	if (id == QRIO3_ID && rev >= QRIO3_REV) {
+		out_be32(qrio_base + EBOOTCNT_OFF, ebootcount);
+	} else {
+		printf("QRIO: warning: early bootcount not supported, ");
+		printf("id = %u, rev = %u\n", id, rev);
+	}
+}
+
 /* I2C deblocking uses the algorithm defined in board/keymile/common/common.c
  * 2 dedicated QRIO GPIOs externally pull the SCL and SDA lines
  * For I2C only the low state is activly driven and high state is pulled-up