diff options
author | Kyösti Mälkki <kyosti.malkki@gmail.com> | 2018-05-24 00:34:15 +0300 |
---|---|---|
committer | Kyösti Mälkki <kyosti.malkki@gmail.com> | 2018-05-31 03:42:11 +0000 |
commit | d840eb5719e51e1946ab322c0eb94defc72dde1d (patch) | |
tree | d74fa8bb59692dbb92fed137363d61f427dda2d0 /src/northbridge/amd/amdk8/raminit_f_dqs.c | |
parent | 4979ffc5cb267c7b0a5ad84c8bb9729e6b5613b1 (diff) | |
download | coreboot-d840eb5719e51e1946ab322c0eb94defc72dde1d.tar.xz |
Remove AMD K8 cpu and northbridge support
Change-Id: I9c53dfa93bf906334f5c80e4525a1c27153656a3
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: https://review.coreboot.org/26673
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Diffstat (limited to 'src/northbridge/amd/amdk8/raminit_f_dqs.c')
-rw-r--r-- | src/northbridge/amd/amdk8/raminit_f_dqs.c | 2058 |
1 files changed, 0 insertions, 2058 deletions
diff --git a/src/northbridge/amd/amdk8/raminit_f_dqs.c b/src/northbridge/amd/amdk8/raminit_f_dqs.c deleted file mode 100644 index 1573ce1899..0000000000 --- a/src/northbridge/amd/amdk8/raminit_f_dqs.c +++ /dev/null @@ -1,2058 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2005 YingHai Lu - * Copyright (C) 2008 Advanced Micro Devices, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. -*/ - -#include <arch/stages.h> -#include <cpu/x86/cr.h> -#include <cpu/x86/mtrr.h> -#include <arch/early_variables.h> -#if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700) -#include <southbridge/amd/sb700/sb700.h> -#endif - -//0: mean no debug info -#define DQS_TRAIN_DEBUG 0 - -static inline void print_debug_dqs(const char *str, unsigned val, unsigned level) -{ -#if DQS_TRAIN_DEBUG > 0 - if (DQS_TRAIN_DEBUG > level) { - printk(BIOS_DEBUG, "%s%x\n", str, val); - } -#endif -} - -static inline void print_debug_dqs_pair(const char *str, unsigned val, const char *str2, unsigned val2, unsigned level) -{ -#if DQS_TRAIN_DEBUG > 0 - if (DQS_TRAIN_DEBUG > level) { - printk(BIOS_DEBUG, "%s%08x%s%08x\n", str, val, str2, val2); - } -#endif -} - -static inline void print_debug_dqs_tsc(const char *str, unsigned i, unsigned val, unsigned val2, unsigned level) -{ -#if DQS_TRAIN_DEBUG > 0 - if (DQS_TRAIN_DEBUG > level) { - printk(BIOS_DEBUG, "%s[%02x]=%08x%08x\n", str, i, val, val2); - } -#endif -} - -static inline void print_debug_dqs_tsc_x(const char *str, unsigned i, unsigned val, unsigned val2) -{ - printk(BIOS_DEBUG, "%s[%02x]=%08x%08x\n", str, i, val, val2); - -} - -static void fill_mem_cs_sysinfo(unsigned nodeid, const struct mem_controller *ctrl, struct sys_info *sysinfo) -{ - - int i; - sysinfo->mem_base[nodeid] = pci_read_config32(ctrl->f1, 0x40 + (nodeid << 3)); - - for (i = 0; i < 8; i++) { - sysinfo->cs_base[nodeid*8+i] = pci_read_config32(ctrl->f2, 0x40 + (i << 2)); - } - - sysinfo->hole_reg[nodeid] = pci_read_config32(ctrl->f1, 0xf0); - -} -static unsigned Get_MCTSysAddr(const struct mem_controller *ctrl, unsigned cs_idx, struct sys_info *sysinfo) -{ - uint32_t dword; - uint32_t mem_base; - unsigned nodeid = ctrl->node_id; - -#if CONFIG_HW_MEM_HOLE_SIZEK != 0 - uint32_t hole_reg; -#endif - - //get the local base addr of the chipselect - dword = sysinfo->cs_base[nodeid * 8 + cs_idx]; - dword &= 0xfffffff0; - - //sys addr= node base + local cs base - mem_base = sysinfo->mem_base[nodeid]; - mem_base &= 0xffff0000; - - dword += mem_base; -#if CONFIG_HW_MEM_HOLE_SIZEK != 0 - hole_reg = sysinfo->hole_reg[nodeid]; - if (hole_reg & 1) { - unsigned hole_startk; - hole_startk = (hole_reg & (0xff << 24)) >> 10; - if ((dword >= (hole_startk << 2)) && (dword < ((4*1024*1024) << 2))) { - dword += ((4*1024*1024 - hole_startk) << 2); - } - } -#endif - - //add 1MB offset to avoid compat area - dword += (1<<(20-8)); - - //So final result is upper 32 bit addr - - return dword; - -} - -static unsigned Get_RcvrSysAddr(const struct mem_controller * ctrl, unsigned channel, unsigned cs_idx, struct sys_info *sysinfo) -{ - return Get_MCTSysAddr(ctrl, cs_idx, sysinfo); - -} - -static inline void enable_sse2(void) -{ - unsigned long cr4; - cr4 = read_cr4(); - cr4 |= (1<<9); - write_cr4(cr4); -} - -static inline void disable_sse2(void) -{ - unsigned long cr4; - cr4 = read_cr4(); - cr4 &= ~(1<<9); - write_cr4(cr4); -} - - -static void set_wrap32dis(void) { - msr_t msr; - - msr = rdmsr(0xc0010015); - msr.lo |= (1<<17); - - wrmsr(0xc0010015, msr); - -} - -static void clear_wrap32dis(void) { - msr_t msr; - - msr = rdmsr(0xc0010015); - msr.lo &= ~(1<<17); - - wrmsr(0xc0010015, msr); - -} - -static void set_FSBASE(uint32_t addr_hi) -{ - msr_t msr; - - //set fs and use fs prefix to access the mem - msr.hi = addr_hi; - msr.lo = 0; - wrmsr(0xc0000100, msr); //FS_BASE - -} - -static unsigned ChipSelPresent(const struct mem_controller *ctrl, unsigned cs_idx, struct sys_info *sysinfo) -{ - unsigned enabled; - unsigned nodeid = ctrl->node_id; - - - enabled = sysinfo->cs_base[nodeid * 8 + cs_idx]; - enabled &= 1; - - return enabled; - -} - -static unsigned RcvrRankEnabled(const struct mem_controller *ctrl, int channel, int cs_idx, unsigned is_Width128, struct sys_info *sysinfo) -{ - return ChipSelPresent(ctrl, cs_idx, sysinfo); -} - -static void WriteLNTestPattern(unsigned addr_lo, uint8_t *buf_a, unsigned line_num) -{ - __asm__ volatile ( - "1:\n\t" - "movdqa (%3), %%xmm0\n\t" - "movntdq %%xmm0, %%fs:(%0)\n\t" /* xmm0 is 128 bit */ - "addl %1, %0\n\t" - "addl %1, %3\n\t" - "loop 1b\n\t" - - :: "a" (addr_lo), "d" (16), "c" (line_num * 4), "b"(buf_a) - ); - - -} - -static void Write1LTestPattern(unsigned addr, unsigned p, uint8_t *buf_a, uint8_t *buf_b) -{ - uint8_t *buf; - if (p == 1) { buf = buf_b; } - else { buf = buf_a; } - - set_FSBASE (addr >> 24); - - WriteLNTestPattern(addr << 8, buf, 1); -} - -static void Read1LTestPattern(unsigned addr) -{ - unsigned value; - - set_FSBASE(addr>>24); - - /* 1st move causes read fill (to exclusive or shared)*/ - __asm__ volatile ( - "movl %%fs:(%1), %0\n\t" - :"=b"(value): "a" (addr << 8) - ); - -} - -#define DQS_PASS 0 -#define DQS_FAIL 1 - -#define DQS_FIRST_PASS 1 -#define DQS_SECOND_PASS 2 - -#define SB_NORCVREN 11 -#define RCVREN_MARGIN 6 -#define SB_SmallRCVR 13 -#define SB_CHA2BRCVREN 12 -#define SB_NODQSPOS 14 -#define MIN_DQS_WNDW 3 -#define SB_SMALLDQS 15 - - -static unsigned CompareTestPatternQW0(unsigned channel, unsigned addr, unsigned pattern, const uint32_t *TestPattern0, const uint32_t *TestPattern1, const uint32_t *TestPattern2, unsigned Pass, unsigned is_Width128) -{ - uint32_t addr_lo; - uint32_t *test_buf; - uint32_t value; - uint32_t value_test; - unsigned result = DQS_FAIL; - - if (Pass == DQS_FIRST_PASS) { - if (pattern == 1) { - test_buf = (uint32_t *)TestPattern1; - } - else { - test_buf = (uint32_t *)TestPattern0; - } - } - else { - test_buf = (uint32_t *)TestPattern2; - } - - set_FSBASE(addr >> 24); - - addr_lo = addr << 8; - - if (is_Width128 && (channel == 1)) { - addr_lo += 8; //second channel - test_buf += 2; - } - - __asm__ volatile ( - "movl %%fs:(%1), %0\n\t" - :"=b"(value): "a" (addr_lo) - ); - - value_test = *test_buf; - - - print_debug_dqs_pair("\t\t\t\t\t\tQW0.lo : test_buf= ", (unsigned)test_buf, " value = ", value_test, 4); - print_debug_dqs_pair("\t\t\t\t\t\tQW0.lo : addr_lo = ", addr_lo, " value = ", value, 4); - - if (value == value_test) { - addr_lo += 4; - test_buf++; - __asm__ volatile ( - "movl %%fs:(%1), %0\n\t" - :"=b"(value): "a" (addr_lo) - ); - value_test = *test_buf; - print_debug_dqs_pair("\t\t\t\t\t\tQW0.hi : test_buf= ", (unsigned)test_buf, " value = ", value_test, 4); - print_debug_dqs_pair("\t\t\t\t\t\tQW0.hi : addr_lo = ", addr_lo, " value = ", value, 4); - - if (value == value_test) { - result = DQS_PASS; - } - } - - if (Pass == DQS_SECOND_PASS) { // second pass need to be inverted - if (result == DQS_PASS) { - result = DQS_FAIL; - } - else { - result = DQS_PASS; - } - } - - return result; - -} - -static void SetMaxAL_RcvrDly(const struct mem_controller *ctrl, unsigned dly) -{ - uint32_t reg; - - dly += (20-1); // round it - dly /= 20; // convert from unit 50ps to 1ns - - dly += 6; - - - reg = pci_read_config32(ctrl->f2, DRAM_CONFIG_HIGH); - reg &= ~(DCH_MaxAsyncLat_MASK << DCH_MaxAsyncLat_SHIFT); - reg |= ((dly - DCH_MaxAsyncLat_BASE) << DCH_MaxAsyncLat_SHIFT); - pci_write_config32(ctrl->f2, DRAM_CONFIG_HIGH, reg); - -} - -/* - Set the Target range to WT IO (using an IORR overlapping the already existing - WB dram type). Use IORR0 -*/ -static void SetTargetWTIO(unsigned addr) -{ - msr_t msr; - msr.hi = addr >> 24; - msr.lo = addr << 8; - wrmsr(0xc0010016, msr); //IORR0 BASE - - msr.hi = 0xff; - msr.lo = 0xfc000800; // 64MB Mask - wrmsr(0xc0010017, msr); // IORR0 Mask -} - -static void ResetTargetWTIO(void) -{ - msr_t msr; - - msr.hi = 0; - msr.lo = 0; - wrmsr(0xc0010017, msr); // IORR0 Mask -} - -static void proc_CLFLUSH(unsigned addr) -{ - - set_FSBASE(addr>>24); - - /* 1st move causes read fill (to exclusive or shared)*/ - __asm__ volatile ( - /* clflush fs:[eax] */ - "clflush %%fs:(%0)\n\t" - ::"a" (addr << 8) - ); - -} -static void proc_IOCLFLUSH(unsigned addr) -{ - SetTargetWTIO(addr); - proc_CLFLUSH(addr); - ResetTargetWTIO(); -} - -static void ResetDCTWrPtr(const struct mem_controller *ctrl) -{ - uint32_t dword; - unsigned index = 0x10; - - dword = pci_read_config32_index_wait(ctrl->f2, 0x98, index); - pci_write_config32_index_wait(ctrl->f2, 0x98, index, dword); - - index += 0x20; - dword = pci_read_config32_index_wait(ctrl->f2, 0x98, index); - pci_write_config32_index_wait(ctrl->f2, 0x98, index, dword); - -} - - -static uint16_t get_exact_T1000(unsigned i) -{ - // 200 266, 333, 400 - static const uint16_t T1000_a[]= { 5000, 3759, 3003, 2500 }; - - static const uint16_t TT_a[] = { - /*200 266 333 400 */ - /*4 */ 6250, 6250, 6250, 6250, - /*5 */ 5000, 5000, 5000, 2500, - /*6 */ 5000, 4166, 4166, 2500, - /*7 */ 5000, 4285, 3571, 2500, - - /*8 */ 5000, 3750, 3125, 2500, - /*9 */ 5000, 3888, 3333, 2500, - /*10*/ 5000, 4000, 3000, 2500, - /*11*/ 5000, 4090, 3181, 2500, - - /*12*/ 5000, 3750, 3333, 2500, - /*13*/ 5000, 3846, 3076, 2500, - /*14*/ 5000, 3928, 3214, 2500, - /*15*/ 5000, 4000, 3000, 2500, - }; - - int index; - msr_t msr; - - /* Check for FID control support */ - struct cpuid_result cpuid1; - cpuid1 = cpuid(0x80000007); - if (cpuid1.edx & 0x02) { - /* Use current FID */ - unsigned fid_cur; - msr = rdmsr(0xc0010042); - fid_cur = msr.lo & 0x3f; - - index = fid_cur>>1; - } else { - /* Use startup FID */ - unsigned fid_start; - msr = rdmsr(0xc0010015); - fid_start = (msr.lo & (0x3f << 24)); - - index = fid_start>>25; - } - - if (index > 12) return T1000_a[i]; - - return TT_a[index * 4+i]; - -} - -static void InitDQSPos4RcvrEn(const struct mem_controller *ctrl) -{ - int i; - uint32_t dword; - - dword = 0x00000000; - for (i = 1; i <= 3; i++) { - /* Program the DQS Write Timing Control Registers (Function 2:Offset 0x9c, index 0x01-0x03, 0x21-0x23) to 0x00 for all bytes */ - pci_write_config32_index_wait(ctrl->f2, 0x98, i, dword); - pci_write_config32_index_wait(ctrl->f2, 0x98, i+0x20, dword); - } - - dword = 0x2f2f2f2f; - for (i = 5; i <= 7; i++) { - /* Program the DQS Write Timing Control Registers (Function 2:Offset 0x9c, index 0x05-0x07, 0x25-0x27) to 0x2f for all bytes */ - pci_write_config32_index_wait(ctrl->f2, 0x98, i, dword); - pci_write_config32_index_wait(ctrl->f2, 0x98, i+0x20, dword); - } - - -} - -static unsigned TrainRcvrEn(const struct mem_controller *ctrl, unsigned Pass, struct sys_info *sysinfo) -{ - - static const uint32_t TestPattern0[] = { - 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, - 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, - 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, - 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, - }; - static const uint32_t TestPattern1[] = { - 0x55555555, 0x55555555, 0x55555555, 0x55555555, - 0x55555555, 0x55555555, 0x55555555, 0x55555555, - 0x55555555, 0x55555555, 0x55555555, 0x55555555, - 0x55555555, 0x55555555, 0x55555555, 0x55555555, - }; - static const uint32_t TestPattern2[] = { - 0x12345678, 0x87654321, 0x23456789, 0x98765432, - 0x59385824, 0x30496724, 0x24490795, 0x99938733, - 0x40385642, 0x38465245, 0x29432163, 0x05067894, - 0x12349045, 0x98723467, 0x12387634, 0x34587623, - }; - - uint8_t pattern_buf_x[64 * 4 + 16]; // We need to two cache line So have more 16 bytes to keep 16 byte alignment */ - uint8_t *buf_a, *buf_b; - uint32_t ecc_bit; - uint32_t dword; - uint8_t *dqs_rcvr_dly_a = &sysinfo->dqs_rcvr_dly_a[ctrl->node_id * 2* 8]; //8 node, channel 2, receiver 8 - - int i; - - unsigned channel, receiver; - - unsigned Errors; - unsigned CTLRMaxDelay; - unsigned T1000; - - unsigned LastTest; - unsigned CurrTest; - unsigned Test0, Test1; - - unsigned RcvrEnDlyRmin; - - unsigned two_ranks; - unsigned RcvrEnDly; - - unsigned PatternA; - unsigned PatternB; - - unsigned TestAddr0, TestAddr0B, TestAddr1 = 0, TestAddr1B = 0; - - unsigned CurrRcvrCHADelay = 0; - - unsigned tmp; - - unsigned is_Width128 = sysinfo->meminfo[ctrl->node_id].is_Width128; - -#if K8_REV_F_SUPPORT_F0_F1_WORKAROUND == 1 - unsigned cpu_f0_f1 = 0; -#endif - - if (Pass == DQS_FIRST_PASS) { - InitDQSPos4RcvrEn(ctrl); - } - - //enable SSE2 - enable_sse2(); - - //wrap32dis - set_wrap32dis(); - - //disable ECC temp - dword = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW); - ecc_bit = dword & DCL_DimmEccEn; - dword &= ~(DCL_DimmEccEn); - pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dword); - - - if (Pass == DQS_FIRST_PASS) { -#if K8_REV_F_SUPPORT_F0_F1_WORKAROUND == 1 - cpu_f0_f1 = is_cpu_pre_f2_in_bsp(ctrl->node_id); - if (!cpu_f0_f1) -#endif - { -#if 1 - /* Set the DqsRcvEnTrain bit */ - dword = pci_read_config32(ctrl->f2, DRAM_CTRL); - dword |= DC_DqsRcvEnTrain; - pci_write_config32(ctrl->f2, DRAM_CTRL, dword); -#endif - } - } - - //get T1000 figures (cycle time (ns)) * 1K - dword = pci_read_config32(ctrl->f2, DRAM_CONFIG_HIGH); - dword &= DCH_MemClkFreq_MASK; - - T1000 = get_exact_T1000(dword); - - // SetupRcvrPattern - buf_a = (uint8_t *)(((uint32_t)(&pattern_buf_x[0]) + 0x10) & (0xfffffff0)); - buf_b = buf_a + 128; //?? - if (Pass == DQS_FIRST_PASS) { - for (i = 0; i < 16; i++) { - *((uint32_t *)(buf_a + i*4)) = TestPattern0[i]; - *((uint32_t *)(buf_b + i*4)) = TestPattern1[i]; - } - } - else { - for (i = 0; i < 16; i++) { - *((uint32_t *)(buf_a + i*4)) = TestPattern2[i]; - *((uint32_t *)(buf_b + i*4)) = TestPattern2[i]; - } - } - - print_debug_dqs("\nTrainRcvEn: 0 ctrl", ctrl->node_id, 0); - - print_debug_addr("TrainRcvEn: buf_a:", buf_a); - - Errors = 0; - /* for each channel */ - CTLRMaxDelay = 0; - channel = 0; - - if (!(sysinfo->meminfo[ctrl->node_id].dimm_mask & 0x0F) && - (sysinfo->meminfo[ctrl->node_id].dimm_mask & 0xF0)) { /* channelB only? */ - channel = 1; - } - - for (; (channel < 2) && (!Errors); channel++) - { - print_debug_dqs("\tTrainRcvEn51: channel ",channel, 1); - - /* for each rank */ - /* there are four receiver pairs, loosely associated with CS */ - for (receiver = 0; (receiver < 8) && (!Errors); receiver+=2) - { - - unsigned index=(receiver>>1) * 3 + 0x10; - - print_debug_dqs("\t\tTrainRcvEn52: index ", index, 2); - - if (is_Width128) { - if (channel) { - dword = pci_read_config32_index_wait(ctrl->f2, 0x98, index); - CurrRcvrCHADelay= dword & 0xff; - } - } - else { - if (channel) { - index += 0x20; - } - } - - LastTest = DQS_FAIL; - RcvrEnDlyRmin = 0xaf; - - if (!RcvrRankEnabled(ctrl, channel, receiver, is_Width128, sysinfo)) continue; - - /* for each DQS receiver enable setting */ - - TestAddr0 = Get_RcvrSysAddr(ctrl, channel, receiver, sysinfo); - - TestAddr0B = TestAddr0 + (1<<(20+2-8)); // 4MB - - if (RcvrRankEnabled(ctrl, channel, receiver+1, is_Width128, sysinfo)) { - TestAddr1 = Get_RcvrSysAddr(ctrl, channel, receiver+1, sysinfo); - TestAddr1B = TestAddr1 + (1<<(20+2-8)); //4MB - two_ranks = 1; - } - else { - two_ranks = 0; - } - - print_debug_dqs("\t\tTrainRcvEn53: TestAddr0B ", TestAddr0B, 2); - - Write1LTestPattern(TestAddr0, 0, buf_a, buf_b); // rank0 of dimm, test p0 - Write1LTestPattern(TestAddr0B, 1, buf_a, buf_b); //rank0 of dimm, test p1 - - if (two_ranks == 1) { - Write1LTestPattern(TestAddr1, 0, buf_a, buf_b); //rank 1 of dimm - Write1LTestPattern(TestAddr1B, 1, buf_a, buf_b);//rank 1 of dimm - } - - if (Pass == DQS_FIRST_PASS) { - RcvrEnDly = 0; - } else { - RcvrEnDly = dqs_rcvr_dly_a[channel * 8 + receiver]; - } - - while (RcvrEnDly < 0xaf) { // Sweep Delay value here - print_debug_dqs("\t\t\tTrainRcvEn541: RcvrEnDly ", RcvrEnDly, 3); - - if (RcvrEnDly & 1) { - /* Odd steps get another pattern such that even - * and odd steps alternate. - * The pointers to the patterns will be swapped - * at the end of the loop so they are correspond - */ - PatternA = 1; - PatternB = 0; - } - else { - /* Even step */ - PatternA = 0; - PatternB = 1; - } - - /* Program current Receiver enable delay */ - pci_write_config32_index_wait(ctrl->f2, 0x98, index, RcvrEnDly); - /* FIXME: 64bit MUX */ - - if (is_Width128) { - /* Program current Receiver enable delay channel b */ - pci_write_config32_index_wait(ctrl->f2, 0x98, index+ 0x20, RcvrEnDly); - } - - /* Program the MaxAsyncLat filed with the - * current DQS receiver enable setting plus 6ns - */ - /* Program MaxAsyncLat to correspond with current delay */ - SetMaxAL_RcvrDly(ctrl, RcvrEnDly); - - CurrTest = DQS_FAIL; - - Read1LTestPattern(TestAddr0); //Cache Fill - /* ROM vs cache compare */ - Test0 = CompareTestPatternQW0(channel, TestAddr0, PatternA, TestPattern0, TestPattern1, TestPattern2, Pass, is_Width128); - proc_IOCLFLUSH(TestAddr0); - - ResetDCTWrPtr(ctrl); - - print_debug_dqs("\t\t\tTrainRcvEn542: Test0 ", Test0, 3); - - if (Test0 == DQS_PASS) { - - Read1LTestPattern(TestAddr0B); - Test1 = CompareTestPatternQW0(channel, TestAddr0B, PatternB, TestPattern0, TestPattern1, TestPattern2, Pass, is_Width128); - proc_IOCLFLUSH(TestAddr0B); - - ResetDCTWrPtr(ctrl); - - print_debug_dqs("\t\t\tTrainRcvEn543: Test1 ", Test1, 3); - - if (Test1 == DQS_PASS) { - if (two_ranks) { - Read1LTestPattern(TestAddr1); - Test0 = CompareTestPatternQW0(channel, TestAddr1, PatternA, TestPattern0, TestPattern1, TestPattern2, Pass, is_Width128); - proc_IOCLFLUSH(TestAddr1); - ResetDCTWrPtr(ctrl); - - if (Test0 == DQS_PASS) { - Read1LTestPattern(TestAddr1B); - Test1 = CompareTestPatternQW0(channel, TestAddr1B, PatternB, TestPattern0, TestPattern1, TestPattern2, Pass, is_Width128); - proc_IOCLFLUSH(TestAddr1B); - ResetDCTWrPtr(ctrl); - - if (Test1 == DQS_PASS) { - CurrTest = DQS_PASS; - } - } - print_debug_dqs("\t\t\tTrainRcvEn544: Test0 ", Test0, 3); - } - else { - CurrTest = DQS_PASS; - } - } - } - - print_debug_dqs("\t\t\tTrainRcvEn55: RcvrEnDly ", RcvrEnDly, 3); - - if (CurrTest == DQS_PASS) { - if (LastTest == DQS_FAIL) { - RcvrEnDlyRmin = RcvrEnDly; - break; - } - } - - LastTest = CurrTest; - - /* swap the rank 0 pointers */ - tmp = TestAddr0; - TestAddr0 = TestAddr0B; - TestAddr0B = tmp; - - /* swap the rank 1 pointers */ - tmp = TestAddr1; - TestAddr1 = TestAddr1B; - TestAddr1B = tmp; - - print_debug_dqs("\t\t\tTrainRcvEn56: RcvrEnDly ", RcvrEnDly, 3); - - RcvrEnDly++; - - } // while RcvrEnDly - - print_debug_dqs("\t\tTrainRcvEn61: RcvrEnDly ", RcvrEnDly, 2); - - if (RcvrEnDlyRmin == 0xaf) { - //no passing window - Errors |= SB_NORCVREN; - } - - if (Pass == DQS_FIRST_PASS) { - // We need a better value for DQSPos training - RcvrEnDly = RcvrEnDlyRmin /* + RCVREN_MARGIN * T1000/64/50 */; - } else { - RcvrEnDly = RcvrEnDlyRmin; - } - - if (RcvrEnDly > 0xae) { - //passing window too narrow, too far delayed - Errors |= SB_SmallRCVR; - RcvrEnDly = 0xae; - } - - if (Pass == DQS_SECOND_PASS) { //second pass must average vales - RcvrEnDly += dqs_rcvr_dly_a[channel * 8 + receiver] /* - (RCVREN_MARGIN * T1000/64/50)*/; - RcvrEnDly >>= 1; - } - - dqs_rcvr_dly_a[channel * 8 + receiver] = RcvrEnDly; - - //Set final RcvrEnDly for this DIMM and Channel - pci_write_config32_index_wait(ctrl->f2, 0x98, index, RcvrEnDly); - - if (is_Width128) { - pci_write_config32_index_wait(ctrl->f2, 0x98, index+0x20, RcvrEnDly); // channel B - if (channel) { - pci_write_config32_index_wait(ctrl->f2, 0x98, index, CurrRcvrCHADelay); - if (RcvrEnDly > CurrRcvrCHADelay) { - dword = RcvrEnDly - CurrRcvrCHADelay; - } - else { - dword = CurrRcvrCHADelay - RcvrEnDly; - } - dword *= 50; - if (dword > T1000) { - Errors |= SB_CHA2BRCVREN; - } - } - } - - print_debug_dqs("\t\tTrainRcvEn63: RcvrEnDly ", RcvrEnDly, 2); - - if (RcvrEnDly > CTLRMaxDelay) { - CTLRMaxDelay = RcvrEnDly; - } - - print_debug_dqs("\t\tTrainRcvEn64: CTLRMaxDelay ", CTLRMaxDelay, 2); - - } /* receiver */ - } /* channel */ - - print_debug_dqs("\tTrainRcvEn65: CTLRMaxDelay ", CTLRMaxDelay, 1); - - /* Program the MaxAsysncLat field with the largest DQS Receiver Enable setting */ - SetMaxAL_RcvrDly(ctrl, CTLRMaxDelay); - ResetDCTWrPtr(ctrl); - - //Enable ECC again - dword = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW); - dword &= ~(DCL_DimmEccEn); - dword |= ecc_bit; - pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dword); - - if (Pass == DQS_FIRST_PASS) { -#if K8_REV_F_SUPPORT_F0_F1_WORKAROUND == 1 - if (!cpu_f0_f1) -#endif - { - dword = pci_read_config32(ctrl->f2, DRAM_CTRL); - dword &= ~DC_DqsRcvEnTrain; - pci_write_config32(ctrl->f2, DRAM_CTRL, dword); - } - } - - //Clear wrap32dis - - clear_wrap32dis(); - - //restore SSE2 setting - disable_sse2(); - -#if CONFIG_MEM_TRAIN_SEQ != 1 - /* We need tidy output for type 1 */ - printk(BIOS_DEBUG, " CTLRMaxDelay=%02x\n", CTLRMaxDelay); -#endif - - return (CTLRMaxDelay == 0xae)?1:0; - -} - -#define DQS_READDIR 1 -#define DQS_WRITEDIR 0 - - -static void SetDQSDelayCSR(const struct mem_controller *ctrl, unsigned channel, unsigned bytelane, unsigned direction, unsigned dqs_delay) -{ //ByteLane could be 0-8, last is for ECC - unsigned index; - uint32_t dword; - unsigned shift; - - dqs_delay &= 0xff; - - index = (bytelane>>2) + 1 + channel * 0x20 + (direction << 2); - shift = bytelane; - while (shift > 3) { - shift-=4; - } - shift <<= 3; // 8 bit - - dword = pci_read_config32_index_wait(ctrl->f2, 0x98, index); - dword &= ~(0x3f << shift); - dword |= (dqs_delay << shift); - pci_write_config32_index_wait(ctrl->f2, 0x98, index, dword); - -} - -static void SetDQSDelayAllCSR(const struct mem_controller *ctrl, unsigned channel, unsigned direction, unsigned dqs_delay) -{ - unsigned index; - uint32_t dword; - int i; - - dword = 0; - dqs_delay &= 0xff; - for (i = 0; i < 4; i++) { - dword |= dqs_delay << (i*8); - } - - index = 1 + channel * 0x20 + direction * 4; - - for (i = 0; i < 2; i++) { - pci_write_config32_index_wait(ctrl->f2, 0x98, index + i, dword); - } - -} - -static unsigned MiddleDQS(unsigned min_d, unsigned max_d) -{ - unsigned size_d; - size_d = max_d-min_d; - if (size_d & 1) { //need round up - min_d++; - } - return (min_d + (size_d>>1)); -} - -static inline void save_dqs_delay(unsigned channel, unsigned bytelane, unsigned direction, uint8_t *dqs_delay_a, uint8_t dqs_delay) -{ - dqs_delay_a[channel * 2*9 + direction * 9 + bytelane] = dqs_delay; -} - -static void WriteDQSTestPattern(unsigned addr_lo, unsigned pattern , uint8_t *buf_a) -{ - WriteLNTestPattern(addr_lo, buf_a, (pattern+1) * 9); -} - -static void ReadL18TestPattern(unsigned addr_lo) -{ - //set fs and use fs prefix to access the mem - __asm__ volatile ( - "movl %%fs:-128(%%esi), %%eax\n\t" //TestAddr cache line - "movl %%fs:-64(%%esi), %%eax\n\t" //+1 - "movl %%fs:(%%esi), %%eax\n\t" //+2 - "movl %%fs:64(%%esi), %%eax\n\t" //+3 - - "movl %%fs:-128(%%edi), %%eax\n\t" //+4 - "movl %%fs:-64(%%edi), %%eax\n\t" //+5 - "movl %%fs:(%%edi), %%eax\n\t" //+6 - "movl %%fs:64(%%edi), %%eax\n\t" //+7 - - "movl %%fs:-128(%%ebx), %%eax\n\t" //+8 - "movl %%fs:-64(%%ebx), %%eax\n\t" //+9 - "movl %%fs:(%%ebx), %%eax\n\t" //+10 - "movl %%fs:64(%%ebx), %%eax\n\t" //+11 - - "movl %%fs:-128(%%ecx), %%eax\n\t" //+12 - "movl %%fs:-64(%%ecx), %%eax\n\t" //+13 - "movl %%fs:(%%ecx), %%eax\n\t" //+14 - "movl %%fs:64(%%ecx), %%eax\n\t" //+15 - - "movl %%fs:-128(%%edx), %%eax\n\t" //+16 - "movl %%fs:-64(%%edx), %%eax\n\t" //+17 - - :: "a"(0), "b" (addr_lo+128+8*64), "c" (addr_lo+128+12*64), "d" (addr_lo +128+16*64), "S"(addr_lo+128), "D"(addr_lo+128+4*64) - ); - -} - -static void ReadL9TestPattern(unsigned addr_lo) -{ - - //set fs and use fs prefix to access the mem - __asm__ volatile ( - - "movl %%fs:-128(%%ecx), %%eax\n\t" //TestAddr cache line - "movl %%fs:-64(%%ecx), %%eax\n\t" //+1 - "movl %%fs:(%%ecx), %%eax\n\t" //+2 - "movl %%fs:64(%%ecx), %%eax\n\t" //+3 - - "movl %%fs:-128(%%edx), %%eax\n\t" //+4 - "movl %%fs:-64(%%edx), %%eax\n\t" //+5 - "movl %%fs:(%%edx), %%eax\n\t" //+6 - "movl %%fs:64(%%edx), %%eax\n\t" //+7 - - "movl %%fs:-128(%%ebx), %%eax\n\t" //+8 - - :: "a"(0), "b" (addr_lo+128+8*64), "c"(addr_lo+128), "d"(addr_lo+128+4*64) - ); - -} - - -static void ReadDQSTestPattern(unsigned addr_lo, unsigned pattern) -{ - if (pattern == 0) { - ReadL9TestPattern(addr_lo); - } - else { - ReadL18TestPattern(addr_lo); - } -} - -static void FlushDQSTestPattern_L9(unsigned addr_lo) -{ - __asm__ volatile ( - "clflush %%fs:-128(%%ecx)\n\t" - "clflush %%fs:-64(%%ecx)\n\t" - "clflush %%fs:(%%ecx)\n\t" - "clflush %%fs:64(%%ecx)\n\t" - - "clflush %%fs:-128(%%eax)\n\t" - "clflush %%fs:-64(%%eax)\n\t" - "clflush %%fs:(%%eax)\n\t" - "clflush %%fs:64(%%eax)\n\t" - - "clflush %%fs:-128(%%ebx)\n\t" - - :: "b" (addr_lo+128+8*64), "c"(addr_lo+128), "a"(addr_lo+128+4*64) - ); - -} -static __attribute__((noinline)) void FlushDQSTestPattern_L18(unsigned addr_lo) -{ - __asm__ volatile ( - "clflush %%fs:-128(%%eax)\n\t" - "clflush %%fs:-64(%%eax)\n\t" - "clflush %%fs:(%%eax)\n\t" - "clflush %%fs:64(%%eax)\n\t" - - "clflush %%fs:-128(%%edi)\n\t" - "clflush %%fs:-64(%%edi)\n\t" - "clflush %%fs:(%%edi)\n\t" - "clflush %%fs:64(%%edi)\n\t" - - "clflush %%fs:-128(%%ebx)\n\t" - "clflush %%fs:-64(%%ebx)\n\t" - "clflush %%fs:(%%ebx)\n\t" - "clflush %%fs:64(%%ebx)\n\t" - - "clflush %%fs:-128(%%ecx)\n\t" - "clflush %%fs:-64(%%ecx)\n\t" - "clflush %%fs:(%%ecx)\n\t" - "clflush %%fs:64(%%ecx)\n\t" - - "clflush %%fs:-128(%%edx)\n\t" - "clflush %%fs:-64(%%edx)\n\t" - - :: "b" (addr_lo+128+8*64), "c" (addr_lo+128+12*64), "d" (addr_lo +128+16*64), "a"(addr_lo+128), "D"(addr_lo+128+4*64) - ); -} - -static void FlushDQSTestPattern(unsigned addr_lo, unsigned pattern) -{ - - if (pattern == 0) { - FlushDQSTestPattern_L9(addr_lo); - } - else { - FlushDQSTestPattern_L18(addr_lo); - } -} - -static unsigned CompareDQSTestPattern(unsigned channel, unsigned addr_lo, unsigned pattern, uint8_t *buf_a) -{ - uint32_t *test_buf; - unsigned bitmap = 0xff; - unsigned bytelane; - int i; - uint32_t value; - int j; - uint32_t value_test; - - test_buf = (uint32_t *)buf_a; - - - if (pattern && channel) { - addr_lo += 8; //second channel - test_buf+= 2; - } - - bytelane = 0; - for (i = 0; i < 9*64/4; i++) { - __asm__ volatile ( - "movl %%fs:(%1), %0\n\t" - :"=b"(value): "a" (addr_lo) - ); - value_test = *test_buf; - - print_debug_dqs_pair("\t\t\t\t\t\ttest_buf= ", (unsigned)test_buf, " value = ", value_test, 7); - print_debug_dqs_pair("\t\t\t\t\t\ttaddr_lo = ",addr_lo, " value = ", value, 7); - - for (j = 0; j < 4*8; j+=8) { - if (((value>>j)&0xff) != ((value_test>>j)& 0xff)) { - bitmap &= ~(1 << bytelane); - } - - bytelane++; - bytelane &= 0x7; - } - print_debug_dqs("\t\t\t\t\t\tbitmap = ", bitmap, 7); - - if (bytelane == 0) { - if (pattern == 1) { //dual channel - addr_lo += 8; //skip over other channel's data - test_buf += 2; - } - } - addr_lo += 4; - test_buf +=1; - - } - - - return bitmap; - -} - -static unsigned TrainDQSPos(const struct mem_controller *ctrl, unsigned channel, unsigned Direction, unsigned Pattern, uint8_t *buf_a, uint8_t *dqs_delay_a, struct sys_info *sysinfo) -{ - unsigned ByteLane; - unsigned Errors; - unsigned BanksPresent; - - unsigned MutualCSPassW[48]; - - unsigned ChipSel; - unsigned DQSDelay; - - unsigned TestAddr; - - unsigned LastTest; - unsigned RnkDlyFilterMax, RnkDlyFilterMin = 0; - unsigned RnkDlySeqPassMax, RnkDlySeqPassMin = 0; - - Errors = 0; - BanksPresent = 0; - - print_debug_dqs("\t\t\tTrainDQSPos begin ", 0, 3); - - printk(BIOS_DEBUG, "TrainDQSPos: MutualCSPassW[48] :%p\n", MutualCSPassW); - - for (DQSDelay = 0; DQSDelay < 48; DQSDelay++) { - MutualCSPassW[DQSDelay] = 0xff; // Bitmapped status per delay setting, 0xff=All positions passing (1= PASS) - } - - for (ChipSel = 0; ChipSel < 8; ChipSel++) { //logical register chipselects 0..7 - print_debug_dqs("\t\t\t\tTrainDQSPos: 11 ChipSel ", ChipSel, 4); - //FIXME: process 64MUXedMode - if (!ChipSelPresent(ctrl, ChipSel, sysinfo)) continue; - BanksPresent = 1; - - TestAddr = Get_MCTSysAddr(ctrl, ChipSel, sysinfo); - - print_debug_dqs("\t\t\t\tTrainDQSPos: 12 TestAddr ", TestAddr, 4); - - //set fs and use fs prefix to access the mem - set_FSBASE(TestAddr>>24); - - if (Direction == DQS_READDIR) { - print_debug_dqs("\t\t\t\tTrainDQSPos: 13 for read so write at first", 0, 4); - WriteDQSTestPattern(TestAddr << 8, Pattern, buf_a); - } - - for (DQSDelay = 0; DQSDelay < 48; DQSDelay++) { - print_debug_dqs("\t\t\t\t\tTrainDQSPos: 141 DQSDelay ", DQSDelay, 5); - if (MutualCSPassW[DQSDelay] == 0) continue; //skip current delay value if other chipselects have failed all 8 bytelanes - SetDQSDelayAllCSR(ctrl, channel, Direction, DQSDelay); - print_debug_dqs("\t\t\t\t\tTrainDQSPos: 142 MutualCSPassW ", MutualCSPassW[DQSDelay], 5); - if (Direction == DQS_WRITEDIR) { - print_debug_dqs("\t\t\t\t\tTrainDQSPos: 143 for write", 0, 5); - WriteDQSTestPattern(TestAddr << 8, Pattern, buf_a); - } - print_debug_dqs("\t\t\t\t\tTrainDQSPos: 144 Pattern ", Pattern, 5); - ReadDQSTestPattern(TestAddr << 8, Pattern); - print_debug_dqs("\t\t\t\t\tTrainDQSPos: 145 MutualCSPassW ", MutualCSPassW[DQSDelay], 5); - MutualCSPassW[DQSDelay] &= CompareDQSTestPattern(channel, TestAddr << 8, Pattern, buf_a); //0: fail, 1=pass - print_debug_dqs("\t\t\t\t\tTrainDQSPos: 146 MutualCSPassW ", MutualCSPassW[DQSDelay], 5); - SetTargetWTIO(TestAddr); - FlushDQSTestPattern(TestAddr << 8, Pattern); - ResetTargetWTIO(); - } - } - - if (BanksPresent) - for (ByteLane = 0; ByteLane < 8; ByteLane++) { - print_debug_dqs("\t\t\t\tTrainDQSPos: 31 ByteLane ",ByteLane, 4); - - LastTest = DQS_FAIL; - RnkDlySeqPassMax = 0; - RnkDlyFilterMax = 0; - RnkDlyFilterMin = 0; - for (DQSDelay = 0; DQSDelay < 48; DQSDelay++) { - if (MutualCSPassW[DQSDelay] & (1 << ByteLane)) { - - print_debug_dqs("\t\t\t\t\tTrainDQSPos: 321 DQSDelay ", DQSDelay, 5); - print_debug_dqs("\t\t\t\t\tTrainDQSPos: 322 MutualCSPassW ", MutualCSPassW[DQSDelay], 5); - - RnkDlySeqPassMax = DQSDelay; - if (LastTest == DQS_FAIL) { - RnkDlySeqPassMin = DQSDelay; //start sequential run - } - if ((RnkDlySeqPassMax - RnkDlySeqPassMin)>(RnkDlyFilterMax-RnkDlyFilterMin)) { - RnkDlyFilterMin = RnkDlySeqPassMin; - RnkDlyFilterMax = RnkDlySeqPassMax; - } - LastTest = DQS_PASS; - } - else { - LastTest = DQS_FAIL; - } - } - print_debug_dqs("\t\t\t\tTrainDQSPos: 33 RnkDlySeqPassMax ", RnkDlySeqPassMax, 4); - - if (RnkDlySeqPassMax == 0) { - Errors |= SB_NODQSPOS; // no passing window - } - else { - print_debug_dqs("\t\t\t\tTrainDQSPos: 34 RnkDlyFilterMax ", RnkDlyFilterMax, 4); - print_debug_dqs("\t\t\t\tTrainDQSPos: 34 RnkDlyFilterMin ", RnkDlyFilterMin, 4); - if ((RnkDlyFilterMax - RnkDlyFilterMin)< MIN_DQS_WNDW) { - Errors |= SB_SMALLDQS; - } - else { - unsigned middle_dqs; - middle_dqs = MiddleDQS(RnkDlyFilterMin, RnkDlyFilterMax); - print_debug_dqs("\t\t\t\tTrainDQSPos: 35 middle_dqs ",middle_dqs, 4); - SetDQSDelayCSR(ctrl, channel, ByteLane, Direction, middle_dqs); - save_dqs_delay(channel, ByteLane, Direction, dqs_delay_a, middle_dqs); - } - } - - } - - print_debug_dqs("\t\t\tTrainDQSPos: end", 0xff, 3); - - return Errors; - - -} - -static unsigned TrainReadDQS(const struct mem_controller *ctrl, unsigned channel, unsigned pattern, uint8_t *buf_a, uint8_t *dqs_delay_a, struct sys_info *sysinfo) -{ - print_debug_dqs("\t\tTrainReadPos", 0, 2); - return TrainDQSPos(ctrl, channel, DQS_READDIR, pattern, buf_a, dqs_delay_a, sysinfo); -} - -static unsigned TrainWriteDQS(const struct mem_controller *ctrl, unsigned channel, unsigned pattern, uint8_t *buf_a, uint8_t *dqs_delay_a, struct sys_info *sysinfo) -{ - print_debug_dqs("\t\tTrainWritePos", 0, 2); - return TrainDQSPos(ctrl, channel, DQS_WRITEDIR, pattern, buf_a, dqs_delay_a, sysinfo); -} - - - -static unsigned TrainDQSRdWrPos(const struct mem_controller *ctrl, struct sys_info *sysinfo) -{ - static const uint32_t TestPatternJD1a[] = { - 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF, // QW0-1, ALL-EVEN - 0x00000000,0x00000000,0x00000000,0x00000000, // QW2-3, ALL-EVEN - 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF, // QW4-5, ALL-EVEN - 0x00000000,0x00000000,0x00000000,0x00000000, // QW6-7, ALL-EVEN - 0xFeFeFeFe,0xFeFeFeFe,0x01010101,0x01010101, // QW0-1, DQ0-ODD - 0xFeFeFeFe,0xFeFeFeFe,0x01010101,0x01010101, // QW2-3, DQ0-ODD - 0x01010101,0x01010101,0xFeFeFeFe,0xFeFeFeFe, // QW4-5, DQ0-ODD - 0xFeFeFeFe,0xFeFeFeFe,0x01010101,0x01010101, // QW6-7, DQ0-ODD - 0x02020202,0x02020202,0x02020202,0x02020202, // QW0-1, DQ1-ODD - 0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd, // QW2-3, DQ1-ODD - 0xFdFdFdFd,0xFdFdFdFd,0x02020202,0x02020202, // QW4-5, DQ1-ODD - 0x02020202,0x02020202,0x02020202,0x02020202, // QW6-7, DQ1-ODD - 0x04040404,0x04040404,0xfBfBfBfB,0xfBfBfBfB, // QW0-1, DQ2-ODD - 0x04040404,0x04040404,0x04040404,0x04040404, // QW2-3, DQ2-ODD - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, // QW4-5, DQ2-ODD - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, // QW6-7, DQ2-ODD - 0x08080808,0x08080808,0xF7F7F7F7,0xF7F7F7F7, // QW0-1, DQ3-ODD - 0x08080808,0x08080808,0x08080808,0x08080808, // QW2-3, DQ3-ODD - 0xF7F7F7F7,0xF7F7F7F7,0x08080808,0x08080808, // QW4-5, DQ3-ODD - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, // QW6-7, DQ3-ODD - 0x10101010,0x10101010,0x10101010,0x10101010, // QW0-1, DQ4-ODD - 0xeFeFeFeF,0xeFeFeFeF,0x10101010,0x10101010, // QW2-3, DQ4-ODD - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, // QW4-5, DQ4-ODD - 0xeFeFeFeF,0xeFeFeFeF,0x10101010,0x10101010, // QW6-7, DQ4-ODD - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, // QW0-1, DQ5-ODD - 0xdFdFdFdF,0xdFdFdFdF,0x20202020,0x20202020, // QW2-3, DQ5-ODD - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, // QW4-5, DQ5-ODD - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, // QW6-7, DQ5-ODD - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, // QW0-1, DQ6-ODD - 0x40404040,0x40404040,0xBfBfBfBf,0xBfBfBfBf, // QW2-3, DQ6-ODD - 0x40404040,0x40404040,0xBfBfBfBf,0xBfBfBfBf, // QW4-5, DQ6-ODD - 0x40404040,0x40404040,0xBfBfBfBf,0xBfBfBfBf, // QW6-7, DQ6-ODD - 0x80808080,0x80808080,0x7F7F7F7F,0x7F7F7F7F, // QW0-1, DQ7-ODD - 0x80808080,0x80808080,0x7F7F7F7F,0x7F7F7F7F, // QW2-3, DQ7-ODD - 0x80808080,0x80808080,0x7F7F7F7F,0x7F7F7F7F, // QW4-5, DQ7-ODD - 0x80808080,0x80808080,0x80808080,0x80808080 // QW6-7, DQ7-ODD - }; - static const uint32_t TestPatternJD1b[] = { - 0x00000000,0x00000000,0x00000000,0x00000000, // QW0,CHA-B, ALL-EVEN - 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, // QW1,CHA-B, ALL-EVEN - 0x00000000,0x00000000,0x00000000,0x00000000, // QW2,CHA-B, ALL-EVEN - 0x00000000,0x00000000,0x00000000,0x00000000, // QW3,CHA-B, ALL-EVEN - 0x00000000,0x00000000,0x00000000,0x00000000, // QW4,CHA-B, ALL-EVEN - 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, // QW5,CHA-B, ALL-EVEN - 0x00000000,0x00000000,0x00000000,0x00000000, // QW6,CHA-B, ALL-EVEN - 0x00000000,0x00000000,0x00000000,0x00000000, // QW7,CHA-B, ALL-EVEN - 0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe, // QW0,CHA-B, DQ0-ODD - 0x01010101,0x01010101,0x01010101,0x01010101, // QW1,CHA-B, DQ0-ODD - 0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe, // QW2,CHA-B, DQ0-ODD - 0x01010101,0x01010101,0x01010101,0x01010101, // QW3,CHA-B, DQ0-ODD - 0x01010101,0x01010101,0x01010101,0x01010101, // QW4,CHA-B, DQ0-ODD - 0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe, // QW5,CHA-B, DQ0-ODD - 0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe, // QW6,CHA-B, DQ0-ODD - 0x01010101,0x01010101,0x01010101,0x01010101, // QW7,CHA-B, DQ0-ODD - 0x02020202,0x02020202,0x02020202,0x02020202, // QW0,CHA-B, DQ1-ODD - 0x02020202,0x02020202,0x02020202,0x02020202, // QW1,CHA-B, DQ1-ODD - 0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd, // QW2,CHA-B, DQ1-ODD - 0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd, // QW3,CHA-B, DQ1-ODD - 0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd, // QW4,CHA-B, DQ1-ODD - 0x02020202,0x02020202,0x02020202,0x02020202, // QW5,CHA-B, DQ1-ODD - 0x02020202,0x02020202,0x02020202,0x02020202, // QW6,CHA-B, DQ1-ODD - 0x02020202,0x02020202,0x02020202,0x02020202, // QW7,CHA-B, DQ1-ODD - 0x04040404,0x04040404,0x04040404,0x04040404, // QW0,CHA-B, DQ2-ODD - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, // QW1,CHA-B, DQ2-ODD - 0x04040404,0x04040404,0x04040404,0x04040404, // QW2,CHA-B, DQ2-ODD - 0x04040404,0x04040404,0x04040404,0x04040404, // QW3,CHA-B, DQ2-ODD - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, // QW4,CHA-B, DQ2-ODD - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, // QW5,CHA-B, DQ2-ODD - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, // QW6,CHA-B, DQ2-ODD - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, // QW7,CHA-B, DQ2-ODD - 0x08080808,0x08080808,0x08080808,0x08080808, // QW0,CHA-B, DQ3-ODD - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, // QW1,CHA-B, DQ3-ODD - 0x08080808,0x08080808,0x08080808,0x08080808, // QW2,CHA-B, DQ3-ODD - 0x08080808,0x08080808,0x08080808,0x08080808, // QW3,CHA-B, DQ3-ODD - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, // QW4,CHA-B, DQ3-ODD - 0x08080808,0x08080808,0x08080808,0x08080808, // QW5,CHA-B, DQ3-ODD - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, // QW6,CHA-B, DQ3-ODD - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, // QW7,CHA-B, DQ3-ODD - 0x10101010,0x10101010,0x10101010,0x10101010, // QW0,CHA-B, DQ4-ODD - 0x10101010,0x10101010,0x10101010,0x10101010, // QW1,CHA-B, DQ4-ODD - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, // QW2,CHA-B, DQ4-ODD - 0x10101010,0x10101010,0x10101010,0x10101010, // QW3,CHA-B, DQ4-ODD - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, // QW4,CHA-B, DQ4-ODD - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, // QW5,CHA-B, DQ4-ODD - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, // QW6,CHA-B, DQ4-ODD - 0x10101010,0x10101010,0x10101010,0x10101010, // QW7,CHA-B, DQ4-ODD - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, // QW0,CHA-B, DQ5-ODD - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, // QW1,CHA-B, DQ5-ODD - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, // QW2,CHA-B, DQ5-ODD - 0x20202020,0x20202020,0x20202020,0x20202020, // QW3,CHA-B, DQ5-ODD - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, // QW4,CHA-B, DQ5-ODD - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, // QW5,CHA-B, DQ5-ODD - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, // QW6,CHA-B, DQ5-ODD - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, // QW7,CHA-B, DQ5-ODD - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, // QW0,CHA-B, DQ6-ODD - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, // QW1,CHA-B, DQ6-ODD - 0x40404040,0x40404040,0x40404040,0x40404040, // QW2,CHA-B, DQ6-ODD - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, // QW3,CHA-B, DQ6-ODD - 0x40404040,0x40404040,0x40404040,0x40404040, // QW4,CHA-B, DQ6-ODD - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, // QW5,CHA-B, DQ6-ODD - 0x40404040,0x40404040,0x40404040,0x40404040, // QW6,CHA-B, DQ6-ODD - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, // QW7,CHA-B, DQ6-ODD - 0x80808080,0x80808080,0x80808080,0x80808080, // QW0,CHA-B, DQ7-ODD - 0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F, // QW1,CHA-B, DQ7-ODD - 0x80808080,0x80808080,0x80808080,0x80808080, // QW2,CHA-B, DQ7-ODD - 0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F, // QW3,CHA-B, DQ7-ODD - 0x80808080,0x80808080,0x80808080,0x80808080, // QW4,CHA-B, DQ7-ODD - 0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F, // QW5,CHA-B, DQ7-ODD - 0x80808080,0x80808080,0x80808080,0x80808080, // QW6,CHA-B, DQ7-ODD - 0x80808080,0x80808080,0x80808080,0x80808080 // QW7,CHA-B, DQ7-ODD - }; - uint8_t pattern_buf_x[64 * 18 + 16]; // We need to two cache line So have more 16 bytes to keep 16 byte alignment */ - uint8_t *buf_a; - - unsigned pattern; - uint32_t dword; - uint32_t ecc_bit; - unsigned Errors; - unsigned channel; - int i; - unsigned DQSWrDelay; - unsigned is_Width128 = sysinfo->meminfo[ctrl->node_id].is_Width128; - uint8_t *dqs_delay_a = &sysinfo->dqs_delay_a[ctrl->node_id * 2*2*9]; //channel 2, direction 2 , bytelane *9 - - //enable SSE2 - enable_sse2(); - - //wrap32dis - set_wrap32dis(); - - //disable ECC temp - dword = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW); - ecc_bit = dword & DCL_DimmEccEn; - dword &= ~(DCL_DimmEccEn); - pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dword); - - //SetupDqsPattern - buf_a = (uint8_t *)(((uint32_t)(&pattern_buf_x[0]) + 0x10) & (~0xf)); - - if (is_Width128) { - pattern = 1; - for (i = 0; i < 16*18; i++) { - *((uint32_t *)(buf_a + i*4)) = TestPatternJD1b[i]; - } - } - else { - pattern = 0; - for (i = 0; i < 16*9; i++) { - *((uint32_t *)(buf_a + i*4)) = TestPatternJD1a[i]; - } - - } - - print_debug_dqs("\nTrainDQSRdWrPos: 0 ctrl ", ctrl->node_id, 0); - - printk(BIOS_DEBUG, "TrainDQSRdWrPos: buf_a:%p\n", buf_a); - - Errors = 0; - channel = 0; - - if (!(sysinfo->meminfo[ctrl->node_id].dimm_mask & 0x0F) && - (sysinfo->meminfo[ctrl->node_id].dimm_mask & 0xF0)) { /* channelB only? */ - channel = 1; - } - - while ((channel < 2) && (!Errors)) { - print_debug_dqs("\tTrainDQSRdWrPos: 1 channel ",channel, 1); - for (DQSWrDelay = 0; DQSWrDelay < 48; DQSWrDelay++) { - unsigned err; - SetDQSDelayAllCSR(ctrl, channel, DQS_WRITEDIR, DQSWrDelay); - print_debug_dqs("\t\tTrainDQSRdWrPos: 21 DQSWrDelay ", DQSWrDelay, 2); - err= TrainReadDQS(ctrl, channel, pattern, buf_a, dqs_delay_a, sysinfo); - print_debug_dqs("\t\tTrainDQSRdWrPos: 22 err ",err, 2); - if (err == 0) break; - Errors |= err; - } - - print_debug_dqs("\tTrainDQSRdWrPos: 3 DQSWrDelay ", DQSWrDelay, 1); - - if (DQSWrDelay < 48) { - Errors = TrainWriteDQS(ctrl, channel, pattern, buf_a, dqs_delay_a, sysinfo); - print_debug_dqs("\tTrainDQSRdWrPos: 4 Errors ", Errors, 1); - - } - channel++; - if (!is_Width128) { - //FIXME: 64MuxMode?? - channel++; // skip channel if 64-bit mode - } - } - - //Enable ECC again - dword = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW); - dword &= ~(DCL_DimmEccEn); - dword |= ecc_bit; - pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dword); - - //Clear wrap32dis - - clear_wrap32dis(); - - //restore SSE2 setting - disable_sse2(); - - print_debug_dqs("TrainDQSRdWrPos: ", 5, 0); - - return Errors; - -} -static inline uint8_t get_dqs_delay(unsigned channel, unsigned bytelane, unsigned direction, uint8_t *dqs_delay_a) -{ - return dqs_delay_a[channel * 2*9 + direction * 9 + bytelane]; -} - -static unsigned CalcEccDQSPos(unsigned channel,unsigned ByteLane0, unsigned ByteLane1, unsigned InterFactor, unsigned Direction, uint8_t *dqs_delay_a) -/* InterFactor: 0: 100% ByteLane 0 - 0x80: 50% between ByteLane 0 and 1 - 0xff: 99.6% ByteLane 1 and 0.4% like 0 -*/ -{ - unsigned DQSDelay0, DQSDelay1; - unsigned DQSDelay; - - DQSDelay0 = get_dqs_delay(channel, ByteLane0, Direction, dqs_delay_a); - DQSDelay1 = get_dqs_delay(channel, ByteLane1, Direction, dqs_delay_a); - - if (DQSDelay0 > DQSDelay1) { - DQSDelay = DQSDelay0 - DQSDelay1; - InterFactor = 0xff - InterFactor; - } - else { - DQSDelay = DQSDelay1 - DQSDelay0; - } - - DQSDelay *= InterFactor; - - DQSDelay >>= 8; // /255 - - if (DQSDelay0 > DQSDelay1) { - DQSDelay += DQSDelay1; - } - else { - DQSDelay += DQSDelay0; - } - - return DQSDelay; - -} - -static void SetEccDQSRdWrPos(const struct mem_controller *ctrl, struct sys_info *sysinfo) -{ - unsigned channel; - unsigned ByteLane; - unsigned Direction; - unsigned lane0, lane1, ratio; - unsigned dqs_delay; - - unsigned direction[] = { DQS_READDIR, DQS_WRITEDIR }; - int i; - uint8_t *dqs_delay_a = &sysinfo->dqs_delay_a[ctrl->node_id * 2*2*9]; //channel 2, direction 2 , bytelane *9 - - ByteLane = 8; - - for (channel = 0; channel < 2; channel++) { - for (i = 0; i < 2; i++) { - Direction = direction[i]; - lane0 = 4; lane1 = 5; ratio = 0; - dqs_delay = CalcEccDQSPos(channel, lane0, lane1, ratio, Direction, dqs_delay_a); - print_debug_dqs_pair("\t\tSetEccDQSRdWrPos: channel ", channel, Direction == DQS_READDIR? " R dqs_delay":" W dqs_delay", dqs_delay, 2); - SetDQSDelayCSR(ctrl, channel, ByteLane, Direction, dqs_delay); - save_dqs_delay(channel, ByteLane, Direction, dqs_delay_a, dqs_delay); - } - } -} - -static unsigned train_DqsRcvrEn(const struct mem_controller *ctrl, unsigned Pass, struct sys_info *sysinfo) -{ - print_debug_dqs("\ntrain_DqsRcvrEn: begin ctrl ", ctrl->node_id, 0); - if (TrainRcvrEn(ctrl, Pass, sysinfo)) { - return 1; - } - print_debug_dqs("\ntrain_DqsRcvrEn: end ctrl ", ctrl->node_id, 0); - return 0; - -} -static unsigned train_DqsPos(const struct mem_controller *ctrl, struct sys_info *sysinfo) -{ - print_debug_dqs("\ntrain_DqsPos: begin ctrl ", ctrl->node_id, 0); - if (TrainDQSRdWrPos(ctrl, sysinfo) != 0) { - printk(BIOS_ERR, "\nDQS Training Rd Wr failed ctrl%02x\n", ctrl->node_id); - return 1; - } - else { - SetEccDQSRdWrPos(ctrl, sysinfo); - } - print_debug_dqs("\ntrain_DqsPos: end ctrl ", ctrl->node_id, 0); - return 0; - -} - -#if K8_REV_F_SUPPORT_F0_F1_WORKAROUND == 1 -static void f0_svm_workaround(int controllers, const struct mem_controller *ctrl, tsc_t *tsc0, struct sys_info *sysinfo) -{ - tsc_t tsc1[8]; - unsigned cpu_f0_f1[8]; - int i; - - print_debug_addr("dqs_timing: tsc1[8] :", tsc1); - - for (i = 0; i < controllers; i++) { - if (!sysinfo->ctrl_present[i]) - continue; - - /* Skip everything if I don't have any memory on this controller */ - if (sysinfo->meminfo[i].dimm_mask == 0x00) continue; - - uint32_t dword; - - cpu_f0_f1[i] = is_cpu_pre_f2_in_bsp(i); - - if (!cpu_f0_f1[i]) continue; - - dword = pci_read_config32(ctrl[i].f2, DRAM_CTRL); - dword &= ~DC_DqsRcvEnTrain; - pci_write_config32(ctrl[i].f2, DRAM_CTRL, dword); - - dword = pci_read_config32(ctrl[i].f2, DRAM_INIT); - dword |= DI_EnDramInit; - pci_write_config32(ctrl[i].f2, DRAM_INIT, dword); - dword &= ~DI_EnDramInit; - pci_write_config32(ctrl[i].f2, DRAM_INIT, dword); - - tsc1[i] = rdtsc(); - print_debug_dqs_tsc("begin: tsc1", i, tsc1[i].hi, tsc1[i].lo, 2); - - dword = tsc1[i].lo + tsc0[i].lo; - if ((dword < tsc1[i].lo) || (dword < tsc0[i].lo)) { - tsc1[i].hi++; - } - tsc1[i].lo = dword; - tsc1[i].hi+= tsc0[i].hi; - - print_debug_dqs_tsc("end : tsc1", i, tsc1[i].hi, tsc1[i].lo, 2); - - } - - for (i = 0; i < controllers; i++) { - if (!sysinfo->ctrl_present[i]) - continue; - - /* Skip everything if I don't have any memory on this controller */ - if (sysinfo->meminfo[i].dimm_mask == 0x00) continue; - - if (!cpu_f0_f1[i]) continue; - - tsc_t tsc; - - do { - tsc = rdtsc(); - } while ((tsc1[i].hi > tsc.hi) || ((tsc1[i].hi == tsc.hi) && (tsc1[i].lo > tsc.lo))); - - print_debug_dqs_tsc("end : tsc ", i, tsc.hi, tsc.lo, 2); - } - -} - -#endif - - -/* setting variable mtrr, comes from linux kernel source */ -static void set_var_mtrr_dqs( - unsigned int reg, unsigned long basek, unsigned long sizek, - unsigned char type, unsigned address_bits) -{ - msr_t base, mask; - unsigned address_mask_high; - - address_mask_high = ((1u << (address_bits - 32u)) - 1u); - - base.hi = basek >> 22; - base.lo = basek << 10; - - if (sizek < 4*1024*1024) { - mask.hi = address_mask_high; - mask.lo = ~((sizek << 10) -1); - } - else { - mask.hi = address_mask_high & (~((sizek >> 22) -1)); - mask.lo = 0; - } - - if (reg >= 8) - return; - - if (sizek == 0) { - msr_t zero; - zero.lo = zero.hi = 0; - /* The invalid bit is kept in the mask, so we simply clear the - relevant mask register to disable a range. */ - wrmsr (MTRR_PHYS_MASK(reg), zero); - } else { - /* Bit 32-35 of MTRRphysMask should be set to 1 */ - base.lo |= type; - mask.lo |= 0x800; - wrmsr (MTRR_PHYS_BASE(reg), base); - wrmsr (MTRR_PHYS_MASK(reg), mask); - } -} - -static unsigned int range_to_mtrr(unsigned int reg, - unsigned long range_startk, unsigned long range_sizek, - unsigned long next_range_startk, unsigned char type, unsigned address_bits) -{ - if (!range_sizek || (reg >= 8)) { - return reg; - } - while (range_sizek) { - unsigned long max_align, align; - unsigned long sizek; - /* Compute the maximum size I can make a range */ - max_align = fls(range_startk); - align = fms(range_sizek); - if (align > max_align) { - align = max_align; - } - sizek = 1 << align; -#if CONFIG_MEM_TRAIN_SEQ != 1 - printk(BIOS_DEBUG, "Setting variable MTRR %d, base: %4ldMB, range: %4ldMB, type %s\n", - reg, range_startk >>10, sizek >> 10, - (type == MTRR_TYPE_UNCACHEABLE)?"UC": - ((type == MTRR_TYPE_WRBACK)?"WB":"Other") - ); -#endif - set_var_mtrr_dqs(reg++, range_startk, sizek, type, address_bits); - range_startk += sizek; - range_sizek -= sizek; - if (reg >= 8) - break; - } - return reg; -} - -#if CONFIG_MEM_TRAIN_SEQ == 1 -static void set_top_mem_ap(unsigned tom_k, unsigned tom2_k) -{ - msr_t msr; - - /* Now set top of memory */ - msr.lo = (tom2_k & 0x003fffff) << 10; - msr.hi = (tom2_k & 0xffc00000) >> 22; - wrmsr(TOP_MEM2, msr); - - msr.lo = (tom_k & 0x003fffff) << 10; - msr.hi = (tom_k & 0xffc00000) >> 22; - wrmsr(TOP_MEM, msr); -} -#endif - -static void setup_mtrr_dqs(unsigned tom_k, unsigned tom2_k) -{ - msr_t msr; - - //[0,512k), [512k, 640k) - msr.hi = 0x1e1e1e1e; - msr.lo = msr.hi; - wrmsr(0x250, msr); - wrmsr(0x258, msr); - - //[1M, TOM) - range_to_mtrr(2, 0, tom_k,4*1024*1024, MTRR_TYPE_WRBACK, 40); - - //[4G, TOM2) - if (tom2_k) { - //enable tom2 and type - msr = rdmsr(SYSCFG_MSR); - msr.lo |= (1<<21) | (1<<22); //MtrrTom2En and Tom2ForceMemTypeWB - wrmsr(SYSCFG_MSR, msr); - } - -} - -static void clear_mtrr_dqs(unsigned tom2_k) -{ - msr_t msr; - unsigned i; - - //still enable from cache_as_ram.inc - msr = rdmsr(SYSCFG_MSR); - msr.lo |= SYSCFG_MSR_MtrrFixDramModEn; - wrmsr(SYSCFG_MSR,msr); - - //[0,512k), [512k, 640k) - msr.hi = 0; - msr.lo = msr.hi; - wrmsr(0x250, msr); - wrmsr(0x258, msr); - - //[1M, TOM) - for (i = 0x204; i < 0x210; i++) { - wrmsr(i, msr); - } - - //[4G, TOM2) - if (tom2_k) { - //enable tom2 and type - msr = rdmsr(SYSCFG_MSR); - msr.lo &= ~((1<<21) | (1<<22)); //MtrrTom2En and Tom2ForceMemTypeWB - wrmsr(SYSCFG_MSR, msr); - } -} - -#if CONFIG_MEM_TRAIN_SEQ == 1 -static void set_htic_bit(unsigned i, unsigned val, unsigned bit) -{ - uint32_t dword; - dword = pci_read_config32(PCI_DEV(0, 0x18+i, 0), HT_INIT_CONTROL); - dword &= ~(1 << bit); - dword |= ((val & 1) << bit); - pci_write_config32(PCI_DEV(0, 0x18+i, 0), HT_INIT_CONTROL, dword); -} - -static unsigned get_htic_bit(unsigned i, unsigned bit) -{ - uint32_t dword; - dword = pci_read_config32(PCI_DEV(0, 0x18+i, 0), HT_INIT_CONTROL); - dword &= (1 << bit); - return dword; -} - -static void wait_till_sysinfo_in_ram(void) -{ - while (1) { - if (get_htic_bit(0, 9)) return; - } -} -#endif - -void set_sysinfo_in_ram(unsigned val) -{ -#if CONFIG_MEM_TRAIN_SEQ == 1 - set_htic_bit(0, val, 9); -#endif -} - -#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME) - -#if CONFIG_MEM_TRAIN_SEQ == 0 -static int save_index_to_pos(unsigned int dev, int size, int index, int nvram_pos) -{ - u32 dword = pci_read_config32_index_wait(dev, 0x98, index); - - return s3_save_nvram_early(dword, size, nvram_pos); -} -#endif - -static int load_index_to_pos(unsigned int dev, int size, int index, int nvram_pos) -{ - - u32 old_dword = pci_read_config32_index_wait(dev, 0x98, index); - nvram_pos = s3_load_nvram_early(size, &old_dword, nvram_pos); - pci_write_config32_index_wait(dev, 0x98, index, old_dword); - return nvram_pos; -} - -static int dqs_load_MC_NVRAM_ch(unsigned int dev, int ch, int pos) -{ - /* 30 bytes per channel */ - ch *= 0x20; - pos = load_index_to_pos(dev, 4, 0x00 + ch, pos); - pos = load_index_to_pos(dev, 4, 0x01 + ch, pos); - pos = load_index_to_pos(dev, 4, 0x02 + ch, pos); - pos = load_index_to_pos(dev, 1, 0x03 + ch, pos); - pos = load_index_to_pos(dev, 4, 0x04 + ch, pos); - pos = load_index_to_pos(dev, 4, 0x05 + ch, pos); - pos = load_index_to_pos(dev, 4, 0x06 + ch, pos); - pos = load_index_to_pos(dev, 1, 0x07 + ch, pos); - pos = load_index_to_pos(dev, 1, 0x10 + ch, pos); - pos = load_index_to_pos(dev, 1, 0x13 + ch, pos); - pos = load_index_to_pos(dev, 1, 0x16 + ch, pos); - pos = load_index_to_pos(dev, 1, 0x19 + ch, pos); - return pos; -} - -#if CONFIG_MEM_TRAIN_SEQ == 0 -static int dqs_save_MC_NVRAM_ch(unsigned int dev, int ch, int pos) -{ - /* 30 bytes per channel */ - ch *= 0x20; - pos = save_index_to_pos(dev, 4, 0x00 + ch, pos); - pos = save_index_to_pos(dev, 4, 0x01 + ch, pos); - pos = save_index_to_pos(dev, 4, 0x02 + ch, pos); - pos = save_index_to_pos(dev, 1, 0x03 + ch, pos); - pos = save_index_to_pos(dev, 4, 0x04 + ch, pos); - pos = save_index_to_pos(dev, 4, 0x05 + ch, pos); - pos = save_index_to_pos(dev, 4, 0x06 + ch, pos); - pos = save_index_to_pos(dev, 1, 0x07 + ch, pos); - pos = save_index_to_pos(dev, 1, 0x10 + ch, pos); - pos = save_index_to_pos(dev, 1, 0x13 + ch, pos); - pos = save_index_to_pos(dev, 1, 0x16 + ch, pos); - pos = save_index_to_pos(dev, 1, 0x19 + ch, pos); - return pos; -} - -static void dqs_save_MC_NVRAM(unsigned int dev) -{ - int pos = 0; - u32 reg; - printk(BIOS_DEBUG, "DQS SAVE NVRAM: %x\n", dev); - pos = dqs_save_MC_NVRAM_ch(dev, 0, pos); - pos = dqs_save_MC_NVRAM_ch(dev, 1, pos); - /* save the maxasync lat here */ - reg = pci_read_config32(dev, DRAM_CONFIG_HIGH); - pos = s3_save_nvram_early(reg, 4, pos); -} -#endif - -void dqs_restore_MC_NVRAM(unsigned int dev) -{ - int pos = 0; - u32 reg; - - printk(BIOS_DEBUG, "DQS RESTORE FROM NVRAM: %x\n", dev); - pos = dqs_load_MC_NVRAM_ch(dev, 0, pos); - pos = dqs_load_MC_NVRAM_ch(dev, 1, pos); - /* load the maxasync lat here */ - pos = s3_load_nvram_early(4, ®, pos); - reg &= (DCH_MaxAsyncLat_MASK << DCH_MaxAsyncLat_SHIFT); - reg |= pci_read_config32(dev, DRAM_CONFIG_HIGH); - pci_write_config32(dev, DRAM_CONFIG_HIGH, reg); -} -#endif - -#if CONFIG_MEM_TRAIN_SEQ == 0 -#if K8_REV_F_SUPPORT_F0_F1_WORKAROUND == 1 -static void dqs_timing(int controllers, const struct mem_controller *ctrl, tsc_t *tsc0, struct sys_info *sysinfo) -#else -static void dqs_timing(int controllers, const struct mem_controller *ctrl, struct sys_info *sysinfo) -#endif -{ - int i; - - tsc_t tsc[5]; - - //need to enable mtrr, so dqs training could access the test address - setup_mtrr_dqs(sysinfo->tom_k, sysinfo->tom2_k); - - for (i = 0; i < controllers; i++) { - if (!sysinfo->ctrl_present[ i ]) - continue; - - /* Skip everything if I don't have any memory on this controller */ - if (sysinfo->meminfo[i].dimm_mask == 0x00) continue; - - fill_mem_cs_sysinfo(i, ctrl+i, sysinfo); - } - - tsc[0] = rdtsc(); - for (i = 0; i < controllers; i++) { - if (!sysinfo->ctrl_present[ i ]) - continue; - - /* Skip everything if I don't have any memory on this controller */ - if (sysinfo->meminfo[i].dimm_mask == 0x00) continue; - - printk(BIOS_DEBUG, "DQS Training:RcvrEn:Pass1: %02x\n", i); - if (train_DqsRcvrEn(ctrl+i, 1, sysinfo)) goto out; - printk(BIOS_DEBUG, " done\n"); - } - - tsc[1] = rdtsc(); -#if K8_REV_F_SUPPORT_F0_F1_WORKAROUND == 1 - f0_svm_workaround(controllers, ctrl, tsc0, sysinfo); -#endif - - tsc[2] = rdtsc(); - for (i = 0; i < controllers; i++) { - if (!sysinfo->ctrl_present[i]) - continue; - - /* Skip everything if I don't have any memory on this controller */ - if (sysinfo->meminfo[i].dimm_mask == 0x00) continue; - - printk(BIOS_DEBUG, "DQS Training:DQSPos: %02x\n", i); - if (train_DqsPos(ctrl+i, sysinfo)) goto out; - printk(BIOS_DEBUG, " done\n"); - } - - tsc[3] = rdtsc(); - for (i = 0; i < controllers; i++) { - if (!sysinfo->ctrl_present[i]) - continue; - - /* Skip everything if I don't have any memory on this controller */ - if (sysinfo->meminfo[i].dimm_mask == 0x00) continue; - - printk(BIOS_DEBUG, "DQS Training:RcvrEn:Pass2: %02x\n", i); - if (train_DqsRcvrEn(ctrl+i, 2, sysinfo)) goto out; - printk(BIOS_DEBUG, " done\n"); - sysinfo->mem_trained[i]=1; -#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME) - dqs_save_MC_NVRAM((ctrl+i)->f2); -#endif - } - -out: - tsc[4] = rdtsc(); - clear_mtrr_dqs(sysinfo->tom2_k); - - - for (i = 0; i < 5; i++) { - print_debug_dqs_tsc_x("DQS Training:tsc", i, tsc[i].hi, tsc[i].lo); - } - - - -} - -#endif - - -#if CONFIG_MEM_TRAIN_SEQ > 0 - -static void dqs_timing(int i, const struct mem_controller *ctrl, struct sys_info *sysinfo, unsigned v) -{ - - int ii; - - tsc_t tsc[4]; - - if (sysinfo->mem_trained[i] != 0x80) return; - -#if CONFIG_MEM_TRAIN_SEQ == 1 - //need to enable mtrr, so dqs training could access the test address - setup_mtrr_dqs(sysinfo->tom_k, sysinfo->tom2_k); -#endif - - fill_mem_cs_sysinfo(i, ctrl, sysinfo); - - if (v) { - tsc[0] = rdtsc(); - - printk(BIOS_DEBUG, "set DQS timing:RcvrEn:Pass1: %02x\n", i); - } - if (train_DqsRcvrEn(ctrl, 1, sysinfo)) { - sysinfo->mem_trained[i]=0x81; // - goto out; - } - - if (v) { - printk(BIOS_DEBUG, " done\n"); - tsc[1] = rdtsc(); - printk(BIOS_DEBUG, "set DQS timing:DQSPos: %02x\n", i); - } - - if (train_DqsPos(ctrl, sysinfo)) { - sysinfo->mem_trained[i]=0x82; // - goto out; - } - - if (v) { - printk(BIOS_DEBUG, " done\n"); - tsc[2] = rdtsc(); - - printk(BIOS_DEBUG, "set DQS timing:RcvrEn:Pass2: %02x\n", i); - } - if (train_DqsRcvrEn(ctrl, 2, sysinfo)) { - sysinfo->mem_trained[i]=0x83; // - goto out; - } - - if (v) { - printk(BIOS_DEBUG, " done\n"); - - tsc[3] = rdtsc(); - } - -out: -#if CONFIG_MEM_TRAIN_SEQ == 1 - clear_mtrr_dqs(sysinfo->tom2_k); -#endif - - if (v) { - for (ii = 0; ii < 4; ii++) { - print_debug_dqs_tsc_x("Total DQS Training : tsc ", ii, tsc[ii].hi, tsc[ii].lo); - } - } - - if (sysinfo->mem_trained[i] == 0x80) { - sysinfo->mem_trained[i]=1; - } - -} -#endif - -#if CONFIG_MEM_TRAIN_SEQ == 1 -static void train_ram(unsigned nodeid, struct sys_info *sysinfo, struct sys_info *sysinfox) -{ - dqs_timing(nodeid, &sysinfo->ctrl[nodeid], sysinfo, 0); // keep the output tidy - sysinfox->mem_trained[nodeid] = sysinfo->mem_trained[nodeid]; - -} - -void train_ram_on_node(unsigned nodeid, unsigned coreid, struct sys_info *sysinfo, unsigned retcall) -{ - if (coreid) return; // only do it on core0 - struct sys_info *sysinfox; - uintptr_t migrated_base = CONFIG_RAMTOP - car_data_size(); - - sysinfox = (void *)(migrated_base + car_object_offset(&sysinfo_car)); - - wait_till_sysinfo_in_ram(); // use pci to get it - - if (sysinfox->mem_trained[nodeid] == 0x80) { - memcpy(sysinfo, sysinfox, sizeof(*sysinfo)); - set_top_mem_ap(sysinfo->tom_k, sysinfo->tom2_k); // keep the ap's tom consistent with bsp's - printk(BIOS_DEBUG, "CODE IN ROM AND RUN ON NODE: %02x\n", nodeid); - train_ram(nodeid, sysinfo, sysinfox); - } -} -#endif |