#include "r_typedefs.h"
#include "dr7f701401.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;
    /*    uint32_t u32size;
        uint32_t *p = 0;*/
    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 ];

        /*        p = 0x4000000ul;
                for (u32size = 0ul; u32size < 4000000ul; u32size++)
                {
                    *p = 0ul;
                    p++;
                }*/
    }
}

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