📄 spd_sdram.c
字号:
| (odt_cfg << 21) /* ODT */ | (d_init << 4) /* D_INIT auto init DDR */ ); debug("DDR: sdram_cfg_2 = 0x%08x\n", ddr->sdram_cfg_2);#ifdef MPC86xx_DDR_SDRAM_CLK_CNTL /* * Setup the clock control. * SDRAM_CLK_CNTL[0] = Source synchronous enable == 1 * SDRAM_CLK_CNTL[5-7] = Clock Adjust * 0110 3/4 cycle late * 0111 7/8 cycle late */ if (spd.mem_type == SPD_MEMTYPE_DDR) clk_adjust = 0x6; else clk_adjust = 0x7; ddr->sdram_clk_cntl = (0 | 0x80000000 | (clk_adjust << 23) ); debug("DDR: sdram_clk_cntl = 0x%08x\n", ddr->sdram_clk_cntl);#endif /* * Figure out memory size in Megabytes. */ debug("# ranks = %d, rank_density = 0x%08lx\n", n_ranks, rank_density); memsize = n_ranks * rank_density / 0x100000; return memsize;}unsigned int enable_ddr(unsigned int ddr_num){ volatile immap_t *immap = (immap_t *)CFG_IMMR; spd_eeprom_t spd1,spd2; volatile ccsr_ddr_t *ddr; unsigned sdram_cfg_1; unsigned char sdram_type, mem_type, config, mod_attr; unsigned char d_init; unsigned int no_dimm1=0, no_dimm2=0; /* Set up pointer to enable the current ddr controller */ if (ddr_num == 1) ddr = &immap->im_ddr1; else ddr = &immap->im_ddr2; /* * Read both dimm slots and decide whether * or not to enable this controller. */ memset((void *)&spd1,0,sizeof(spd1)); memset((void *)&spd2,0,sizeof(spd2)); if (ddr_num == 1) { CFG_READ_SPD(SPD_EEPROM_ADDRESS1, 0, 1, (uchar *) &spd1, sizeof(spd1)); CFG_READ_SPD(SPD_EEPROM_ADDRESS2, 0, 1, (uchar *) &spd2, sizeof(spd2)); } else { CFG_READ_SPD(SPD_EEPROM_ADDRESS3, 0, 1, (uchar *) &spd1, sizeof(spd1)); CFG_READ_SPD(SPD_EEPROM_ADDRESS4, 0, 1, (uchar *) &spd2, sizeof(spd2)); } /* * Check for supported memory module types. */ if (spd1.mem_type != SPD_MEMTYPE_DDR && spd1.mem_type != SPD_MEMTYPE_DDR2) { no_dimm1 = 1; } else { debug("\nFound memory of type 0x%02lx ",spd1.mem_type ); if (spd1.mem_type == SPD_MEMTYPE_DDR) debug("DDR I\n"); else debug("DDR II\n"); } if (spd2.mem_type != SPD_MEMTYPE_DDR && spd2.mem_type != SPD_MEMTYPE_DDR2) { no_dimm2 = 1; } else { debug("\nFound memory of type 0x%02lx ",spd2.mem_type ); if (spd2.mem_type == SPD_MEMTYPE_DDR) debug("DDR I\n"); else debug("DDR II\n"); }#ifdef CONFIG_DDR_INTERLEAVE if (no_dimm1) { printf("For interleaved operation memory modules need to be present in CS0 DIMM slots of both DDR controllers!\n"); return 0; }#endif /* * Memory is not present in DIMM1 and DIMM2 - so do not enable DDRn */ if (no_dimm1 && no_dimm2) { printf("No memory modules found for DDR controller %d!!\n", ddr_num); return 0; } else { mem_type = no_dimm2 ? spd1.mem_type : spd2.mem_type; /* * Figure out the settings for the sdram_cfg register. * Build up the entire register in 'sdram_cfg' before * writing since the write into the register will * actually enable the memory controller; all settings * must be done before enabling. * * sdram_cfg[0] = 1 (ddr sdram logic enable) * sdram_cfg[1] = 1 (self-refresh-enable) * sdram_cfg[5:7] = (SDRAM type = DDR SDRAM) * 010 DDR 1 SDRAM * 011 DDR 2 SDRAM */ sdram_type = (mem_type == SPD_MEMTYPE_DDR) ? 2 : 3; sdram_cfg_1 = (0 | (1 << 31) /* Enable */ | (1 << 30) /* Self refresh */ | (sdram_type << 24) /* SDRAM type */ ); /* * sdram_cfg[3] = RD_EN - registered DIMM enable * A value of 0x26 indicates micron registered * DIMMS (micron.com) */ mod_attr = no_dimm2 ? spd1.mod_attr : spd2.mod_attr; if (mem_type == SPD_MEMTYPE_DDR && mod_attr == 0x26) { sdram_cfg_1 |= 0x10000000; /* RD_EN */ }#if defined(CONFIG_DDR_ECC) config = no_dimm2 ? spd1.config : spd2.config; /* * If the user wanted ECC (enabled via sdram_cfg[2]) */ if (config == 0x02) { ddr->err_disable = 0x00000000; asm volatile("sync;isync;"); ddr->err_sbe = 0x00ff0000; ddr->err_int_en = 0x0000000d; sdram_cfg_1 |= 0x20000000; /* ECC_EN */ }#endif /* * Set 1T or 2T timing based on 1 or 2 modules */ { if (!(no_dimm1 || no_dimm2)) { /* * 2T timing,because both DIMMS are present. * Enable 2T timing by setting sdram_cfg[16]. */ sdram_cfg_1 |= 0x8000; /* 2T_EN */ } } /* * 200 painful micro-seconds must elapse between * the DDR clock setup and the DDR config enable. */ udelay(200); /* * Go! */ ddr->sdram_cfg_1 = sdram_cfg_1; asm volatile("sync;isync"); udelay(500); debug("DDR: sdram_cfg = 0x%08x\n", ddr->sdram_cfg_1);#if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER) d_init = 1; debug("DDR: memory initializing\n"); /* * Poll until memory is initialized. * 512 Meg at 400 might hit this 200 times or so. */ while ((ddr->sdram_cfg_2 & (d_init << 4)) != 0) { udelay(1000); } debug("DDR: memory initialized\n\n");#endif debug("Enabled DDR Controller %d\n", ddr_num); return 1; }}long intspd_sdram(void){ int memsize_ddr1_dimm1 = 0; int memsize_ddr1_dimm2 = 0; int memsize_ddr2_dimm1 = 0; int memsize_ddr2_dimm2 = 0; int memsize_total = 0; int memsize_ddr1 = 0; int memsize_ddr2 = 0; unsigned int ddr1_enabled = 0; unsigned int ddr2_enabled = 0; unsigned int law_size_ddr1; unsigned int law_size_ddr2; volatile immap_t *immap = (immap_t *)CFG_IMMR; volatile ccsr_local_mcm_t *mcm = &immap->im_local_mcm;#ifdef CONFIG_DDR_INTERLEAVE unsigned int law_size_interleaved; volatile ccsr_ddr_t *ddr1 = &immap->im_ddr1; volatile ccsr_ddr_t *ddr2 = &immap->im_ddr2; memsize_ddr1_dimm1 = spd_init(SPD_EEPROM_ADDRESS1, 1, 1, (unsigned int)memsize_total * 1024*1024); memsize_total += memsize_ddr1_dimm1; memsize_ddr2_dimm1 = spd_init(SPD_EEPROM_ADDRESS3, 2, 1, (unsigned int)memsize_total * 1024*1024); memsize_total += memsize_ddr2_dimm1; if (memsize_ddr1_dimm1 != memsize_ddr2_dimm1) { if (memsize_ddr1_dimm1 < memsize_ddr2_dimm1) memsize_total -= memsize_ddr1_dimm1; else memsize_total -= memsize_ddr2_dimm1; debug("Total memory available for interleaving 0x%08lx\n", memsize_total * 1024 * 1024); debug("Adjusting CS0_BNDS to account for unequal DIMM sizes in interleaved memory\n"); ddr1->cs0_bnds = ((memsize_total * 1024 * 1024) - 1) >> 24; ddr2->cs0_bnds = ((memsize_total * 1024 * 1024) - 1) >> 24; debug("DDR1: cs0_bnds = 0x%08x\n", ddr1->cs0_bnds); debug("DDR2: cs0_bnds = 0x%08x\n", ddr2->cs0_bnds); } ddr1_enabled = enable_ddr(1); ddr2_enabled = enable_ddr(2); /* * Both controllers need to be enabled for interleaving. */ if (ddr1_enabled && ddr2_enabled) { law_size_interleaved = 19 + __ilog2(memsize_total); /* * Set up LAWBAR for DDR 1 space. */ mcm->lawbar1 = ((CFG_DDR_SDRAM_BASE >> 12) & 0xfffff); mcm->lawar1 = (LAWAR_EN | LAWAR_TRGT_IF_DDR_INTERLEAVED | (LAWAR_SIZE & law_size_interleaved)); debug("DDR: LAWBAR1=0x%08x\n", mcm->lawbar1); debug("DDR: LAWAR1=0x%08x\n", mcm->lawar1); debug("Interleaved memory size is 0x%08lx\n", memsize_total);#ifdef CONFIG_DDR_INTERLEAVE#if (CFG_PAGE_INTERLEAVING == 1) printf("Page ");#elif (CFG_BANK_INTERLEAVING == 1) printf("Bank ");#elif (CFG_SUPER_BANK_INTERLEAVING == 1) printf("Super-bank ");#else printf("Cache-line ");#endif#endif printf("Interleaved"); return memsize_total * 1024 * 1024; } else { printf("Interleaved memory not enabled - check CS0 DIMM slots for both controllers.\n"); return 0; }#else /* * Call spd_sdram() routine to init ddr1 - pass I2c address, * controller number, dimm number, and starting address. */ memsize_ddr1_dimm1 = spd_init(SPD_EEPROM_ADDRESS1, 1, 1, (unsigned int)memsize_total * 1024*1024); memsize_total += memsize_ddr1_dimm1; memsize_ddr1_dimm2 = spd_init(SPD_EEPROM_ADDRESS2, 1, 2, (unsigned int)memsize_total * 1024*1024); memsize_total += memsize_ddr1_dimm2; /* * Enable the DDR controller - pass ddr controller number. */ ddr1_enabled = enable_ddr(1); /* Keep track of memory to be addressed by DDR1 */ memsize_ddr1 = memsize_ddr1_dimm1 + memsize_ddr1_dimm2; /* * First supported LAW size is 16M, at LAWAR_SIZE_16M == 23. Fnord. */ if (ddr1_enabled) { law_size_ddr1 = 19 + __ilog2(memsize_ddr1); /* * Set up LAWBAR for DDR 1 space. */ mcm->lawbar1 = ((CFG_DDR_SDRAM_BASE >> 12) & 0xfffff); mcm->lawar1 = (LAWAR_EN | LAWAR_TRGT_IF_DDR1 | (LAWAR_SIZE & law_size_ddr1)); debug("DDR: LAWBAR1=0x%08x\n", mcm->lawbar1); debug("DDR: LAWAR1=0x%08x\n", mcm->lawar1); }#if (CONFIG_NUM_DDR_CONTROLLERS > 1) memsize_ddr2_dimm1 = spd_init(SPD_EEPROM_ADDRESS3, 2, 1, (unsigned int)memsize_total * 1024*1024); memsize_total += memsize_ddr2_dimm1; memsize_ddr2_dimm2 = spd_init(SPD_EEPROM_ADDRESS4, 2, 2, (unsigned int)memsize_total * 1024*1024); memsize_total += memsize_ddr2_dimm2; ddr2_enabled = enable_ddr(2); /* Keep track of memory to be addressed by DDR2 */ memsize_ddr2 = memsize_ddr2_dimm1 + memsize_ddr2_dimm2; if (ddr2_enabled) { law_size_ddr2 = 19 + __ilog2(memsize_ddr2); /* * Set up LAWBAR for DDR 2 space. */ if (ddr1_enabled) mcm->lawbar8 = (((memsize_ddr1 * 1024 * 1024) >> 12) & 0xfffff); else mcm->lawbar8 = ((CFG_DDR_SDRAM_BASE >> 12) & 0xfffff); mcm->lawar8 = (LAWAR_EN | LAWAR_TRGT_IF_DDR2 | (LAWAR_SIZE & law_size_ddr2)); debug("\nDDR: LAWBAR8=0x%08x\n", mcm->lawbar8); debug("DDR: LAWAR8=0x%08x\n", mcm->lawar8); }#endif /* CONFIG_NUM_DDR_CONTROLLERS > 1 */ debug("\nMemory sizes are DDR1 = 0x%08lx, DDR2 = 0x%08lx\n", memsize_ddr1, memsize_ddr2); /* * If neither DDR controller is enabled return 0. */ if (!ddr1_enabled && !ddr2_enabled) return 0; printf("Non-interleaved"); return memsize_total * 1024 * 1024;#endif /* CONFIG_DDR_INTERLEAVE */}#endif /* CONFIG_SPD_EEPROM */#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)/* * Initialize all of memory for ECC, then enable errors. */voidddr_enable_ecc(unsigned int dram_size){ uint *p = 0; uint i = 0; volatile immap_t *immap = (immap_t *)CFG_IMMR; volatile ccsr_ddr_t *ddr1= &immap->im_ddr1; dma_init(); for (*p = 0; p < (uint *)(8 * 1024); p++) { if (((unsigned int)p & 0x1f) == 0) { ppcDcbz((unsigned long) p); } *p = (unsigned int)CONFIG_MEM_INIT_VALUE; if (((unsigned int)p & 0x1c) == 0x1c) { ppcDcbf((unsigned long) p); } } dma_xfer((uint *)0x002000, 0x002000, (uint *)0); /* 8K */ dma_xfer((uint *)0x004000, 0x004000, (uint *)0); /* 16K */ dma_xfer((uint *)0x008000, 0x008000, (uint *)0); /* 32K */ dma_xfer((uint *)0x010000, 0x010000, (uint *)0); /* 64K */ dma_xfer((uint *)0x020000, 0x020000, (uint *)0); /* 128k */ dma_xfer((uint *)0x040000, 0x040000, (uint *)0); /* 256k */ dma_xfer((uint *)0x080000, 0x080000, (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); } /* * Enable errors for ECC. */ debug("DMA DDR: err_disable = 0x%08x\n", ddr1->err_disable); ddr1->err_disable = 0x00000000; asm volatile("sync;isync"); debug("DMA DDR: err_disable = 0x%08x\n", ddr1->err_disable);}#endif /* CONFIG_DDR_ECC && ! CONFIG_ECC_INIT_VIA_DDRCONTROLLER */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -