📄 44x_spd_ddr2.c
字号:
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; mtsdram(SDRAM_INITPLR0, 0xB5000000 | CMD_NOP); /* NOP */ udelay(1000); mtsdram(SDRAM_INITPLR1, 0x82000400 | CMD_PRECHARGE); /* precharge 8 DDR clock cycle */ mtsdram(SDRAM_INITPLR2, 0x80800000 | emr2); /* EMR2 */ mtsdram(SDRAM_INITPLR3, 0x80800000 | emr3); /* EMR3 */ mtsdram(SDRAM_INITPLR4, 0x80800000 | emr); /* EMR DLL ENABLE */ mtsdram(SDRAM_INITPLR5, 0x80800000 | mr | DLL_RESET); /* MR w/ DLL reset */ udelay(1000); mtsdram(SDRAM_INITPLR6, 0x82000400 | CMD_PRECHARGE); /* precharge 8 DDR clock cycle */ mtsdram(SDRAM_INITPLR7, 0x8a000000 | CMD_REFRESH); /* Refresh 50 DDR clock cycle */ mtsdram(SDRAM_INITPLR8, 0x8a000000 | CMD_REFRESH); /* Refresh 50 DDR clock cycle */ mtsdram(SDRAM_INITPLR9, 0x8a000000 | CMD_REFRESH); /* Refresh 50 DDR clock cycle */ mtsdram(SDRAM_INITPLR10, 0x8a000000 | CMD_REFRESH); /* Refresh 50 DDR clock cycle */ mtsdram(SDRAM_INITPLR11, 0x80000000 | mr); /* MR w/o DLL reset */ mtsdram(SDRAM_INITPLR12, 0x80800380 | emr); /* EMR OCD Default */ mtsdram(SDRAM_INITPLR13, 0x80800000 | emr); /* EMR OCD Exit */ } 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]; PPC440_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=%d cycle3=%d cycle4=%d cycle5=%d\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 { /* 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) t_wr_ns = max(t_wr_ns, spd_read(iic0_dimm_addr[dimm_num], 36) >> 2); } /* * convert from nanoseconds to ddr clocks * round up if necessary */ t_wr_clk = MULDIV64(sdram_freq, t_wr_ns, ONE_BILLION); ddr_check = MULDIV64(ONE_BILLION, t_wr_clk, t_wr_ns); if (sdram_freq != ddr_check) t_wr_clk++; switch (t_wr_clk) { case 0: case 1: case 2: case 3: mmode |= SDRAM_MMODE_WR_DDR2_3_CYC; break; case 4: mmode |= SDRAM_MMODE_WR_DDR2_4_CYC; break; case 5: mmode |= SDRAM_MMODE_WR_DDR2_5_CYC; break; default: mmode |= SDRAM_MMODE_WR_DDR2_6_CYC; break; } *write_recovery = t_wr_clk; } debug("CAS latency = %d\n", *selected_cas); debug("Write recovery = %d\n", *write_recovery); mtsdram(SDRAM_MMODE, mmode);}/*-----------------------------------------------------------------------------+ * program_rtr. *-----------------------------------------------------------------------------*/static void program_rtr(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks){ PPC440_SYS_INFO board_cfg; unsigned long max_refresh_rate; unsigned long dimm_num; unsigned long refresh_rate_type; unsigned long refresh_rate; unsigned long rint;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -