]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - arch/arm/mm/cache-l2x0.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[mv-sheeva.git] / arch / arm / mm / cache-l2x0.c
index cb8fc6573b1b2c9dedbeeec0f9a87c491a78ba85..21ad68ba22bab8a3acd859cbba4df0fc36c93b72 100644 (file)
@@ -42,6 +42,66 @@ static inline void cache_sync(void)
        cache_wait(base + L2X0_CACHE_SYNC, 1);
 }
 
+static inline void l2x0_clean_line(unsigned long addr)
+{
+       void __iomem *base = l2x0_base;
+       cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
+       writel(addr, base + L2X0_CLEAN_LINE_PA);
+}
+
+static inline void l2x0_inv_line(unsigned long addr)
+{
+       void __iomem *base = l2x0_base;
+       cache_wait(base + L2X0_INV_LINE_PA, 1);
+       writel(addr, base + L2X0_INV_LINE_PA);
+}
+
+#ifdef CONFIG_PL310_ERRATA_588369
+static void debug_writel(unsigned long val)
+{
+       extern void omap_smc1(u32 fn, u32 arg);
+
+       /*
+        * Texas Instrument secure monitor api to modify the
+        * PL310 Debug Control Register.
+        */
+       omap_smc1(0x100, val);
+}
+
+static inline void l2x0_flush_line(unsigned long addr)
+{
+       void __iomem *base = l2x0_base;
+
+       /* Clean by PA followed by Invalidate by PA */
+       cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
+       writel(addr, base + L2X0_CLEAN_LINE_PA);
+       cache_wait(base + L2X0_INV_LINE_PA, 1);
+       writel(addr, base + L2X0_INV_LINE_PA);
+}
+#else
+
+/* Optimised out for non-errata case */
+static inline void debug_writel(unsigned long val)
+{
+}
+
+static inline void l2x0_flush_line(unsigned long addr)
+{
+       void __iomem *base = l2x0_base;
+       cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
+       writel(addr, base + L2X0_CLEAN_INV_LINE_PA);
+}
+#endif
+
+static void l2x0_cache_sync(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&l2x0_lock, flags);
+       cache_sync();
+       spin_unlock_irqrestore(&l2x0_lock, flags);
+}
+
 static inline void l2x0_inv_all(void)
 {
        unsigned long flags;
@@ -62,23 +122,24 @@ static void l2x0_inv_range(unsigned long start, unsigned long end)
        spin_lock_irqsave(&l2x0_lock, flags);
        if (start & (CACHE_LINE_SIZE - 1)) {
                start &= ~(CACHE_LINE_SIZE - 1);
-               cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
-               writel(start, base + L2X0_CLEAN_INV_LINE_PA);
+               debug_writel(0x03);
+               l2x0_flush_line(start);
+               debug_writel(0x00);
                start += CACHE_LINE_SIZE;
        }
 
        if (end & (CACHE_LINE_SIZE - 1)) {
                end &= ~(CACHE_LINE_SIZE - 1);
-               cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
-               writel(end, base + L2X0_CLEAN_INV_LINE_PA);
+               debug_writel(0x03);
+               l2x0_flush_line(end);
+               debug_writel(0x00);
        }
 
        while (start < end) {
                unsigned long blk_end = start + min(end - start, 4096UL);
 
                while (start < blk_end) {
-                       cache_wait(base + L2X0_INV_LINE_PA, 1);
-                       writel(start, base + L2X0_INV_LINE_PA);
+                       l2x0_inv_line(start);
                        start += CACHE_LINE_SIZE;
                }
 
@@ -103,8 +164,7 @@ static void l2x0_clean_range(unsigned long start, unsigned long end)
                unsigned long blk_end = start + min(end - start, 4096UL);
 
                while (start < blk_end) {
-                       cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
-                       writel(start, base + L2X0_CLEAN_LINE_PA);
+                       l2x0_clean_line(start);
                        start += CACHE_LINE_SIZE;
                }
 
@@ -128,11 +188,12 @@ static void l2x0_flush_range(unsigned long start, unsigned long end)
        while (start < end) {
                unsigned long blk_end = start + min(end - start, 4096UL);
 
+               debug_writel(0x03);
                while (start < blk_end) {
-                       cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
-                       writel(start, base + L2X0_CLEAN_INV_LINE_PA);
+                       l2x0_flush_line(start);
                        start += CACHE_LINE_SIZE;
                }
+               debug_writel(0x00);
 
                if (blk_end < end) {
                        spin_unlock_irqrestore(&l2x0_lock, flags);
@@ -173,6 +234,7 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
        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;
 
        printk(KERN_INFO "L2X0 cache controller enabled\n");
 }