示例#1
0
文件: sdr_sdram.c 项目: sobczyk/bsp
/***********************************************************************
 *
 * 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);
}
示例#2
0
/***********************************************************************
 *
 * 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;
}