diff options
Diffstat (limited to 'src/cpu/k8')
-rw-r--r-- | src/cpu/k8/cpufixup.c | 149 |
1 files changed, 121 insertions, 28 deletions
diff --git a/src/cpu/k8/cpufixup.c b/src/cpu/k8/cpufixup.c index d5ccfc299d..6aa6722579 100644 --- a/src/cpu/k8/cpufixup.c +++ b/src/cpu/k8/cpufixup.c @@ -4,15 +4,67 @@ #include <cpu/p6/msr.h> #include <cpu/k8/mtrr.h> #include <device/device.h> +#include "../../northbridge/amd/amdk8/cpu_rev.c" #include <device/chip.h> - #include "chip.h" +#define MCI_STATUS 0x401 + +static inline void disable_cache(void) +{ + unsigned int tmp; + /* Disable cache */ + /* Write back the cache and flush TLB */ + asm volatile ( + "movl %%cr0, %0\n\t" + "orl $0x40000000, %0\n\t" + "wbinvd\n\t" + "movl %0, %%cr0\n\t" + "wbinvd\n\t" + :"=r" (tmp) + ::"memory"); +} + +static inline void enable_cache(void) +{ + unsigned int tmp; + // turn cache back on. + asm volatile ( + "movl %%cr0, %0\n\t" + "andl $0x9fffffff, %0\n\t" + "movl %0, %%cr0\n\t" + :"=r" (tmp) + ::"memory"); +} + +static inline msr_t rdmsr_amd(unsigned index) +{ + msr_t result; + __asm__ __volatile__ ( + "rdmsr" + : "=a" (result.lo), "=d" (result.hi) + : "c" (index), "D" (0x9c5a203a) + ); + return result; +} + +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) + ); +} + void k8_cpufixup(struct mem_range *mem) { unsigned long mmio_basek, tomk; unsigned long i; msr_t msr; + + disable_cache(); + /* Except for the PCI MMIO hold just before 4GB there are no * significant holes in the address space, so just account * for those two and move on. @@ -32,28 +84,15 @@ void k8_cpufixup(struct mem_range *mem) mmio_basek = tomk; } -#if 1 - /* Report the amount of memory. */ - print_debug("cpufixup RAM: 0x"); - print_debug_hex32(tomk); - print_debug(" KB\r\n"); -#endif - - /* Now set top of memory */ - msr.lo = (tomk & 0x003fffff) << 10; - msr.hi = (tomk & 0xffc00000) >> 22; - wrmsr(TOP_MEM2, msr); - - /* Leave a 64M hole between TOP_MEM and TOP_MEM2 - * so I can see my rom chip and other I/O devices. - */ - if (tomk >= 0x003f0000) { - tomk = 0x3f0000; - } // tom_k = 0x3c0000; - msr.lo = (tomk & 0x003fffff) << 10; - msr.hi = (tomk & 0xffc00000) >> 22; - wrmsr(TOP_MEM, msr); + /* Setup TOP_MEM */ + msr.hi = mmio_basek >> 22; + msr.lo = mmio_basek << 10; + wrmsr(TOP_MEM, msr); + /* Setup TOP_MEM2 */ + msr.hi = tomk >> 22; + msr.lo = tomk << 10; + wrmsr(TOP_MEM2, msr); /* zero the IORR's before we enable to prevent * undefined side effects. @@ -66,6 +105,64 @@ void k8_cpufixup(struct mem_range *mem) msr = rdmsr(SYSCFG_MSR); msr.lo |= SYSCFG_MSR_MtrrVarDramEn | SYSCFG_MSR_TOM2En; wrmsr(SYSCFG_MSR, msr); + + /* zero the machine check error status registers */ + msr.lo = 0; + msr.hi = 0; + for(i=0; i<5; i++) { + wrmsr(MCI_STATUS + (i*4),msr); + } + + if (is_cpu_pre_c0()) { + /* Erratum 63... */ + msr = rdmsr(HWCR_MSR); + msr.lo |= (1 << 6); + wrmsr(HWCR_MSR, msr); + /* Erratum 69... */ +#if 1 + msr = rdmsr_amd(BU_CFG_MSR); + msr.hi |= (1 << (45 - 32)); + wrmsr_amd(BU_CFG_MSR, msr); +#endif + /* Erratum 81... */ +#if 1 + msr = rdmsr_amd(DC_CFG_MSR); + msr.lo |= (1 << 10); + wrmsr_amd(DC_CFG_MSR, msr); +#endif + + } + /* Erratum 89 ... */ + msr = rdmsr(NB_CFG_MSR); + msr.lo |= 1 << 3; + + if (!is_cpu_pre_c0()) { + /* Erratum 86 Disable data masking on C0 and + * later processor revs. + * FIXME this is only needed if ECC is enabled. + */ + msr.hi |= 1 << (36 - 32); + } + wrmsr(NB_CFG_MSR, msr); +#if 1 /* The following erratum fixes reset the cpu ???? */ + + /* Erratum 97 ... */ + if (!is_cpu_pre_c0()) { + msr = rdmsr_amd(DC_CFG_MSR); + msr.lo |= 1 << 3; + wrmsr_amd(DC_CFG_MSR, msr); + } + + /* Erratum 94 ... */ + msr = rdmsr_amd(IC_CFG_MSR); + msr.lo |= 1 << 11; + wrmsr_amd(IC_CFG_MSR, msr); + +#endif + + /* Erratum 91 prefetch miss is handled in the kernel */ + + enable_cache(); } static @@ -87,10 +184,6 @@ void k8_enable(struct chip *chip, enum chip_pass pass) } struct chip_control cpu_k8_control = { - enable: k8_enable, - name: "AMD K8" + .enable = k8_enable, + .name = "AMD K8", }; - - - - |