/*********************************************************************** * * Function: sdr_sdram_setup * * Purpose: Setup SDRAM * * Processing: * See function. * * Parameters: * clk : Base SDRAM controller clock rate * lp : Low power SDRAM flag * * Outputs: None * * Returns: Nothing * * Notes: None * **********************************************************************/ void sdr_sdram_setup(UNS_32 clk, int lp) { volatile UNS_32 tmp32; UNS_32 tmp; /* Enables SDR clocking mode, (7*0.25nS) HCLK delay Tests of HCLK delay have shown that voltage and frequency are not driving factors for it's timing. Over testing, a working value of 3 to 27 (average) appears to work and not effect other operation. For this value, a hardcoded value of 7 is used. */ CLKPWR->clkpwr_sdramclk_ctrl = CLKPWR_SDRCLK_HCLK_DLY(7); /* Setup slew rates */ #ifdef SDRAM_USE_SLOW_SLEW CLKPWR->clkpwr_sdramclk_ctrl |= (CLKPWR_SDRCLK_SLOWSLEW_CLK | CLKPWR_SDRCLK_SLOWSLEW | CLKPWR_SDRCLK_SLOWSLEW_DAT); #else CLKPWR->clkpwr_sdramclk_ctrl &= ~(CLKPWR_SDRCLK_SLOWSLEW_CLK | CLKPWR_SDRCLK_SLOWSLEW | CLKPWR_SDRCLK_SLOWSLEW_DAT); #endif tmp = sdram_find_config(); if (!tmp) { /* Nothing matches, exit, DRAM won't work */ return; } /* Setup address mapping, its ok to use low power SDRAM mode with standard SDRAM devices */ EMC->emcdynamicconfig0 = (tmp << 7) | EMC_DYN_DEV_LP_SDR_SDRAM; /* Setup CAS and RAS latencies */ EMC->emcdynamicrascas0 = EMC_SET_CAS_IN_HALF_CYCLES(SDRAM_CAS_LATENCY) | EMC_SET_RAS_IN_CYCLES(SDRAM_RAS_LATENCY); #ifdef USE_DUAL_SDRAM_DEVICES /* DYCS1 chip select */ EMC->emcdynamicconfig1 = (tmp << 7) | EMC_DYN_DEV_LP_SDR_SDRAM; EMC->emcdynamicrascas1 = EMC_SET_CAS_IN_HALF_CYCLES(SDRAM_CAS_LATENCY) | EMC_SET_RAS_IN_CYCLES(SDRAM_RAS_LATENCY); #endif /* Setup SDRAM read strategy */ EMC->emcdynamicreadconfig = (EMC_SDR_CLK_NODLY_CMD_DEL | EMC_SDR_READCAP_POS_POL); /* Setup SDRAM timing for current HCLK clock settings */ sdram_adjust_timing(clk); /* Enable clocks and delay for at least 100uS to stabilize */ tmp = (EMC_DYN_CLK_ALWAYS_ON | EMC_DYN_CLKEN_ALWAYS_ON | EMC_DYN_DIS_INV_MEMCLK); EMC->emcdynamiccontrol = (tmp | EMC_DYN_NOP_MODE); timer_wait_us(TIMER_CNTR0, 100); /* Issue a precharge all command */ EMC->emcdynamiccontrol = (tmp | EMC_DYN_PALL_MODE); EMC->emcdynamicrefresh = EMC_DYN_REFRESH_IVAL(4); timer_wait_us(TIMER_CNTR0, 10); /* Fast dynamic refresh for at least a few SDRAM clock cycles */ timer_wait_us(TIMER_CNTR0, 10); /* Normal refresh timing */ EMC->emcdynamicrefresh = EMC_DYN_REFRESH_IVAL(clk / SDRAM_RFSH_INTERVAL); /* Issue load mode command and normal mode word */ EMC->emcdynamiccontrol = (tmp | EMC_DYN_CMD_MODE); tmp32 = * (volatile UNS_32 *) (EMC_DYCS0_BASE + (SDRAM_MODE_WORD << modeshift)); #ifdef ENABLE_DEBUG modeaddr = EMC_DYCS0_BASE + (SDRAM_MODE_WORD << modeshift); #endif timer_wait_us(TIMER_CNTR0, 1); /* Only mobile (low power) SDRAMs use the extended mode word */ if (lp) { tmp32 = * (volatile UNS_32 *) (EMC_DYCS0_BASE + SDRAM_EXT_MODE_BB + (SDRAM_EXT_MODE_WORD << modeshift)); #ifdef ENABLE_DEBUG extmodeaddr = EMC_DYCS0_BASE + SDRAM_EXT_MODE_BB + (SDRAM_EXT_MODE_WORD << modeshift); #endif timer_wait_us(TIMER_CNTR0, 1); } #ifdef USE_DUAL_SDRAM_DEVICES /* Configuration for other chip select */ tmp32 = * (volatile UNS_32 *) (EMC_DYCS1_BASE + (SDRAM_MODE_WORD << modeshift)); timer_wait_us(TIMER_CNTR0, 1); if (lp) { tmp32 = * (volatile UNS_32 *) (EMC_DYCS1_BASE + SDRAM_EXT_MODE_BB + (SDRAM_EXT_MODE_WORD << modeshift)); timer_wait_us(TIMER_CNTR0, 1); } #endif /* Normal SDRAM mode */ EMC->emcdynamiccontrol = EMC_DYN_NORMAL_MODE | EMC_DYN_DIS_INV_MEMCLK | EMC_DYN_DIS_MEMCLK_IN_SFRSH; timer_wait_us(TIMER_CNTR0, 1); }
/*********************************************************************** * * Function: ddr_sdram_lp_setup * * Purpose: Setup and calibrate DDR * * Processing: * See function. * * Parameters: * clk : Base SDRAM controller clock rate * * Outputs: None * * Returns: Nothing * * Notes: None * **********************************************************************/ void ddr_sdram_lp_setup(UNS_32 clk) { UNS_32 tmp; volatile UNS_32 tmp16; /* Enables DDR clocking mode, (15*0.25nS) HCLK delay Tests of HCLK delay have shown that voltage and frequency are not driving factors for it's timing. Over testing, a working value of 3 to 27 (average) appears to work and not effect other operation. For this value, a hardcoded value of 15 is used. */ CLKPWR->clkpwr_sdramclk_ctrl = CLKPWR_SDRCLK_USE_DDR; CLKPWR->clkpwr_sdramclk_ctrl = CLKPWR_SDRCLK_USE_DDR | CLKPWR_SDRCLK_HCLK_DLY(15); /* 16-bit interface for DDR memory. There's no point in using a 32-bit interface, as several high data lines are used for DDR control signals, but this is optional */ EMC->emcstatic_regs[0].emcstaticconfig = EMC->emcstatic_regs[1].emcstaticconfig = (EMC_STC_MEMWIDTH_16 | EMC_STC_BLS_EN_BIT); tmp = sdram_find_config(); if (!tmp) { /* Nothing matches, exit, DRAM won't work */ return; } /* Setup DDR interface */ ddr_if_init(tmp); /* Setup interface timing */ sdram_adjust_timing(clk); /* Issue NOP with Clock enables active */ tmp = (EMC_DYN_CLK_ALWAYS_ON | EMC_DYN_CLKEN_ALWAYS_ON); EMC->emcdynamiccontrol = (tmp | EMC_DYN_NOP_MODE); timer_wait_us(TIMER_CNTR0, 200); /* Issue a precharge all command */ EMC->emcdynamiccontrol = (tmp | EMC_DYN_PALL_MODE); /* Fast dynamic refresh */ EMC->emcdynamicrefresh = EMC_DYN_REFRESH_IVAL(4); timer_wait_us(TIMER_CNTR0, 10); /* Compute nominal refresh period of DDR for current clock */ EMC->emcdynamicrefresh = EMC_DYN_REFRESH_IVAL(clk / SDRAM_RFSH_INTERVAL); /* Issue load mode command and normal mode word */ EMC->emcdynamiccontrol = (tmp | EMC_DYN_CMD_MODE); tmp16 = * (volatile UNS_16 *) (EMC_DYCS0_BASE + (SDRAM_MODE_WORD << modeshift)); #ifdef ENABLE_DEBUG modeaddr = EMC_DYCS0_BASE + (SDRAM_MODE_WORD << modeshift); #endif timer_wait_us(TIMER_CNTR0, 1); /* Issue extended mode word */ tmp16 = * (volatile UNS_16 *) (EMC_DYCS0_BASE + (SDRAM_EXT_MODE_WORD << modeshift) + SDRAM_EXT_MODE_BB); #ifdef ENABLE_DEBUG extmodeaddr = EMC_DYCS0_BASE + SDRAM_EXT_MODE_BB + (SDRAM_EXT_MODE_WORD << modeshift); #endif timer_wait_us(TIMER_CNTR0, 1); #ifdef USE_DUAL_SDRAM_DEVICES /* Also do this for SDRAM chip select 1 if devices are present */ tmp16 = * (volatile UNS_16 *) (EMC_DYCS1_BASE + (SDRAM_MODE_WORD << modeshift)); timer_wait_us(TIMER_CNTR0, 1); tmp16 = * (volatile UNS_16 *) (EMC_DYCS1_BASE + (SDRAM_EXT_MODE_WORD << modeshift) + SDRAM_EXT_MODE_BB); timer_wait_us(TIMER_CNTR0, 1); #endif /* Normal DDR mode */ EMC->emcdynamiccontrol = EMC_DYN_NORMAL_MODE | EMC_DYN_DIS_MEMCLK_IN_SFRSH; timer_wait_us(TIMER_CNTR0, 10); /* Find optimal DQSin delay and calibration sensitivity, tested over DRAM bank 0 with a size of 64MBytes */ ddr_find_dqsin_delay(EMC_DYCS0_BASE, SDRAM_SIZE); /* Enable automatic calibration */ CLKPWR->clkpwr_sdramclk_ctrl |= CLKPWR_SDRCLK_USE_CAL; }