]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/mips/mm/sc-mips.c
Merge remote-tracking branch 'metag/for-next'
[karo-tx-linux.git] / arch / mips / mm / sc-mips.c
1 /*
2  * Copyright (C) 2006 Chris Dearman (chris@mips.com),
3  */
4 #include <linux/init.h>
5 #include <linux/kernel.h>
6 #include <linux/sched.h>
7 #include <linux/mm.h>
8
9 #include <asm/cpu-type.h>
10 #include <asm/mipsregs.h>
11 #include <asm/bcache.h>
12 #include <asm/cacheops.h>
13 #include <asm/page.h>
14 #include <asm/pgtable.h>
15 #include <asm/mmu_context.h>
16 #include <asm/r4kcache.h>
17 #include <asm/mips-cm.h>
18
19 /*
20  * MIPS32/MIPS64 L2 cache handling
21  */
22
23 /*
24  * Writeback and invalidate the secondary cache before DMA.
25  */
26 static void mips_sc_wback_inv(unsigned long addr, unsigned long size)
27 {
28         blast_scache_range(addr, addr + size);
29 }
30
31 /*
32  * Invalidate the secondary cache before DMA.
33  */
34 static void mips_sc_inv(unsigned long addr, unsigned long size)
35 {
36         unsigned long lsize = cpu_scache_line_size();
37         unsigned long almask = ~(lsize - 1);
38
39         cache_op(Hit_Writeback_Inv_SD, addr & almask);
40         cache_op(Hit_Writeback_Inv_SD, (addr + size - 1) & almask);
41         blast_inv_scache_range(addr, addr + size);
42 }
43
44 static void mips_sc_enable(void)
45 {
46         /* L2 cache is permanently enabled */
47 }
48
49 static void mips_sc_disable(void)
50 {
51         /* L2 cache is permanently enabled */
52 }
53
54 static struct bcache_ops mips_sc_ops = {
55         .bc_enable = mips_sc_enable,
56         .bc_disable = mips_sc_disable,
57         .bc_wback_inv = mips_sc_wback_inv,
58         .bc_inv = mips_sc_inv
59 };
60
61 /*
62  * Check if the L2 cache controller is activated on a particular platform.
63  * MTI's L2 controller and the L2 cache controller of Broadcom's BMIPS
64  * cores both use c0_config2's bit 12 as "L2 Bypass" bit, that is the
65  * cache being disabled.  However there is no guarantee for this to be
66  * true on all platforms.  In an act of stupidity the spec defined bits
67  * 12..15 as implementation defined so below function will eventually have
68  * to be replaced by a platform specific probe.
69  */
70 static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
71 {
72         unsigned int config2 = read_c0_config2();
73         unsigned int tmp;
74
75         /* Check the bypass bit (L2B) */
76         switch (current_cpu_type()) {
77         case CPU_34K:
78         case CPU_74K:
79         case CPU_1004K:
80         case CPU_1074K:
81         case CPU_INTERAPTIV:
82         case CPU_PROAPTIV:
83         case CPU_P5600:
84         case CPU_BMIPS5000:
85         case CPU_QEMU_GENERIC:
86                 if (config2 & (1 << 12))
87                         return 0;
88         }
89
90         tmp = (config2 >> 4) & 0x0f;
91         if (0 < tmp && tmp <= 7)
92                 c->scache.linesz = 2 << tmp;
93         else
94                 return 0;
95         return 1;
96 }
97
98 static int __init mips_sc_probe_cm3(void)
99 {
100         struct cpuinfo_mips *c = &current_cpu_data;
101         unsigned long cfg = read_gcr_l2_config();
102         unsigned long sets, line_sz, assoc;
103
104         if (cfg & CM_GCR_L2_CONFIG_BYPASS_MSK)
105                 return 0;
106
107         sets = cfg & CM_GCR_L2_CONFIG_SET_SIZE_MSK;
108         sets >>= CM_GCR_L2_CONFIG_SET_SIZE_SHF;
109         c->scache.sets = 64 << sets;
110
111         line_sz = cfg & CM_GCR_L2_CONFIG_LINE_SIZE_MSK;
112         line_sz >>= CM_GCR_L2_CONFIG_LINE_SIZE_SHF;
113         c->scache.linesz = 2 << line_sz;
114
115         assoc = cfg & CM_GCR_L2_CONFIG_ASSOC_MSK;
116         assoc >>= CM_GCR_L2_CONFIG_ASSOC_SHF;
117         c->scache.ways = assoc + 1;
118         c->scache.waysize = c->scache.sets * c->scache.linesz;
119         c->scache.waybit = __ffs(c->scache.waysize);
120
121         c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
122
123         return 1;
124 }
125
126 void __weak platform_early_l2_init(void)
127 {
128 }
129
130 static inline int __init mips_sc_probe(void)
131 {
132         struct cpuinfo_mips *c = &current_cpu_data;
133         unsigned int config1, config2;
134         unsigned int tmp;
135
136         /* Mark as not present until probe completed */
137         c->scache.flags |= MIPS_CACHE_NOT_PRESENT;
138
139         /*
140          * Do we need some platform specific probing before
141          * we configure L2?
142          */
143         platform_early_l2_init();
144
145         if (mips_cm_revision() >= CM_REV_CM3)
146                 return mips_sc_probe_cm3();
147
148         /* Ignore anything but MIPSxx processors */
149         if (!(c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
150                               MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 |
151                               MIPS_CPU_ISA_M64R2 | MIPS_CPU_ISA_M64R6)))
152                 return 0;
153
154         /* Does this MIPS32/MIPS64 CPU have a config2 register? */
155         config1 = read_c0_config1();
156         if (!(config1 & MIPS_CONF_M))
157                 return 0;
158
159         config2 = read_c0_config2();
160
161         if (!mips_sc_is_activated(c))
162                 return 0;
163
164         tmp = (config2 >> 8) & 0x0f;
165         if (0 <= tmp && tmp <= 7)
166                 c->scache.sets = 64 << tmp;
167         else
168                 return 0;
169
170         tmp = (config2 >> 0) & 0x0f;
171         if (0 <= tmp && tmp <= 7)
172                 c->scache.ways = tmp + 1;
173         else
174                 return 0;
175
176         c->scache.waysize = c->scache.sets * c->scache.linesz;
177         c->scache.waybit = __ffs(c->scache.waysize);
178
179         c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
180
181         return 1;
182 }
183
184 int mips_sc_init(void)
185 {
186         int found = mips_sc_probe();
187         if (found) {
188                 mips_sc_enable();
189                 bcops = &mips_sc_ops;
190         }
191         return found;
192 }