#include "r_typedefs.h"
#include "dr7f701441.dvf.h"
#include "rh850_macros.h"
#include "SDRAM.h"


typedef struct
{
    uint32_t u32DBCONF;     /* SDRAM Address Configuration */
    uint32_t u32DBTR0;      /* SDRAM Timing Configuration (1) */
    uint32_t u32DBTR1;      /* SDRAM Timing Configuration (2) */
    uint32_t u32DBTR2;      /* SDRAM Timing Configuration (3) */
    uint32_t u32DBRFPDN1;   /* Refresh time: (tREF_AT*fRAM/nROWS) - SSCG_factor */
    uint32_t u32DBRFPDN2;   /* Idle- and Busy-thresholds */
    uint32_t u32ModeReg;    /* Mode Register */
}Mem_SDRAM_Cfg_st_t;





static const uint32_t g_u32MemSDRAMDrvStrConf[4] = 
{
   /* Mem_SDRAM_DRV_25Ohm  */  0x00000000UL,
   /* Mem_SDRAM_DRV_33Ohm  */  0x00001554UL,
   /* Mem_SDRAM_DRV_50Ohm  */  0x00002AA8UL,
   /* Mem_SDRAM_DRV_100Ohm */  0x00003FFCUL,
};

static const Mem_SDRAM_Cfg_st_t g_stMemSDRAMProfileList[] =
{
    /* MEM_SDRAM_2x_MT48LC16M16A2P_120MHz */
    {
        /* u32DBCONF   -- SDRAM Address Configuration */
        ((0x011AUL << 16U) |  /* - SPLIT[8:0]  = 1 0001 1010 = 0x011A */
         (   0x0UL << 14U) |  /* - BKADM[1:0]  = 00, Consecutive addresses */
         (  0x0CUL <<  8U) |  /* - BKADP[5:0]  = 00 1100, BA0 set to address 12 */
         (  0x00UL <<  2U) |  /* - BKADB[5:0]  = 00 0000, Ineffective when BKM[1:0] = 00 */
         (  0x02UL <<  0U)),  /* - BWIDTH[1:0] = 10, 32 bit bus */
         
        /* u32DBTR0    -- SDRAM Timing Configuration (1) */
        ((     2UL << 24U) |  /* - CL   = 2 clk */
         (     4UL << 16U) |  /* - tRAS = 5 clk       (42ns / 8.33ns = 5.04clk) */
         (     7UL <<  8U) |  /* - tRFC = 8 clk       (60ns / 8.33ns = 7.2clk)  */
         (     1UL <<  0U)),  /* - tRCD = 2 clk       (18ns / 8.33ns = 2.16clk) */
         
        /* u32DBTR1    -- SDRAM Timing Configuration (2) */
        ((     0UL << 24U) |  /* - CKEH = 1 clk */
         (     1UL << 16U) |  /* - tRP  = 2 clk       (18ns) */
         (     1UL <<  8U) |  /* - tRRD = 2 clk       (12ns) */
         (     2UL <<  0U)),  /* - tWR  = 2 clk       (1 clk + 6ns) */
         
        /* u32DBTR2    -- SDRAM Timing Configuration (3) */
        ((     1UL << 24U) |  /* - tRTP = 2 clk */
         (     5UL << 16U) |  /* - tRC  = 6 clk       (60ns) */
         (     5UL <<  8U) |  /* - RDWR = 6 clk       (BL = Burst Length + CL = CAS Latency + 1)  Would be 7 acc to formula. Hand optimised. */
         (     4UL <<  0U)),  /* - WRRD = 5 clk       (BL = Burst Length + 1) */
         
        /* u32DBRFPDN1 -- Refresh time */
        ((0x00EAUL <<  0U)),  /* - TREFI = (tREF_AT *   fRAM /    nROWS) - SSCG_factor
                                         = (   16ms * 120MHz / 8192rows) - 0%SSCG = 0xEA
                                   SSCG is downspread only, so there is no correction needed */
                                   
        /* u32DBRFPDN2 -- Idle- and Busy-thresholds */
        ((0x0555UL << 16U) |  /* - LV1TH: tREFI  <= LV1TH <= tREFI x 9 */
         ( 0x02DUL <<  0U)),  /* - LV0TH: LV0TH =  (tRP + tRCD + tWR + 3) x 5 = 45 = 0x02D */ 
         
        /* u32ModeReg  -- Mode Register (Data field refer to DBMRCNT register and SDRAM datasheet) */
        ((   0x0UL << 16U) |  /* - BA[1:0] = 00 */
         (   0x0UL << 10U) |  /* - Rsvd    = 000 */
         (   0x0UL <<  9U) |  /* - WB      = 0, Programmed Burst Length */
         (   0x0UL <<  7U) |  /* - OP Mode = 00, Standard Operation */
         (   0x2UL <<  4U) |  /* - Latency = 010, CAS Latency = 2 */
         (   0x0UL <<  3U) |  /* - BT      = 0, Burst Type = Sequential */
         (   0x2UL <<  0U)),  /* - BL      = 010, Burst Length = 4 */
    },
    
    /* MEM_SDRAM_2x_IS45S16800F_120MHz */
    {
        /* u32DBCONF   -- SDRAM Address Configuration */
        ((0x0112UL << 16U) |  /* - SPLIT[8:0]  = 1 0001 0010 = 0x0112 */
         (   0x0UL << 14U) |  /* - BKADM[1:0]  = 00, Consecutive addresses */
         (  0x00UL <<  8U) |  /* - BKADP[5:0]  = 00 0000, BA0 set to address 12 */
         (  0x00UL <<  2U) |  /* - BKADB[5:0]  = 00 0000, Ineffective when BKM[1:0] = 00 */
         (  0x02UL <<  0U)),  /* - BWIDTH[1:0] = 10, 32 bit bus */
         
        /* u32DBTR0    -- SDRAM Timing Configuration (1) */
        ((     3UL << 24U) |  /* - CL   =  3 clk */
         (     6UL << 16U) |  /* - tRAS =  7 clk */
         (     9UL <<  8U) |  /* - tRFC = 10 clk */
         (     2UL <<  0U)),  /* - tRCD =  3 clk */
         
        /* u32DBTR1    -- SDRAM Timing Configuration (2) */
        ((     0UL << 24U) |  /* - CKEH = 1 clk */
         (     2UL << 16U) |  /* - tRP  = 3 clk */
         (     1UL <<  8U) |  /* - tRRD = 2 clk */
         (     1UL <<  0U)),  /* - tWR  = 2 clk (tDPL) */
         
        /* u32DBTR2    -- SDRAM Timing Configuration (3) */
        ((     2UL << 24U) |  /* - tRTP = 3  clk (tRQL)*/
         (     9UL << 16U) |  /* - tRC  = 10 clk */
         (     7UL <<  8U) |  /* - RDWR = 8  clk (BL = Burst Length + CL = CAS Latency + 1) */
         (     4UL <<  0U)),  /* - WRRD = 5  clk  (BL = Burst Length + 1) */
         
        /* u32DBRFPDN1 -- Refresh time */
        ((0x01D5UL <<  0U)),  /* - TREFI = (tREF_AT *   fRAM /    nROWS) - SSCG_factor
                                         = (   16ms * 120MHz / 4096rows) - 0%SSCG = 0x1D5
                                   SSCG is downspread only, so there is no correction needed */
                                   
        /* u32DBRFPDN2 -- Idle- and Busy-thresholds */
        ((0x0AAAUL << 16U) |  /* - LV1TH: tREFI  <= LV1TH <= tREFI x 9 */
         ( 0x037UL <<  0U)),  /* - LV0TH: LV0TH =  (tRP + tRCD + tWR + 3) x 5 = 55 = 0x037 */ 
         
        /* u32ModeReg  -- Mode Register (Data field refer to DBMRCNT register and SDRAM datasheet) */
        ((   0x0UL << 16U) |  /* - BA[1:0] = 00 */
         (   0x0UL << 10U) |  /* - Rsvd    = 000 */
         (   0x0UL <<  9U) |  /* - WB      = 0, Programmed Burst Length */
         (   0x0UL <<  7U) |  /* - OP Mode = 00, Standard Operation */
         (   0x3UL <<  4U) |  /* - Latency = 011, CAS Latency = 3 */
         (   0x0UL <<  3U) |  /* - BT      = 0, Burst Type = Sequential */
         (   0x2UL <<  0U)),  /* - BL      = 010, Burst Length = 4 */
    },

    /* MEM_SDRAM_2x_W9812G6KH_120MHz */
    {
        /* u32DBCONF   -- SDRAM Address Configuration */
        ((0x0112UL << 16U) |  /* - SPLIT[8:0]  = 1 0001 0010 = 0x0112 */
         (   0x0UL << 14U) |  /* - BKADM[1:0]  = 00, Consecutive addresses */
         (  0x00UL <<  8U) |  /* - BKADP[5:0]  = 00 0000, BA0 set to address 12 */
         (  0x00UL <<  2U) |  /* - BKADB[5:0]  = 00 0000, Ineffective when BKM[1:0] = 00 */
         (  0x02UL <<  0U)),  /* - BWIDTH[1:0] = 10, 32 bit bus */
         
        /* u32DBTR0    -- SDRAM Timing Configuration (1) */
        ((     2UL << 24U) |  /* - CL   =  2 clk */
         (     4UL << 16U) |  /* - tRAS =  5 clk */
         (     7UL <<  8U) |  /* - tRFC =  8 clk */
         (     1UL <<  0U)),  /* - tRCD =  2 clk */
         
        /* u32DBTR1    -- SDRAM Timing Configuration (2) */
        ((     0UL << 24U) |  /* - CKEH = 1 clk */
         (     1UL << 16U) |  /* - tRP  = 2 clk */
         (     1UL <<  8U) |  /* - tRRD = 2 clk */
         (     2UL <<  0U)),  /* - tWR  = 3 clk (tDPL) */
         
        /* u32DBTR2    -- SDRAM Timing Configuration (3) */
        ((     1UL << 24U) |  /* - tRTP = 2  clk (tRQL)*/
         (     7UL << 16U) |  /* - tRC  = 8  clk */
         (     6UL <<  8U) |  /* - RDWR = 7  clk (BL = Burst Length + CL = CAS Latency + 1) */
         (     4UL <<  0U)),  /* - WRRD = 5  clk  (BL = Burst Length + 1) */
         
        /* u32DBRFPDN1 -- Refresh time */
        ((0x00EAUL <<  0U)),  /* - TREFI = (tREF_AT *   fRAM /    nROWS) - SSCG_factor
                                         = (   16ms * 120MHz / 8192rows) - 0%SSCG = 0xEA
                                   SSCG is downspread only, so there is no correction needed */
                                   
        /* u32DBRFPDN2 -- Idle- and Busy-thresholds */
        ((0x0555UL << 16U) |  /* - LV1TH: tREFI  <= LV1TH <= tREFI x 9 */
         ( 0x032UL <<  0U)),  /* - LV0TH: LV0TH =  (tRP + tRCD + tWR + 3) x 5 = 50 = 0x032 */ 
         
        /* u32ModeReg  -- Mode Register (Data field refer to DBMRCNT register and SDRAM datasheet) */
        ((   0x0UL << 16U) |  /* - BA[1:0] = 00 */
         (   0x0UL << 10U) |  /* - Rsvd    = 000 */
         (   0x0UL <<  9U) |  /* - Wr Mode = 0, Burst read and Burst write */
         (   0x0UL <<  7U) |  /* - Rsvd    = 00 */
         (   0x2UL <<  4U) |  /* - Latency = 010, CAS Latency = 2 */
         (   0x0UL <<  3U) |  /* - BT      = 0, Burst Type = Sequential */
         (   0x2UL <<  0U)),  /* - BL      = 010, Burst Length = 4 */
    },
};

