Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
probe.c
Go to the documentation of this file.
1 /*
2  * arch/sh/kernel/cpu/sh4/probe.c
3  *
4  * CPU Subtype Probing for SH-4.
5  *
6  * Copyright (C) 2001 - 2007 Paul Mundt
7  * Copyright (C) 2003 Richard Curnow
8  *
9  * This file is subject to the terms and conditions of the GNU General Public
10  * License. See the file "COPYING" in the main directory of this archive
11  * for more details.
12  */
13 #include <linux/init.h>
14 #include <linux/io.h>
15 #include <asm/processor.h>
16 #include <asm/cache.h>
17 
18 void __cpuinit cpu_probe(void)
19 {
20  unsigned long pvr, prr, cvr;
21  unsigned long size;
22 
23  static unsigned long sizes[16] = {
24  [1] = (1 << 12),
25  [2] = (1 << 13),
26  [4] = (1 << 14),
27  [8] = (1 << 15),
28  [9] = (1 << 16)
29  };
30 
31  pvr = (__raw_readl(CCN_PVR) >> 8) & 0xffffff;
32  prr = (__raw_readl(CCN_PRR) >> 4) & 0xff;
33  cvr = (__raw_readl(CCN_CVR));
34 
35  /*
36  * Setup some sane SH-4 defaults for the icache
37  */
38  boot_cpu_data.icache.way_incr = (1 << 13);
39  boot_cpu_data.icache.entry_shift = 5;
40  boot_cpu_data.icache.sets = 256;
41  boot_cpu_data.icache.ways = 1;
42  boot_cpu_data.icache.linesz = L1_CACHE_BYTES;
43 
44  /*
45  * And again for the dcache ..
46  */
47  boot_cpu_data.dcache.way_incr = (1 << 14);
48  boot_cpu_data.dcache.entry_shift = 5;
49  boot_cpu_data.dcache.sets = 512;
50  boot_cpu_data.dcache.ways = 1;
51  boot_cpu_data.dcache.linesz = L1_CACHE_BYTES;
52 
53  /* We don't know the chip cut */
54  boot_cpu_data.cut_major = boot_cpu_data.cut_minor = -1;
55 
56  /*
57  * Setup some generic flags we can probe on SH-4A parts
58  */
59  if (((pvr >> 16) & 0xff) == 0x10) {
61 
62  if ((cvr & 0x10000000) == 0) {
63  boot_cpu_data.flags |= CPU_HAS_DSP;
65  }
66 
68  boot_cpu_data.cut_major = pvr & 0x7f;
69 
70  boot_cpu_data.icache.ways = 4;
71  boot_cpu_data.dcache.ways = 4;
72  } else {
73  /* And some SH-4 defaults.. */
76  }
77 
78  /* FPU detection works for almost everyone */
79  if ((cvr & 0x20000000))
80  boot_cpu_data.flags |= CPU_HAS_FPU;
81 
82  /* Mask off the upper chip ID */
83  pvr &= 0xffff;
84 
85  /*
86  * Probe the underlying processor version/revision and
87  * adjust cpu_data setup accordingly.
88  */
89  switch (pvr) {
90  case 0x205:
94  break;
95  case 0x206:
99  break;
100  case 0x1100:
101  boot_cpu_data.type = CPU_SH7751;
102  break;
103  case 0x2001:
104  case 0x2004:
105  boot_cpu_data.type = CPU_SH7770;
106  break;
107  case 0x2006:
108  case 0x200A:
109  if (prr == 0x61)
110  boot_cpu_data.type = CPU_SH7781;
111  else if (prr == 0xa1)
112  boot_cpu_data.type = CPU_SH7763;
113  else
114  boot_cpu_data.type = CPU_SH7780;
115 
116  break;
117  case 0x3000:
118  case 0x3003:
119  case 0x3009:
120  boot_cpu_data.type = CPU_SH7343;
121  break;
122  case 0x3004:
123  case 0x3007:
124  boot_cpu_data.type = CPU_SH7785;
125  break;
126  case 0x4004:
127  case 0x4005:
128  boot_cpu_data.type = CPU_SH7786;
130  break;
131  case 0x3008:
132  switch (prr) {
133  case 0x50:
134  case 0x51:
135  boot_cpu_data.type = CPU_SH7723;
137  break;
138  case 0x70:
139  boot_cpu_data.type = CPU_SH7366;
140  break;
141  case 0xa0:
142  case 0xa1:
143  boot_cpu_data.type = CPU_SH7722;
144  break;
145  }
146  break;
147  case 0x300b:
148  switch (prr) {
149  case 0x20:
150  boot_cpu_data.type = CPU_SH7724;
152  break;
153  case 0x10:
154  case 0x11:
155  boot_cpu_data.type = CPU_SH7757;
156  break;
157  case 0xd0:
158  case 0x40: /* yon-ten-go */
159  boot_cpu_data.type = CPU_SH7372;
160  break;
161  case 0xE0: /* 0x4E0 */
162  boot_cpu_data.type = CPU_SH7734; /* SH7733/SH7734 */
163  break;
164 
165  }
166  break;
167  case 0x4000: /* 1st cut */
168  case 0x4001: /* 2nd cut */
169  boot_cpu_data.type = CPU_SHX3;
170  break;
171  case 0x700:
172  boot_cpu_data.type = CPU_SH4_501;
173  boot_cpu_data.flags &= ~CPU_HAS_FPU;
174  boot_cpu_data.icache.ways = 2;
175  boot_cpu_data.dcache.ways = 2;
176  break;
177  case 0x600:
178  boot_cpu_data.type = CPU_SH4_202;
179  boot_cpu_data.icache.ways = 2;
180  boot_cpu_data.dcache.ways = 2;
181  break;
182  case 0x500 ... 0x501:
183  switch (prr) {
184  case 0x10:
185  boot_cpu_data.type = CPU_SH7750R;
186  break;
187  case 0x11:
188  boot_cpu_data.type = CPU_SH7751R;
189  break;
190  case 0x50 ... 0x5f:
191  boot_cpu_data.type = CPU_SH7760;
192  break;
193  }
194 
195  boot_cpu_data.icache.ways = 2;
196  boot_cpu_data.dcache.ways = 2;
197 
198  break;
199  }
200 
201  /*
202  * On anything that's not a direct-mapped cache, look to the CVR
203  * for I/D-cache specifics.
204  */
205  if (boot_cpu_data.icache.ways > 1) {
206  size = sizes[(cvr >> 20) & 0xf];
207  boot_cpu_data.icache.way_incr = (size >> 1);
208  boot_cpu_data.icache.sets = (size >> 6);
209 
210  }
211 
212  /* And the rest of the D-cache */
213  if (boot_cpu_data.dcache.ways > 1) {
214  size = sizes[(cvr >> 16) & 0xf];
215  boot_cpu_data.dcache.way_incr = (size >> 1);
216  boot_cpu_data.dcache.sets = (size >> 6);
217  }
218 
219  /*
220  * SH-4A's have an optional PIPT L2.
221  */
222  if (boot_cpu_data.flags & CPU_HAS_L2_CACHE) {
223  /*
224  * Verify that it really has something hooked up, this
225  * is the safety net for CPUs that have optional L2
226  * support yet do not implement it.
227  */
228  if ((cvr & 0xf) == 0)
230  else {
231  /*
232  * Silicon and specifications have clearly never
233  * met..
234  */
235  cvr ^= 0xf;
236 
237  /*
238  * Size calculation is much more sensible
239  * than it is for the L1.
240  *
241  * Sizes are 128KB, 256KB, 512KB, and 1MB.
242  */
243  size = (cvr & 0xf) << 17;
244 
245  boot_cpu_data.scache.way_incr = (1 << 16);
246  boot_cpu_data.scache.entry_shift = 5;
247  boot_cpu_data.scache.ways = 4;
248  boot_cpu_data.scache.linesz = L1_CACHE_BYTES;
249 
250  boot_cpu_data.scache.entry_mask =
251  (boot_cpu_data.scache.way_incr -
252  boot_cpu_data.scache.linesz);
253 
254  boot_cpu_data.scache.sets = size /
255  (boot_cpu_data.scache.linesz *
256  boot_cpu_data.scache.ways);
257 
258  boot_cpu_data.scache.way_size =
259  (boot_cpu_data.scache.sets *
260  boot_cpu_data.scache.linesz);
261  }
262  }
263 }