This patch unifies the use of config options in v2 to all start with CONFIG_
[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
39 /* The maximum length of CPU names is 48 bytes, including the final NULL byte.
40  * If you change these names your BIOS will _NOT_ pass the AMD validation and
41  * your mainboard will not be posted on the AMD Recommended Motherboard Website
42  */
43
44 #if CONFIG_K8_REV_F_SUPPORT == 0
45 static char *processor_names[]={
46         /* 0x00 */ "AMD Engineering Sample",
47         /* 0x01-0x03 */ NULL, NULL, NULL,
48         /* 0x04 */ "AMD Athlon(tm) 64 Processor XX00+",
49         /* 0x05 */ "AMD Athlon(tm) 64 X2 Dual Core Processor XX00+",
50         /* 0x06-0x07 */ NULL, NULL,
51         /* 0x08 */ "Mobile AMD Athlon(tm) 64 Processor XX00+",
52         /* 0x09 */ "Mobile AMD Athlon(tm) 64 Processor XX00+",
53         /* 0x0A */ "AMD Turion(tm) 64 Mobile Technology ML-XX",
54         /* 0x0B */ "AMD Turion(tm) 64 Mobile Technology MT-XX",
55         /* 0x0C */ "AMD Opteron(tm) Processor 1YY",
56         /* 0x0D */ "AMD Opteron(tm) Processor 1YY",
57         /* 0x0E */ "AMD Opteron(tm) Processor 1YY HE",
58         /* 0x0F */ "AMD Opteron(tm) Processor 1YY EE",
59         /* 0x10 */ "AMD Opteron(tm) Processor 2YY",
60         /* 0x11 */ "AMD Opteron(tm) Processor 2YY",
61         /* 0x12 */ "AMD Opteron(tm) Processor 2YY HE",
62         /* 0x13 */ "AMD Opteron(tm) Processor 2YY EE",
63         /* 0x14 */ "AMD Opteron(tm) Processor 8YY",
64         /* 0x15 */ "AMD Opteron(tm) Processor 8YY",
65         /* 0x16 */ "AMD Opteron(tm) Processor 8YY HE",
66         /* 0x17 */ "AMD Opteron(tm) Processor 8YY EE",
67         /* 0x18 */ "AMD Athlon(tm) 64 Processor VV00+",
68         /* 0x19-0x1C */ NULL, NULL, NULL, NULL,
69         /* 0x1D */ "Mobile AMD Athlon(tm) XP-M Processor XX00+",
70         /* 0x1E */ "Mobile AMD Athlon(tm) XP-M Processor XX00+",
71         /* 0x1F */ NULL,
72         /* 0x20 */ "AMD Athlon(tm) XP Processor XX00+",
73         /* 0x21 */ "Mobile AMD Sempron(tm) Processor TT00+",
74         /* 0x22 */ "AMD Sempron(tm) Processor TT00+",
75         /* 0x23 */ "Mobile AMD Sempron(tm) Processor TT00+",
76         /* 0x24 */ "AMD Athlon(tm) 64 FX-ZZ Processor",
77         /* 0x25 */ NULL,
78         /* 0x26 */ "AMD Sempron(tm) Processor TT00+",
79         /* 0x27-0x28 */ NULL, NULL, 
80         /* 0x29 */ "Dual Core AMD Opteron(tm) Processor 1RR SE",
81         /* 0x2A */ "Dual Core AMD Opteron(tm) Processor 2RR SE",
82         /* 0x2B */ "Dual Core AMD Opteron(tm) Processor 8RR SE",
83         /* 0x2C */ "Dual Core AMD Opteron(tm) Processor 1RR",
84         /* 0x2D */ "Dual Core AMD Opteron(tm) Processor 1RR",
85         /* 0x2E */ "Dual Core AMD Opteron(tm) Processor 1RR HE",
86         /* 0x2F */ "Dual Core AMD Opteron(tm) Processor 1RR EE",
87         /* 0x30 */ "Dual Core AMD Opteron(tm) Processor 2RR",
88         /* 0x31 */ "Dual Core AMD Opteron(tm) Processor 2RR",
89         /* 0x32 */ "Dual Core AMD Opteron(tm) Processor 2RR HE",
90         /* 0x33 */ "Dual Core AMD Opteron(tm) Processor 2RR EE",
91         /* 0x34 */ "Dual Core AMD Opteron(tm) Processor 8RR",
92         /* 0x35 */ "Dual Core AMD Opteron(tm) Processor 8RR",
93         /* 0x36 */ "Dual Core AMD Opteron(tm) Processor 8RR HE",
94         /* 0x37 */ "Dual Core AMD Opteron(tm) Processor 8RR EE",
95         /* 0x38 */ "Dual Core AMD Opteron(tm) Processor 1RR",
96         /* 0x39 */ "Dual Core AMD Opteron(tm) Processor 2RR",
97         /* 0x3A */ "Dual Core AMD Opteron(tm) Processor 8RR"
98 #define MAX_CPU_NUMBER 0x3A
99 };
100 #endif
101
102 /* wrmsr_amd() is from yhlu's changes to model_fxx_init.c */
103
104 static inline void wrmsr_amd(unsigned index, msr_t msr)
105 {
106         __asm__ __volatile__ (
107                 "wrmsr"
108                 : /* No outputs */
109                 : "c" (index), "a" (msr.lo), "d" (msr.hi), "D" (0x9c5a203a)
110                 );
111 }
112
113 static inline unsigned int cpuid_eax(unsigned int op)
114 {
115         unsigned int eax;
116
117         __asm__("cpuid"
118                 : "=a" (eax)
119                 : "0" (op)
120                 : "ebx", "ecx", "edx");
121         return eax;
122 }
123
124 static inline unsigned int cpuid_ebx(unsigned int op)
125 {
126         unsigned int eax, ebx;
127
128         __asm__("cpuid"
129                 : "=a" (eax), "=b" (ebx)
130                 : "0" (op)
131                 : "ecx", "edx" );
132         return ebx;
133 }
134
135 static inline unsigned int cpuid_ecx(unsigned int op)
136 {
137         unsigned int eax, ecx;
138
139         __asm__("cpuid"
140                 : "=a" (eax), "=c" (ecx)
141                 : "0" (op)
142                 : "ebx", "edx" );
143         return ecx;
144 }
145
146 static inline void strcpy(char *dst, char *src) 
147 {
148         while (*src) *dst++ = *src++;
149 }
150
151
152 int init_processor_name(void)
153 {
154         u32 EightBitBrandId;
155         u32 BrandId;
156         u32 BrandTableIndex;
157         u32 NN;
158         u32 ModelNumber=0;
159         msr_t progmsr;
160         int i;
161
162         char *processor_name_string=NULL;
163         char program_string[48];
164         unsigned int *program_values = (unsigned int *)program_string;
165
166 #if CONFIG_K8_REV_F_SUPPORT == 0
167         /* Find out which CPU brand it is */
168         EightBitBrandId = cpuid_ebx(0x00000001) & 0xff;
169         BrandId = cpuid_ebx(0x80000001) & 0xffff;
170
171         if(!EightBitBrandId && !BrandId) {
172                 BrandTableIndex = 0;
173                 NN = 0xffffff;
174         } else if(!EightBitBrandId) {
175                 BrandTableIndex = (BrandId >> 6) & 0x3f; // BrandId[11:6]
176                 NN = BrandId & 0x3f; // // BrandId[6:0]
177         } else {
178                 BrandTableIndex = EightBitBrandId >> (5-2) & 0xfc; // { 0b, 8BitBrandId[7:5], 00b }
179                 NN = EightBitBrandId & 0x1f; // 8BitBrandId[4:0]
180         }
181
182         /* Look up the CPU brand in above table */
183         if (BrandTableIndex <= MAX_CPU_NUMBER)
184                 processor_name_string = processor_names[BrandTableIndex];
185
186         if (!processor_name_string)
187                 processor_name_string = "AMD Processor model unknown";
188 #endif
189
190 #if CONFIG_K8_REV_F_SUPPORT == 1
191         u32 Socket;
192         u32 CmpCap;
193         u32 PwrLmt;
194
195         BrandId = cpuid_ebx(0x80000001) & 0xffff;
196         Socket = (cpuid_eax(0x80000001) & 0x00000030) >> 4; // 00b = S1g1, 01b = F (1207), 11b = AM2
197         CmpCap = cpuid_ecx(0x80000008) & 0x03; // Number of CPU cores
198
199         PwrLmt = ((BrandId >> 14) & 0x01) | ((BrandId >> 5) & 0x0e); // BrandId[8:6,14]
200         BrandTableIndex = (BrandId >> 9) & 0x1f; // BrandId[13:9]
201         NN = ((BrandId >> 15) & 0x01) | (BrandId & 0x3f); // BrandId[15,5:0]
202
203         if (((BrandTableIndex == 0) && (PwrLmt == 0)) || (NN == 0)) {
204                 processor_name_string = "AMD Engineering Sample";
205         } else {
206                 /* Use all fields to identify CPU */
207                 switch ((Socket << 16) | (CmpCap << 12) | (BrandTableIndex << 4)
208                         | PwrLmt) {
209                 /* Socket F */
210                 case 0x11002:
211                         processor_name_string =
212                             "Dual-Core AMD Opteron(tm) Processor 12RR EE";
213                         break;
214                 case 0x11006:
215                         processor_name_string =
216                             "Dual-Core AMD Opteron(tm) Processor 12RR HE";
217                         break;
218                 case 0x11012:
219                         processor_name_string =
220                             "Dual-Core AMD Opteron(tm) Processor 22RR EE";
221                         break;
222                 case 0x11016:
223                         processor_name_string =
224                             "Dual-Core AMD Opteron(tm) Processor 22RR HE";
225                         break;
226                 case 0x1101a:
227                         processor_name_string =
228                             "Dual-Core AMD Opteron(tm) Processor 22RR";
229                         break;
230                 case 0x1101c:
231                         processor_name_string =
232                             "Dual-Core AMD Opteron(tm) Processor 22RR SE";
233                         break;
234                 case 0x11042:
235                         processor_name_string =
236                             "Dual-Core AMD Opteron(tm) Processor 82RR EE";
237                         break;
238                 case 0x11046:
239                         processor_name_string =
240                             "Dual-Core AMD Opteron(tm) Processor 82RR HE";
241                         break;
242                 case 0x1104a:
243                         processor_name_string =
244                             "Dual-Core AMD Opteron(tm) Processor 82RR";
245                         break;
246                 case 0x1104c:
247                         processor_name_string =
248                             "Dual-Core AMD Opteron(tm) Processor 82RR SE";
249                         break;
250                 case 0x1106e:
251                         processor_name_string =
252                             "AMD Athlon(tm) 64 Processor FX-ZZ Processor";
253                         break;
254                 /* Socket AM2 */
255                 case 0x30015:
256                         processor_name_string =
257                             "AMD Sempron(tm) Processor LE-1RR0";
258                         break;
259                 case 0x30026:
260                         processor_name_string =
261                             "AMD Athlon(tm) Processor LE-1ZZ0";
262                         break;
263                 case 0x30041:
264                 case 0x30042:
265                 case 0x30043:
266                 case 0x30044:
267                 case 0x30045:
268                 case 0x30048:
269                         processor_name_string =
270                             "AMD Athlon(tm) 64 Processor TT00+";
271                         break;
272                 case 0x30064:
273                 case 0x30068:
274                         processor_name_string =
275                             "AMD Sempron(tm) Processor TT00+";
276                         break;
277                 case 0x31016:
278                         processor_name_string =
279                             "Dual-Core AMD Opteron(tm) Processor 12RR HE";
280                         break;
281                 case 0x3101a:
282                         processor_name_string =
283                             "Dual-Core AMD Opteron(tm) Processor 12RR";
284                         break;
285                 case 0x3101c:
286                         processor_name_string =
287                             "Dual-Core AMD Opteron(tm) Processor 12RR SE";
288                         break;
289                 case 0x31033:
290                         processor_name_string =
291                             "AMD Athlon(tm) X2 Dual Core Processor BE-2TT0";
292                         break;
293                 case 0x31042:
294                 case 0x31046:
295                 case 0x31048:
296                 case 0x3104c:
297                         processor_name_string =
298                             "AMD Athlon(tm) 64 X2 Dual Core Processor TT00+";
299                         break;
300                 case 0x3105c:
301                         processor_name_string =
302                             "AMD Athlon(tm) 64 FX-ZZ Dual Core Processor";
303                         break;
304                 /* Socket S1g1 */
305                 case 0x00012:
306                         processor_name_string =
307                             "AMD Athlon(tm) 64 Processor TT00+";
308                         break;
309                 case 0x00031:
310                         processor_name_string =
311                             "Mobile AMD Sempron(tm) Processor TT00+";
312                         break;
313                 case 0x00036:
314                         processor_name_string =
315                             "Mobile AMD Sempron(tm) Processor PP00+";
316                         break;
317                 case 0x00042:
318                         processor_name_string =
319                             "AMD Sempron(tm) Processor TT00+";
320                         break;
321                 case 0x0102c:
322                         processor_name_string =
323                             "AMD Turion(tm) 64 X2 Mobile Technology TL-YY";
324                         break;
325                 case 0x01054:
326                         processor_name_string =
327                             "AMD Athlon(tm) 64 X2 Dual Core Processor TT00+";
328                         break;
329                 default:
330                         processor_name_string = "AMD Processor model unknown";
331                 }
332         }
333 #endif
334
335         memset(program_string, 0, 48);
336         strcpy(program_string, processor_name_string);
337         
338         /* Now create a model number - See Table 4. Model Number Calculation
339          * in the Revision Guide. NOTE: #6, EE was changed to VV because 
340          * otherwise it clashes with the brand names.
341          */
342         
343         for (i=0; i<47; i++) { // 48 -1 
344                 if(program_string[i] == program_string[i+1]) {
345                         switch (program_string[i]) {
346 #if CONFIG_K8_REV_F_SUPPORT == 0
347                         case 'X': ModelNumber = 22+ NN; break;
348                         case 'Y': ModelNumber = 38 + (2*NN); break;
349                         case 'Z':
350                         case 'T': ModelNumber = 24 + NN; break;
351                         case 'R': ModelNumber = 45 + (5*NN); break;
352                         case 'V': ModelNumber =  9 + NN; break;
353 #endif
354
355 #if CONFIG_K8_REV_F_SUPPORT == 1
356                         case 'R': ModelNumber = NN - 1; break;
357                         case 'P': ModelNumber = 26 + NN; break;
358                         case 'T': ModelNumber = 15 + (CmpCap * 10) + NN; break;
359                         case 'Z': ModelNumber = 57 + NN; break;
360                         case 'Y': ModelNumber = 29 + NN; break;
361 #endif
362                         }
363                         
364                         if(ModelNumber && ModelNumber < 100) {
365                                 // No idea what to do with RR=100. According
366                                 // to the revision guide this is possible.
367                                 // 
368                                 // --> "AMD Opteron(tm) Processor 8100"?
369                                 program_string[i]=(ModelNumber/10)+'0';
370                                 program_string[i+1]=(ModelNumber%10)+'0';
371                                 break;
372                         }
373                 }
374         }
375         
376         printk_debug("CPU model %s\n", program_string);
377
378         for (i=0; i<6; i++) {
379                 progmsr.lo = program_values[(2*i)+0];
380                 progmsr.hi = program_values[(2*i)+1];
381                 wrmsr_amd(0xc0010030+i, progmsr);
382         }
383
384         return 0;
385 }
386