static const uint32_t g_u32MemSDRAMSizeList[] = 
{
    /* MEM_SDRAM_2x_MT48LC16M16A2P_120MHz */  64UL * 1024UL * 1024UL,
    /* MEM_SDRAM_2x_IS45S16800F_120MHz    */  32UL * 1024UL * 1024UL,
    /* MEM_SDRAM_2x_W9812G6KH_120MHz      */  32UL * 1024UL * 1024UL,
};

uint32_t g_u32MemSDRAMSize;

void Mem_SDRAM_Init(Mem_SDRAM_Profile_en_t enProfile, Mem_SDRAM_Drv_Str_en_t enDrvStr)
{
    uint32_t i;
    uint32_t u32RegVal;
    
    g_u32MemSDRAMSize = 0UL;
    if ((enProfile < 3U) && (enDrvStr < 4U))
    {
        /* Set drive strength for SDRAM related IO ports */
        u32RegVal   = SELBDSCTRL;
        u32RegVal  &= 0xFFFFC003UL;
        u32RegVal  |= g_u32MemSDRAMDrvStrConf[enDrvStr];
        SELBDSCTRL  = u32RegVal;
        
        /* Reset SDRAM  controller */
        Sys_Peripheral_Reset(SYS_PERI_SDRB0);
        
        /* Release the clock supply of PHY */
        SDRA0DBPDCNT0 = 0x23000000UL;
        SDRA0DBPDCNT0 = 0x23000001UL;
        
        /* Set CKE to high level */
        SDRA0DBCMDCNT = 0x00000003UL;
        
        /* Wait 200 us */
        for(i = 0U; i < 48000U; i++)
        {
            nop();    /* => 48000 CPU cycles x 4.167ns */
        }
        
        SDRA0DBCONF   = g_stMemSDRAMProfileList[enProfile].u32DBCONF;   /* SDRAM Address Configuration    */
        SDRA0DBTR0    = g_stMemSDRAMProfileList[enProfile].u32DBTR0;    /* SDRAM Timing Configuration (1) */
        SDRA0DBTR1    = g_stMemSDRAMProfileList[enProfile].u32DBTR1;    /* SDRAM Timing Configuration (2) */
        SDRA0DBTR2    = g_stMemSDRAMProfileList[enProfile].u32DBTR2;    /* SDRAM Timing Configuration (3) */
        
        SDRA0DBKIND   = 0x00000001UL;    /* Set SDR SDRAM operation */
        
        SDRA0DBCMDCNT = 0x00000002UL;    /* Execute "Precharge All" */
        
        /*  Wait at least tRP time (20ns) */
        for(i = 0U; i < 5U; i++)
        {
            nop();    /* => 5 CPU cycles x 4.167ns */
        }
        
        SDRA0DBCMDCNT = 0x00000004UL;    /* Execute "Refresh" */
        
        /*  Wait at least tRFC time (70ns) */
        for(i = 0U; i < 17U; i++)
        {
            nop();    /* => 17 CPU cycles x 4.167ns */
        }
        
        SDRA0DBCMDCNT = 0x00000004UL;    /* Execute "Refresh" */
        
        /*  Wait at least tRFC time (70ns) */
        for(i = 0U; i < 17U; i++)
        {
            nop();    /* => 17 CPU cycles x 4.167ns */
        }
        
        SDRA0DBMRCNT  = g_stMemSDRAMProfileList[enProfile].u32ModeReg;  /* Execute "Mode Register Set" */
        
        /*  Wait at least tMRD time (20ns) */
        for(i = 0U; i < 5U; i++)
        {
            nop();    /* => 5 CPU cycles x 4.167ns */
        }
        
        SDRA0DBEN     = 0x00000001UL;    /* Enable SDRAM data operations */
        
        SDRA0DBRFPDN1 = g_stMemSDRAMProfileList[enProfile].u32DBRFPDN1; /* Refresh time */
        SDRA0DBRFPDN2 = g_stMemSDRAMProfileList[enProfile].u32DBRFPDN2; /* Idle- and Busy- thresholds */
        SDRA0DBRFPDN0 = 0x00010000UL;   /* Enable auto refresh, disable power-down */

        g_u32MemSDRAMSize = g_u32MemSDRAMSizeList[enProfile];
    }
}

uint32_t Mem_SDRAM_Size(void)
{
    return 32UL * 1024UL * 1024UL;
    //return g_u32MemSDRAMSize;
}