c18db57d43d9ccd2613775d52c13add5c08b600d
[coreboot.git] / src / cpu / amd / model_fxx / processor_name.c
1 /*
2  * processor_name.c
3  *
4  * This code sets the Processor Name String for AMD64 CPUs.
5  *
6  * Written by Stefan Reinauer <stepan@coresystems.de> using
7  * the Revision Guide for AMD Athlon™ 64 and AMD Opteron™ Processors
8  * Document ID 25759 Rev 3.59, April 2006 (Public Version)
9  *
10  * (C) 2006 by coresystems GmbH <info@coresystems.de>
11  *
12  * This file is subject to the terms and conditions of the GNU General
13  * Public License. See the file COPYING in the main directory of this
14  * archive for more details.
15  *
16  */
17
18 #include <console/console.h>
19
20 #include <string.h>
21 #include <cpu/x86/msr.h>
22
23 typedef unsigned int u32;
24
25 /* The maximum length of CPU names is 48 bytes, including the final NULL byte.
26  * If you change these names your BIOS will _NOT_ pass the AMD validation and
27  * your mainboard will not be posted on the AMD Recommended Motherboard Website
28  */
29
30 static char *processor_names[]={
31         /* 0x00 */ "AMD Engineering Sample",
32         /* 0x01-0x03 */ NULL, NULL, NULL,
33         /* 0x04 */ "AMD Athlon(tm) 64 Processor XX00+",
34         /* 0x05 */ "AMD Athlon(tm) 64 X2 Dual Core Processor XX00+",
35         /* 0x06-0x07 */ NULL, NULL,
36         /* 0x08 */ "Mobile AMD Athlon(tm) 64 Processor XX00+",
37         /* 0x09 */ "Mobile AMD Athlon(tm) 64 Processor XX00+",
38         /* 0x0A */ "AMD Turion(tm) 64 Mobile Technology ML-XX",
39         /* 0x0B */ "AMD Turion(tm) 64 Mobile Technology MT-XX",
40         /* 0x0C */ "AMD Opteron(tm) Processor 1YY",
41         /* 0x0D */ "AMD Opteron(tm) Processor 1YY",
42         /* 0x0E */ "AMD Opteron(tm) Processor 1YY HE",
43         /* 0x0F */ "AMD Opteron(tm) Processor 1YY EE",
44         /* 0x10 */ "AMD Opteron(tm) Processor 2YY",
45         /* 0x11 */ "AMD Opteron(tm) Processor 2YY",
46         /* 0x12 */ "AMD Opteron(tm) Processor 2YY HE",
47         /* 0x13 */ "AMD Opteron(tm) Processor 2YY EE",
48         /* 0x14 */ "AMD Opteron(tm) Processor 8YY",
49         /* 0x15 */ "AMD Opteron(tm) Processor 8YY",
50         /* 0x16 */ "AMD Opteron(tm) Processor 8YY HE",
51         /* 0x17 */ "AMD Opteron(tm) Processor 8YY EE",
52         /* 0x18 */ "AMD Athlon(tm) 64 Processor VV00+",
53         /* 0x19-0x1C */ NULL, NULL, NULL, NULL,
54         /* 0x1D */ "Mobile AMD Athlon(tm) XP-M Processor XX00+",
55         /* 0x1E */ "Mobile AMD Athlon(tm) XP-M Processor XX00+",
56         /* 0x1F */ NULL,
57         /* 0x20 */ "AMD Athlon(tm) XP Processor XX00+",
58         /* 0x21 */ "Mobile AMD Sempron(tm) Processor TT00+",
59         /* 0x22 */ "AMD Sempron(tm) Processor TT00+",
60         /* 0x23 */ "Mobile AMD Sempron(tm) Processor TT00+",
61         /* 0x24 */ "AMD Athlon(tm) 64 FX-ZZ Processor",
62         /* 0x25 */ NULL,
63         /* 0x26 */ "AMD Sempron(tm) Processor TT00+",
64         /* 0x27-0x28 */ NULL, NULL, 
65         /* 0x29 */ "Dual Core AMD Opteron(tm) Processor 1RR SE",
66         /* 0x2A */ "Dual Core AMD Opteron(tm) Processor 2RR SE",
67         /* 0x2B */ "Dual Core AMD Opteron(tm) Processor 8RR SE",
68         /* 0x2C */ "Dual Core AMD Opteron(tm) Processor 1RR",
69         /* 0x2D */ "Dual Core AMD Opteron(tm) Processor 1RR",
70         /* 0x2E */ "Dual Core AMD Opteron(tm) Processor 1RR HE",
71         /* 0x2F */ "Dual Core AMD Opteron(tm) Processor 1RR EE",
72         /* 0x30 */ "Dual Core AMD Opteron(tm) Processor 2RR",
73         /* 0x31 */ "Dual Core AMD Opteron(tm) Processor 2RR",
74         /* 0x32 */ "Dual Core AMD Opteron(tm) Processor 2RR HE",
75         /* 0x33 */ "Dual Core AMD Opteron(tm) Processor 2RR EE",
76         /* 0x34 */ "Dual Core AMD Opteron(tm) Processor 8RR",
77         /* 0x35 */ "Dual Core AMD Opteron(tm) Processor 8RR",
78         /* 0x36 */ "Dual Core AMD Opteron(tm) Processor 8RR HE",
79         /* 0x37 */ "Dual Core AMD Opteron(tm) Processor 8RR EE",
80         /* 0x38 */ "Dual Core AMD Opteron(tm) Processor 1RR",
81         /* 0x39 */ "Dual Core AMD Opteron(tm) Processor 2RR",
82         /* 0x3A */ "Dual Core AMD Opteron(tm) Processor 8RR"
83 #define MAX_CPU_NUMBER 0x3A
84 };
85
86 /* wrmsr_amd() is from yhlu's changes to model_fxx_init.c */
87
88 static inline void wrmsr_amd(unsigned index, msr_t msr)
89 {
90         __asm__ __volatile__ (
91                 "wrmsr"
92                 : /* No outputs */
93                 : "c" (index), "a" (msr.lo), "d" (msr.hi), "D" (0x9c5a203a)
94                 );
95 }
96
97 static inline unsigned int cpuid_ebx(unsigned int op)
98 {
99         unsigned int eax, ebx;
100
101         __asm__("cpuid"
102                 : "=a" (eax), "=b" (ebx)
103                 : "0" (op)
104                 : "ecx", "edx" );
105         return ebx;
106 }
107
108 static inline void strcpy(char *dst, char *src) 
109 {
110         while (*src) *dst++ = *src++;
111 }
112
113
114 int init_processor_name(void)
115 {
116         u32 EightBitBrandId;
117         u32 BrandId;
118         u32 BrandTableIndex;
119         u32 NN;
120         u32 ModelNumber=0;
121         msr_t progmsr;
122         int i;
123
124         char *processor_name_string=NULL;
125         char program_string[48];
126         unsigned int *program_values = (unsigned int *)program_string;
127
128         /* Find out which CPU brand it is */
129         EightBitBrandId = cpuid_ebx(0x00000001) & 0xff;
130         BrandId = cpuid_ebx(0x80000001) & 0xffff;
131
132         if(!EightBitBrandId && !BrandId) {
133                 BrandTableIndex = 0;
134                 NN = 0xffffff;
135         } else if(!EightBitBrandId) {
136                 BrandTableIndex = (BrandId >> 6) & 0x3f; // BrandId[11:6]
137                 NN = BrandId & 0x3f; // // BrandId[6:0]
138         } else {
139                 BrandTableIndex = EightBitBrandId >> (5-2) & 0xfc; // { 0b, 8BitBrandId[7:5], 00b }
140                 NN = EightBitBrandId & 0x1f; // 8BitBrandId[4:0]
141         }
142
143         /* Look up the CPU brand in above table */
144         if (BrandTableIndex <= MAX_CPU_NUMBER)
145                 processor_name_string = processor_names[BrandTableIndex];
146
147         if (!processor_name_string)
148                 processor_name_string = "AMD Processor model unknown";
149
150         memset(program_string, 0, 48);
151         strcpy(program_string, processor_name_string);
152         
153         /* Now create a model number - See Table 4. Model Number Calculation
154          * in the Revision Guide. NOTE: #6, EE was changed to VV because 
155          * otherwise it clashes with the brand names.
156          */
157         
158         for (i=0; i<47; i++) { // 48 -1 
159                 if(program_string[i] == program_string[i+1]) {
160                         switch (program_string[i]) {
161                         case 'X': ModelNumber = 22+ NN; break;
162                         case 'Y': ModelNumber = 38 + (2*NN); break;
163                         case 'Z':
164                         case 'T': ModelNumber = 24 + NN; break;
165                         case 'R': ModelNumber = 45 + (5*NN); break;
166                         case 'V': ModelNumber =  9 + NN; break;
167                         }
168                         
169                         if(ModelNumber && ModelNumber < 100) {
170                                 // No idea what to do with RR=100. According
171                                 // to the revision guide this is possible.
172                                 // 
173                                 // --> "AMD Opteron(tm) Processor 8100"?
174                                 program_string[i]=(ModelNumber/10)+'0';
175                                 program_string[i+1]=(ModelNumber%10)+'0';
176                                 break;
177                         }
178                 }
179         }
180         
181         printk_debug("CPU model %s\n", program_string);
182
183         for (i=0; i<6; i++) {
184                 progmsr.lo = program_values[(2*i)+0];
185                 progmsr.hi = program_values[(2*i)+1];
186                 wrmsr_amd(0xc0010030+i, progmsr);
187         }
188
189         return 0;
190 }
191