Since some people disapprove of white space cleanups mixed in regular commits
[coreboot.git] / src / cpu / amd / model_fxx / processor_name.c
1 /*
2  * This file is part of the coreboot project.
3  *
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.)
8  *
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.
12  *
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.
17  *
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
21  */
22
23 /*
24  * This code sets the Processor Name String for AMD64 CPUs.
25  *
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).
29  *
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).
33  */
34
35 #include <console/console.h>
36 #include <string.h>
37 #include <cpu/x86/msr.h>
38 #include <cpu/amd/model_fxx_rev.h>
39
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
43  */
44
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+",
72         /* 0x1F */ NULL,
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",
78         /* 0x25 */ NULL,
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
100 };
101 #endif
102
103 /* wrmsr_amd() is from yhlu's changes to model_fxx_init.c */
104
105 static inline void wrmsr_amd(unsigned index, msr_t msr)
106 {
107         __asm__ __volatile__ (
108                 "wrmsr"
109                 : /* No outputs */
110                 : "c" (index), "a" (msr.lo), "d" (msr.hi), "D" (0x9c5a203a)
111                 );
112 }
113
114 static inline void strcpy(char *dst, const char *src)
115 {
116         while (*src) *dst++ = *src++;
117 }
118
119
120 int init_processor_name(void)
121 {
122 #if CONFIG_K8_REV_F_SUPPORT == 0
123         u32 EightBitBrandId;
124 #endif
125         u32 BrandId;
126         u32 BrandTableIndex;
127         u32 NN;
128         u32 ModelNumber=0;
129         msr_t progmsr;
130         int i;
131
132         const char *processor_name_string=NULL;
133         char program_string[48];
134         unsigned int *program_values = (unsigned int *)program_string;
135
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;
140
141         if(!EightBitBrandId && !BrandId) {
142                 BrandTableIndex = 0;
143                 NN = 0xffffff;
144         } else if(!EightBitBrandId) {
145                 BrandTableIndex = (BrandId >> 6) & 0x3f; // BrandId[11:6]
146                 NN = BrandId & 0x3f; // // BrandId[6:0]
147         } else {
148                 BrandTableIndex = EightBitBrandId >> (5-2) & 0xfc; // { 0b, 8BitBrandId[7:5], 00b }
149                 NN = EightBitBrandId & 0x1f; // 8BitBrandId[4:0]
150         }
151
152         /* Look up the CPU brand in above table */
153         if (BrandTableIndex <= MAX_CPU_NUMBER)
154                 processor_name_string = processor_names[BrandTableIndex];
155
156         if (!processor_name_string)
157                 processor_name_string = "AMD Processor model unknown";
158 #endif
159
160 #if CONFIG_K8_REV_F_SUPPORT == 1
161         u32 Socket;
162         u32 CmpCap;
163         u32 PwrLmt;
164
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
168
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]
172
173         if (((BrandTableIndex == 0) && (PwrLmt == 0)) || (NN == 0)) {
174                 processor_name_string = "AMD Engineering Sample";
175         } else {
176                 /* Use all fields to identify CPU */
177                 switch ((Socket << 16) | (CmpCap << 12) | (BrandTableIndex << 4)
178                         | PwrLmt) {
179                 /* Socket F */
180                 case 0x10012:
181                         processor_name_string =
182                             "AMD Opteron(tm) Processor 22RR EE";
183                         break;
184                 case 0x11002:
185                         processor_name_string =
186                             "Dual-Core AMD Opteron(tm) Processor 12RR EE";
187                         break;
188                 case 0x11006:
189                         processor_name_string =
190                             "Dual-Core AMD Opteron(tm) Processor 12RR HE";
191                         break;
192                 case 0x11012:
193                         processor_name_string =
194                             "Dual-Core AMD Opteron(tm) Processor 22RR EE";
195                         break;
196                 case 0x11016:
197                         processor_name_string =
198                             "Dual-Core AMD Opteron(tm) Processor 22RR HE";
199                         break;
200                 case 0x1101a:
201                         processor_name_string =
202                             "Dual-Core AMD Opteron(tm) Processor 22RR";
203                         break;
204                 case 0x1101c:
205                         processor_name_string =
206                             "Dual-Core AMD Opteron(tm) Processor 22RR SE";
207                         break;
208                 case 0x11042:
209                         processor_name_string =
210                             "Dual-Core AMD Opteron(tm) Processor 82RR EE";
211                         break;
212                 case 0x11046:
213                         processor_name_string =
214                             "Dual-Core AMD Opteron(tm) Processor 82RR HE";
215                         break;
216                 case 0x1104a:
217                         processor_name_string =
218                             "Dual-Core AMD Opteron(tm) Processor 82RR";
219                         break;
220                 case 0x1104c:
221                         processor_name_string =
222                             "Dual-Core AMD Opteron(tm) Processor 82RR SE";
223                         break;
224                 case 0x1106e:
225                         processor_name_string =
226                             "AMD Athlon(tm) 64 Processor FX-ZZ Processor";
227                         break;
228                 /* Socket AM2 */
229                 /* single core */
230                 case 0x30015:
231                         processor_name_string =
232                             "AMD Sempron(tm) Processor LE-1RR0";
233                         break;
234                 case 0x30026:
235                         processor_name_string =
236                             "AMD Athlon(tm) Processor LE-1ZZ0";
237                         break;
238                 case 0x30036:
239                         processor_name_string =
240                             "AMD Athlon(tm) Processor 1ZZ0B";
241                         break;
242                 case 0x30041:
243                 case 0x30042:
244                 case 0x30043:
245                 case 0x30044:
246                 case 0x30045:
247                 case 0x30048:
248                         processor_name_string =
249                             "AMD Athlon(tm) 64 Processor TT00+";
250                         break;
251                 case 0x30052:
252                         processor_name_string =
253                             "AMD Sempron(tm) Processor RR50p";
254                 case 0x30064:
255                 case 0x30068:
256                         processor_name_string =
257                             "AMD Sempron(tm) Processor TT00+";
258                         break;
259                 case 0x30071:
260                 case 0x30072:
261                         processor_name_string =
262                             "AMD Sempron(tm) Processor TT0U";
263                         break;
264                 case 0x30082:
265                 case 0x30083:
266                         processor_name_string =
267                             "AMD Athlon(tm) Processor TT50e";
268                         break;
269                 case 0x30092:
270                         processor_name_string =
271                             "AMD Athlon(tm) Neo Processor MV-TT";
272                         break;
273                 case 0x300c2:
274                         processor_name_string =
275                             "AMD Sempron(tm) Processor 2RRU";
276                         break;
277                 /* dual-core */
278                 case 0x31016:
279                         processor_name_string =
280                             "Dual-Core AMD Opteron(tm) Processor 12RR HE";
281                         break;
282                 case 0x3101a:
283                         processor_name_string =
284                             "Dual-Core AMD Opteron(tm) Processor 12RR";
285                         break;
286                 case 0x3101c:
287                         processor_name_string =
288                             "Dual-Core AMD Opteron(tm) Processor 12RR SE";
289                         break;
290                 case 0x31033:
291                         processor_name_string =
292                             "AMD Athlon(tm) X2 Dual Core Processor BE-2TT0";
293                         break;
294                 case 0x31041:
295                 case 0x31042:
296                 case 0x31046:
297                 case 0x31048:
298                 case 0x3104c:
299                         processor_name_string =
300                             "AMD Athlon(tm) 64 X2 Dual Core Processor TT00+";
301                         break;
302                 case 0x3105c:
303                         processor_name_string =
304                             "AMD Athlon(tm) 64 FX-ZZ Dual Core Processor";
305                         break;
306                 case 0x31066:
307                         processor_name_string =
308                             "AMD Sempron(tm) Dual Core Processor RR00";
309                         break;
310                 case 0x31073:
311                         processor_name_string =
312                             "AMD Athlon(tm) Dual Core Processor TT50e";
313                         break;
314                 case 0x31076:
315                 case 0x31077:
316                         processor_name_string =
317                             "AMD Athlon(tm) Dual Core Processor TT00B";
318                         break;
319                 case 0x31083:
320                         processor_name_string =
321                             "AMD Athlon(tm) Dual Core Processor TT50B";
322                         break;
323                 case 0x31091:
324                         processor_name_string =
325                             "AMD Athlon(tm) X2 Dual Core Processor TT50e";
326                         break;
327                 case 0x310a1:
328                 case 0x310a2:
329                         processor_name_string =
330                             "AMD Athlon(tm) Neo X2 Dual Core Processor TT50e";
331                         break;
332                 case 0x310b0:
333                 case 0x310c0:
334                         processor_name_string =
335                             "AMD Turion(tm) Neo X2 Dual Core Processor L6RR";
336                         break;
337                 /* Socket S1g1 */
338                 /* single core */
339                 case 0x00012:
340                         processor_name_string =
341                             "AMD Athlon(tm) 64 Processor TT00+";
342                         break;
343                 case 0x0002c:
344                         processor_name_string =
345                             "AMD Turion(tm) 64 Mobile Technology MK-YY";
346                         break;
347                 case 0x00031:
348                         processor_name_string =
349                             "Mobile AMD Sempron(tm) Processor TT00+";
350                         break;
351                 case 0x00036:
352                         processor_name_string =
353                             "Mobile AMD Sempron(tm) Processor PP00+";
354                         break;
355                 case 0x0003c:
356                         processor_name_string =
357                             "Mobile AMD Sempron(tm) Processor PP00+";
358                         break;
359                 case 0x00042:
360                         processor_name_string =
361                             "AMD Sempron(tm) Processor TT00+";
362                         break;
363                 case 0x00064:
364                 case 0x00066:
365                 case 0x0006c:
366                         processor_name_string =
367                             "AMD Athlon(tm) Processor TF-TT";
368                         break;
369                 case 0x00073:
370                         processor_name_string =
371                             "AMD Athlon(tm) Processor L1RR";
372                         break;
373                 /* dual-core */
374                 case 0x0101c:
375                         processor_name_string =
376                             "AMD Sempron(tm) Dual Core Processor TJ-YY";
377                         break;
378                 case 0x0102c:
379                         processor_name_string =
380                             "AMD Turion(tm) 64 X2 Mobile Technology TL-YY";
381                         break;
382                 case 0x01034:
383                 case 0x0103c:
384                         processor_name_string =
385                             "AMD Athlon(tm) 64 X2 Dual-Core Processor TK-YY";
386                         break;
387                 case 0x01054:
388                         processor_name_string =
389                             "AMD Athlon(tm) 64 X2 Dual Core Processor TT00+";
390                         break;
391                 case 0x01062:
392                         processor_name_string =
393                             "AMD Athlon(tm) X2 Dual Core Processor L3RR";
394                         break;
395                 case 0x01074:
396                         processor_name_string =
397                             "AMD Athlon(tm) X2 Dual Core Processor L5RR";
398                         break;
399                 default:
400                         processor_name_string = "AMD Processor model unknown";
401                 }
402         }
403 #endif
404
405         memset(program_string, 0, 48);
406         strcpy(program_string, processor_name_string);
407
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.
411          */
412
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;
419                         case 'Z':
420                         case 'T': ModelNumber = 24 + NN; break;
421                         case 'R': ModelNumber = 45 + (5*NN); break;
422                         case 'V': ModelNumber =  9 + NN; break;
423 #endif
424
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;
431 #endif
432                         }
433
434                         if(ModelNumber && ModelNumber < 100) {
435                                 // No idea what to do with RR=100. According
436                                 // to the revision guide this is possible.
437                                 //
438                                 // --> "AMD Opteron(tm) Processor 8100"?
439                                 program_string[i]=(ModelNumber/10)+'0';
440                                 program_string[i+1]=(ModelNumber%10)+'0';
441                                 break;
442                         }
443                 }
444         }
445
446         printk(BIOS_DEBUG, "CPU model %s\n", program_string);
447
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);
452         }
453
454         return 0;
455 }
456