#include "TYW_FLASH.h"
#include "SFMA_Driver.h"
#include "stdint.h"
#include "r_dev_api.h"
#include "r_sfma_api.h"
#include "SFMA_APP.h"
#include "Watchdog.h"
#include "GPIO.h"
#include "RTC.h"
#include "rh850_macros.h"


#define SYSPROTCMDD1                (INT32U)(0xfff87000)
#define SYSCKSC_ISFMAS_CTL          (INT32U)(0xfff85340)
#define SYSCKSC_ISFMAD_CTL          (INT32U)(0xfff85380)
#define CKSC_ISFMAS_ACT             (INT32U)(0xFFF85348)
#define CKSC_ISFMAD_ACT             (INT32U)(0xFFF85380)
#define BUSY_TIMEOUT                (INT32U)(500000ul)
#define CMNCR                       (INT8U)(0x00u)
#define SSLDR                       (INT8U)(0x04u)
#define SPBCR                       (INT8U)(0x08u)
#define CKDLY                       (INT8U)(0x50u)
#define SPODLY                      (INT8U)(0x68u)
#define CMNSR                       (INT8U)(0x48u)
#define SMCMR                       (INT8U)(0x24u)
#define SMENR                       (INT8U)(0x30u)
#define SMCR                        (INT8U)(0x20u)
#define SMRDR0                      (INT8U)(0x38u)
#define SMRDR1                      (INT8U)(0x3Cu)
#define SMWDR0                      (INT8U)(0x40u)
#define SMWDR1                      (INT8U)(0x44u)
#define DRCMR                       (INT8U)(0x10u)
#define DRENR                       (INT8U)(0x1Cu)
#define DRDMCR                      (INT8U)(0x58u)
#define DRCR                        (INT8U)(0x0cu)
#define DREAR                       (INT8U)(0x14u)
#define DRDRENR                     (INT8U)(0x5cu)
#define SMADR                       (INT8U)(0x28u)
#define SMOPR                       (INT8U)(0x2Cu)
#define SMDMCR                      (INT8U)(0x60u)
#define SMDRENR                     (INT8U)(0x64u)
#define DROPR                       (INT8U)(0x18u)






static void Flash_WaitNop(INT32U loopcount);
static void Flash_WaitNop(INT32U loopcount)
{
    uint32_t i;
	WDT_Clear();
    for (i = 0; i < loopcount; i++)
    {
	    WDT_Clear();
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
    }
}


void TYW_FLASH_PreInit(void)
{
    uint16_t WhileCnts = 0;
    r_sfma0_Error_t          ret;
    uint32_t ssldr = 0x00000000u;
    uint32_t spbcr = 0x00000100u;
    uint32_t ckdly = 0xa5040001u;
    uint32_t spodly = 0xa5000000u;
    uint32_t cmncr = 0x80005000u;
    uint32_t smenr = 0x00005000u;
    uint32_t smcmr = 0x00ff00ffu;
    uint32_t smcr  = 0x00000001u;
    uint32_t regval = 0;


    /*    ssldr   =   0x00000000ul;*/
    spbcr   =   0x00000100ul;
    ckdly   =   0xa5050001ul;
    spodly  =   0xa5000000ul;
    cmncr   =   0x80505001ul;
    smenr   =   0x00005000ul;
    smcmr   =   0x00ff00fful;
    smcr    =   0x00000001ul;

    regval = 0;
    R_DEV_WRITE_PROT_REG(SYSPROTCMDD1, SYSCKSC_ISFMAS_CTL, 0X02);/*PLL1CLK 480M  fPHCLK */
    while (0x02u != R_DEV_READ_REG(32, CKSC_ISFMAS_ACT)) {}

    R_DEV_WRITE_PROT_REG(SYSPROTCMDD1, SYSCKSC_ISFMAD_CTL, 0X03);/* 4分频率 480M/4=120M  BΦ */
    while (0x03u != R_DEV_READ_REG(32, SYSCKSC_ISFMAD_CTL)) {}

    regval = R_DEV_READ_REG(32, (0xF2FF0000ul + CMNSR));
    if (0x1u != (regval & 0x1u)) {
        RTC_Backup_Time();
        TestBackupRam = 0xaabbccddu;
        hardware_reset();
    }

    R_DEV_WRITE_REG(32, (0xF2FF0000ul + CMNCR), cmncr);
    /*    R_DEV_WRITE_REG(32, (0xF2FF0000ul + SSLDR), ssldr);*/
    R_DEV_WRITE_REG(32, (0xF2FF0000ul + SPBCR), spbcr);
    R_DEV_WRITE_REG(32, (0xF2FF0000ul + SPODLY), spodly);
    R_DEV_WRITE_REG(32, (0xF2FF0000ul + CKDLY), ckdly);

    WhileCnts = 0;
    while (0x1u != (regval & 0x1u))
    {
        if (WhileCnts++ >= 100) {
            RTC_Backup_Time();
            TestBackupRam = 0xaabbccddu;
            hardware_reset();
        }
        WDT_Clear();
        regval = R_DEV_READ_REG(32, (0xF2FF0000ul + CMNSR));
    }
}

void TYW_FLASH_DDRPreInit(SFMA_DDR_Parameter_t *DDR_Parameter)
{
    uint16_t WhileCnts = 0;
    r_sfma0_Error_t          ret;
    uint32_t ssldr  = 0x00000000u;
    uint32_t spbcr  = 0x00000100u;
    uint32_t ckdly  = 0xa5040001u;
    uint32_t spodly = 0xa5000000u;
    uint32_t cmncr  = 0x80005000u;
    uint32_t smenr  = 0x00005000u;
    uint32_t smcmr  = 0x00ff00ffu;
    uint32_t smcr   = 0x00000001u;
    uint32_t drcr   = 0ul;
    uint32_t drcmr  = 0ul;
    uint32_t drear  = 0ul;
    uint32_t dropr  = 0ul;
    uint32_t drenr  = 0ul;
    uint32_t drdmcr = 0ul;
    uint32_t drdrenr = 0ul;
    uint32_t regval = 0;
    uint32_t u32DummyCycle = 0;



    /*
    bit 31      MD       0 External address space read mode
    bit 24      SFDE     1 Swapping is performed in 8-bit units
    bit 23 22   MOIIO3   11: Output value Hi-Z
    bit 21 20   MOIIO2   11: Output value Hi-Z
    bit 19 18   MOIIO1   11: Output value Hi-Z
    bit 17 16   MOIIO0   11: Output value Hi-Z

    bit 15 14   IO3FV    11: Output value Hi-Z
    bit 13 12   IO2FV    11: Output value Hi-Z
    bit  9  8   IO0FV    11: Output value Hi-Z

    bit 6  CPHAT Data transmission starts at even edge during DDR transfer.
    bit 5  CPHAR Data transmission starts at even edge during DDR transfer.
    bit 4  SSLP   Active low SPBSSL signal
    bit 3  cpol    SPBCLK output is 0 during SPBSSL negation period.
    bit 0 1  BSZ    2 memories
    */
    cmncr       =   0x01FFF301UL;/*    CONFIRMED Fix */
    /*    ssldr       =   0x00000000ul;*/
    spbcr       =   0x00000100ul;/* CONFIRMED Fix  120M/(2*1*1)=60M */
    spodly      =   0xa5000000ul;/*    CONFIRMED Fix */
    /* fphclk/fbΦ =480/120=4  */
    /*
    stepsize = 180/4 =45°
    max step =360/45-2=6
    maxshift = 6*45=270°
     */
    ckdly       =   0xa5050000ul;/*    CONFIRMED Modify but fix */


    smcmr       =   0x00ee0000ul;/*    do not care */
    smenr       =   0x00025000ul;/*    do not care */
    smcr        =   0x00ee0000ul;/*    do not care */

    /*
    • Set the normal read or burst read operation.
    • Set the SPBSSL negation during burst read operation.
    • Set the burst length during burst read operation
     */
    /*
    bit 31-29         0  BFM Burst length depends on the access size. Further the cache is flushed at each cycle.
    BIT 24   SSLN     0  Asserted SPBSSL can be negated by writing 1 to this bit when both the RBE and SSLE bits are 1.
    bit 19-16 RBURST  F  1111: 16 continuous data units
    bit 9 RCF         1  When 1 is written to this bit, all the entries in the read cache are cleared.  This bit is always read as 0.
    bit 8 RBE         1  read cache is enabled, and as many data units as the burst count specified in RBURST[3:0] bits is read
    BIT 0 SSLE        1  SPBSSL is negated when the accessed address is not continuous with the previously transferred address
    */
    drcr        =   0x000f0301ul;/*    CONFIRMED Fix */
    /*
     • Set the command/optional command when reading
    */
    /*
    BIT 23-16 CMD       0XED
    BIT 7-0   OCMD      0X00
    */
    drcmr       =   0x00000000ul;   /*    CONFIRMED Modify */
    drcmr       |=  ((uint32_t)(DDR_Parameter->DTR_CMD)) << 16; /*    CONFIRMED Modify */

    /*
    • Set the option data when reading
     */
    dropr       =   0x00000000UL;/*    CONFIRMED Modify */
    dropr       |=   ((uint32_t)(DDR_Parameter->DTR_MF0_7)) << 24; /*    CONFIRMED Modify */
    /*
    • Enable the transfer data.
    • Set the transfer data size in bit units
    BIT 31 30 CDB       00: 1 bit
    BIT 29 28 OCDB      00: 1 bit
    BIT 25 24 ADB       10: 4 bits
    BIT 21 20 OPDB      10: 4 bits
    BIT 17 16 DRDB      10: 4 bits
    BIT 15 DME          1: Dummy cycle insertion enabled
    BIT 14 CDE          1: Command output enabled
    BIT 12 OCDE         0: Optional command output disable
    BIT 11-8 ADE        1111: Address[32:1]
    BIT 7-4 OPDE        0000: OPD3
     */
    drenr       =   0x0222CF80ul; /*    CONFIRMED Fix */
    /*
    • Set the address when the serial flash address is output in 32-bit units.
    (only when DRENR.ADE[3] = 1)
    bit 23-16 EAV  00000000
    bit 2-0   EAC  100: External address bits [28:0] enabled
     */
    drear       =   0x00000004ul;/*    CONFIRMED Fix */
    /*
    • Set the dummy cycle size in bit units.
    • Set the number of dummy cycles.
     */
    /*
    BIT 17 16 DMDB      2:  4 bits
    BIT 2-0 DMCYC     110:  7 cycles
     */
    drdmcr      =   0x00020000ul; /*    CONFIRMED Modify */
    u32DummyCycle = DDR_Parameter->DTR_DummyCycle;
    if (u32DummyCycle != 0)
    {
        u32DummyCycle = u32DummyCycle - 1;
    }
    drdmcr      |=    u32DummyCycle; /*    CONFIRMED Modify */
    /*
    bit 8 ADDRE  1: DDR transfe
    bit 4 OPDRE  1: DDR transfer
    bit 1 DRDRE  1: DDR transfer
    */
    drdrenr     =   0x00000111ul;/*    CONFIRMED FIX */

    regval = R_DEV_READ_REG(32, (0xF2FF0000ul + CMNSR));
    if (0x1u != (regval & 0x1u)) {
        RTC_Backup_Time();
        TestBackupRam = 0xaabbccddu;
        hardware_reset();
    }

    R_DEV_WRITE_REG(32, (0xF2FF0000ul + CMNCR  ), cmncr);
    /*    R_DEV_WRITE_REG(32, (0xF2FF0000ul + SSLDR  ), ssldr);*/
    R_DEV_WRITE_REG(32, (0xF2FF0000ul + SPBCR  ), spbcr);
    R_DEV_WRITE_REG(32, (0xF2FF0000ul + SPODLY ), spodly);
    R_DEV_WRITE_REG(32, (0xF2FF0000ul + CKDLY  ), ckdly);

    R_DEV_WRITE_REG(32, (0xF2FF0000ul + SMCMR  ), smcmr);
    R_DEV_WRITE_REG(32, (0xF2FF0000ul + SMENR  ), smenr);
    R_DEV_WRITE_REG(32, (0xF2FF0000ul + SMCR  ),  smcr );

    R_DEV_WRITE_REG(32, (0xF2FF0000ul + DRCR   ), drcr);
    R_DEV_WRITE_REG(32, (0xF2FF0000ul + DRCMR  ), drcmr);
    R_DEV_WRITE_REG(32, (0xF2FF0000ul + DREAR  ), drear);
    R_DEV_WRITE_REG(32, (0xF2FF0000ul + DROPR  ), dropr);
    R_DEV_WRITE_REG(32, (0xF2FF0000ul + DRENR  ), drenr);
    R_DEV_WRITE_REG(32, (0xF2FF0000ul + DRDMCR ), drdmcr);
    R_DEV_WRITE_REG(32, (0xF2FF0000ul + DRDRENR), drdrenr);

    WhileCnts = 0;
    while (0x1u != (regval & 0x1u))
    {
        if (WhileCnts++ >= 100) {
            RTC_Backup_Time();
            TestBackupRam = 0xaabbccddu;
            hardware_reset();
        }
        WDT_Clear();
        regval = R_DEV_READ_REG(32, (0xF2FF0000ul + CMNSR));
    }



}

