📄 spd_sdram.c
字号:
* * CAS Lat DDR I DDR II Ctrl * Clocks SPD Bit SPD Bit Value * ------- ------- ------- ----- * 1.0 0 0001 * 1.5 1 0010 * 2.0 2 2 0011 * 2.5 3 0100 * 3.0 4 3 0101 * 3.5 5 0110 * 4.0 4 0111 * 4.5 1000 * 5.0 5 1001 */ caslat = __ilog2(spd.cas_lat); if ((spd.mem_type == SPD_MEMTYPE_DDR) && (caslat > 5)) { printf("DDR I: Invalid SPD CAS Latency: 0x%x.\n", spd.cas_lat); return 0; } else if (spd.mem_type == SPD_MEMTYPE_DDR2 && (caslat < 2 || caslat > 5)) { printf("DDR II: Invalid SPD CAS Latency: 0x%x.\n", spd.cas_lat); return 0; } debug("DDR: caslat SPD bit is %d\n", caslat); /* * Calculate the Maximum Data Rate based on the Minimum Cycle time. * The SPD clk_cycle field (tCKmin) is measured in tenths of * nanoseconds and represented as BCD. */ tCKmin_ps = convert_bcd_tenths_to_cycle_time_ps(spd.clk_cycle); debug("DDR: tCKmin = %d ps\n", tCKmin_ps); /* * Double-data rate, scaled 1000 to picoseconds, and back down to MHz. */ max_data_rate = 2 * 1000 * 1000 / tCKmin_ps; debug("DDR: Module max data rate = %d Mhz\n", max_data_rate); /* * Adjust the CAS Latency to allow for bus speeds that * are slower than the DDR module. */ busfreq = get_bus_freq(0) / 1000000; /* MHz */ tCycle_ps = convert_bcd_tenths_to_cycle_time_ps(spd.clk_cycle3); modfreq = 2 * 1000 * 1000 / tCycle_ps; if ((spd.mem_type == SPD_MEMTYPE_DDR2) && (busfreq < 266)) { printf("DDR: platform frequency too low for correct DDR2 controller operation\n"); return 0; } else if (busfreq < 90) { printf("DDR: platform frequency too low for correct DDR1 operation\n"); return 0; } if ((busfreq <= modfreq) && (spd.cas_lat & (1 << (caslat - 2)))) { caslat -= 2; } else { tCycle_ps = convert_bcd_tenths_to_cycle_time_ps(spd.clk_cycle2); modfreq = 2 * 1000 * 1000 / tCycle_ps; if ((busfreq <= modfreq) && (spd.cas_lat & (1 << (caslat - 1)))) caslat -= 1; else if (busfreq > max_data_rate) { printf("DDR: Bus freq %d MHz is not fit for DDR rate %d MHz\n", busfreq, max_data_rate); return 0; } } /* * Empirically set ~MCAS-to-preamble override for DDR 2. * Your milage will vary. */ cpo = 0; if (spd.mem_type == SPD_MEMTYPE_DDR2) { if (busfreq <= 333) { cpo = 0x7; } else if (busfreq <= 400) { cpo = 0x9; } else { cpo = 0xa; } } /* * Convert caslat clocks to DDR controller value. * Force caslat_ctrl to be DDR Controller field-sized. */ if (spd.mem_type == SPD_MEMTYPE_DDR) { caslat_ctrl = (caslat + 1) & 0x07; } else { caslat_ctrl = (2 * caslat - 1) & 0x0f; } debug("DDR: caslat SPD bit is %d, controller field is 0x%x\n", caslat, caslat_ctrl); /* * Timing Config 0. * Avoid writing for DDR I. The new PQ38 DDR controller * dreams up non-zero default values to be backwards compatible. */ if (spd.mem_type == SPD_MEMTYPE_DDR2) { unsigned char taxpd_clk = 8; /* By the book. */ unsigned char tmrd_clk = 2; /* By the book. */ unsigned char act_pd_exit = 2; /* Empirical? */ unsigned char pre_pd_exit = 6; /* Empirical? */ ddr->timing_cfg_0 = (0 | ((act_pd_exit & 0x7) << 20) /* ACT_PD_EXIT */ | ((pre_pd_exit & 0x7) << 16) /* PRE_PD_EXIT */ | ((taxpd_clk & 0xf) << 8) /* ODT_PD_EXIT */ | ((tmrd_clk & 0xf) << 0) /* MRS_CYC */ ); debug("DDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0); } /* * Some Timing Config 1 values now. * Sneak Extended Refresh Recovery in here too. */ /* * For DDR I, WRREC(Twr) and WRTORD(Twtr) are not in SPD, * use conservative value. * For DDR II, they are bytes 36 and 37, in quarter nanos. */ if (spd.mem_type == SPD_MEMTYPE_DDR) { twr_clk = 3; /* Clocks */ twtr_clk = 1; /* Clocks */ } else { twr_clk = picos_to_clk(spd.twr * 250); twtr_clk = picos_to_clk(spd.twtr * 250); } /* * Calculate Trfc, in picos. * DDR I: Byte 42 straight up in ns. * DDR II: Byte 40 and 42 swizzled some, in ns. */ if (spd.mem_type == SPD_MEMTYPE_DDR) { trfc = spd.trfc * 1000; /* up to ps */ } else { unsigned int byte40_table_ps[8] = { 0, 250, 330, 500, 660, 750, 0, 0 }; trfc = (((spd.trctrfc_ext & 0x1) * 256) + spd.trfc) * 1000 + byte40_table_ps[(spd.trctrfc_ext >> 1) & 0x7]; } trfc_clk = picos_to_clk(trfc); /* * Trcd, Byte 29, from quarter nanos to ps and clocks. */ trcd_clk = picos_to_clk(spd.trcd * 250) & 0x7; /* * Convert trfc_clk to DDR controller fields. DDR I should * fit in the REFREC field (16-19) of TIMING_CFG_1, but the * 8548 controller has an extended REFREC field of three bits. * The controller automatically adds 8 clocks to this value, * so preadjust it down 8 first before splitting it up. */ trfc_low = (trfc_clk - 8) & 0xf; trfc_high = ((trfc_clk - 8) >> 4) & 0x3; /* * Sneak in some Extended Refresh Recovery. */ ddr->ext_refrec = (trfc_high << 16); debug("DDR: ext_refrec = 0x%08x\n", ddr->ext_refrec); ddr->timing_cfg_1 = (0 | ((picos_to_clk(spd.trp * 250) & 0x07) << 28) /* PRETOACT */ | ((picos_to_clk(spd.tras * 1000) & 0x0f ) << 24) /* ACTTOPRE */ | (trcd_clk << 20) /* ACTTORW */ | (caslat_ctrl << 16) /* CASLAT */ | (trfc_low << 12) /* REFEC */ | ((twr_clk & 0x07) << 8) /* WRRREC */ | ((picos_to_clk(spd.trrd * 250) & 0x07) << 4) /* ACTTOACT */ | ((twtr_clk & 0x07) << 0) /* WRTORD */ ); debug("DDR: timing_cfg_1 = 0x%08x\n", ddr->timing_cfg_1); /* * Timing_Config_2 * Was: 0x00000800; */ /* * Additive Latency * For DDR I, 0. * For DDR II, with ODT enabled, use "a value" less than ACTTORW, * which comes from Trcd, and also note that: * add_lat + caslat must be >= 4 */ add_lat = 0; if (spd.mem_type == SPD_MEMTYPE_DDR2 && (odt_wr_cfg || odt_rd_cfg) && (caslat < 4)) { add_lat = 4 - caslat; if (add_lat >= trcd_clk) { add_lat = trcd_clk - 1; } } /* * Write Data Delay * Historically 0x2 == 4/8 clock delay. * Empirically, 0x3 == 6/8 clock delay is suggested for DDR I 266. */ wr_data_delay = 3; /* * Write Latency * Read to Precharge * Minimum CKE Pulse Width. * Four Activate Window */ if (spd.mem_type == SPD_MEMTYPE_DDR) { /* * This is a lie. It should really be 1, but if it is * set to 1, bits overlap into the old controller's * otherwise unused ACSM field. If we leave it 0, then * the HW will magically treat it as 1 for DDR 1. Oh Yea. */ wr_lat = 0; trtp_clk = 2; /* By the book. */ cke_min_clk = 1; /* By the book. */ four_act = 1; /* By the book. */ } else { wr_lat = caslat - 1; /* Convert SPD value from quarter nanos to picos. */ trtp_clk = picos_to_clk(spd.trtp * 250); cke_min_clk = 3; /* By the book. */ four_act = picos_to_clk(37500); /* By the book. 1k pages? */ } ddr->timing_cfg_2 = (0 | ((add_lat & 0x7) << 28) /* ADD_LAT */ | ((cpo & 0x1f) << 23) /* CPO */ | ((wr_lat & 0x7) << 19) /* WR_LAT */ | ((trtp_clk & 0x7) << 13) /* RD_TO_PRE */ | ((wr_data_delay & 0x7) << 10) /* WR_DATA_DELAY */ | ((cke_min_clk & 0x7) << 6) /* CKE_PLS */ | ((four_act & 0x1f) << 0) /* FOUR_ACT */ ); debug("DDR: timing_cfg_2 = 0x%08x\n", ddr->timing_cfg_2); /* * Determine the Mode Register Set. * * This is nominally part specific, but it appears to be * consistent for all DDR I devices, and for all DDR II devices. * * caslat must be programmed * burst length is always 4 * burst type is sequential * * For DDR I: * operating mode is "normal" * * For DDR II: * other stuff */ mode_caslat = 0; /* * Table lookup from DDR I or II Device Operation Specs. */ if (spd.mem_type == SPD_MEMTYPE_DDR) { if (1 <= caslat && caslat <= 4) { unsigned char mode_caslat_table[4] = { 0x5, /* 1.5 clocks */ 0x2, /* 2.0 clocks */ 0x6, /* 2.5 clocks */ 0x3 /* 3.0 clocks */ }; mode_caslat = mode_caslat_table[caslat - 1]; } else { puts("DDR I: Only CAS Latencies of 1.5, 2.0, " "2.5 and 3.0 clocks are supported.\n"); return 0; } } else { if (2 <= caslat && caslat <= 5) { mode_caslat = caslat; } else { puts("DDR II: Only CAS Latencies of 2.0, 3.0, " "4.0 and 5.0 clocks are supported.\n"); return 0; } } /* * Encoded Burst Length of 4. */ burst_len = 2; /* Fiat. */ if (spd.mem_type == SPD_MEMTYPE_DDR) { twr_auto_clk = 0; /* Historical */ } else { /* * Determine tCK max in picos. Grab tWR and convert to picos. * Auto-precharge write recovery is: * WR = roundup(tWR_ns/tCKmax_ns). * * Ponder: Is twr_auto_clk different than twr_clk? */ tCKmax_ps = convert_bcd_tenths_to_cycle_time_ps(spd.tckmax); twr_auto_clk = (spd.twr * 250 + tCKmax_ps - 1) / tCKmax_ps; } /* * Mode Reg in bits 16 ~ 31, * Extended Mode Reg 1 in bits 0 ~ 15. */ mode_odt_enable = 0x0; /* Default disabled */ if (odt_wr_cfg || odt_rd_cfg) { /* * Bits 6 and 2 in Extended MRS(1) * Bit 2 == 0x04 == 75 Ohm, with 2 DIMM modules. * Bit 6 == 0x40 == 150 Ohm, with 1 DIMM module. */ mode_odt_enable = 0x40; /* 150 Ohm */ } ddr->sdram_mode_1 = (0 | (add_lat << (16 + 3)) /* Additive Latency in EMRS1 */ | (mode_odt_enable << 16) /* ODT Enable in EMRS1 */ | (twr_auto_clk << 9) /* Write Recovery Autopre */ | (mode_caslat << 4) /* caslat */ | (burst_len << 0) /* Burst length */ ); debug("DDR: sdram_mode = 0x%08x\n", ddr->sdram_mode_1); /* * Clear EMRS2 and EMRS3. */ ddr->sdram_mode_2 = 0; debug("DDR: sdram_mode_2 = 0x%08x\n", ddr->sdram_mode_2); /* * Determine Refresh Rate. */ refresh_clk = determine_refresh_rate(spd.refresh & 0x7); /* * Set BSTOPRE to 0x100 for page mode * If auto-charge is used, set BSTOPRE = 0 */ ddr->sdram_interval = (0 | (refresh_clk & 0x3fff) << 16 | 0x100 ); debug("DDR: sdram_interval = 0x%08x\n", ddr->sdram_interval); /* * Is this an ECC DDR chip? * But don't mess with it if the DDR controller will init mem. */#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER) if (spd.config == 0x02) { ddr->err_disable = 0x0000000d; ddr->err_sbe = 0x00ff0000; } debug("DDR: err_disable = 0x%08x\n", ddr->err_disable); debug("DDR: err_sbe = 0x%08x\n", ddr->err_sbe);#endif asm volatile("sync;isync"); udelay(500); /* * SDRAM Cfg 2 */ /* * When ODT is enabled, Chap 9 suggests asserting ODT to * internal IOs only during reads. */ odt_cfg = 0; if (odt_rd_cfg | odt_wr_cfg) { odt_cfg = 0x2; /* ODT to IOs during reads */ } /* * Try to use differential DQS with DDR II. */ if (spd.mem_type == SPD_MEMTYPE_DDR) { dqs_cfg = 0; /* No Differential DQS for DDR I */ } else { dqs_cfg = 0x1; /* Differential DQS for DDR II */ }#if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER) /* * Use the DDR controller to auto initialize memory. */ d_init = 1; ddr->sdram_data_init = CONFIG_MEM_INIT_VALUE; debug("DDR: ddr_data_init = 0x%08x\n", ddr->sdram_data_init);#else /* * Memory will be initialized via DMA, or not at all. */ d_init = 0;#endif ddr->sdram_cfg_2 = (0 | (dqs_cfg << 26) /* Differential DQS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -