aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSantosh Shilimkar <santosh.shilimkar@ti.com>2011-03-08 00:59:54 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-03-08 19:18:34 -0500
commit2839e06c95d12ada034cf9b63da60334c7c6358b (patch)
tree9295f80025852f73fbf3c66740eae76df5d61314
parentd239b1dc093d551046a909920b5310c1d1e308c1 (diff)
ARM: 6795/1: l2x0: Errata fix for flush by Way operation can cause data corrupti
PL310 implements the Clean & Invalidate by Way L2 cache maintenance operation (offset 0x7FC). This operation runs in background so that PL310 can handle normal accesses while it is in progress. Under very rare circumstances, due to this erratum, write data can be lost when PL310 treats a cacheable write transaction during a Clean & Invalidate by Way operation. Workaround: Disable Write-Back and Cache Linefill (Debug Control Register) Clean & Invalidate by Way (0x7FC) Re-enable Write-Back and Cache Linefill (Debug Control Register) This patch also removes any OMAP dependency on PL310 Errata's Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Acked-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/Kconfig15
-rw-r--r--arch/arm/include/asm/outercache.h1
-rw-r--r--arch/arm/mm/cache-l2x0.c32
3 files changed, 31 insertions, 17 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 65ea7bb57c4d..ef41f7e39f69 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1135,7 +1135,7 @@ config ARM_ERRATA_742231
1135 1135
1136config PL310_ERRATA_588369 1136config PL310_ERRATA_588369
1137 bool "Clean & Invalidate maintenance operations do not invalidate clean lines" 1137 bool "Clean & Invalidate maintenance operations do not invalidate clean lines"
1138 depends on CACHE_L2X0 && ARCH_OMAP4 1138 depends on CACHE_L2X0
1139 help 1139 help
1140 The PL310 L2 cache controller implements three types of Clean & 1140 The PL310 L2 cache controller implements three types of Clean &
1141 Invalidate maintenance operations: by Physical Address 1141 Invalidate maintenance operations: by Physical Address
@@ -1144,8 +1144,7 @@ config PL310_ERRATA_588369
1144 clean operation followed immediately by an invalidate operation, 1144 clean operation followed immediately by an invalidate operation,
1145 both performing to the same memory location. This functionality 1145 both performing to the same memory location. This functionality
1146 is not correctly implemented in PL310 as clean lines are not 1146 is not correctly implemented in PL310 as clean lines are not
1147 invalidated as a result of these operations. Note that this errata 1147 invalidated as a result of these operations.
1148 uses Texas Instrument's secure monitor api.
1149 1148
1150config ARM_ERRATA_720789 1149config ARM_ERRATA_720789
1151 bool "ARM errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID" 1150 bool "ARM errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID"
@@ -1172,6 +1171,16 @@ config ARM_ERRATA_743622
1172 visible impact on the overall performance or power consumption of the 1171 visible impact on the overall performance or power consumption of the
1173 processor. 1172 processor.
1174 1173
1174config PL310_ERRATA_727915
1175 bool "Background Clean & Invalidate by Way operation can cause data corruption"
1176 depends on CACHE_L2X0
1177 help
1178 PL310 implements the Clean & Invalidate by Way L2 cache maintenance
1179 operation (offset 0x7FC). This operation runs in background so that
1180 PL310 can handle normal accesses while it is in progress. Under very
1181 rare circumstances, due to this erratum, write data can be lost when
1182 PL310 treats a cacheable write transaction during a Clean &
1183 Invalidate by Way operation.
1175endmenu 1184endmenu
1176 1185
1177source "arch/arm/common/Kconfig" 1186source "arch/arm/common/Kconfig"
diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h
index fc1900925275..348d513afa92 100644
--- a/arch/arm/include/asm/outercache.h
+++ b/arch/arm/include/asm/outercache.h
@@ -31,6 +31,7 @@ struct outer_cache_fns {
31#ifdef CONFIG_OUTER_CACHE_SYNC 31#ifdef CONFIG_OUTER_CACHE_SYNC
32 void (*sync)(void); 32 void (*sync)(void);
33#endif 33#endif
34 void (*set_debug)(unsigned long);
34}; 35};
35 36
36#ifdef CONFIG_OUTER_CACHE 37#ifdef CONFIG_OUTER_CACHE
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 170c9bb95866..803bce8845a7 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -67,18 +67,24 @@ static inline void l2x0_inv_line(unsigned long addr)
67 writel_relaxed(addr, base + L2X0_INV_LINE_PA); 67 writel_relaxed(addr, base + L2X0_INV_LINE_PA);
68} 68}
69 69
70#ifdef CONFIG_PL310_ERRATA_588369 70#if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915)
71static void debug_writel(unsigned long val)
72{
73 extern void omap_smc1(u32 fn, u32 arg);
74 71
75 /* 72#define debug_writel(val) outer_cache.set_debug(val)
76 * Texas Instrument secure monitor api to modify the 73
77 * PL310 Debug Control Register. 74static void l2x0_set_debug(unsigned long val)
78 */ 75{
79 omap_smc1(0x100, val); 76 writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL);
80} 77}
78#else
79/* Optimised out for non-errata case */
80static inline void debug_writel(unsigned long val)
81{
82}
83
84#define l2x0_set_debug NULL
85#endif
81 86
87#ifdef CONFIG_PL310_ERRATA_588369
82static inline void l2x0_flush_line(unsigned long addr) 88static inline void l2x0_flush_line(unsigned long addr)
83{ 89{
84 void __iomem *base = l2x0_base; 90 void __iomem *base = l2x0_base;
@@ -91,11 +97,6 @@ static inline void l2x0_flush_line(unsigned long addr)
91} 97}
92#else 98#else
93 99
94/* Optimised out for non-errata case */
95static inline void debug_writel(unsigned long val)
96{
97}
98
99static inline void l2x0_flush_line(unsigned long addr) 100static inline void l2x0_flush_line(unsigned long addr)
100{ 101{
101 void __iomem *base = l2x0_base; 102 void __iomem *base = l2x0_base;
@@ -119,9 +120,11 @@ static void l2x0_flush_all(void)
119 120
120 /* clean all ways */ 121 /* clean all ways */
121 spin_lock_irqsave(&l2x0_lock, flags); 122 spin_lock_irqsave(&l2x0_lock, flags);
123 debug_writel(0x03);
122 writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_INV_WAY); 124 writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_INV_WAY);
123 cache_wait_way(l2x0_base + L2X0_CLEAN_INV_WAY, l2x0_way_mask); 125 cache_wait_way(l2x0_base + L2X0_CLEAN_INV_WAY, l2x0_way_mask);
124 cache_sync(); 126 cache_sync();
127 debug_writel(0x00);
125 spin_unlock_irqrestore(&l2x0_lock, flags); 128 spin_unlock_irqrestore(&l2x0_lock, flags);
126} 129}
127 130
@@ -329,6 +332,7 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
329 outer_cache.flush_all = l2x0_flush_all; 332 outer_cache.flush_all = l2x0_flush_all;
330 outer_cache.inv_all = l2x0_inv_all; 333 outer_cache.inv_all = l2x0_inv_all;
331 outer_cache.disable = l2x0_disable; 334 outer_cache.disable = l2x0_disable;
335 outer_cache.set_debug = l2x0_set_debug;
332 336
333 printk(KERN_INFO "%s cache controller enabled\n", type); 337 printk(KERN_INFO "%s cache controller enabled\n", type);
334 printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n", 338 printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n",