/*====================================< sdram.c >==============================*/
//
// Functions for configuring SDRAM memory on RMS101 SBC.  Code is based on
// library functions from Sharp SMA.
//
// Last modifed date: 01 May 2003 10:24:57
//
// 08-11-02 JAG 
//
/*===========================================================================*/

#include <regs.h>
#include <stddefs.h>
#include <sdram.h>

/*-------------------------------< Defines >---------------------------------*/
// M&I Bit fields
#define SDRAM_INIT_NOP	0x03
#define SDRAM_INIT_MODE	0x02
#define SDRAM_INIT_PALL 0x01
#define SDRAM_INIT_NORMAL 0x0c
// Other bit fields
#define SDRAM_STATUS	0x20


/*-----------------------< Local Function Prototypes >-----------------------*/
static void Memtimer (WORD wDuration);


/*===========================< Unit Functions >==============================*/

// Description of SDRAM setup from Sharp EVB code follows

/**********************************************************************
 * Function: LH79520_init_sdram (unsigned int clock_idx)
 *
 * Purpose: To initialize LH79520 EVB implementation specific SDRAM
 *
 * Description:
 *
 * Two external banks:  Micron MC48LC8M16A2TG 8Mb x 16 SDRAM chips
 *
 *  Two 8Mb x 16 SDRAM chips per bank (16MByte)
 * 
 * 	nCS1 - 16MB at 0x20000000 (SDRAM_BANK0_BASE)
 * 	nCS2 - 16MB at 0x28000000 (SDRAM_BANK1_BASE)
 *
 *  Typical SDRAM controller sequence from SDRAMC TRM (PL170 DDI0159C):
 *
 *    1. Wait 100ms to allow SDRAMs power and clocks to
 *    stabilize.
 *
 *    2. Set the I and M bits. This automatically issues a
 *    NOP to the SDRAMs.
 *
 *    3. Wait 200ms.
 *
 *    4. Reset the M bit (I = 1, M = 0). This automatically
 *    issues a PRE-ALL to the SDRAMs.
 *
 *    5. Write 10 into the refresh timer register. This provides
 *    a refresh cycle every 10 clock cycles.
 *
 *    6. Wait for a time period equivalent to 80 clock cycles
 *    (8 refresh cycles).
 *
 *    7. Program the operational value into the refresh timer.
 *
 *    8. Select command write mode (I = 0, M = 1) and perform a
 *    read from each SDRAM connected to the controller. Address
 *    lines HADDR[26:11] encode the value output on the SDRAM
 *    address lines AddrOut[14:0]. See the SDRAM data sheet
 *    for the bit pattern programmed onto AddrOut[14:0],
 *    for the required operational mode.
 *
 *    9. Program configuration register 0.
 *
 *    Note: Parameters programmed into the SDRAMs, such as
 *    burst length, RAS and CAS delays, must be consistent with
 *    the values written to configuration register 0.  For X=0
 *    (x32 data path), use incremental burst length 4. For X=1
 *    (x16 data path), use incremental burst length 8.
 *
 *    10. Clear the M and I bits and set the other bits in
 *    configuration register 1 to their normal operational
 *    values.
 *
 *    11. The SDRAM is now ready for normal operation.
 *
 *
 *  Micron Initialization Sequence from their data sheet
 *  for the Micron MC48LC8M16A2TG 8Mb x 16 SDRAM chip:
 *
 *    Initialization
 *
 *    SDRAMs must be powered up and initialized in a
 *    predefined manner. Operational procedures other than
 *    those specified may result in undefined operation. Once
 *    power is applied to VDD and VDDQ (simultaneously) and
 *    the clock is stable (stable clock is defined as a signal
 *    cycling within timing constraints specified for the clock
 *    pin), the SDRAM requires a 100µs delay prior to issuing
 *    any command other than a COMMAND INHIBIT or NOP.
 *
 *    Starting at some point during this 100µs period and
 *    continuing at least through the end of this period,
 *    COMMAND INHIBIT or NOP commands should be applied.
 *    Once the 100µs delay has been satisfied with at least
 *    one COMMAND INHIBIT or NOP command having been applied,
 *    a PRECHARGE command should be applied. All banks must
 *    then be precharged, thereby placing the device in the
 *    all banks idle state.
 *
 *    Once in the idle state, two AUTO REFRESH cycles
 *    must be performed. After the AUTO REFRESH cycles are
 *    complete, the SDRAM is ready for mode register programming.
 *
 *    Because the mode register will power up in an
 *    unknown state, it should be loaded prior to applying any
 *    operational command.
 *
 *****  The JEDEC recommendation for initializing SDRAM is:
 *
 *    APPLY POWER (Vdd/Vddq equally, and CLK is stable)
 *    Wait 200uS
 *		PRECHARGE all
 *		8 AUTO REFRESH COMMANDS
 *		LOAD MODE REGISTER
 *		SDRAM is ready for operation
 *
 *****  The Micron SDRAM parts will work fine with the JEDEC sequence,
 *      but also allow for a quicker init sequence of:
 *	APPLY POWER (Vdd/Vddq equally, and CLK is stable)
 *	Wait at least 100uS (during which time start applying and continue
 *			applying NOP or COMMAND INHIBIT)
 *	PRECHARGE all
 *	2 AUTO REFRESH COMMANDS (min requirement, more than 2 is also ok)
 *	LOAD MODE REGISTER
 *	SDRAM is ready for operation
 *
 * Note, the order of the AUTO REFRESH commands and LOAD MODE REGISTER
 * can be reversed if preferred.
 **********************************************************************/

