2 * This file is part of the coreboot project.
4 * Copyright (C) 2006 coresystems GmbH
5 * (Written by Stefan Reinauer <stepan@coresystems.de> for coresystems GmbH)
6 * Copyright (C) 2007 University of Mannheim
7 * (Written by Sven Kapferer <skapfere@rumms.uni-mannheim.de> for Uni Ma.)
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
24 * This code sets the Processor Name String for AMD64 CPUs.
26 * Written by Stefan Reinauer <stepan@coresystems.de> using
27 * the Revision Guide for AMD Athlon™ 64 and AMD Opteron™ Processors
28 * Document ID 25759 Rev 3.59, April 2006 (Public Version).
30 * Updated by Sven Kapferer <skapfere@rumms.uni-mannheim.de> using
31 * the Revision Guide for AMD NPT Family 0Fh Processors
32 * Document ID 33610 Rev 3.00, October 2006 (Public Version).
35 #include <console/console.h>
37 #include <cpu/x86/msr.h>
38 #include <cpu/amd/model_fxx_rev.h>
40 /* The maximum length of CPU names is 48 bytes, including the final NULL byte.
41 * If you change these names your BIOS will _NOT_ pass the AMD validation and
42 * your mainboard will not be posted on the AMD Recommended Motherboard Website
45 #if CONFIG_K8_REV_F_SUPPORT == 0
46 static const char *processor_names[]={
47 /* 0x00 */ "AMD Engineering Sample",
48 /* 0x01-0x03 */ NULL, NULL, NULL,
49 /* 0x04 */ "AMD Athlon(tm) 64 Processor XX00+",
50 /* 0x05 */ "AMD Athlon(tm) 64 X2 Dual Core Processor XX00+",
51 /* 0x06-0x07 */ NULL, NULL,
52 /* 0x08 */ "Mobile AMD Athlon(tm) 64 Processor XX00+",
53 /* 0x09 */ "Mobile AMD Athlon(tm) 64 Processor XX00+",
54 /* 0x0A */ "AMD Turion(tm) 64 Mobile Technology ML-XX",
55 /* 0x0B */ "AMD Turion(tm) 64 Mobile Technology MT-XX",
56 /* 0x0C */ "AMD Opteron(tm) Processor 1YY",
57 /* 0x0D */ "AMD Opteron(tm) Processor 1YY",
58 /* 0x0E */ "AMD Opteron(tm) Processor 1YY HE",
59 /* 0x0F */ "AMD Opteron(tm) Processor 1YY EE",
60 /* 0x10 */ "AMD Opteron(tm) Processor 2YY",
61 /* 0x11 */ "AMD Opteron(tm) Processor 2YY",
62 /* 0x12 */ "AMD Opteron(tm) Processor 2YY HE",
63 /* 0x13 */ "AMD Opteron(tm) Processor 2YY EE",
64 /* 0x14 */ "AMD Opteron(tm) Processor 8YY",
65 /* 0x15 */ "AMD Opteron(tm) Processor 8YY",
66 /* 0x16 */ "AMD Opteron(tm) Processor 8YY HE",
67 /* 0x17 */ "AMD Opteron(tm) Processor 8YY EE",
68 /* 0x18 */ "AMD Athlon(tm) 64 Processor VV00+",
69 /* 0x19-0x1C */ NULL, NULL, NULL, NULL,
70 /* 0x1D */ "Mobile AMD Athlon(tm) XP-M Processor XX00+",
71 /* 0x1E */ "Mobile AMD Athlon(tm) XP-M Processor XX00+",
73 /* 0x20 */ "AMD Athlon(tm) XP Processor XX00+",
74 /* 0x21 */ "Mobile AMD Sempron(tm) Processor TT00+",
75 /* 0x22 */ "AMD Sempron(tm) Processor TT00+",
76 /* 0x23 */ "Mobile AMD Sempron(tm) Processor TT00+",
77 /* 0x24 */ "AMD Athlon(tm) 64 FX-ZZ Processor",
79 /* 0x26 */ "AMD Sempron(tm) Processor TT00+",
80 /* 0x27-0x28 */ NULL, NULL,
81 /* 0x29 */ "Dual Core AMD Opteron(tm) Processor 1RR SE",
82 /* 0x2A */ "Dual Core AMD Opteron(tm) Processor 2RR SE",
83 /* 0x2B */ "Dual Core AMD Opteron(tm) Processor 8RR SE",
84 /* 0x2C */ "Dual Core AMD Opteron(tm) Processor 1RR",
85 /* 0x2D */ "Dual Core AMD Opteron(tm) Processor 1RR",
86 /* 0x2E */ "Dual Core AMD Opteron(tm) Processor 1RR HE",
87 /* 0x2F */ "Dual Core AMD Opteron(tm) Processor 1RR EE",
88 /* 0x30 */ "Dual Core AMD Opteron(tm) Processor 2RR",
89 /* 0x31 */ "Dual Core AMD Opteron(tm) Processor 2RR",
90 /* 0x32 */ "Dual Core AMD Opteron(tm) Processor 2RR HE",
91 /* 0x33 */ "Dual Core AMD Opteron(tm) Processor 2RR EE",
92 /* 0x34 */ "Dual Core AMD Opteron(tm) Processor 8RR",
93 /* 0x35 */ "Dual Core AMD Opteron(tm) Processor 8RR",
94 /* 0x36 */ "Dual Core AMD Opteron(tm) Processor 8RR HE",
95 /* 0x37 */ "Dual Core AMD Opteron(tm) Processor 8RR EE",
96 /* 0x38 */ "Dual Core AMD Opteron(tm) Processor 1RR",
97 /* 0x39 */ "Dual Core AMD Opteron(tm) Processor 2RR",
98 /* 0x3A */ "Dual Core AMD Opteron(tm) Processor 8RR"
99 #define MAX_CPU_NUMBER 0x3A
103 /* wrmsr_amd() is from yhlu's changes to model_fxx_init.c */
105 static inline void wrmsr_amd(unsigned index, msr_t msr)
107 __asm__ __volatile__ (
110 : "c" (index), "a" (msr.lo), "d" (msr.hi), "D" (0x9c5a203a)
114 static inline void strcpy(char *dst, const char *src)
116 while (*src) *dst++ = *src++;
120 int init_processor_name(void)
122 #if CONFIG_K8_REV_F_SUPPORT == 0
132 const char *processor_name_string=NULL;
133 char program_string[48];
134 unsigned int *program_values = (unsigned int *)program_string;
136 #if CONFIG_K8_REV_F_SUPPORT == 0
137 /* Find out which CPU brand it is */
138 EightBitBrandId = cpuid_ebx(0x00000001) & 0xff;
139 BrandId = cpuid_ebx(0x80000001) & 0xffff;
141 if(!EightBitBrandId && !BrandId) {
144 } else if(!EightBitBrandId) {
145 BrandTableIndex = (BrandId >> 6) & 0x3f; // BrandId[11:6]
146 NN = BrandId & 0x3f; // // BrandId[6:0]
148 BrandTableIndex = EightBitBrandId >> (5-2) & 0xfc; // { 0b, 8BitBrandId[7:5], 00b }
149 NN = EightBitBrandId & 0x1f; // 8BitBrandId[4:0]
152 /* Look up the CPU brand in above table */
153 if (BrandTableIndex <= MAX_CPU_NUMBER)
154 processor_name_string = processor_names[BrandTableIndex];
156 if (!processor_name_string)
157 processor_name_string = "AMD Processor model unknown";
160 #if CONFIG_K8_REV_F_SUPPORT == 1
165 BrandId = cpuid_ebx(0x80000001) & 0xffff;
166 Socket = (cpuid_eax(0x80000001) & 0x00000030) >> 4; // 00b = S1g1, 01b = F (1207), 11b = AM2
167 CmpCap = cpuid_ecx(0x80000008) & 0x03; // Number of CPU cores
169 PwrLmt = ((BrandId >> 14) & 0x01) | ((BrandId >> 5) & 0x0e); // BrandId[8:6,14]
170 BrandTableIndex = (BrandId >> 9) & 0x1f; // BrandId[13:9]
171 NN = ((BrandId >> 15) & 0x01) | (BrandId & 0x3f); // BrandId[15,5:0]
173 if (((BrandTableIndex == 0) && (PwrLmt == 0)) || (NN == 0)) {
174 processor_name_string = "AMD Engineering Sample";
176 /* Use all fields to identify CPU */
177 switch ((Socket << 16) | (CmpCap << 12) | (BrandTableIndex << 4)
181 processor_name_string =
182 "AMD Opteron(tm) Processor 22RR EE";
185 processor_name_string =
186 "Dual-Core AMD Opteron(tm) Processor 12RR EE";
189 processor_name_string =
190 "Dual-Core AMD Opteron(tm) Processor 12RR HE";
193 processor_name_string =
194 "Dual-Core AMD Opteron(tm) Processor 22RR EE";
197 processor_name_string =
198 "Dual-Core AMD Opteron(tm) Processor 22RR HE";
201 processor_name_string =
202 "Dual-Core AMD Opteron(tm) Processor 22RR";
205 processor_name_string =
206 "Dual-Core AMD Opteron(tm) Processor 22RR SE";
209 processor_name_string =
210 "Dual-Core AMD Opteron(tm) Processor 82RR EE";
213 processor_name_string =
214 "Dual-Core AMD Opteron(tm) Processor 82RR HE";
217 processor_name_string =
218 "Dual-Core AMD Opteron(tm) Processor 82RR";
221 processor_name_string =
222 "Dual-Core AMD Opteron(tm) Processor 82RR SE";
225 processor_name_string =
226 "AMD Athlon(tm) 64 Processor FX-ZZ Processor";
231 processor_name_string =
232 "AMD Sempron(tm) Processor LE-1RR0";
235 processor_name_string =
236 "AMD Athlon(tm) Processor LE-1ZZ0";
239 processor_name_string =
240 "AMD Athlon(tm) Processor 1ZZ0B";
248 processor_name_string =
249 "AMD Athlon(tm) 64 Processor TT00+";
252 processor_name_string =
253 "AMD Sempron(tm) Processor RR50p";
256 processor_name_string =
257 "AMD Sempron(tm) Processor TT00+";
261 processor_name_string =
262 "AMD Sempron(tm) Processor TT0U";
266 processor_name_string =
267 "AMD Athlon(tm) Processor TT50e";
270 processor_name_string =
271 "AMD Athlon(tm) Neo Processor MV-TT";
274 processor_name_string =
275 "AMD Sempron(tm) Processor 2RRU";
279 processor_name_string =
280 "Dual-Core AMD Opteron(tm) Processor 12RR HE";
283 processor_name_string =
284 "Dual-Core AMD Opteron(tm) Processor 12RR";
287 processor_name_string =
288 "Dual-Core AMD Opteron(tm) Processor 12RR SE";
291 processor_name_string =
292 "AMD Athlon(tm) X2 Dual Core Processor BE-2TT0";
299 processor_name_string =
300 "AMD Athlon(tm) 64 X2 Dual Core Processor TT00+";
303 processor_name_string =
304 "AMD Athlon(tm) 64 FX-ZZ Dual Core Processor";
307 processor_name_string =
308 "AMD Sempron(tm) Dual Core Processor RR00";
311 processor_name_string =
312 "AMD Athlon(tm) Dual Core Processor TT50e";
316 processor_name_string =
317 "AMD Athlon(tm) Dual Core Processor TT00B";
320 processor_name_string =
321 "AMD Athlon(tm) Dual Core Processor TT50B";
324 processor_name_string =
325 "AMD Athlon(tm) X2 Dual Core Processor TT50e";
329 processor_name_string =
330 "AMD Athlon(tm) Neo X2 Dual Core Processor TT50e";
334 processor_name_string =
335 "AMD Turion(tm) Neo X2 Dual Core Processor L6RR";
340 processor_name_string =
341 "AMD Athlon(tm) 64 Processor TT00+";
344 processor_name_string =
345 "AMD Turion(tm) 64 Mobile Technology MK-YY";
348 processor_name_string =
349 "Mobile AMD Sempron(tm) Processor TT00+";
352 processor_name_string =
353 "Mobile AMD Sempron(tm) Processor PP00+";
356 processor_name_string =
357 "Mobile AMD Sempron(tm) Processor PP00+";
360 processor_name_string =
361 "AMD Sempron(tm) Processor TT00+";
366 processor_name_string =
367 "AMD Athlon(tm) Processor TF-TT";
370 processor_name_string =
371 "AMD Athlon(tm) Processor L1RR";
375 processor_name_string =
376 "AMD Sempron(tm) Dual Core Processor TJ-YY";
379 processor_name_string =
380 "AMD Turion(tm) 64 X2 Mobile Technology TL-YY";
384 processor_name_string =
385 "AMD Athlon(tm) 64 X2 Dual-Core Processor TK-YY";
388 processor_name_string =
389 "AMD Athlon(tm) 64 X2 Dual Core Processor TT00+";
392 processor_name_string =
393 "AMD Athlon(tm) X2 Dual Core Processor L3RR";
396 processor_name_string =
397 "AMD Athlon(tm) X2 Dual Core Processor L5RR";
400 processor_name_string = "AMD Processor model unknown";
405 memset(program_string, 0, 48);
406 strcpy(program_string, processor_name_string);
408 /* Now create a model number - See Table 4. Model Number Calculation
409 * in the Revision Guide. NOTE: #6, EE was changed to VV because
410 * otherwise it clashes with the brand names.
413 for (i=0; i<47; i++) { // 48 -1
414 if(program_string[i] == program_string[i+1]) {
415 switch (program_string[i]) {
416 #if CONFIG_K8_REV_F_SUPPORT == 0
417 case 'X': ModelNumber = 22+ NN; break;
418 case 'Y': ModelNumber = 38 + (2*NN); break;
420 case 'T': ModelNumber = 24 + NN; break;
421 case 'R': ModelNumber = 45 + (5*NN); break;
422 case 'V': ModelNumber = 9 + NN; break;
425 #if CONFIG_K8_REV_F_SUPPORT == 1
426 case 'R': ModelNumber = NN - 1; break;
427 case 'P': ModelNumber = 26 + NN; break;
428 case 'T': ModelNumber = 15 + (CmpCap * 10) + NN; break;
429 case 'Z': ModelNumber = 57 + NN; break;
430 case 'Y': ModelNumber = 29 + NN; break;
434 if(ModelNumber && ModelNumber < 100) {
435 // No idea what to do with RR=100. According
436 // to the revision guide this is possible.
438 // --> "AMD Opteron(tm) Processor 8100"?
439 program_string[i]=(ModelNumber/10)+'0';
440 program_string[i+1]=(ModelNumber%10)+'0';
446 printk(BIOS_DEBUG, "CPU model %s\n", program_string);
448 for (i=0; i<6; i++) {
449 progmsr.lo = program_values[(2*i)+0];
450 progmsr.hi = program_values[(2*i)+1];
451 wrmsr_amd(0xc0010030+i, progmsr);