📄 bcm1480_draminit.c
字号:
cs = &(mc->csdata[init->geom.geom_csel]); cs->rows = init->geom.geom_rows; cs->cols = init->geom.geom_cols; cs->banks = init->geom.geom_banks; cs->flags |= CS_PRESENT; break; case MCR_SPD: cs = &(mc->csdata[init->spd.spd_csel]); bcm1480_dram_getinfo(init->spd.spd_smbuschan, init->spd.spd_smbusdev, mc, init->spd.spd_csel); if (mc->dramtype == DRAM_TYPE_SPD) { /* Use the DRAM type we get from the SPD */ if (cs->spd_dramtype == SPD_MEMTYPE_FCRAM){ mc->dramtype = FCRAM; mc->pagepolicy = CLOSED; if (mc->roundtrip == 0) mc->roundtrip = DEFAULT_MEMORY_ROUNDTRIP_TIME_FCRAM; } else { if(cs->spd_dramtype == SPD_MEMTYPE_DDR2){ mc->dramtype = JEDEC_DDR2; } else { mc->dramtype = JEDEC; } if (mc->roundtrip == 0) mc->roundtrip = DEFAULT_MEMORY_ROUNDTRIP_TIME; } } /* * The line below lets you put a MCR_MANTIMING record * before an MCR_SPD to work around some missing information * on certain DIMMs. Normally you have only one or the * other. */ mc->rfsh = cs->spd_rfsh; /* XXX flags ignored */ break; case MCR_MANTIMING: /* Manual timing - pick record up as bytes because we cannot guarantee the alignment of the "mtm_timing" field in our structure -- each row is 12 bytes, not good */ mc->rfsh = (uint16_t) init->mtm.mtm_rfsh; /* units: JEDEC refresh value */ mc->tCK = (uint16_t) init->mtm.mtm_tCK; /* units: BCD, like SPD */ mc->mantiming = (((uint64_t) init->mtm.mtm_timing[0]) << 56) | (((uint64_t) init->mtm.mtm_timing[1]) << 48) | (((uint64_t) init->mtm.mtm_timing[2]) << 40) | (((uint64_t) init->mtm.mtm_timing[3]) << 32) | (((uint64_t) init->mtm.mtm_timing[4]) << 24) | (((uint64_t) init->mtm.mtm_timing[5]) << 16) | (((uint64_t) init->mtm.mtm_timing[6]) << 8) | (((uint64_t) init->mtm.mtm_timing[7]) << 0); break; default: break; } init++; } /* * Okay, now we've internalized all the data from the SPDs * and/or the init table. */ }/* ********************************************************************* * BCM1480_DRAMINIT_DELAY * * This little routine delays at least 200 microseconds. * * Input parameters: * nothing * * Return value: * nothing. * * Registers used: * tmp0,tmp1 ********************************************************************* *//* 200 microseconds = 5KHz, so delay 1GHz/5Khz = 200,000 cycles */#if defined(_FASTEMUL_) && !defined(_DENALI_)#define DRAMINIT_DELAY_CNT "50"#else#define DRAMINIT_DELAY_CNT "(1000000000/5000)"#endif#if defined(_MCSTANDALONE_)#if defined(_MCSTANDALONE_NOISY_)#define DRAMINIT_DELAY() printf("DELAY 200us\n");#define bcm1480_draminit_smalldelay(x) printf("DELAY 200 MCLKS\n");#else#define DRAMINIT_DELAY() /* not running on a 1250, no delays */#define bcm1480_draminit_smalldelay(x)#endif#else#define DRAMINIT_DELAY() bcm1480_draminit_delay()static void bcm1480_draminit_delay(void){ __asm(" li $9," DRAMINIT_DELAY_CNT " ; " " mtc0 $0,$9 ; " "1: mfc0 $8,$9 ; " " .set push ; .set mips64 ; ssnop ; ssnop ; .set pop ;" " blt $8,$9,1b ;");}static void bcm1480_draminit_smalldelay(uint64_t clks){ __asm __volatile (" move $9,%0 ; " " mtc0 $0,$9 ; " "1: mfc0 $8,$9 ; " " .set push ; .set mips64 ; ssnop ; ssnop ; .set pop ;" " blt $8,$9,1b ;" :: "r"(clks));}#endif/* ********************************************************************* * MAKEDRAMMASK(dest,width,pos) * * Create a 64-bit mask for the DRAM config registers * * Input parameters: * width - number of '1' bits to set * pos - position (from the right) of the first '1' bit * * Return value: * mask with specified with at specified position ********************************************************************* */#define MAKEDRAMMASK(width,pos) _SB_MAKEMASK(width,pos)/* ********************************************************************* * BCM1480_JEDEC_DDR2_INITCMDS * * Issue the sequence of DRAM init commands (JEDEC DDR2) * * Input parameters: * mcnum - memory controller index (0/1/2/3) * mc - pointer to data for this memory controller * csel - which chip select to send init commands for * lmbank - for largemem systems, the cs qualifiers to be * output on CS[2:3] * tdata - chip select to use as a template for timing data * * Return value: * nothing ********************************************************************* */static void bcm1480_jedec_ddr2_initcmds(int mcnum,mcdata_t *mc,unsigned int csel, int lmbank,csdata_t *tdata){ uint64_t csmask; sbport_t cmd; sbport_t mode; uint64_t modebits; uint64_t casbits; uint64_t wrbits; uint64_t clk_ratio; uint64_t plldiv; uint64_t ns400; /* clkratio = number of core clocks per mclk */ cmd = (sbport_t) PHYS_TO_K1(A_BCM1480_MC_REGISTER(mcnum,R_BCM1480_MC_MCLK_CFG)); clk_ratio = G_BCM1480_MC_CLK_RATIO(READCSR(cmd));#if defined(_FUNCSIM_) plldiv = 16;#else plldiv = G_BCM1480_SYS_PLL_DIV(READCSR(PHYS_TO_K1(A_SCD_SYSTEM_CFG)));#endif if (plldiv == 0) { plldiv = 6; } /* * During the init sequence we'll need to delay 400ns (or thereabouts). * Calculate this from the system PLL setting * * Freq(MHz) = reference_clock * plldiv / 2 * * Now figure out how much 400ns is. Since MHz is the same units as uSec, * multiply by 1000 first. * * 400ns = (400 * 1000) / Freq(Mhz) */ ns400 = (400 * 1000) / (BCM1480_REFCLK * plldiv / 2); csmask = csel << S_BCM1480_MC_CS0; /* move mask to right place */ if (mc->flags & MCFLG_BIGMEM) { /* * so that the banks will all get their precharge signals, * put the CS qualifiers out on CS[2:3]. */ csmask |= (uint64_t)(lmbank << 6); } cmd = (sbport_t) PHYS_TO_K1(A_BCM1480_MC_REGISTER(mcnum,R_BCM1480_MC_DRAMCMD)); mode = (sbport_t) PHYS_TO_K1(A_BCM1480_MC_REGISTER(mcnum,R_BCM1480_MC_DRAMMODE)); /* * Using the data in the timing template, figure out which * CAS latency command to issue. Only whole CAS lat for DDR2. */ casbits = 0; if (mc->chantype == MC_64BIT_CHAN) { /* Use 4-byte bursts for 64-bit channels */ switch (tdata->flags & CS_CASLAT_MASK) { case CS_CASLAT_40: casbits = V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_CAS4); break; default: case CS_CASLAT_30: casbits = V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_CAS3); break; case CS_CASLAT_20: casbits = V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_CAS2); break; } } else if (mc->chantype == MC_32BIT_CHAN) { /* Use 8-byte bursts for 32-bit channels */ switch (tdata->flags & CS_CASLAT_MASK) { case CS_CASLAT_40: casbits = V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_CAS4_BL8); default: case CS_CASLAT_30: casbits = V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_CAS3_BL8); break; case CS_CASLAT_20: casbits = V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_CAS2_BL8); break; } } switch (mc->tWR) { case 4: wrbits = V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_WR_4); break; case 3: wrbits = V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_WR_3); break; case 2: default: wrbits = V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_WR_2); break; } /* * Set up for doing mode register writes to the SDRAMs * * First time, we set bit 8 to reset the DLL on MR * * Enable DLL on EMR */ modebits = V_BCM1480_MC_EMODE(JEDEC_SDRAM_EMRVAL) | V_BCM1480_MC_EMODE(JEDEC_SDRAM_EMRVAL_DQS_DISABLE) | V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_RESETDLL); /* * Bring the "bcm1480_draminit_smalldelay" routine into the ICache to * prevent the refresh from interfering between power-down-clear and * precharge. */ bcm1480_draminit_smalldelay(1); /* * Remember to set the "ganged" bit properly if in 64-bit mode. * Also, set the page policy here. */ WRITECSR(mode,modebits | casbits | mc->modebits | wrbits); WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_CLRPWRDN); /* * Wait 400ns. */ bcm1480_draminit_smalldelay(ns400); WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_PRE); /* * Also need to load EMR(2) and EMR(3). Currently no support on 1480 pass1 */ WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_EMRS); WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_MRS); bcm1480_draminit_smalldelay(ns400); WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_PRE); WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_AR); WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_AR); /* * This time, clear bit 8 to start the DLL */ modebits = V_BCM1480_MC_EMODE(JEDEC_SDRAM_EMRVAL) | V_BCM1480_MC_MODE_DEFAULT; WRITECSR(mode,modebits | casbits | mc->modebits | wrbits); WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_MRS); /* * Enable OCD default by setting bits 7,8,and 9 on EMR. */ modebits = V_BCM1480_MC_EMODE(JEDEC_SDRAM_EMRVAL_OCD_DEFAULT) | V_BCM1480_MC_EMODE(JEDEC_SDRAM_EMRVAL_DQS_DISABLE); WRITECSR(mode,modebits | casbits | mc->modebits | wrbits); WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_EMRS); /* * Enable OCD exit by clearing bits 7,8,and 9 on EMR. */ modebits = V_BCM1480_MC_EMODE(JEDEC_SDRAM_EMRVAL) | V_BCM1480_MC_EMODE(JEDEC_SDRAM_EMRVAL_DQS_DISABLE); WRITECSR(mode,modebits | casbits | mc->modebits | wrbits); WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_EMRS); } /* ********************************************************************* * BCM1480_JEDEC_INITCMDS * * Issue the sequence of DRAM init commands (JEDEC SDRAMs) * * Input parameters: * mcnum - memory controller index (0/1/2/3) * mc - pointer to data for this memory controller * csel - which chip select to send init commands for * lmbank - for largemem systems, the cs qualifiers to be * output on CS[2:3] * tdata - chip select to use as a template for timing data * * Return value: * nothing ********************************************************************* */static void bcm1480_jedec_initcmds(int mcnum,mcdata_t *mc,unsigned int csel, int lmbank,csdata_t *tdata){ uint64_t csmask; sbport_t cmd; sbport_t mode; uint64_t modebits; uint64_t casbits; uint64_t clk_ratio; uint64_t plldiv; uint64_t ns400; /* clkratio = number of core clocks per mclk */ cmd = (sbport_t) PHYS_TO_K1(A_BCM1480_MC_REGISTER(mcnum,R_BCM1480_MC_MCLK_CFG)); clk_ratio = G_BCM1480_MC_CLK_RATIO(READCSR(cmd));#if defined(_FUNCSIM_) plldiv = 16;#else plldiv = G_BCM1480_SYS_PLL_DIV(READCSR(PHYS_TO_K1(A_SCD_SYSTEM_CFG)));#endif if (plldiv == 0) { plldiv = 6; } /* * During the init sequence we'll need to delay 400ns (or thereabouts). * Calculate this from the system PLL setting * * Freq(MHz) = reference_clock * plldiv / 2 * * Now figure out how much 400ns is. Since MHz is the same units as uSec, * multiply by 1000 first. * * 400ns = (400 * 1000) / Freq(Mhz) */ ns400 = (400 * 1000) / (BCM1480_REFCLK * plldiv / 2); csmask = csel << S_BCM1480_MC_CS0; /* move mask to right place */ if (mc->flags & MCFLG_BIGMEM) { /* * so that the banks will all get their precharge signals, * put the CS qualifier
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -