ARM: 7080/1: l2x0: make sure I&D are not locked down on init

Fighting unfixed U-Boots and other beasts that may the cache in
a locked-down state when starting the kernel, we make sure to
disable all cache lock-down when initializing the l2x0 so we
are in a known state.

Change-Id: I2bad6513e8689a554b8b981d294dc6f3e6656ed4
Cc: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
Cc: Rabin Vincent <rabin.vincent@stericsson.com>
Cc: Adrian Bunk <adrian.bunk@movial.com>
Cc: Rob Herring <robherring2@gmail.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Reviewed-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reported-by: Jan Rinze <janrinze@gmail.com>
Tested-by: Robert Marklund <robert.marklund@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
[tdas@codeaurora.org: Remove PL210 function hooks which are no longer
valid in upstream kernel and to keep the erratas which are not in upstream
yet but as we want to keep them made variable changes]
Signed-off-by: Taniya Das <tdas@codeaurora.org>
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 8b2566a..7fcd0bf 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -254,27 +254,6 @@
 	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
-static void l2x0_inv_range_atomic(unsigned long start, unsigned long end)
-{
-	unsigned long addr;
-
-	if (start & (CACHE_LINE_SIZE - 1)) {
-		start &= ~(CACHE_LINE_SIZE - 1);
-		writel_relaxed(start, l2x0_base + L2X0_CLEAN_INV_LINE_PA);
-		start += CACHE_LINE_SIZE;
-	}
-
-	if (end & (CACHE_LINE_SIZE - 1)) {
-		end &= ~(CACHE_LINE_SIZE - 1);
-		writel_relaxed(end, l2x0_base + L2X0_CLEAN_INV_LINE_PA);
-	}
-
-	for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
-		writel_relaxed(addr, l2x0_base + L2X0_INV_LINE_PA);
-
-	mb();
-}
-
 static void l2x0_clean_range(unsigned long start, unsigned long end)
 {
 	void __iomem *base = l2x0_base;
@@ -305,17 +284,6 @@
 	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
-static void l2x0_clean_range_atomic(unsigned long start, unsigned long end)
-{
-	unsigned long addr;
-
-	start &= ~(CACHE_LINE_SIZE - 1);
-	for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
-		writel_relaxed(addr, l2x0_base + L2X0_CLEAN_LINE_PA);
-
-	mb();
-}
-
 static void l2x0_flush_range(unsigned long start, unsigned long end)
 {
 	void __iomem *base = l2x0_base;
@@ -370,18 +338,36 @@
 	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
+static void __init l2x0_unlock(__u32 cache_id)
+{
+	int lockregs;
+	int i;
+
+	if (cache_id == L2X0_CACHE_ID_PART_L310)
+		lockregs = 8;
+	else
+		/* L210 and unknown types */
+		lockregs = 1;
+
+	for (i = 0; i < lockregs; i++) {
+		writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE +
+			       i * L2X0_LOCKDOWN_STRIDE);
+		writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE +
+			       i * L2X0_LOCKDOWN_STRIDE);
+	}
+}
+
 void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
 {
-	__u32 aux, bits;
+	__u32 aux;
+	__u32 cache_id;
 	__u32 way_size = 0;
+	int ways;
 	const char *type;
 
 	l2x0_base = base;
-	l2x0_cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID);
-
-	bits = readl_relaxed(l2x0_base + L2X0_CTRL);
-	bits &= ~0x01; /* clear bit 0 */
-	writel_relaxed(bits, l2x0_base + L2X0_CTRL);
+	cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID);
+	l2x0_cache_id = cache_id;
 
 	aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
 
@@ -389,64 +375,57 @@
 	aux |= aux_val;
 
 	/* Determine the number of ways */
-	switch (l2x0_cache_id & L2X0_CACHE_ID_PART_MASK) {
+	switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
 	case L2X0_CACHE_ID_PART_L310:
 		if (aux & (1 << 16))
-			l2x0_ways = 16;
+			ways = 16;
 		else
-			l2x0_ways = 8;
+			ways = 8;
 		type = "L310";
 		break;
 	case L2X0_CACHE_ID_PART_L210:
-		l2x0_ways = (aux >> 13) & 0xf;
+		ways = (aux >> 13) & 0xf;
 		type = "L210";
 		break;
 	default:
 		/* Assume unknown chips have 8 ways */
-		l2x0_ways = 8;
+		ways = 8;
 		type = "L2x0 series";
 		break;
 	}
 	writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL);
-	l2x0_way_mask = (1 << l2x0_ways) - 1;
+	l2x0_way_mask = (1 << ways) - 1;
 
 	/*
 	 * L2 cache Size =  Way size * Number of ways
 	 */
 	way_size = (aux & L2X0_AUX_CTRL_WAY_SIZE_MASK) >> 17;
-	way_size = SZ_1K << (way_size + 3);
-	l2x0_size = l2x0_ways * way_size;
+	way_size = 1 << (way_size + 3);
+	l2x0_size = ways * way_size * SZ_1K;
 	l2x0_sets = way_size / CACHE_LINE_SIZE;
+	l2x0_ways = ways;
 
-	l2x0_inv_all();
+	/*
+	 * Check if l2x0 controller is already enabled.
+	 * If you are booting from non-secure mode
+	 * accessing the below registers will fault.
+	 */
+	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+		/* Make sure that I&D is not locked down when starting */
+		l2x0_unlock(cache_id);
 
-	/* enable L2X0 */
-	bits = readl_relaxed(l2x0_base + L2X0_CTRL);
-	bits |= 0x01;	/* set bit 0 */
-	writel_relaxed(bits, l2x0_base + L2X0_CTRL);
+		/* l2x0 controller is disabled */
+		writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL);
 
-	switch (l2x0_cache_id & L2X0_CACHE_ID_PART_MASK) {
-	case L2X0_CACHE_ID_PART_L220:
-		outer_cache.inv_range = l2x0_inv_range;
-		outer_cache.clean_range = l2x0_clean_range;
-		outer_cache.flush_range = l2x0_flush_range;
-		printk(KERN_INFO "L220 cache controller enabled\n");
-		break;
-	case L2X0_CACHE_ID_PART_L310:
-		outer_cache.inv_range = l2x0_inv_range;
-		outer_cache.clean_range = l2x0_clean_range;
-		outer_cache.flush_range = l2x0_flush_range;
-		printk(KERN_INFO "L310 cache controller enabled\n");
-		break;
-	case L2X0_CACHE_ID_PART_L210:
-	default:
-		outer_cache.inv_range = l2x0_inv_range_atomic;
-		outer_cache.clean_range = l2x0_clean_range_atomic;
-		outer_cache.flush_range = l2x0_flush_range_atomic;
-		printk(KERN_INFO "L210 cache controller enabled\n");
-		break;
+		l2x0_inv_all();
+
+		/* enable L2X0 */
+		writel_relaxed(1, l2x0_base + L2X0_CTRL);
 	}
 
+	outer_cache.inv_range = l2x0_inv_range;
+	outer_cache.clean_range = l2x0_clean_range;
+	outer_cache.flush_range = l2x0_flush_range;
 	outer_cache.sync = l2x0_cache_sync;
 
 	outer_cache.flush_all = l2x0_flush_all;
@@ -457,7 +436,7 @@
 	mb();
 	printk(KERN_INFO "%s cache controller enabled\n", type);
 	printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n",
-			l2x0_ways, l2x0_cache_id, aux, l2x0_size);
+			ways, cache_id, aux, l2x0_size);
 }
 
 void l2x0_suspend(void)