#pragma ghs section bss=".NonInitArea"
uint32_t i_count;
uint32_t TestBackupRam;
#pragma ghs section bss=default
void TYW_FLASH_Init(void)
{
    uint32_t TEMP[2];
    FLASH_MANUFACTURER_ID_t FlashType;
    SFMA_DDR_Parameter_t SFMA_Parameter;
    i_count=0;
Total_Begin:
    i_count++;
    if(i_count>=20)
    {
        goto End_Begin;
    }
    Flash_WaitNop(1000);
    TYW_FLASH_PreInit();
    FlashType = SPI_NOR_Init();
    switch (FlashType)
    {
    case SPANSION:
        SFMA_Parameter.DTR_CMD = 0xEE;
        SFMA_Parameter.DTR_MF0_7 = 0xff;
        SFMA_Parameter.DTR_DummyCycle = 0x08;
        break;
    case WINBOND:
        SFMA_Parameter.DTR_CMD = 0xED;
        SFMA_Parameter.DTR_MF0_7 = 0xFF;
        SFMA_Parameter.DTR_DummyCycle = 0x07;
        break;
    case ISSI:
        SFMA_Parameter.DTR_CMD = 0xEE;
        SFMA_Parameter.DTR_MF0_7 = 0xFF;
        SFMA_Parameter.DTR_DummyCycle = 0x06;
        break;
    case Macronix:
        break;
    case GIGADEVICE:
        break;
    default:
        break;
    }
    TYW_FLASH_DDRPreInit(&SFMA_Parameter);
    Flash_WaitNop(1000);

    TEMP[0] = ((*((volatile uint32_t *)((0x10000000u)))));
    TEMP[1] = ((*((volatile uint32_t *)((0x10000004u)))));

    if ((TEMP[0] != 0x50415247) || (TEMP[1] != 0x50415f45))
    {
       goto Total_Begin;
    }
End_Begin:
    //i_count=0;
}

