#include "TYW_FLASH.h"
#include "SFMA_Driver.h"
#include "r_typedefs.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 PROTCMDD1           (uint32_t)(0xfff87000)
#define CKSC_ISFMAS_CTL    (uint32_t)(0xfff85340)
#define CKSC_ISFMAD_CTL    (uint32_t)(0xfff85380)
#define CKSC_ISFMAS_ACT    (uint32_t)(0xFFF85348)
#define CKSC_ISFMAD_ACT    (uint32_t)(0xFFF85380)
#define BUSY_TIMEOUT       (uint32_t)(500000ul)
#define CMNCR              (uint8_t)(0x00u)
#define SSLDR              (uint8_t)(0x04u)
#define SPBCR              (uint8_t)(0x08u)
#define CKDLY              (uint8_t)(0x50u)
#define SPODLY             (uint8_t)(0x68u)
#define CMNSR              (uint8_t)(0x48u)
#define SMCMR              (uint8_t)(0x24u)
#define SMENR              (uint8_t)(0x30u)
#define SMCR               (uint8_t)(0x20u)
#define SMRDR0             (uint8_t)(0x38u)
#define SMRDR1             (uint8_t)(0x3Cu)
#define SMWDR0             (uint8_t)(0x40u)
#define SMWDR1             (uint8_t)(0x44u)
#define DRCMR              (uint8_t)(0x10u)
#define DRENR              (uint8_t)(0x1Cu)
#define DRDMCR             (uint8_t)(0x58u)
#define DRCR               (uint8_t)(0x0cu)
#define DREAR              (uint8_t)(0x14u)
#define DRDRENR            (uint8_t)(0x5cu)
#define SMADR              (uint8_t)(0x28u)
#define SMOPR              (uint8_t)(0x2Cu)
#define SMDMCR             (uint8_t)(0x60u)
#define SMDRENR            (uint8_t)(0x64u)
#define DROPR              (uint8_t)(0x18u)

static void Flash_WaitNop(uint32_t loopcount);
static void Flash_WaitNop(uint32_t 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   =   0x80505000ul;
    smenr   =   0x00005000ul;
    smcmr   =   0x00ff00fful;
    smcr    =   0x00000001ul;

    regval = 0;
    WhileCnts = 0;

    R_DEV_WRITE_PROT_REG(PROTCMDD1, CKSC_ISFMAS_CTL, 0X02);/*PLL1CLK 480M  fPHCLK */
    while (0x02u != R_DEV_READ_REG(32, CKSC_ISFMAS_ACT)) 
    {
        if (WhileCnts++ >= 1000) {
            break;
        }
    }

    WhileCnts = 0;
    R_DEV_WRITE_PROT_REG(PROTCMDD1, CKSC_ISFMAD_CTL, 0X04);/* 4 div 480M/6=80M  BΦ */
    regval = R_DEV_READ_REG(32, CKSC_ISFMAD_CTL);
    while (0x04u != regval) 
    {
        regval = R_DEV_READ_REG(32, CKSC_ISFMAD_CTL);
        if (WhileCnts++ >= 1000) {
            break;
        }
    }

    regval = R_DEV_READ_REG(32, (0xF2FF0000ul + CMNSR));
    if (0x1u != (regval & 0x1u)) {
        ////RTC_Backup_Time();
        TestBackupRam1 = 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) )
    {
		WDT_Clear( );
        regval = R_DEV_READ_REG(32, (0xF2FF0000ul + CMNSR));
        if ( WhileCnts++ >= 100 )
        {
            ////RTC_Backup_Time( );
            TestBackupRam1 = 0xaabbccddu;
            hardware_reset( );
        }
        
    }
}

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       =   0x01FFF300UL;/*    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 *//*qitiancun test 20220118*/


    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       =   0x0222C780ul; /*    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       =   0x00000000ul;/*    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     =   0x00000000ul;/*    CONFIRMED FIX */

    regval = R_DEV_READ_REG(32, (0xF2FF0000ul + CMNSR));
    if (0x1u != (regval & 0x1u)) {
        ////RTC_Backup_Time();
        TestBackupRam1 = 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))
    {
	    WDT_Clear( );
        regval = R_DEV_READ_REG(32, (0xF2FF0000ul + CMNSR));
        if ( WhileCnts++ >= 100 )
        {
            ////RTC_Backup_Time( );
            TestBackupRam1 = 0xaabbccddu;
            hardware_reset( );
        }
        
    }
}

#pragma ghs section bss = ".NonInitArea"
uint32_t            i_count;
#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;
    uint32_t i_count;
    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 = 0xEB;
        SFMA_Parameter.DTR_MF0_7 = 0xFF;
        SFMA_Parameter.DTR_DummyCycle = 0x04;
        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] != 0x31323032) || (TEMP[1] != 0x31313131))
    //{
    //   goto Total_Begin;
    //}
End_Begin:
    i_count=0;
}
