* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <arch/stages.h>
+
//0: mean no debug info
#define DQS_TRAIN_DEBUG 0
{
#if DQS_TRAIN_DEBUG > 0
if(DQS_TRAIN_DEBUG > level) {
- #if CONFIG_USE_PRINTK_IN_CAR
- printk_debug("%s%x\r\n", str, val);
- #else
- print_debug(str); print_debug_hex32(val); print_debug("\r\n");
- #endif
+ printk(BIOS_DEBUG, "%s%x\n", str, val);
}
#endif
}
{
#if DQS_TRAIN_DEBUG > 0
if(DQS_TRAIN_DEBUG > level) {
- #if CONFIG_USE_PRINTK_IN_CAR
- printk_debug("%s%08x%s%08x\r\n", str, val, str2, val2);
- #else
- print_debug(str); print_debug_hex32(val); print_debug(str2); print_debug_hex32(val2); print_debug("\r\n");
- #endif
+ printk(BIOS_DEBUG, "%s%08x%s%08x\n", str, val, str2, val2);
}
#endif
}
{
#if DQS_TRAIN_DEBUG > 0
if(DQS_TRAIN_DEBUG > level) {
- #if CONFIG_USE_PRINTK_IN_CAR
- printk_debug("%s[%02x]=%08x%08x\r\n", str, i, val, val2);
- #else
- print_debug(str); print_debug("["); print_debug_hex8(i); print_debug("]="); print_debug_hex32(val); print_debug_hex32(val2); print_debug("\r\n");
- #endif
+ 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)
{
- #if CONFIG_USE_PRINTK_IN_CAR
- printk_debug("%s[%02x]=%08x%08x\r\n", str, i, val, val2);
- #else
- print_debug(str); print_debug("["); print_debug_hex8(i); print_debug("]="); print_debug_hex32(val); print_debug_hex32(val2); print_debug("\r\n");
- #endif
+ printk(BIOS_DEBUG, "%s[%02x]=%08x%08x\n", str, i, val, val2);
}
uint32_t mem_base;
unsigned nodeid = ctrl->node_id;
-#if HW_MEM_HOLE_SIZEK != 0
+#if CONFIG_HW_MEM_HOLE_SIZEK != 0
uint32_t hole_reg;
#endif
mem_base &= 0xffff0000;
dword += mem_base;
-#if HW_MEM_HOLE_SIZEK != 0
+#if CONFIG_HW_MEM_HOLE_SIZEK != 0
hole_reg = sysinfo->hole_reg[nodeid];
if(hole_reg & 1) {
unsigned hole_startk;
}
-static inline void enable_sse2()
+static inline void enable_sse2(void)
{
unsigned long cr4;
cr4 = read_cr4();
write_cr4(cr4);
}
-static inline void disable_sse2()
+static inline void disable_sse2(void)
{
unsigned long cr4;
cr4 = read_cr4();
/*15*/ 5000, 4000, 3000, 2500,
};
- unsigned fid_cur;
int index;
-
msr_t msr;
- msr = rdmsr(0xc0010042);
- fid_cur = msr.lo & 0x3f;
- index = fid_cur>>1;
+ /* 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];
unsigned PatternA;
unsigned PatternB;
- unsigned TestAddr0, TestAddr0B, TestAddr1, TestAddr1B = 0;
+ unsigned TestAddr0, TestAddr0B, TestAddr1 = 0, TestAddr1B = 0;
unsigned CurrRcvrCHADelay = 0;
unsigned is_Width128 = sysinfo->meminfo[ctrl->node_id].is_Width128;
+#if K8_REV_F_SUPPORT_F0_F1_WORKAROUND == 1
unsigned cpu_f0_f1;
+#endif
if(Pass == DQS_FIRST_PASS) {
InitDQSPos4RcvrEn(ctrl);
}
}
- print_debug_dqs("\r\nTrainRcvEn: 0 ctrl", ctrl->node_id, 0);
+ print_debug_dqs("\nTrainRcvEn: 0 ctrl", ctrl->node_id, 0);
print_debug_addr("TrainRcvEn: buf_a:", buf_a);
//restore SSE2 setting
disable_sse2();
-#if MEM_TRAIN_SEQ != 1
+#if CONFIG_MEM_TRAIN_SEQ != 1
/* We need tidy output for type 1 */
- #if CONFIG_USE_PRINTK_IN_CAR
- printk_debug(" CTLRMaxDelay=%02x", CTLRMaxDelay);
- #else
- print_debug(" CTLRMaxDelay="); print_debug_hex8(CTLRMaxDelay);
- #endif
+ printk(BIOS_DEBUG, " CTLRMaxDelay=%02x\n", CTLRMaxDelay);
#endif
return (CTLRMaxDelay==0xae)?1:0;
print_debug_dqs("\t\t\tTrainDQSPos begin ", 0, 3);
- print_debug_addr("TrainDQSPos: MutualCSPassW[48] :", MutualCSPassW);
+ 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)
}
- print_debug_dqs("\r\nTrainDQSRdWrPos: 0 ctrl ", ctrl->node_id, 0);
+ print_debug_dqs("\nTrainDQSRdWrPos: 0 ctrl ", ctrl->node_id, 0);
- print_debug_addr("TrainDQSRdWrPos: buf_a:", buf_a);
+ printk(BIOS_DEBUG, "TrainDQSRdWrPos: buf_a:%p\n", buf_a);
Errors = 0;
channel = 0;
static unsigned train_DqsRcvrEn(const struct mem_controller *ctrl, unsigned Pass, struct sys_info *sysinfo)
{
- print_debug_dqs("\r\ntrain_DqsRcvrEn: begin ctrl ", ctrl->node_id, 0);
+ print_debug_dqs("\ntrain_DqsRcvrEn: begin ctrl ", ctrl->node_id, 0);
if(TrainRcvrEn(ctrl, Pass, sysinfo)) {
return 1;
}
- print_debug_dqs("\r\ntrain_DqsRcvrEn: end ctrl ", ctrl->node_id, 0);
+ 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("\r\ntrain_DqsPos: begin ctrl ", ctrl->node_id, 0);
+ print_debug_dqs("\ntrain_DqsPos: begin ctrl ", ctrl->node_id, 0);
if(TrainDQSRdWrPos(ctrl, sysinfo) != 0) {
- print_err("\r\nDQS Training Rd Wr failed ctrl"); print_err_hex8(ctrl->node_id); print_err("\r\n");
+ printk(BIOS_ERR, "\nDQS Training Rd Wr failed ctrl%02x\n", ctrl->node_id);
return 1;
}
else {
SetEccDQSRdWrPos(ctrl, sysinfo);
}
- print_debug_dqs("\r\ntrain_DqsPos: end ctrl ", ctrl->node_id, 0);
+ print_debug_dqs("\ntrain_DqsPos: end ctrl ", ctrl->node_id, 0);
return 0;
}
return r;
}
-/* fms: find least sigificant bit set */
+/* fls: find least sigificant bit set */
static inline unsigned int fls(unsigned int x)
{
int r;
align = max_align;
}
sizek = 1 << align;
-#if MEM_TRAIN_SEQ != 1
- #if CONFIG_USE_PRINTK_IN_CAR
- printk_debug("Setting variable MTRR %d, base: %4dMB, range: %4dMB, type %s\r\n",
+#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")
);
- #else
- print_debug("Setting variable MTRR "); print_debug_hex8(reg); print_debug(", base: "); print_debug_hex16(range_startk>>10);
- print_debug("MB, range: "); print_debug_hex16(sizek >> 10); print_debug("MB, type ");
- print_debug( (type==MTRR_TYPE_UNCACHEABLE)?"UC\r\n":
- ((type==MTRR_TYPE_WRBACK)?"WB\r\n":"Other\r\n")
- );
- #endif
#endif
set_var_mtrr_dqs(reg++, range_startk, sizek, type, address_bits);
range_startk += sizek;
wrmsr(TOP_MEM, msr);
}
-static void setup_mtrr_dqs(unsigned tom_k, unsigned tom2_k){
+static void setup_mtrr_dqs(unsigned tom_k, unsigned tom2_k)
+{
unsigned reg;
msr_t msr;
}
-static void clear_mtrr_dqs(unsigned tom2_k){
+static void clear_mtrr_dqs(unsigned tom2_k)
+{
msr_t msr;
unsigned i;
set_htic_bit(0, val, 9);
}
+#ifdef S3_NVRAM_EARLY
+int s3_save_nvram_early(u32 dword, int size, int nvram_pos);
+int s3_load_nvram_early(int size, u32 *old_dword, int nvram_pos);
+#else
+static int s3_save_nvram_early(u32 dword, int size, int nvram_pos)
+{
+ return nvram_pos;
+}
+
+static int s3_load_nvram_early(int size, u32 *old_dword, int nvram_pos)
+{
+ die("No memory NVRAM loader for DQS data! Unable to restore memory state\n");
+
+ return nvram_pos; /* Make GCC happy */
+}
+#endif
+
+#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);
-#if MEM_TRAIN_SEQ == 0
+ 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
+
+static 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);
+}
+
+#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
/* Skip everything if I don't have any memory on this controller */
if(sysinfo->meminfo[i].dimm_mask==0x00) continue;
- print_debug("DQS Training:RcvrEn:Pass1: ");
- print_debug_hex8(i);
+ printk(BIOS_DEBUG, "DQS Training:RcvrEn:Pass1: %02x\n", i);
if(train_DqsRcvrEn(ctrl+i, 1, sysinfo)) goto out;
- print_debug(" done\r\n");
+ printk(BIOS_DEBUG, " done\n");
}
tsc[1] = rdtsc();
/* Skip everything if I don't have any memory on this controller */
if(sysinfo->meminfo[i].dimm_mask==0x00) continue;
- print_debug("DQS Training:DQSPos: ");
- print_debug_hex8(i);
+ printk(BIOS_DEBUG, "DQS Training:DQSPos: %02x\n", i);
if(train_DqsPos(ctrl+i, sysinfo)) goto out;
- print_debug(" done\r\n");
+ printk(BIOS_DEBUG, " done\n");
}
tsc[3] = rdtsc();
/* Skip everything if I don't have any memory on this controller */
if(sysinfo->meminfo[i].dimm_mask==0x00) continue;
- print_debug("DQS Training:RcvrEn:Pass2: ");
- print_debug_hex8(i);
+ printk(BIOS_DEBUG, "DQS Training:RcvrEn:Pass2: %02x\n", i);
if(train_DqsRcvrEn(ctrl+i, 2, sysinfo)) goto out;
- print_debug(" done\r\n");
+ printk(BIOS_DEBUG, " done\n");
sysinfo->mem_trained[i]=1;
+ dqs_save_MC_NVRAM((ctrl+i)->f2);
}
out:
#endif
-#if MEM_TRAIN_SEQ > 0
+#if CONFIG_MEM_TRAIN_SEQ > 0
static void dqs_timing(int i, const struct mem_controller *ctrl, struct sys_info *sysinfo, unsigned v)
{
if(sysinfo->mem_trained[i] != 0x80) return;
-#if MEM_TRAIN_SEQ == 1
+#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
if(v) {
tsc[0] = rdtsc();
- print_debug("set DQS timing:RcvrEn:Pass1: ");
- print_debug_hex8(i);
+ printk(BIOS_DEBUG, "set DQS timing:RcvrEn:Pass1: %02x\n", i);
}
if(train_DqsRcvrEn(ctrl, 1, sysinfo)) {
sysinfo->mem_trained[i]=0x81; //
}
if(v) {
- print_debug(" done\r\n");
+ printk(BIOS_DEBUG, " done\n");
tsc[1] = rdtsc();
- print_debug("set DQS timing:DQSPos: ");
- print_debug_hex8(i);
+ printk(BIOS_DEBUG, "set DQS timing:DQSPos: %02x\n", i);
}
if(train_DqsPos(ctrl, sysinfo)) {
}
if(v) {
- print_debug(" done\r\n");
+ printk(BIOS_DEBUG, " done\n");
tsc[2] = rdtsc();
- print_debug("set DQS timing:RcvrEn:Pass2: ");
- print_debug_hex8(i);
+ printk(BIOS_DEBUG, "set DQS timing:RcvrEn:Pass2: %02x\n", i);
}
if(train_DqsRcvrEn(ctrl, 2, sysinfo)){
sysinfo->mem_trained[i]=0x83; //
}
if(v) {
- print_debug(" done\r\n");
+ printk(BIOS_DEBUG, " done\n");
tsc[3] = rdtsc();
}
out:
-#if MEM_TRAIN_SEQ == 1
+#if CONFIG_MEM_TRAIN_SEQ == 1
clear_mtrr_dqs(sysinfo->tom2_k);
#endif
}
#endif
-#if MEM_TRAIN_SEQ == 1
+#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];
}
-static void copy_and_run_ap_code_in_car(unsigned ret_addr);
+
static inline 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 = ((CONFIG_LB_MEM_TOPK<<10) - DCACHE_RAM_GLOBAL_VAR_SIZE);
+ struct sys_info *sysinfox = (void*)((CONFIG_RAMTOP) - CONFIG_DCACHE_RAM_GLOBAL_VAR_SIZE);
wait_till_sysinfo_in_ram(); // use pci to get it
if(sysinfox->mem_trained[nodeid] == 0x80) {
sysinfo->mem_trained[nodeid] = sysinfox->mem_trained[nodeid];
memcpy(&sysinfo->ctrl[nodeid], &sysinfox->ctrl[nodeid], sizeof(struct mem_controller));
#else
- memcpy(sysinfo, sysinfox, DCACHE_RAM_GLOBAL_VAR_SIZE);
+ memcpy(sysinfo, sysinfox, CONFIG_DCACHE_RAM_GLOBAL_VAR_SIZE);
#endif
set_top_mem_ap(sysinfo->tom_k, sysinfo->tom2_k); // keep the ap's tom consistent with bsp's
#if CONFIG_AP_CODE_IN_CAR == 0
- print_debug("CODE IN ROM AND RUN ON NODE:"); print_debug_hex8(nodeid); print_debug("\r\n");
+ printk(BIOS_DEBUG, "CODE IN ROM AND RUN ON NODE: %02x\n", nodeid);
train_ram(nodeid, sysinfo, sysinfox);
#else
/* Can copy dqs_timing to ap cache and run from cache?