From 6ab0fa9fedbfd3f0b21b84aed280bc8971ea324f Mon Sep 17 00:00:00 2001 From: Stefan Reinauer Date: Wed, 14 Jun 2006 23:22:04 +0000 Subject: add k8 processor name handling as required by the k8 revision guide. git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2322 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/cpu/amd/model_fxx/Config.lb | 1 + src/cpu/amd/model_fxx/model_fxx_init.c | 3 + src/cpu/amd/model_fxx/processor_name.c | 191 +++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 src/cpu/amd/model_fxx/processor_name.c diff --git a/src/cpu/amd/model_fxx/Config.lb b/src/cpu/amd/model_fxx/Config.lb index 4067bfc5eb..ca83a1def1 100644 --- a/src/cpu/amd/model_fxx/Config.lb +++ b/src/cpu/amd/model_fxx/Config.lb @@ -15,3 +15,4 @@ dir /cpu/amd/microcode driver model_fxx_init.o object apic_timer.o object model_fxx_update_microcode.o +object processor_name.o diff --git a/src/cpu/amd/model_fxx/model_fxx_init.c b/src/cpu/amd/model_fxx/model_fxx_init.c index a28ebff60f..e83873e3b0 100644 --- a/src/cpu/amd/model_fxx/model_fxx_init.c +++ b/src/cpu/amd/model_fxx/model_fxx_init.c @@ -425,6 +425,7 @@ static inline void k8_errata(void) extern void model_fxx_update_microcode(unsigned cpu_deviceid); +int init_processor_name(void); void model_fxx_init(device_t dev) { @@ -454,6 +455,8 @@ void model_fxx_init(device_t dev) k8_errata(); + init_processor_name(); + enable_cache(); /* Enable the local cpu apics */ diff --git a/src/cpu/amd/model_fxx/processor_name.c b/src/cpu/amd/model_fxx/processor_name.c new file mode 100644 index 0000000000..c18db57d43 --- /dev/null +++ b/src/cpu/amd/model_fxx/processor_name.c @@ -0,0 +1,191 @@ +/* + * processor_name.c + * + * This code sets the Processor Name String for AMD64 CPUs. + * + * Written by Stefan Reinauer using + * the Revision Guide for AMD Athlon™ 64 and AMD Opteron™ Processors + * Document ID 25759 Rev 3.59, April 2006 (Public Version) + * + * (C) 2006 by coresystems GmbH + * + * 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 + * archive for more details. + * + */ + +#include + +#include +#include + +typedef unsigned int u32; + +/* The maximum length of CPU names is 48 bytes, including the final NULL byte. + * If you change these names your BIOS will _NOT_ pass the AMD validation and + * your mainboard will not be posted on the AMD Recommended Motherboard Website + */ + +static char *processor_names[]={ + /* 0x00 */ "AMD Engineering Sample", + /* 0x01-0x03 */ NULL, NULL, NULL, + /* 0x04 */ "AMD Athlon(tm) 64 Processor XX00+", + /* 0x05 */ "AMD Athlon(tm) 64 X2 Dual Core Processor XX00+", + /* 0x06-0x07 */ NULL, NULL, + /* 0x08 */ "Mobile AMD Athlon(tm) 64 Processor XX00+", + /* 0x09 */ "Mobile AMD Athlon(tm) 64 Processor XX00+", + /* 0x0A */ "AMD Turion(tm) 64 Mobile Technology ML-XX", + /* 0x0B */ "AMD Turion(tm) 64 Mobile Technology MT-XX", + /* 0x0C */ "AMD Opteron(tm) Processor 1YY", + /* 0x0D */ "AMD Opteron(tm) Processor 1YY", + /* 0x0E */ "AMD Opteron(tm) Processor 1YY HE", + /* 0x0F */ "AMD Opteron(tm) Processor 1YY EE", + /* 0x10 */ "AMD Opteron(tm) Processor 2YY", + /* 0x11 */ "AMD Opteron(tm) Processor 2YY", + /* 0x12 */ "AMD Opteron(tm) Processor 2YY HE", + /* 0x13 */ "AMD Opteron(tm) Processor 2YY EE", + /* 0x14 */ "AMD Opteron(tm) Processor 8YY", + /* 0x15 */ "AMD Opteron(tm) Processor 8YY", + /* 0x16 */ "AMD Opteron(tm) Processor 8YY HE", + /* 0x17 */ "AMD Opteron(tm) Processor 8YY EE", + /* 0x18 */ "AMD Athlon(tm) 64 Processor VV00+", + /* 0x19-0x1C */ NULL, NULL, NULL, NULL, + /* 0x1D */ "Mobile AMD Athlon(tm) XP-M Processor XX00+", + /* 0x1E */ "Mobile AMD Athlon(tm) XP-M Processor XX00+", + /* 0x1F */ NULL, + /* 0x20 */ "AMD Athlon(tm) XP Processor XX00+", + /* 0x21 */ "Mobile AMD Sempron(tm) Processor TT00+", + /* 0x22 */ "AMD Sempron(tm) Processor TT00+", + /* 0x23 */ "Mobile AMD Sempron(tm) Processor TT00+", + /* 0x24 */ "AMD Athlon(tm) 64 FX-ZZ Processor", + /* 0x25 */ NULL, + /* 0x26 */ "AMD Sempron(tm) Processor TT00+", + /* 0x27-0x28 */ NULL, NULL, + /* 0x29 */ "Dual Core AMD Opteron(tm) Processor 1RR SE", + /* 0x2A */ "Dual Core AMD Opteron(tm) Processor 2RR SE", + /* 0x2B */ "Dual Core AMD Opteron(tm) Processor 8RR SE", + /* 0x2C */ "Dual Core AMD Opteron(tm) Processor 1RR", + /* 0x2D */ "Dual Core AMD Opteron(tm) Processor 1RR", + /* 0x2E */ "Dual Core AMD Opteron(tm) Processor 1RR HE", + /* 0x2F */ "Dual Core AMD Opteron(tm) Processor 1RR EE", + /* 0x30 */ "Dual Core AMD Opteron(tm) Processor 2RR", + /* 0x31 */ "Dual Core AMD Opteron(tm) Processor 2RR", + /* 0x32 */ "Dual Core AMD Opteron(tm) Processor 2RR HE", + /* 0x33 */ "Dual Core AMD Opteron(tm) Processor 2RR EE", + /* 0x34 */ "Dual Core AMD Opteron(tm) Processor 8RR", + /* 0x35 */ "Dual Core AMD Opteron(tm) Processor 8RR", + /* 0x36 */ "Dual Core AMD Opteron(tm) Processor 8RR HE", + /* 0x37 */ "Dual Core AMD Opteron(tm) Processor 8RR EE", + /* 0x38 */ "Dual Core AMD Opteron(tm) Processor 1RR", + /* 0x39 */ "Dual Core AMD Opteron(tm) Processor 2RR", + /* 0x3A */ "Dual Core AMD Opteron(tm) Processor 8RR" +#define MAX_CPU_NUMBER 0x3A +}; + +/* wrmsr_amd() is from yhlu's changes to model_fxx_init.c */ + +static inline void wrmsr_amd(unsigned index, msr_t msr) +{ + __asm__ __volatile__ ( + "wrmsr" + : /* No outputs */ + : "c" (index), "a" (msr.lo), "d" (msr.hi), "D" (0x9c5a203a) + ); +} + +static inline unsigned int cpuid_ebx(unsigned int op) +{ + unsigned int eax, ebx; + + __asm__("cpuid" + : "=a" (eax), "=b" (ebx) + : "0" (op) + : "ecx", "edx" ); + return ebx; +} + +static inline void strcpy(char *dst, char *src) +{ + while (*src) *dst++ = *src++; +} + + +int init_processor_name(void) +{ + u32 EightBitBrandId; + u32 BrandId; + u32 BrandTableIndex; + u32 NN; + u32 ModelNumber=0; + msr_t progmsr; + int i; + + char *processor_name_string=NULL; + char program_string[48]; + unsigned int *program_values = (unsigned int *)program_string; + + /* Find out which CPU brand it is */ + EightBitBrandId = cpuid_ebx(0x00000001) & 0xff; + BrandId = cpuid_ebx(0x80000001) & 0xffff; + + if(!EightBitBrandId && !BrandId) { + BrandTableIndex = 0; + NN = 0xffffff; + } else if(!EightBitBrandId) { + BrandTableIndex = (BrandId >> 6) & 0x3f; // BrandId[11:6] + NN = BrandId & 0x3f; // // BrandId[6:0] + } else { + BrandTableIndex = EightBitBrandId >> (5-2) & 0xfc; // { 0b, 8BitBrandId[7:5], 00b } + NN = EightBitBrandId & 0x1f; // 8BitBrandId[4:0] + } + + /* Look up the CPU brand in above table */ + if (BrandTableIndex <= MAX_CPU_NUMBER) + processor_name_string = processor_names[BrandTableIndex]; + + if (!processor_name_string) + processor_name_string = "AMD Processor model unknown"; + + memset(program_string, 0, 48); + strcpy(program_string, processor_name_string); + + /* Now create a model number - See Table 4. Model Number Calculation + * in the Revision Guide. NOTE: #6, EE was changed to VV because + * otherwise it clashes with the brand names. + */ + + for (i=0; i<47; i++) { // 48 -1 + if(program_string[i] == program_string[i+1]) { + switch (program_string[i]) { + case 'X': ModelNumber = 22+ NN; break; + case 'Y': ModelNumber = 38 + (2*NN); break; + case 'Z': + case 'T': ModelNumber = 24 + NN; break; + case 'R': ModelNumber = 45 + (5*NN); break; + case 'V': ModelNumber = 9 + NN; break; + } + + if(ModelNumber && ModelNumber < 100) { + // No idea what to do with RR=100. According + // to the revision guide this is possible. + // + // --> "AMD Opteron(tm) Processor 8100"? + program_string[i]=(ModelNumber/10)+'0'; + program_string[i+1]=(ModelNumber%10)+'0'; + break; + } + } + } + + printk_debug("CPU model %s\n", program_string); + + for (i=0; i<6; i++) { + progmsr.lo = program_values[(2*i)+0]; + progmsr.hi = program_values[(2*i)+1]; + wrmsr_amd(0xc0010030+i, progmsr); + } + + return 0; +} + -- cgit v1.2.3