diff options
Diffstat (limited to 'arch/sh/kernel/cpu/sh4/probe.c')
-rw-r--r-- | arch/sh/kernel/cpu/sh4/probe.c | 138 |
1 files changed, 118 insertions, 20 deletions
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c index 42427b79697b..c294de1e14a3 100644 --- a/arch/sh/kernel/cpu/sh4/probe.c +++ b/arch/sh/kernel/cpu/sh4/probe.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * CPU Subtype Probing for SH-4. | 4 | * CPU Subtype Probing for SH-4. |
5 | * | 5 | * |
6 | * Copyright (C) 2001, 2002, 2003, 2004 Paul Mundt | 6 | * Copyright (C) 2001 - 2006 Paul Mundt |
7 | * Copyright (C) 2003 Richard Curnow | 7 | * Copyright (C) 2003 Richard Curnow |
8 | * | 8 | * |
9 | * This file is subject to the terms and conditions of the GNU General Public | 9 | * This file is subject to the terms and conditions of the GNU General Public |
@@ -29,7 +29,7 @@ int __init detect_cpu_and_cache_system(void) | |||
29 | [9] = (1 << 16) | 29 | [9] = (1 << 16) |
30 | }; | 30 | }; |
31 | 31 | ||
32 | pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffff; | 32 | pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffffff; |
33 | prr = (ctrl_inl(CCN_PRR) >> 4) & 0xff; | 33 | prr = (ctrl_inl(CCN_PRR) >> 4) & 0xff; |
34 | cvr = (ctrl_inl(CCN_CVR)); | 34 | cvr = (ctrl_inl(CCN_CVR)); |
35 | 35 | ||
@@ -38,7 +38,6 @@ int __init detect_cpu_and_cache_system(void) | |||
38 | */ | 38 | */ |
39 | cpu_data->icache.way_incr = (1 << 13); | 39 | cpu_data->icache.way_incr = (1 << 13); |
40 | cpu_data->icache.entry_shift = 5; | 40 | cpu_data->icache.entry_shift = 5; |
41 | cpu_data->icache.entry_mask = 0x1fe0; | ||
42 | cpu_data->icache.sets = 256; | 41 | cpu_data->icache.sets = 256; |
43 | cpu_data->icache.ways = 1; | 42 | cpu_data->icache.ways = 1; |
44 | cpu_data->icache.linesz = L1_CACHE_BYTES; | 43 | cpu_data->icache.linesz = L1_CACHE_BYTES; |
@@ -48,13 +47,29 @@ int __init detect_cpu_and_cache_system(void) | |||
48 | */ | 47 | */ |
49 | cpu_data->dcache.way_incr = (1 << 14); | 48 | cpu_data->dcache.way_incr = (1 << 14); |
50 | cpu_data->dcache.entry_shift = 5; | 49 | cpu_data->dcache.entry_shift = 5; |
51 | cpu_data->dcache.entry_mask = 0x3fe0; | ||
52 | cpu_data->dcache.sets = 512; | 50 | cpu_data->dcache.sets = 512; |
53 | cpu_data->dcache.ways = 1; | 51 | cpu_data->dcache.ways = 1; |
54 | cpu_data->dcache.linesz = L1_CACHE_BYTES; | 52 | cpu_data->dcache.linesz = L1_CACHE_BYTES; |
55 | 53 | ||
56 | /* Set the FPU flag, virtually all SH-4's have one */ | 54 | /* |
57 | cpu_data->flags |= CPU_HAS_FPU; | 55 | * Setup some generic flags we can probe |
56 | * (L2 and DSP detection only work on SH-4A) | ||
57 | */ | ||
58 | if (((pvr >> 16) & 0xff) == 0x10) { | ||
59 | if ((cvr & 0x02000000) == 0) | ||
60 | cpu_data->flags |= CPU_HAS_L2_CACHE; | ||
61 | if ((cvr & 0x10000000) == 0) | ||
62 | cpu_data->flags |= CPU_HAS_DSP; | ||
63 | |||
64 | cpu_data->flags |= CPU_HAS_LLSC; | ||
65 | } | ||
66 | |||
67 | /* FPU detection works for everyone */ | ||
68 | if ((cvr & 0x20000000) == 1) | ||
69 | cpu_data->flags |= CPU_HAS_FPU; | ||
70 | |||
71 | /* Mask off the upper chip ID */ | ||
72 | pvr &= 0xffff; | ||
58 | 73 | ||
59 | /* | 74 | /* |
60 | * Probe the underlying processor version/revision and | 75 | * Probe the underlying processor version/revision and |
@@ -63,56 +78,101 @@ int __init detect_cpu_and_cache_system(void) | |||
63 | switch (pvr) { | 78 | switch (pvr) { |
64 | case 0x205: | 79 | case 0x205: |
65 | cpu_data->type = CPU_SH7750; | 80 | cpu_data->type = CPU_SH7750; |
66 | cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_PERF_COUNTER; | 81 | cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU | |
82 | CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA; | ||
67 | break; | 83 | break; |
68 | case 0x206: | 84 | case 0x206: |
69 | cpu_data->type = CPU_SH7750S; | 85 | cpu_data->type = CPU_SH7750S; |
70 | cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_PERF_COUNTER; | 86 | cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU | |
87 | CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA; | ||
71 | break; | 88 | break; |
72 | case 0x1100: | 89 | case 0x1100: |
73 | cpu_data->type = CPU_SH7751; | 90 | cpu_data->type = CPU_SH7751; |
91 | cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; | ||
74 | break; | 92 | break; |
75 | case 0x2000: | 93 | case 0x2000: |
76 | cpu_data->type = CPU_SH73180; | 94 | cpu_data->type = CPU_SH73180; |
77 | cpu_data->icache.ways = 4; | 95 | cpu_data->icache.ways = 4; |
78 | cpu_data->dcache.ways = 4; | 96 | cpu_data->dcache.ways = 4; |
79 | cpu_data->flags &= ~CPU_HAS_FPU; | 97 | cpu_data->flags |= CPU_HAS_LLSC; |
98 | break; | ||
99 | case 0x2001: | ||
100 | case 0x2004: | ||
101 | cpu_data->type = CPU_SH7770; | ||
102 | cpu_data->icache.ways = 4; | ||
103 | cpu_data->dcache.ways = 4; | ||
104 | |||
105 | cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_LLSC; | ||
106 | break; | ||
107 | case 0x2006: | ||
108 | case 0x200A: | ||
109 | if (prr == 0x61) | ||
110 | cpu_data->type = CPU_SH7781; | ||
111 | else | ||
112 | cpu_data->type = CPU_SH7780; | ||
113 | |||
114 | cpu_data->icache.ways = 4; | ||
115 | cpu_data->dcache.ways = 4; | ||
116 | |||
117 | cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER | | ||
118 | CPU_HAS_LLSC; | ||
119 | break; | ||
120 | case 0x3000: | ||
121 | case 0x3003: | ||
122 | cpu_data->type = CPU_SH7343; | ||
123 | cpu_data->icache.ways = 4; | ||
124 | cpu_data->dcache.ways = 4; | ||
125 | cpu_data->flags |= CPU_HAS_LLSC; | ||
80 | break; | 126 | break; |
81 | case 0x8000: | 127 | case 0x8000: |
82 | cpu_data->type = CPU_ST40RA; | 128 | cpu_data->type = CPU_ST40RA; |
129 | cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; | ||
83 | break; | 130 | break; |
84 | case 0x8100: | 131 | case 0x8100: |
85 | cpu_data->type = CPU_ST40GX1; | 132 | cpu_data->type = CPU_ST40GX1; |
133 | cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; | ||
86 | break; | 134 | break; |
87 | case 0x700: | 135 | case 0x700: |
88 | cpu_data->type = CPU_SH4_501; | 136 | cpu_data->type = CPU_SH4_501; |
89 | cpu_data->icache.ways = 2; | 137 | cpu_data->icache.ways = 2; |
90 | cpu_data->dcache.ways = 2; | 138 | cpu_data->dcache.ways = 2; |
91 | 139 | cpu_data->flags |= CPU_HAS_PTEA; | |
92 | /* No FPU on the SH4-500 series.. */ | ||
93 | cpu_data->flags &= ~CPU_HAS_FPU; | ||
94 | break; | 140 | break; |
95 | case 0x600: | 141 | case 0x600: |
96 | cpu_data->type = CPU_SH4_202; | 142 | cpu_data->type = CPU_SH4_202; |
97 | cpu_data->icache.ways = 2; | 143 | cpu_data->icache.ways = 2; |
98 | cpu_data->dcache.ways = 2; | 144 | cpu_data->dcache.ways = 2; |
145 | cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; | ||
99 | break; | 146 | break; |
100 | case 0x500 ... 0x501: | 147 | case 0x500 ... 0x501: |
101 | switch (prr) { | 148 | switch (prr) { |
102 | case 0x10: cpu_data->type = CPU_SH7750R; break; | 149 | case 0x10: |
103 | case 0x11: cpu_data->type = CPU_SH7751R; break; | 150 | cpu_data->type = CPU_SH7750R; |
104 | case 0x50: cpu_data->type = CPU_SH7760; break; | 151 | break; |
152 | case 0x11: | ||
153 | cpu_data->type = CPU_SH7751R; | ||
154 | break; | ||
155 | case 0x50 ... 0x5f: | ||
156 | cpu_data->type = CPU_SH7760; | ||
157 | break; | ||
105 | } | 158 | } |
106 | 159 | ||
107 | cpu_data->icache.ways = 2; | 160 | cpu_data->icache.ways = 2; |
108 | cpu_data->dcache.ways = 2; | 161 | cpu_data->dcache.ways = 2; |
109 | 162 | ||
163 | cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; | ||
164 | |||
110 | break; | 165 | break; |
111 | default: | 166 | default: |
112 | cpu_data->type = CPU_SH_NONE; | 167 | cpu_data->type = CPU_SH_NONE; |
113 | break; | 168 | break; |
114 | } | 169 | } |
115 | 170 | ||
171 | #ifdef CONFIG_SH_DIRECT_MAPPED | ||
172 | cpu_data->icache.ways = 1; | ||
173 | cpu_data->dcache.ways = 1; | ||
174 | #endif | ||
175 | |||
116 | /* | 176 | /* |
117 | * On anything that's not a direct-mapped cache, look to the CVR | 177 | * On anything that's not a direct-mapped cache, look to the CVR |
118 | * for I/D-cache specifics. | 178 | * for I/D-cache specifics. |
@@ -121,18 +181,56 @@ int __init detect_cpu_and_cache_system(void) | |||
121 | size = sizes[(cvr >> 20) & 0xf]; | 181 | size = sizes[(cvr >> 20) & 0xf]; |
122 | cpu_data->icache.way_incr = (size >> 1); | 182 | cpu_data->icache.way_incr = (size >> 1); |
123 | cpu_data->icache.sets = (size >> 6); | 183 | cpu_data->icache.sets = (size >> 6); |
124 | cpu_data->icache.entry_mask = | 184 | |
125 | (cpu_data->icache.way_incr - (1 << 5)); | ||
126 | } | 185 | } |
127 | 186 | ||
187 | /* Setup the rest of the I-cache info */ | ||
188 | cpu_data->icache.entry_mask = cpu_data->icache.way_incr - | ||
189 | cpu_data->icache.linesz; | ||
190 | |||
191 | cpu_data->icache.way_size = cpu_data->icache.sets * | ||
192 | cpu_data->icache.linesz; | ||
193 | |||
194 | /* And the rest of the D-cache */ | ||
128 | if (cpu_data->dcache.ways > 1) { | 195 | if (cpu_data->dcache.ways > 1) { |
129 | size = sizes[(cvr >> 16) & 0xf]; | 196 | size = sizes[(cvr >> 16) & 0xf]; |
130 | cpu_data->dcache.way_incr = (size >> 1); | 197 | cpu_data->dcache.way_incr = (size >> 1); |
131 | cpu_data->dcache.sets = (size >> 6); | 198 | cpu_data->dcache.sets = (size >> 6); |
132 | cpu_data->dcache.entry_mask = | 199 | } |
133 | (cpu_data->dcache.way_incr - (1 << 5)); | 200 | |
201 | cpu_data->dcache.entry_mask = cpu_data->dcache.way_incr - | ||
202 | cpu_data->dcache.linesz; | ||
203 | |||
204 | cpu_data->dcache.way_size = cpu_data->dcache.sets * | ||
205 | cpu_data->dcache.linesz; | ||
206 | |||
207 | /* | ||
208 | * Setup the L2 cache desc | ||
209 | * | ||
210 | * SH-4A's have an optional PIPT L2. | ||
211 | */ | ||
212 | if (cpu_data->flags & CPU_HAS_L2_CACHE) { | ||
213 | /* | ||
214 | * Size calculation is much more sensible | ||
215 | * than it is for the L1. | ||
216 | * | ||
217 | * Sizes are 128KB, 258KB, 512KB, and 1MB. | ||
218 | */ | ||
219 | size = (cvr & 0xf) << 17; | ||
220 | |||
221 | BUG_ON(!size); | ||
222 | |||
223 | cpu_data->scache.way_incr = (1 << 16); | ||
224 | cpu_data->scache.entry_shift = 5; | ||
225 | cpu_data->scache.ways = 4; | ||
226 | cpu_data->scache.linesz = L1_CACHE_BYTES; | ||
227 | cpu_data->scache.entry_mask = | ||
228 | (cpu_data->scache.way_incr - cpu_data->scache.linesz); | ||
229 | cpu_data->scache.sets = size / | ||
230 | (cpu_data->scache.linesz * cpu_data->scache.ways); | ||
231 | cpu_data->scache.way_size = | ||
232 | (cpu_data->scache.sets * cpu_data->scache.linesz); | ||
134 | } | 233 | } |
135 | 234 | ||
136 | return 0; | 235 | return 0; |
137 | } | 236 | } |
138 | |||