aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/cache-l2x0.c
diff options
context:
space:
mode:
authorSantosh Shilimkar <santosh.shilimkar@ti.com>2010-02-04 13:42:42 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-02-15 16:39:55 -0500
commit9e65582a8e8715f883a34eea66e0643778ce878d (patch)
tree36fd7010f69175fa6296a6eb14ead145c54c16e7 /arch/arm/mm/cache-l2x0.c
parentd309427e792ea750cdd312e7a92cf6047ae44962 (diff)
ARM: 5919/1: ARM: L2 : Errata 588369: Clean & Invalidate do not invalidate clean lines
This patch implements the work-around for the errata 588369.The secure API is used to alter L2 debug register because of trust-zone. This version updated with comments from Russell and Catalin and generated against 2.6.33-rc6 mainline kernel. Detail comments can be found: http://www.spinics.net/lists/linux-omap/msg23431.html Signed-off-by: Woodruff Richard <r-woodruff2@ti.com> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Acked-by: Catalin Marinas <catalin.marinas@arm.com> Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm/cache-l2x0.c')
-rw-r--r--arch/arm/mm/cache-l2x0.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 1a14d18e5713..07334632d3e2 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -56,12 +56,42 @@ static inline void l2x0_inv_line(unsigned long addr)
56 writel(addr, base + L2X0_INV_LINE_PA); 56 writel(addr, base + L2X0_INV_LINE_PA);
57} 57}
58 58
59#ifdef CONFIG_PL310_ERRATA_588369
60static void debug_writel(unsigned long val)
61{
62 extern void omap_smc1(u32 fn, u32 arg);
63
64 /*
65 * Texas Instrument secure monitor api to modify the
66 * PL310 Debug Control Register.
67 */
68 omap_smc1(0x100, val);
69}
70
71static inline void l2x0_flush_line(unsigned long addr)
72{
73 void __iomem *base = l2x0_base;
74
75 /* Clean by PA followed by Invalidate by PA */
76 cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
77 writel(addr, base + L2X0_CLEAN_LINE_PA);
78 cache_wait(base + L2X0_INV_LINE_PA, 1);
79 writel(addr, base + L2X0_INV_LINE_PA);
80}
81#else
82
83/* Optimised out for non-errata case */
84static inline void debug_writel(unsigned long val)
85{
86}
87
59static inline void l2x0_flush_line(unsigned long addr) 88static inline void l2x0_flush_line(unsigned long addr)
60{ 89{
61 void __iomem *base = l2x0_base; 90 void __iomem *base = l2x0_base;
62 cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1); 91 cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
63 writel(addr, base + L2X0_CLEAN_INV_LINE_PA); 92 writel(addr, base + L2X0_CLEAN_INV_LINE_PA);
64} 93}
94#endif
65 95
66static inline void l2x0_inv_all(void) 96static inline void l2x0_inv_all(void)
67{ 97{
@@ -83,13 +113,17 @@ static void l2x0_inv_range(unsigned long start, unsigned long end)
83 spin_lock_irqsave(&l2x0_lock, flags); 113 spin_lock_irqsave(&l2x0_lock, flags);
84 if (start & (CACHE_LINE_SIZE - 1)) { 114 if (start & (CACHE_LINE_SIZE - 1)) {
85 start &= ~(CACHE_LINE_SIZE - 1); 115 start &= ~(CACHE_LINE_SIZE - 1);
116 debug_writel(0x03);
86 l2x0_flush_line(start); 117 l2x0_flush_line(start);
118 debug_writel(0x00);
87 start += CACHE_LINE_SIZE; 119 start += CACHE_LINE_SIZE;
88 } 120 }
89 121
90 if (end & (CACHE_LINE_SIZE - 1)) { 122 if (end & (CACHE_LINE_SIZE - 1)) {
91 end &= ~(CACHE_LINE_SIZE - 1); 123 end &= ~(CACHE_LINE_SIZE - 1);
124 debug_writel(0x03);
92 l2x0_flush_line(end); 125 l2x0_flush_line(end);
126 debug_writel(0x00);
93 } 127 }
94 128
95 while (start < end) { 129 while (start < end) {
@@ -145,10 +179,12 @@ static void l2x0_flush_range(unsigned long start, unsigned long end)
145 while (start < end) { 179 while (start < end) {
146 unsigned long blk_end = start + min(end - start, 4096UL); 180 unsigned long blk_end = start + min(end - start, 4096UL);
147 181
182 debug_writel(0x03);
148 while (start < blk_end) { 183 while (start < blk_end) {
149 l2x0_flush_line(start); 184 l2x0_flush_line(start);
150 start += CACHE_LINE_SIZE; 185 start += CACHE_LINE_SIZE;
151 } 186 }
187 debug_writel(0x00);
152 188
153 if (blk_end < end) { 189 if (blk_end < end) {
154 spin_unlock_irqrestore(&l2x0_lock, flags); 190 spin_unlock_irqrestore(&l2x0_lock, flags);