📄 44x_spd_ddr2.c
字号:
u32 emr; u32 emr2; u32 emr3; int dimm_num; int total_dimm = 0; /****************************************************** ** Assumption: if more than one DIMM, all DIMMs are the same ** as already checked in check_memory_type ******************************************************/ if ((dimm_populated[0] == SDRAM_DDR1) || (dimm_populated[1] == SDRAM_DDR1)) { mtsdram(SDRAM_INITPLR0, 0x81B80000); mtsdram(SDRAM_INITPLR1, 0x81900400); mtsdram(SDRAM_INITPLR2, 0x81810000); mtsdram(SDRAM_INITPLR3, 0xff800162); mtsdram(SDRAM_INITPLR4, 0x81900400); mtsdram(SDRAM_INITPLR5, 0x86080000); mtsdram(SDRAM_INITPLR6, 0x86080000); mtsdram(SDRAM_INITPLR7, 0x81000062); } else if ((dimm_populated[0] == SDRAM_DDR2) || (dimm_populated[1] == SDRAM_DDR2)) { switch (selected_cas) { case DDR_CAS_3: cas = 3 << 4; break; case DDR_CAS_4: cas = 4 << 4; break; case DDR_CAS_5: cas = 5 << 4; break; default: printf("ERROR: ucode error on selected_cas value %d", selected_cas); spd_ddr_init_hang (); break; }#if 0 /* * ToDo - Still a problem with the write recovery: * On the Corsair CM2X512-5400C4 module, setting write recovery * in the INITPLR reg to the value calculated in program_mode() * results in not correctly working DDR2 memory (crash after * relocation). * * So for now, set the write recovery to 3. This seems to work * on the Corair module too. * * 2007-03-01, sr */ switch (write_recovery) { case 3: wr = WRITE_RECOV_3; break; case 4: wr = WRITE_RECOV_4; break; case 5: wr = WRITE_RECOV_5; break; case 6: wr = WRITE_RECOV_6; break; default: printf("ERROR: write recovery not support (%d)", write_recovery); spd_ddr_init_hang (); break; }#else wr = WRITE_RECOV_3; /* test-only, see description above */#endif for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) if (dimm_populated[dimm_num] != SDRAM_NONE) total_dimm++; if (total_dimm == 1) { odt = ODT_150_OHM; ods = ODS_FULL; } else if (total_dimm == 2) { odt = ODT_75_OHM; ods = ODS_REDUCED; } else { printf("ERROR: Unsupported number of DIMM's (%d)", total_dimm); spd_ddr_init_hang (); } mr = CMD_EMR | SELECT_MR | BURST_LEN_4 | wr | cas; emr = CMD_EMR | SELECT_EMR | odt | ods; emr2 = CMD_EMR | SELECT_EMR2; emr3 = CMD_EMR | SELECT_EMR3; /* NOP - Wait 106 MemClk cycles */ mtsdram(SDRAM_INITPLR0, SDRAM_INITPLR_ENABLE | CMD_NOP | SDRAM_INITPLR_IMWT_ENCODE(106)); udelay(1000); /* precharge 4 MemClk cycles */ mtsdram(SDRAM_INITPLR1, SDRAM_INITPLR_ENABLE | CMD_PRECHARGE | SDRAM_INITPLR_IMWT_ENCODE(4)); /* EMR2 - Wait tMRD (2 MemClk cycles) */ mtsdram(SDRAM_INITPLR2, SDRAM_INITPLR_ENABLE | emr2 | SDRAM_INITPLR_IMWT_ENCODE(2)); /* EMR3 - Wait tMRD (2 MemClk cycles) */ mtsdram(SDRAM_INITPLR3, SDRAM_INITPLR_ENABLE | emr3 | SDRAM_INITPLR_IMWT_ENCODE(2)); /* EMR DLL ENABLE - Wait tMRD (2 MemClk cycles) */ mtsdram(SDRAM_INITPLR4, SDRAM_INITPLR_ENABLE | emr | SDRAM_INITPLR_IMWT_ENCODE(2)); /* MR w/ DLL reset - 200 cycle wait for DLL reset */ mtsdram(SDRAM_INITPLR5, SDRAM_INITPLR_ENABLE | mr | DLL_RESET | SDRAM_INITPLR_IMWT_ENCODE(200)); udelay(1000); /* precharge 4 MemClk cycles */ mtsdram(SDRAM_INITPLR6, SDRAM_INITPLR_ENABLE | CMD_PRECHARGE | SDRAM_INITPLR_IMWT_ENCODE(4)); /* Refresh 25 MemClk cycles */ mtsdram(SDRAM_INITPLR7, SDRAM_INITPLR_ENABLE | CMD_REFRESH | SDRAM_INITPLR_IMWT_ENCODE(25)); /* Refresh 25 MemClk cycles */ mtsdram(SDRAM_INITPLR8, SDRAM_INITPLR_ENABLE | CMD_REFRESH | SDRAM_INITPLR_IMWT_ENCODE(25)); /* Refresh 25 MemClk cycles */ mtsdram(SDRAM_INITPLR9, SDRAM_INITPLR_ENABLE | CMD_REFRESH | SDRAM_INITPLR_IMWT_ENCODE(25)); /* Refresh 25 MemClk cycles */ mtsdram(SDRAM_INITPLR10, SDRAM_INITPLR_ENABLE | CMD_REFRESH | SDRAM_INITPLR_IMWT_ENCODE(25)); /* MR w/o DLL reset - Wait tMRD (2 MemClk cycles) */ mtsdram(SDRAM_INITPLR11, SDRAM_INITPLR_ENABLE | mr | SDRAM_INITPLR_IMWT_ENCODE(2)); /* EMR OCD Default - Wait tMRD (2 MemClk cycles) */ mtsdram(SDRAM_INITPLR12, SDRAM_INITPLR_ENABLE | OCD_CALIB_DEF | SDRAM_INITPLR_IMWT_ENCODE(2) | emr); /* EMR OCD Exit */ mtsdram(SDRAM_INITPLR13, SDRAM_INITPLR_ENABLE | emr | SDRAM_INITPLR_IMWT_ENCODE(2)); } else { printf("ERROR: ucode error as unknown DDR type in program_initplr"); spd_ddr_init_hang (); }}/*------------------------------------------------------------------ * This routine programs the SDRAM_MMODE register. * the selected_cas is an output parameter, that will be passed * by caller to call the above program_initplr( ) *-----------------------------------------------------------------*/static void program_mode(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks, ddr_cas_id_t *selected_cas, int *write_recovery){ unsigned long dimm_num; unsigned long sdram_ddr1; unsigned long t_wr_ns; unsigned long t_wr_clk; unsigned long cas_bit; unsigned long cas_index; unsigned long sdram_freq; unsigned long ddr_check; unsigned long mmode; unsigned long tcyc_reg; unsigned long cycle_2_0_clk; unsigned long cycle_2_5_clk; unsigned long cycle_3_0_clk; unsigned long cycle_4_0_clk; unsigned long cycle_5_0_clk; unsigned long max_2_0_tcyc_ns_x_100; unsigned long max_2_5_tcyc_ns_x_100; unsigned long max_3_0_tcyc_ns_x_100; unsigned long max_4_0_tcyc_ns_x_100; unsigned long max_5_0_tcyc_ns_x_100; unsigned long cycle_time_ns_x_100[3]; PPC4xx_SYS_INFO board_cfg; unsigned char cas_2_0_available; unsigned char cas_2_5_available; unsigned char cas_3_0_available; unsigned char cas_4_0_available; unsigned char cas_5_0_available; unsigned long sdr_ddrpll; /*------------------------------------------------------------------ * Get the board configuration info. *-----------------------------------------------------------------*/ get_sys_info(&board_cfg); mfsdr(SDR0_DDR0, sdr_ddrpll); sdram_freq = MULDIV64((board_cfg.freqPLB), SDR0_DDR0_DDRM_DECODE(sdr_ddrpll), 1); debug("sdram_freq=%d\n", sdram_freq); /*------------------------------------------------------------------ * Handle the timing. We need to find the worst case timing of all * the dimm modules installed. *-----------------------------------------------------------------*/ t_wr_ns = 0; cas_2_0_available = TRUE; cas_2_5_available = TRUE; cas_3_0_available = TRUE; cas_4_0_available = TRUE; cas_5_0_available = TRUE; max_2_0_tcyc_ns_x_100 = 10; max_2_5_tcyc_ns_x_100 = 10; max_3_0_tcyc_ns_x_100 = 10; max_4_0_tcyc_ns_x_100 = 10; max_5_0_tcyc_ns_x_100 = 10; sdram_ddr1 = TRUE; /* loop through all the DIMM slots on the board */ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { /* If a dimm is installed in a particular slot ... */ if (dimm_populated[dimm_num] != SDRAM_NONE) { if (dimm_populated[dimm_num] == SDRAM_DDR1) sdram_ddr1 = TRUE; else sdram_ddr1 = FALSE; /* t_wr_ns = max(t_wr_ns, (unsigned long)dimm_spd[dimm_num][36] >> 2); */ /* not used in this loop. */ cas_bit = spd_read(iic0_dimm_addr[dimm_num], 18); debug("cas_bit[SPD byte 18]=%02x\n", cas_bit); /* For a particular DIMM, grab the three CAS values it supports */ for (cas_index = 0; cas_index < 3; cas_index++) { switch (cas_index) { case 0: tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 9); break; case 1: tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 23); break; default: tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 25); break; } if ((tcyc_reg & 0x0F) >= 10) { if ((tcyc_reg & 0x0F) == 0x0D) { /* Convert from hex to decimal */ cycle_time_ns_x_100[cas_index] = (((tcyc_reg & 0xF0) >> 4) * 100) + 75; } else { printf("ERROR: SPD reported Tcyc is incorrect for DIMM " "in slot %d\n", (unsigned int)dimm_num); spd_ddr_init_hang (); } } else { /* Convert from hex to decimal */ cycle_time_ns_x_100[cas_index] = (((tcyc_reg & 0xF0) >> 4) * 100) + ((tcyc_reg & 0x0F)*10); } debug("cas_index=%d: cycle_time_ns_x_100=%d\n", cas_index, cycle_time_ns_x_100[cas_index]); } /* The rest of this routine determines if CAS 2.0, 2.5, 3.0, 4.0 and 5.0 are */ /* supported for a particular DIMM. */ cas_index = 0; if (sdram_ddr1) { /* * DDR devices use the following bitmask for CAS latency: * Bit 7 6 5 4 3 2 1 0 * TBD 4.0 3.5 3.0 2.5 2.0 1.5 1.0 */ if (((cas_bit & 0x40) == 0x40) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { max_4_0_tcyc_ns_x_100 = max(max_4_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); cas_index++; } else { if (cas_index != 0) cas_index++; cas_4_0_available = FALSE; } if (((cas_bit & 0x10) == 0x10) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { max_3_0_tcyc_ns_x_100 = max(max_3_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); cas_index++; } else { if (cas_index != 0) cas_index++; cas_3_0_available = FALSE; } if (((cas_bit & 0x08) == 0x08) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { max_2_5_tcyc_ns_x_100 = max(max_2_5_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); cas_index++; } else { if (cas_index != 0) cas_index++; cas_2_5_available = FALSE; } if (((cas_bit & 0x04) == 0x04) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { max_2_0_tcyc_ns_x_100 = max(max_2_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); cas_index++; } else { if (cas_index != 0) cas_index++; cas_2_0_available = FALSE; } } else { /* * DDR2 devices use the following bitmask for CAS latency: * Bit 7 6 5 4 3 2 1 0 * TBD 6.0 5.0 4.0 3.0 2.0 TBD TBD */ if (((cas_bit & 0x20) == 0x20) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { max_5_0_tcyc_ns_x_100 = max(max_5_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); cas_index++; } else { if (cas_index != 0) cas_index++; cas_5_0_available = FALSE; } if (((cas_bit & 0x10) == 0x10) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { max_4_0_tcyc_ns_x_100 = max(max_4_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); cas_index++; } else { if (cas_index != 0) cas_index++; cas_4_0_available = FALSE; } if (((cas_bit & 0x08) == 0x08) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { max_3_0_tcyc_ns_x_100 = max(max_3_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); cas_index++; } else { if (cas_index != 0) cas_index++; cas_3_0_available = FALSE; } } } } /*------------------------------------------------------------------ * Set the SDRAM mode, SDRAM_MMODE *-----------------------------------------------------------------*/ mfsdram(SDRAM_MMODE, mmode); mmode = mmode & ~(SDRAM_MMODE_WR_MASK | SDRAM_MMODE_DCL_MASK); /* add 10 here because of rounding problems */ cycle_2_0_clk = MULDIV64(ONE_BILLION, 100, max_2_0_tcyc_ns_x_100) + 10; cycle_2_5_clk = MULDIV64(ONE_BILLION, 100, max_2_5_tcyc_ns_x_100) + 10; cycle_3_0_clk = MULDIV64(ONE_BILLION, 100, max_3_0_tcyc_ns_x_100) + 10; cycle_4_0_clk = MULDIV64(ONE_BILLION, 100, max_4_0_tcyc_ns_x_100) + 10; cycle_5_0_clk = MULDIV64(ONE_BILLION, 100, max_5_0_tcyc_ns_x_100) + 10; debug("cycle_3_0_clk=%d\n", cycle_3_0_clk); debug("cycle_4_0_clk=%d\n", cycle_4_0_clk); debug("cycle_5_0_clk=%d\n", cycle_5_0_clk); if (sdram_ddr1 == TRUE) { /* DDR1 */ if ((cas_2_0_available == TRUE) && (sdram_freq <= cycle_2_0_clk)) { mmode |= SDRAM_MMODE_DCL_DDR1_2_0_CLK; *selected_cas = DDR_CAS_2; } else if ((cas_2_5_available == TRUE) && (sdram_freq <= cycle_2_5_clk)) { mmode |= SDRAM_MMODE_DCL_DDR1_2_5_CLK; *selected_cas = DDR_CAS_2_5; } else if ((cas_3_0_available == TRUE) && (sdram_freq <= cycle_3_0_clk)) { mmode |= SDRAM_MMODE_DCL_DDR1_3_0_CLK; *selected_cas = DDR_CAS_3; } else { printf("ERROR: Cannot find a supported CAS latency with the installed DIMMs.\n"); printf("Only DIMMs DDR1 with CAS latencies of 2.0, 2.5, and 3.0 are supported.\n"); printf("Make sure the PLB speed is within the supported range of the DIMMs.\n\n"); spd_ddr_init_hang (); } } else { /* DDR2 */ debug("cas_3_0_available=%d\n", cas_3_0_available); debug("cas_4_0_available=%d\n", cas_4_0_available); debug("cas_5_0_available=%d\n", cas_5_0_available); if ((cas_3_0_available == TRUE) && (sdram_freq <= cycle_3_0_clk)) { mmode |= SDRAM_MMODE_DCL_DDR2_3_0_CLK; *selected_cas = DDR_CAS_3; } else if ((cas_4_0_available == TRUE) && (sdram_freq <= cycle_4_0_clk)) { mmode |= SDRAM_MMODE_DCL_DDR2_4_0_CLK; *selected_cas = DDR_CAS_4; } else if ((cas_5_0_available == TRUE) && (sdram_freq <= cycle_5_0_clk)) { mmode |= SDRAM_MMODE_DCL_DDR2_5_0_CLK; *selected_cas = DDR_CAS_5; } else { printf("ERROR: Cannot find a supported CAS latency with the installed DIMMs.\n"); printf("Only DIMMs DDR2 with CAS latencies of 3.0, 4.0, and 5.0 are supported.\n"); printf("Make sure the PLB speed is within the supported range of the DIMMs.\n"); printf("cas3=%d cas4=%d cas5=%d\n", cas_3_0_available, cas_4_0_available, cas_5_0_available); printf("sdram_freq=%lu cycle3=%lu cycle4=%lu cycle5=%lu\n\n", sdram_freq, cycle_3_0_clk, cycle_4_0_clk, cycle_5_0_clk); spd_ddr_init_hang (); } } if (sdram_ddr1 == TRUE) mmode |= SDRAM_MMODE_WR_DDR1; else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -