arm/km: adapt bootcounter evaluation

The bootcounter (stored in the RAM) is not enough protected with the 4 Bytes
BOOTCOUNT_MAGIC against bit errors due to short power loss or holding a system
in RESET. It has been seen, that the bootcounter value has been changed due to
a bit flip on a system holding in RESET, but the BOOTCOUNT_MAGIC was still valid.

A bit pattern with 4000 bytes (after BOOTCOUNT_MAGIC) has been implemented,
which should be enough to detect a bit error.

Signed-off-by: Holger Brunck <holger.brunck@keymile.com>
Signed-off-by: Valentin Longchamp <valentin.longchamp@keymile.com>
cc: Prafulla Wadaskar <prafulla@marvell.com>
diff --git a/board/keymile/km_arm/km_arm.c b/board/keymile/km_arm/km_arm.c
index 3c9b917..ca33aae 100644
--- a/board/keymile/km_arm/km_arm.c
+++ b/board/keymile/km_arm/km_arm.c
@@ -405,6 +405,15 @@
 #endif
 
 #if defined(CONFIG_BOOTCOUNT_LIMIT)
+const ulong patterns[]      = {	0x00000000,
+				0xFFFFFFFF,
+				0xFF00FF00,
+				0x0F0F0F0F,
+				0xF0F0F0F0};
+const ulong NBR_OF_PATTERNS = sizeof(patterns)/sizeof(*patterns);
+const ulong OFFS_PATTERN    = 3;
+const ulong REPEAT_PATTERN  = 1000;
+
 void bootcount_store(ulong a)
 {
 	volatile ulong *save_addr;
@@ -416,21 +425,34 @@
 	save_addr = (ulong*)(size - BOOTCOUNT_ADDR);
 	writel(a, save_addr);
 	writel(BOOTCOUNT_MAGIC, &save_addr[1]);
+
+	for (i = 0; i < REPEAT_PATTERN; i++)
+		writel(patterns[i % NBR_OF_PATTERNS],
+			&save_addr[i+OFFS_PATTERN]);
+
 }
 
 ulong bootcount_load(void)
 {
 	volatile ulong *save_addr;
 	volatile ulong size = 0;
-	int i;
+	ulong counter = 0;
+	int i, tmp;
+
 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
 		size += gd->bd->bi_dram[i].size;
 	}
 	save_addr = (ulong*)(size - BOOTCOUNT_ADDR);
-	if (readl(&save_addr[1]) != BOOTCOUNT_MAGIC)
-		return 0;
-	else
-		return readl(save_addr);
+
+	counter = readl(&save_addr[0]);
+
+	/* Is the counter reliable, check in the big pattern for bit errors */
+	for (i = 0; (i < REPEAT_PATTERN) && (counter != 0); i++) {
+		tmp = readl(&save_addr[i+OFFS_PATTERN]);
+		if (tmp != patterns[i % NBR_OF_PATTERNS])
+			counter = 0;
+	}
+	return counter;
 }
 #endif