aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/metag/mm/cache.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/arch/metag/mm/cache.c b/arch/metag/mm/cache.c
index 89da74a80ea7..4dd96e457fa2 100644
--- a/arch/metag/mm/cache.c
+++ b/arch/metag/mm/cache.c
@@ -14,6 +14,7 @@
14#include <linux/io.h> 14#include <linux/io.h>
15#include <asm/cacheflush.h> 15#include <asm/cacheflush.h>
16#include <asm/core_reg.h> 16#include <asm/core_reg.h>
17#include <asm/global_lock.h>
17#include <asm/metag_isa.h> 18#include <asm/metag_isa.h>
18#include <asm/metag_mem.h> 19#include <asm/metag_mem.h>
19#include <asm/metag_regs.h> 20#include <asm/metag_regs.h>
@@ -36,6 +37,82 @@ static int icache_set_shift = METAG_TBI_CACHE_SIZE_BASE_LOG2
36static unsigned char dcache_sets_log2 = DEFAULT_CACHE_WAYS_LOG2; 37static unsigned char dcache_sets_log2 = DEFAULT_CACHE_WAYS_LOG2;
37static unsigned char icache_sets_log2 = DEFAULT_CACHE_WAYS_LOG2; 38static unsigned char icache_sets_log2 = DEFAULT_CACHE_WAYS_LOG2;
38 39
40#ifndef CONFIG_METAG_META12
41/**
42 * metag_lnkget_probe() - Probe whether lnkget/lnkset go around the cache
43 */
44static volatile u32 lnkget_testdata[16] __initdata __aligned(64);
45
46#define LNKGET_CONSTANT 0xdeadbeef
47
48void __init metag_lnkget_probe(void)
49{
50 int temp;
51 long flags;
52
53 /*
54 * It's conceivable the user has configured a globally coherent cache
55 * shared with non-Linux hardware threads, so use LOCK2 to prevent them
56 * from executing and causing cache eviction during the test.
57 */
58 __global_lock2(flags);
59
60 /* read a value to bring it into the cache */
61 (void)lnkget_testdata[0];
62 lnkget_testdata[0] = 0;
63
64 /* lnkget/lnkset it to modify it */
65 asm volatile(
66 "1: LNKGETD %0, [%1]\n"
67 " LNKSETD [%1], %2\n"
68 " DEFR %0, TXSTAT\n"
69 " ANDT %0, %0, #HI(0x3f000000)\n"
70 " CMPT %0, #HI(0x02000000)\n"
71 " BNZ 1b\n"
72 : "=&d" (temp)
73 : "da" (&lnkget_testdata[0]), "bd" (LNKGET_CONSTANT)
74 : "cc");
75
76 /* re-read it to see if the cached value changed */
77 temp = lnkget_testdata[0];
78
79 __global_unlock2(flags);
80
81 /* flush the cache line to fix any incoherency */
82 __builtin_dcache_flush((void *)&lnkget_testdata[0]);
83
84#if defined(CONFIG_METAG_LNKGET_AROUND_CACHE)
85 /* if the cache is right, LNKGET_AROUND_CACHE is unnecessary */
86 if (temp == LNKGET_CONSTANT)
87 pr_info("LNKGET/SET go through cache but CONFIG_METAG_LNKGET_AROUND_CACHE=y\n");
88#elif defined(CONFIG_METAG_ATOMICITY_LNKGET)
89 /*
90 * if the cache is wrong, LNKGET_AROUND_CACHE is really necessary
91 * because the kernel is configured to use LNKGET/SET for atomicity
92 */
93 WARN(temp != LNKGET_CONSTANT,
94 "LNKGET/SET go around cache but CONFIG_METAG_LNKGET_AROUND_CACHE=n\n"
95 "Expect kernel failure as it's used for atomicity primitives\n");
96#elif defined(CONFIG_SMP)
97 /*
98 * if the cache is wrong, LNKGET_AROUND_CACHE should be used or the
99 * gateway page won't flush and userland could break.
100 */
101 WARN(temp != LNKGET_CONSTANT,
102 "LNKGET/SET go around cache but CONFIG_METAG_LNKGET_AROUND_CACHE=n\n"
103 "Expect userland failure as it's used for user gateway page\n");
104#else
105 /*
106 * if the cache is wrong, LNKGET_AROUND_CACHE is set wrong, but it
107 * doesn't actually matter as it doesn't have any effect on !SMP &&
108 * !ATOMICITY_LNKGET.
109 */
110 if (temp != LNKGET_CONSTANT)
111 pr_warn("LNKGET/SET go around cache but CONFIG_METAG_LNKGET_AROUND_CACHE=n\n");
112#endif
113}
114#endif /* !CONFIG_METAG_META12 */
115
39/** 116/**
40 * metag_cache_probe() - Probe L1 cache configuration. 117 * metag_cache_probe() - Probe L1 cache configuration.
41 * 118 *
@@ -68,6 +145,8 @@ void __init metag_cache_probe(void)
68 dcache_set_shift += (config & METAC_CORECFG2_DCSZ_BITS) 145 dcache_set_shift += (config & METAC_CORECFG2_DCSZ_BITS)
69 >> METAC_CORECFG2_DCSZ_S; 146 >> METAC_CORECFG2_DCSZ_S;
70 dcache_set_shift -= dcache_sets_log2; 147 dcache_set_shift -= dcache_sets_log2;
148
149 metag_lnkget_probe();
71#else 150#else
72 /* Extract cache sizes from global heap segment */ 151 /* Extract cache sizes from global heap segment */
73 unsigned long val, u; 152 unsigned long val, u;