#include <NXP/iolpc3130.h>
#include "drv_cgu.h"

/*90MHz SDRAM Clock*/
#define SDRAM_BASE_ADDR       0x30000000
#define SDRAM_PERIOD          11.1 /*ns*/

#define P2C(Period)           (((Period<SDRAM_PERIOD)?0:(Int32U)((Flo32)Period/SDRAM_PERIOD))+1)

#define SDRAM_REFRESH         15625 

#define SDRAM_TRP             20      /*ns*/
#define SDRAM_TRAS            48      /*ns*/
#define SDRAM_TAPR            2       /*ns*/
#define SDRAM_TWR             15      /*ns*/
#define SDRAM_TRC             72      /*ns*/
#define SDRAM_TRFC            80      /*ns*/
#define SDRAM_TXSR            80      /*ns*/
#define SDRAM_TDAL            5       /*Clocks*/
#define SDRAM_TRRD            2       /*Clocks*/
#define SDRAM_TMRD            2       /*Clocks*/

extern void Fubar(void);

void Dly_us(Int32U Dly) 
{
  Dly *= 6;
  Timer0Ctrl = 0;               // stop counting
  Timer0Load =  Dly;            // load period
  Timer0Clear = 0;              // clear timer pending interrupt
  Timer0Ctrl_bit.Enable = 1;    // enable counting
  while(Timer0Value <= Dly);
  Timer0Ctrl_bit.Enable = 0;     // stop counting
}

void InitSDRAM(void) 
{
  /*Select EBI/MPMC pins*/
  SYSCREG_MUX_LCD_EBI_SEL_bit.Mux_LCD_EBI_sel = 1;
  /*Enalbe EBI Clock*/
  CGU_Run_Clock(EBI_CLK);
  /*Enable MPMC clocks*/
  CGU_Run_Clock(MPMC_CFG_CLK);  
  CGU_Run_Clock(MPMC_CFG_CLK2);
  CGU_Run_Clock(MPMC_CFG_CLK3);
  Fubar();
  /*Enable TMR0 Clock. Used for SDRAM timing*/
  CGU_Run_Clock(TIMER0_PCLK);
  /*Enable MPMC */
  MPMCControl = 1;
  /*HCLK to MPMC_CLK ratio 1:1*/
  MPMCConfig_bit.CLK = 0;
  /*Set commad, address, and data delay */
  SYSCREG_MPMP_DELAYMODES_bit.MPMC_delaymodes0 = 0x24;
  /*Set data read delay*/
  SYSCREG_MPMP_DELAYMODES_bit.MPMC_delaymodes1 = 0x20;  
  /**/
  SYSCREG_MPMP_DELAYMODES_bit.MPMC_delaymodes2 = 0x00;  
  /*Command Delayed strategy*/
  MPMCDynamicReadConfig_bit.RD = 1;
  /*Memory Device type SDRAM*/
  MPMCDynamicConfig0_bit.MD = 0;
  /*512Mb (32Mx16), 4 banks, row length = 13, column length = 9*/
  MPMCDynamicConfig0_bit.AM = 0x0D;
  /*Buffer Disable*/
  MPMCDynamicConfig0_bit.B = 0x0;
  /*writes not protected*/
  MPMCDynamicConfig0_bit.P = 0x0;
  /*Configure RAS latency*/
  MPMCDynamicRasCas0_bit.RAS = 2;
  /*Configure CAS latency*/
  MPMCDynamicRasCas0_bit.CAS = 2;
  
  MPMCDynamictRP = P2C(SDRAM_TRP);
  MPMCDynamictRAS = P2C(SDRAM_TRAS);
  MPMCDynamictSREX = P2C(SDRAM_TXSR);
  MPMCDynamictAPR = SDRAM_TAPR;
  MPMCDynamictDAL = SDRAM_TDAL+P2C(SDRAM_TRP);
  MPMCDynamictWR = SDRAM_TWR;
  MPMCDynamictRC = P2C(SDRAM_TRC);
  MPMCDynamictRFC = P2C(SDRAM_TRFC);
  MPMCDynamictXSR = P2C(SDRAM_TXSR);
  MPMCDynamictRRD = SDRAM_TRRD;
  MPMCDynamictMRD = SDRAM_TMRD; 
  /* JEDEC General SDRAM Initialization Sequence
   DELAY to allow power and clocks to stabilize ~100 us
   NOP*/
  Dly_us(100);
  
  MPMCDynamicControl = 0x4183;

  Dly_us(200);
  // PALL
  MPMCDynamicControl_bit.I = 2;
  
  MPMCDynamicRefresh = 1;
  
  Dly_us(250);
  
  MPMCDynamicRefresh = P2C(SDRAM_REFRESH) >> 4;
  // COMM
  MPMCDynamicControl_bit.I = 1;
  // Burst 8, Sequential, CAS-2
  volatile unsigned long Dummy = *(volatile unsigned int *)(SDRAM_BASE_ADDR | (0x23UL << 12));
  // NORM
  MPMCDynamicControl = 0x4000;
  MPMCDynamicConfig0_bit.B = 1;
}
