📄 spd_sdram.c
字号:
} } else if (max_data_rate >= 190) { /* it is DDR 200 */ if (ddrc_clk <= 350 && ddrc_clk > 230) { /* DDR controller clk at 230~350 */ printf("DDR: DDR controller freq is more than " "max data rate of the module\n"); return 0; } else if (ddrc_clk <= 230 && ddrc_clk > 90) { /* DDR controller clk at 90~230 */ effective_data_rate = 200; /* 10ns */ caslat = caslat; } } debug("DDR:Effective data rate is: %dMhz\n", effective_data_rate); debug("DDR:The MSB 1 of CAS Latency is: %d\n", caslat); /* * Errata DDR6 work around: input enable 2 cycles earlier. * including MPC834x Rev1.0/1.1 and MPC8360 Rev1.1/1.2. */ if (caslat == 2) ddr->debug_reg = 0x201c0000; /* CL=2 */ else if (caslat == 3) ddr->debug_reg = 0x202c0000; /* CL=2.5 */ else if (caslat == 4) ddr->debug_reg = 0x202c0000; /* CL=3.0 */ __asm__ __volatile__ ("sync"); debug("Errata DDR6 (debug_reg=0x%08x)\n", ddr->debug_reg); /* * note: caslat must also be programmed into ddr->sdram_mode * register. * * note: WRREC(Twr) and WRTORD(Twtr) are not in SPD, * use conservative value here. */ caslat_ctrl = (caslat + 1) & 0x07; /* see as above */ ddr->timing_cfg_1 = (((picos_to_clk(spd.trp * 250) & 0x07) << 28 ) | ((picos_to_clk(spd.tras * 1000) & 0x0f ) << 24 ) | ((picos_to_clk(spd.trcd * 250) & 0x07) << 20 ) | ((caslat_ctrl & 0x07) << 16 ) | (((picos_to_clk(spd.trfc * 1000) - 8) & 0x0f) << 12 ) | ( 0x300 ) | ((picos_to_clk(spd.trrd * 250) & 0x07) << 4) | 1); ddr->timing_cfg_2 = 0x00000800; debug("DDR:timing_cfg_1=0x%08x\n", ddr->timing_cfg_1); debug("DDR:timing_cfg_2=0x%08x\n", ddr->timing_cfg_2); /* Setup init value, but not enable */ ddr->sdram_cfg = 0x42000000; /* Check DIMM data bus width */ if (spd.dataw_lsb == 0x20) { burstlen = 0x03; /* 32 bit data bus, burst len is 8 */ printf("\n DDR DIMM: data bus width is 32 bit"); } else { burstlen = 0x02; /* Others act as 64 bit bus, burst len is 4 */ printf("\n DDR DIMM: data bus width is 64 bit"); } /* Is this an ECC DDR chip? */ if (spd.config == 0x02) printf(" with ECC\n"); else printf(" without ECC\n"); /* Burst length is always 4 for 64 bit data bus, 8 for 32 bit data bus, Burst type is sequential */ switch (caslat) { case 1: ddr->sdram_mode = 0x50 | burstlen; /* CL=1.5 */ break; case 2: ddr->sdram_mode = 0x20 | burstlen; /* CL=2.0 */ break; case 3: ddr->sdram_mode = 0x60 | burstlen; /* CL=2.5 */ break; case 4: ddr->sdram_mode = 0x30 | burstlen; /* CL=3.0 */ break; default: printf("DDR:only CL 1.5, 2.0, 2.5, 3.0 is supported\n"); return 0; } debug("DDR:sdram_mode=0x%08x\n", ddr->sdram_mode); switch (spd.refresh) { case 0x00: case 0x80: refresh_clk = picos_to_clk(15625000); break; case 0x01: case 0x81: refresh_clk = picos_to_clk(3900000); break; case 0x02: case 0x82: refresh_clk = picos_to_clk(7800000); break; case 0x03: case 0x83: refresh_clk = picos_to_clk(31300000); break; case 0x04: case 0x84: refresh_clk = picos_to_clk(62500000); break; case 0x05: case 0x85: refresh_clk = picos_to_clk(125000000); break; default: refresh_clk = 0x512; break; } /* * Set BSTOPRE to 0x100 for page mode * If auto-charge is used, set BSTOPRE = 0 */ ddr->sdram_interval = ((refresh_clk & 0x3fff) << 16) | 0x100; debug("DDR:sdram_interval=0x%08x\n", ddr->sdram_interval); /* SS_EN = 0, source synchronous disable * CLK_ADJST = 0, MCK/MCK# is launched aligned with addr/cmd */ ddr->sdram_clk_cntl = 0x00000000; debug("DDR:sdram_clk_cntl=0x%08x\n", ddr->sdram_clk_cntl); asm("sync;isync"); udelay(600); /* * Figure out the settings for the sdram_cfg register. Build up * the value in 'sdram_cfg' before writing since the write into * the register will actually enable the memory controller, and all * settings must be done before enabling. * * sdram_cfg[0] = 1 (ddr sdram logic enable) * sdram_cfg[1] = 1 (self-refresh-enable) * sdram_cfg[6:7] = 2 (SDRAM type = DDR SDRAM) * sdram_cfg[12] = 0 (32_BE =0 , 64 bit bus mode) * sdram_cfg[13] = 0 (8_BE =0, 4-beat bursts) */ sdram_cfg = 0xC2000000; /* sdram_cfg[3] = RD_EN - registered DIMM enable */ if (spd.mod_attr & 0x02) sdram_cfg |= 0x10000000; /* The DIMM is 32bit width */ if (spd.dataw_lsb == 0x20) sdram_cfg |= 0x000C0000; ddrc_ecc_enable = 0;#if defined(CONFIG_DDR_ECC) /* Enable ECC with sdram_cfg[2] */ if (spd.config == 0x02) { sdram_cfg |= 0x20000000; ddrc_ecc_enable = 1; /* disable error detection */ ddr->err_disable = ~ECC_ERROR_ENABLE; /* set single bit error threshold to maximum value, * reset counter to zero */ ddr->err_sbe = (255 << ECC_ERROR_MAN_SBET_SHIFT) | (0 << ECC_ERROR_MAN_SBEC_SHIFT); } debug("DDR:err_disable=0x%08x\n", ddr->err_disable); debug("DDR:err_sbe=0x%08x\n", ddr->err_sbe);#endif printf(" DDRC ECC mode: %s\n", ddrc_ecc_enable ? "ON":"OFF");#if defined(CONFIG_DDR_2T_TIMING) /* * Enable 2T timing by setting sdram_cfg[16]. */ sdram_cfg |= SDRAM_CFG_2T_EN;#endif /* Enable controller, and GO! */ ddr->sdram_cfg = sdram_cfg; asm("sync;isync"); udelay(500); debug("DDR:sdram_cfg=0x%08x\n", ddr->sdram_cfg); return memsize; /*in MBytes*/}#endif /* CONFIG_SPD_EEPROM */#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRC)/* * Use timebase counter, get_timer() is not availabe * at this point of initialization yet. */static __inline__ unsigned long get_tbms (void){ unsigned long tbl; unsigned long tbu1, tbu2; unsigned long ms; unsigned long long tmp; ulong tbclk = get_tbclk(); /* get the timebase ticks */ do { asm volatile ("mftbu %0":"=r" (tbu1):); asm volatile ("mftb %0":"=r" (tbl):); asm volatile ("mftbu %0":"=r" (tbu2):); } while (tbu1 != tbu2); /* convert ticks to ms */ tmp = (unsigned long long)(tbu1); tmp = (tmp << 32); tmp += (unsigned long long)(tbl); ms = tmp/(tbclk/1000); return ms;}/* * Initialize all of memory for ECC, then enable errors. *//* #define CONFIG_DDR_ECC_INIT_VIA_DMA */void ddr_enable_ecc(unsigned int dram_size){ volatile immap_t *immap = (immap_t *)CFG_IMMR; volatile ddr83xx_t *ddr= &immap->ddr; unsigned long t_start, t_end; register u64 *p; register uint size; unsigned int pattern[2];#if defined(CONFIG_DDR_ECC_INIT_VIA_DMA) uint i;#endif icache_enable(); t_start = get_tbms(); pattern[0] = 0xdeadbeef; pattern[1] = 0xdeadbeef;#if !defined(CONFIG_DDR_ECC_INIT_VIA_DMA) debug("ddr init: CPU FP write method\n"); size = dram_size; for (p = 0; p < (u64*)(size); p++) { ppcDWstore((u32*)p, pattern); } __asm__ __volatile__ ("sync");#else debug("ddr init: DMA method\n"); size = 0x2000; for (p = 0; p < (u64*)(size); p++) { ppcDWstore((u32*)p, pattern); } __asm__ __volatile__ ("sync"); /* Initialise DMA for direct transfer */ dma_init(); /* Start DMA to transfer */ dma_xfer((uint *)0x2000, 0x2000, (uint *)0); /* 8K */ dma_xfer((uint *)0x4000, 0x4000, (uint *)0); /* 16K */ dma_xfer((uint *)0x8000, 0x8000, (uint *)0); /* 32K */ dma_xfer((uint *)0x10000, 0x10000, (uint *)0); /* 64K */ dma_xfer((uint *)0x20000, 0x20000, (uint *)0); /* 128K */ dma_xfer((uint *)0x40000, 0x40000, (uint *)0); /* 256K */ dma_xfer((uint *)0x80000, 0x80000, (uint *)0); /* 512K */ dma_xfer((uint *)0x100000, 0x100000, (uint *)0); /* 1M */ dma_xfer((uint *)0x200000, 0x200000, (uint *)0); /* 2M */ dma_xfer((uint *)0x400000, 0x400000, (uint *)0); /* 4M */ for (i = 1; i < dram_size / 0x800000; i++) { dma_xfer((uint *)(0x800000*i), 0x800000, (uint *)0); }#endif t_end = get_tbms(); icache_disable(); debug("\nREADY!!\n"); debug("ddr init duration: %ld ms\n", t_end - t_start); /* Clear All ECC Errors */ if ((ddr->err_detect & ECC_ERROR_DETECT_MME) == ECC_ERROR_DETECT_MME) ddr->err_detect |= ECC_ERROR_DETECT_MME; if ((ddr->err_detect & ECC_ERROR_DETECT_MBE) == ECC_ERROR_DETECT_MBE) ddr->err_detect |= ECC_ERROR_DETECT_MBE; if ((ddr->err_detect & ECC_ERROR_DETECT_SBE) == ECC_ERROR_DETECT_SBE) ddr->err_detect |= ECC_ERROR_DETECT_SBE; if ((ddr->err_detect & ECC_ERROR_DETECT_MSE) == ECC_ERROR_DETECT_MSE) ddr->err_detect |= ECC_ERROR_DETECT_MSE; /* Disable ECC-Interrupts */ ddr->err_int_en &= ECC_ERR_INT_DISABLE; /* Enable errors for ECC */ ddr->err_disable &= ECC_ERROR_ENABLE; __asm__ __volatile__ ("sync"); __asm__ __volatile__ ("isync");}#endif /* CONFIG_DDR_ECC */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -