This patch fixes the processor name string for Rev F. CPUs.

It moves the complete naming functionality to
src/cpu/amd/model_fxx/processor_name.c.

The current code sets the processor name string twice for Rev. F CPUs.

In src/cpu/amd/model_fxx/model_fxx_init.c the function
amd_set_name_string_f is called first. Several lines later
init_processor_name is called which doesn't recognize newer CPUs and
actually programs incorrect values, thus overwriting the previously set
CPU name. For example, this resulted in identifying an Opteron 2218 as a
Turion processor.

This patch removes the amd_set_name_string_f function from
src/cpu/amd/model_fxx/model_fxx_init.c and adds support for Rev. F CPUs
to src/cpu/amd/model_fxx/processor_name.c as described in the Revision
Guide for AMD NPT Family 0Fh Processors, AMD Document ID 33610 Rev 3.00,
October 2006.

Signed-off-by: Sven Kapferer <skapfere@rumms.uni-mannheim.de>
Acked-by: Uwe Hermann <uwe@hermann-uwe.de>



git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2699 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Sven Kapferer 2007-05-26 13:56:34 +00:00 committed by Uwe Hermann
parent cd3afc0524
commit 4834a4f206
2 changed files with 136 additions and 85 deletions

View File

@ -462,87 +462,6 @@ static inline void k8_errata(void)
} }
#if K8_REV_F_SUPPORT == 1
static void amd_set_name_string_f(device_t dev)
{
unsigned socket;
unsigned cmpCap;
unsigned pwrLmt;
unsigned brandId;
unsigned brandTableIndex;
unsigned nN;
unsigned unknown = 1;
uint8_t str[48];
uint32_t *p;
msr_t msr;
unsigned i;
brandId = cpuid_ebx(0x80000001) & 0xffff;
printk_debug("brandId=%04x\n", brandId);
pwrLmt = ((brandId>>14) & 1) | ((brandId>>5) & 0x0e);
brandTableIndex = (brandId>>9) & 0x1f;
nN = (brandId & 0x3f) | ((brandId>>(15-6)) &(1<<6));
socket = (dev->device >> 4) & 0x3;
cmpCap = cpuid_ecx(0x80000008) & 0xff;
if((brandTableIndex == 0) && (pwrLmt == 0)) {
memset(str, 0, 48);
sprintf(str, "AMD Engineering Sample");
unknown = 0;
} else {
memset(str, 0, 48);
sprintf(str, "AMD Processor model unknown");
#if CPU_SOCKET_TYPE == 0x10
if(socket == 0x01) { // socket F
if ((cmpCap == 1) && ((brandTableIndex==0) ||(brandTableIndex ==1) ||(brandTableIndex == 4)) ) {
uint8_t pc[2];
unknown = 0;
switch (pwrLmt) {
case 2: pc[0]= 'E'; pc[1] = 'E'; break;
case 6: pc[0]= 'H'; pc[1] = 'E'; break;
case 0xa: pc[0]= ' '; pc[1] = ' '; break;
case 0xc: pc[0]= 'S'; pc[1] = 'E'; break;
default: unknown = 1;
}
if(!unknown) {
memset(str, 0, 48);
sprintf(str, "Dual-Core AMD Opteron(tm) Processor %1d2%2d %c%c", brandTableIndex<<1, (nN-1)&0x3f, pc[0], pc[1]);
}
}
}
#else
#if CPU_SOCKET_TYPE == 0x11
if(socket == 0x00) { // socket AM2
if(cmpCap == 0) {
sprintf(str, "Athlon 64");
} else {
sprintf(str, "Athlon 64 Dual Core");
}
}
#endif
#endif
}
p = str;
for(i=0;i<6;i++) {
msr.lo = *p; p++; msr.hi = *p; p++;
wrmsr(0xc0010030+i, msr);
}
}
#endif
extern void model_fxx_update_microcode(unsigned cpu_deviceid); extern void model_fxx_update_microcode(unsigned cpu_deviceid);
int init_processor_name(void); int init_processor_name(void);
@ -561,10 +480,6 @@ void model_fxx_init(device_t dev)
struct cpuinfo_x86 c; struct cpuinfo_x86 c;
get_fms(&c, dev->device); get_fms(&c, dev->device);
if((c.x86_model & 0xf0) == 0x40) {
amd_set_name_string_f(dev);
}
#endif #endif
#if CONFIG_USBDEBUG_DIRECT #if CONFIG_USBDEBUG_DIRECT

View File

@ -9,6 +9,10 @@
* *
* (C) 2006 by coresystems GmbH <info@coresystems.de> * (C) 2006 by coresystems GmbH <info@coresystems.de>
* *
* Updated by Sven Kapferer <skapfere@rumms.uni-mannheim.de> using
* the Revision Guide for AMD NPT Family 0Fh Processors
* Document ID 33610 Rev 3.00, October 2006 (Public Version)
*
* This file is subject to the terms and conditions of the GNU General * This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this * Public License. See the file COPYING in the main directory of this
* archive for more details. * archive for more details.
@ -25,6 +29,7 @@
* your mainboard will not be posted on the AMD Recommended Motherboard Website * your mainboard will not be posted on the AMD Recommended Motherboard Website
*/ */
#if K8_REV_F_SUPPORT == 0
static char *processor_names[]={ static char *processor_names[]={
/* 0x00 */ "AMD Engineering Sample", /* 0x00 */ "AMD Engineering Sample",
/* 0x01-0x03 */ NULL, NULL, NULL, /* 0x01-0x03 */ NULL, NULL, NULL,
@ -80,6 +85,7 @@ static char *processor_names[]={
/* 0x3A */ "Dual Core AMD Opteron(tm) Processor 8RR" /* 0x3A */ "Dual Core AMD Opteron(tm) Processor 8RR"
#define MAX_CPU_NUMBER 0x3A #define MAX_CPU_NUMBER 0x3A
}; };
#endif
/* wrmsr_amd() is from yhlu's changes to model_fxx_init.c */ /* wrmsr_amd() is from yhlu's changes to model_fxx_init.c */
@ -92,6 +98,17 @@ static inline void wrmsr_amd(unsigned index, msr_t msr)
); );
} }
static inline unsigned int cpuid_eax(unsigned int op)
{
unsigned int eax;
__asm__("cpuid"
: "=a" (eax)
: "0" (op)
: "ebx", "ecx", "edx");
return eax;
}
static inline unsigned int cpuid_ebx(unsigned int op) static inline unsigned int cpuid_ebx(unsigned int op)
{ {
unsigned int eax, ebx; unsigned int eax, ebx;
@ -103,6 +120,17 @@ static inline unsigned int cpuid_ebx(unsigned int op)
return ebx; return ebx;
} }
static inline unsigned int cpuid_ecx(unsigned int op)
{
unsigned int eax, ecx;
__asm__("cpuid"
: "=a" (eax), "=c" (ecx)
: "0" (op)
: "ebx", "edx" );
return ecx;
}
static inline void strcpy(char *dst, char *src) static inline void strcpy(char *dst, char *src)
{ {
while (*src) *dst++ = *src++; while (*src) *dst++ = *src++;
@ -123,6 +151,7 @@ int init_processor_name(void)
char program_string[48]; char program_string[48];
unsigned int *program_values = (unsigned int *)program_string; unsigned int *program_values = (unsigned int *)program_string;
#if K8_REV_F_SUPPORT == 0
/* Find out which CPU brand it is */ /* Find out which CPU brand it is */
EightBitBrandId = cpuid_ebx(0x00000001) & 0xff; EightBitBrandId = cpuid_ebx(0x00000001) & 0xff;
BrandId = cpuid_ebx(0x80000001) & 0xffff; BrandId = cpuid_ebx(0x80000001) & 0xffff;
@ -144,6 +173,103 @@ int init_processor_name(void)
if (!processor_name_string) if (!processor_name_string)
processor_name_string = "AMD Processor model unknown"; processor_name_string = "AMD Processor model unknown";
#endif
#if K8_REV_F_SUPPORT == 1
u32 Socket;
u32 CmpCap;
u32 PwrLmt;
BrandId = cpuid_ebx(0x80000001) & 0xffff;
Socket = (cpuid_eax(0x80000001) & 0x00000030) >> 4; // 00b = S1g1, 01b = F (1207), 11b = AM2
CmpCap = cpuid_ecx(0x80000008) & 0x03; // Number of CPU cores
PwrLmt = ((BrandId >> 14) & 0x01) | ((BrandId >> 5) & 0x0e); // BrandId[8:6,14]
BrandTableIndex = (BrandId >> 9) & 0x1f; // BrandId[13:9]
NN = ((BrandId >> 15) & 0x01) | (BrandId & 0x3f); // BrandId[15,5:0]
if (((BrandTableIndex == 0) && (PwrLmt == 0)) || (NN == 0)) {
processor_name_string = "AMD Engineering Sample";
} else {
/* Use all fields to identify CPU */
switch ((Socket << 16) | (CmpCap << 12) | (BrandTableIndex << 4)
| PwrLmt) {
/* Socket F */
case 0x11016:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 22RR HE";
break;
case 0x1101a:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 22RR";
break;
case 0x1101c:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 22RR SE";
break;
case 0x11046:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 82RR HE";
break;
case 0x1104a:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 82RR";
break;
case 0x1104c:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 82RR SE";
break;
/* Socket AM2 */
case 0x30044:
processor_name_string =
"AMD Athlon(tm) 64 Processor TT00+";
break;
case 0x30048:
processor_name_string =
"AMD Athlon(tm) 64 Processor TT00+";
break;
case 0x30064:
processor_name_string =
"AMD Sempron(tm) Processor TT00+";
break;
case 0x30068:
processor_name_string =
"AMD Sempron(tm) Processor TT00+";
break;
case 0x3101a:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 12RR";
break;
case 0x3101c:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 12RR SE";
break;
case 0x31042:
processor_name_string =
"AMD Athlon(tm) 64 X2 Dual Core Processor TT00+";
break;
case 0x31046:
processor_name_string =
"AMD Athlon(tm) 64 X2 Dual Core Processor TT00+";
break;
case 0x31048:
processor_name_string =
"AMD Athlon(tm) 64 X2 Dual Core Processor TT00+";
break;
case 0x3105c:
processor_name_string =
"AMD Athlon(tm) 64 FX-ZZ Dual Core Processor";
break;
/* Socket S1g1 */
case 0x0102c:
processor_name_string =
"AMD Turion(tm) 64 X2 Mobile Technology TL-YY";
break;
default:
processor_name_string = "AMD Processor model unknown";
}
}
#endif
memset(program_string, 0, 48); memset(program_string, 0, 48);
strcpy(program_string, processor_name_string); strcpy(program_string, processor_name_string);
@ -156,12 +282,22 @@ int init_processor_name(void)
for (i=0; i<47; i++) { // 48 -1 for (i=0; i<47; i++) { // 48 -1
if(program_string[i] == program_string[i+1]) { if(program_string[i] == program_string[i+1]) {
switch (program_string[i]) { switch (program_string[i]) {
#if K8_REV_F_SUPPORT == 0
case 'X': ModelNumber = 22+ NN; break; case 'X': ModelNumber = 22+ NN; break;
case 'Y': ModelNumber = 38 + (2*NN); break; case 'Y': ModelNumber = 38 + (2*NN); break;
case 'Z': case 'Z':
case 'T': ModelNumber = 24 + NN; break; case 'T': ModelNumber = 24 + NN; break;
case 'R': ModelNumber = 45 + (5*NN); break; case 'R': ModelNumber = 45 + (5*NN); break;
case 'V': ModelNumber = 9 + NN; break; case 'V': ModelNumber = 9 + NN; break;
#endif
#if K8_REV_F_SUPPORT == 1
case 'R': ModelNumber = NN - 1; break;
case 'P': ModelNumber = 26 + NN; break;
case 'T': ModelNumber = 15 + (CmpCap * 10) + NN; break;
case 'Z': ModelNumber = 57 + NN; break;
case 'Y': ModelNumber = 29 + NN; break;
#endif
} }
if(ModelNumber && ModelNumber < 100) { if(ModelNumber && ModelNumber < 100) {