/*-------------------------------< InitSDRAM >-------------------------------*/
void InitSDRAM(void)
{
   volatile WORD tmp; 

	// Assign necessary I/Os to SDRC
   MEMMUX |= 0x00ff;		
   
   // Enable HCLK feed to SDRC
   AHBCLKCTRL &= 0xfffffffd;
   
   Memtimer (200);
 
	SDRCCONFIG1 = SDRAM_INIT_NOP;
	SDRCCONFIG1 = SDRAM_INIT_NOP;

	/*	DELAY   to allow sdram clocks to settle */
	/* load ~200us value to timer1 */
   Memtimer (200);

	/* issue a "pre-charge all" command */
	SDRCCONFIG1 = SDRAM_INIT_PALL;

	/* load ~250us value to timer1 */
   Memtimer (250);

	/* refresh every 16 clock cycles */
	SDRCREFTIMER = 16;
	
	/* DELAY   for at least two auto refresh cycles */
	/* load ~250us value to timer1 */
   Memtimer (250);

	/* set the refresh timer */
	/* Assumes 52 MHz default clock and 16us refresh period */
	SDRCREFTIMER = 800;
	
	/* load ~250us value to timer1 */
   Memtimer (250);

	/* Program the SDRAM internal mode registers on bank nSDCS0-1
	 * Burst Length - 4  (A2:A0 = 0b010)
	 * Burst Type - Sequential (A3 = 0)
	 * CAS Latency - 2 (A6:A4 = 0x010)
	 * Operating Mode - Standard (A8:A7 = 0)
	 * Write Burst Mode - Programmed Burst Length (A9 = 0)
	 */

	/* Select mode register update mode */  
	SDRCCONFIG1 = SDRAM_INIT_MODE;

	tmp = *((volatile int *)(SDRAM_BASE + ((unsigned int) 0x22 << 12)));
  
	/* Wait until idle */
   while (SDRCCONFIG1 & SDRAM_STATUS);

	/*  Configure SDRAM Controller Configuration Register 0 */
	SDRCCONFIG0 = 0x01a40088;		// Latency = 2, 32 bits, 4 banks
	
	/* Wait until idle */
   while (SDRCCONFIG1 & SDRAM_STATUS);

	/* select normal operating mode */
	SDRCCONFIG1 = SDRAM_INIT_NORMAL;

	/* Wait until idle */
   while (SDRCCONFIG1 & SDRAM_STATUS);

	/* Wait ~100 us before using */ 
   Memtimer (128);
}


/*============================< Local Functions >============================*/

/*--------------------------------< Memtimer >-------------------------------*/
// Crude delay timer for sdram initialization.  Extra delay won't matter.
static void Memtimer (WORD wDuration)
{
	volatile WORD wTemp, wTime;
	
	for (wTime=0; wTime < wDuration; wTime++)
	{
		for (wTemp=0 ; wTemp < 500; wTemp++);
	}
}

// end of sdram.c
