#include "SFMA_APP.h"
#include "SFMA_Driver.h"
#include "r_typedefs.h"

#define st_ON (1)
#define st_OFF (0)

#define ERR_SPI_RET_OK ((uint8_t)0)         /* OK                                   */
#define ERR_SPI_RET_NG_PARAM ((uint8_t)1)   /* Parameter Invalid                    */
#define ERR_SPI_RET_NG_WE ((uint8_t)2)      /* "Write Enable" fail                  */
#define ERR_SPI_RET_NG_EFAIL ((uint8_t)3)   /* Erase fail                           */
#define ERR_SPI_RET_NG_PFAIL ((uint8_t)4)   /* Program(Write) fail                  */
#define ERR_SPI_RET_NG_ECC ((uint8_t)5)     /* Too many ECC error                   */
#define ERR_SPI_RET_NG_LUTFULL ((uint8_t)6) /* LUT is full                          */
#define ERR_SPI_RET_NG_TIMEOUT ((uint8_t)7) /* Too many retry                       */
#define ERR_SPI_RET_NG_SPI ((uint8_t)8)     /* SPI fail                             */
#define ERR_SPI_RET_NG_INIT ((uint8_t)9)    /* Initialize failed                    */
#define ERR_SPI_RET_NG_FAIL ((uint8_t)10)   /* Other fail                           */

static void SFMA_Delay(uint32_t loopcount);
static void SFMA_Delay(uint32_t loopcount)
{
    uint32_t i;

    for (i = 0; i < loopcount; i++)
    {
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
    }
}




uint8_t TYW_SFMA_SPISendCmd(uint8_t u8cmd, uint8_t u8data0, uint8_t u8data1, uint8_t u8data2, uint8_t u8data3, uint8_t u8opdataLen)
{
    st_SFMA0_Transfer stt_transfer; /* transfer data of SFMA0               */
    uint8_t u1t_sfma0_ret;          /* return value of SFMA0                */
    uint8_t u1t_ret;                /* return value                         */

    stt_transfer.b4_en_addr = U1G_SFMA0_EN_ADDR_DISABLE; /* Address Enable : disabled            */

    switch (u8opdataLen)
    {
    case 0:
        stt_transfer.b4_en_op_data = U1G_SFMA0_EN_OP_DATA_DISABLE; /* Option Data Enable : disabled        */
        break;
    case 1:
        stt_transfer.b4_en_op_data = U1G_SFMA0_EN_OP_DATA_OPD3; /* Option Data Enable : data0        */
        break;
    case 2:
        stt_transfer.b4_en_op_data = U1G_SFMA0_EN_OP_DATA_OPD3_OPD2; /* Option Data Enable : data0 data1        */
        break;
    case 3:
        stt_transfer.b4_en_op_data = U1G_SFMA0_EN_OP_DATA_OPD3_OPD1; /* Option Data Enable : data0 data1 data2       */
        break;
    case 4:
        stt_transfer.b4_en_op_data = U1G_SFMA0_EN_OP_DATA_OPD3_OPD0; /* Option Data Enable : data0 data1 data2 data3        */
        break;
    default:
        break;
    }
    stt_transfer.b4_en_data = U1G_SFMA0_EN_DATA_DISABLE;         /* Transfer Data Enable : Not transferred */
    stt_transfer.b1_en_cmd = st_ON;                              /* Command Enable : enabled             */
    stt_transfer.b1_en_op_cmd = st_OFF;                          /* Optional Command Enable : disabled   */
    stt_transfer.b1_en_dmy_cycle = st_OFF;                       /* Dummy Cycle Enable : disabled        */
    stt_transfer.b1_en_write = st_OFF;                           /* Data Write Enable : disabled         */
    stt_transfer.b1_en_read = st_OFF;                            /* Data Read Enable : disabled          */
    stt_transfer.b1_ddr_addr = st_OFF;                           /* Address DDR Enable : disabled        */
    stt_transfer.b1_ddr_op_data = st_OFF;                        /* Option Data DDR Enable : disabled    */
    stt_transfer.b1_ddr_data = st_OFF;                           /* Transfer Data DDR Enable : disabled  */
    stt_transfer.b1_keep_ssl = st_OFF;                           /* SPBSSL Signal Level Keep : disabled  */
    stt_transfer.b3_num_dmy_cycle = U1G_SFMA0_NUM_DUMMY_CYCLE_1; /* Number of Dummy Cycles : 1 cycle     */
    stt_transfer.b2_size_cmd = U1G_SFMA0_SIZE_1BIT;              /* Command Bit Size : 1 bit             */
    stt_transfer.b2_size_op_cmd = U1G_SFMA0_SIZE_1BIT;           /* Optional Command Bit Size : 1 bit    */
    stt_transfer.b2_size_addr = U1G_SFMA0_SIZE_1BIT;             /* Address Bit Size : 1 bit             */
    stt_transfer.b2_size_op_data = U1G_SFMA0_SIZE_1BIT;          /* Option Data Bit Size : 1 bit         */
    stt_transfer.b2_size_data = U1G_SFMA0_SIZE_1BIT;             /* Transfer Data Bit Size : 1 bit       */
    stt_transfer.b2_size_dmy_cycle = U1G_SFMA0_SIZE_1BIT;        /* Dummy Cycle Bit Size : 1 bit         */
    stt_transfer.u1_cmd = u8cmd;                                 /* Command : Device Reset               */
    stt_transfer.u1_opcmd = (uint8_t)0x00;                       /* Option Command : unused              */
    stt_transfer.u4_addr = (uint32_t)0x00000000;                 /* Address : unused                     */
    stt_transfer.au1_op_data[0] = (uint8_t)u8data3;              /* Option Data(OPD0) : unused           */
    stt_transfer.au1_op_data[1] = (uint8_t)u8data2;              /* Option Data(OPD1) : unused           */
    stt_transfer.au1_op_data[2] = (uint8_t)u8data1;              /* Option Data(OPD2) : unused           */
    stt_transfer.au1_op_data[3] = (uint8_t)u8data0;              /* Option Data(OPD3) : unused           */
    stt_transfer.au4_wdata[0] = (uint32_t)0x00000000;            /* Write Data(0) : unused               */
    stt_transfer.au4_wdata[1] = (uint32_t)0x00000000;            /* Write Data(1) : unused               */

    u1t_sfma0_ret = TYW_SFMA0_Transfer(&stt_transfer); /* Data Transfer                        */

    /* Transfer success */
    if (u1t_sfma0_ret == U1G_SFMA0_RET_OK)
    {
        u1t_ret = ERR_SPI_RET_OK;
    }
    /* Transfer fail */
    else
    {
        u1t_ret = ERR_SPI_RET_NG_SPI;
    }

    return u1t_ret;
}

uint8_t TYW_SFMA_SPIReadID(uint8_t u8cmd, uint32_t *p32Data0, uint32_t *p32Data1, uint8_t readLen)
{
    st_SFMA0_Transfer stt_transfer; /* transfer data of SFMA0               */
    uint8_t u1t_sfma0_ret;          /* return value of SFMA0                */
    uint8_t u1t_ret;                /* return value                         */

    stt_transfer.b4_en_addr = U1G_SFMA0_EN_ADDR_DISABLE;       /* Address Enable : disabled            */
    stt_transfer.b4_en_op_data = U1G_SFMA0_EN_OP_DATA_DISABLE; /* Option Data Enable : disabled        */
    switch (readLen)
    {
    case 16:
        stt_transfer.b4_en_data = U1G_SFMA0_EN_DATA_16BIT; /* Transfer Data Enable : Not transferred */
        break;
    case 32:
        stt_transfer.b4_en_data = U1G_SFMA0_EN_DATA_32BIT; /* Transfer Data Enable : Not transferred */
        break;
    case 64:
        stt_transfer.b4_en_data = U1G_SFMA0_EN_DATA_64BIT; /* Transfer Data Enable : Not transferred */
        break;
    default:
        stt_transfer.b4_en_data = U1G_SFMA0_EN_DATA_DISABLE; /* Transfer Data Enable : Not transferred */
        break;
    }

    stt_transfer.b1_en_cmd = st_ON;                              /* Command Enable : enabled             */
    stt_transfer.b1_en_op_cmd = st_OFF;                          /* Optional Command Enable : disabled   */
    stt_transfer.b1_en_dmy_cycle = st_ON;                        /* Dummy Cycle Enable : disabled        */
    stt_transfer.b1_en_write = st_OFF;                           /* Data Write Enable : disabled         */
    stt_transfer.b1_en_read = st_ON;                             /* Data Read Enable : enabled          */
    stt_transfer.b1_ddr_addr = st_OFF;                           /* Address DDR Enable : disabled        */
    stt_transfer.b1_ddr_op_data = st_OFF;                        /* Option Data DDR Enable : disabled    */
    stt_transfer.b1_ddr_data = st_OFF;                           /* Transfer Data DDR Enable : disabled  */
    stt_transfer.b1_keep_ssl = st_OFF;                           /* SPBSSL Signal Level Keep : disabled  */
    stt_transfer.b3_num_dmy_cycle = U1G_SFMA0_NUM_DUMMY_CYCLE_8; /* Number of Dummy Cycles : 1 cycle     */
    stt_transfer.b2_size_cmd = U1G_SFMA0_SIZE_1BIT;              /* Command Bit Size : 1 bit             */
    stt_transfer.b2_size_op_cmd = U1G_SFMA0_SIZE_1BIT;           /* Optional Command Bit Size : 1 bit    */
    stt_transfer.b2_size_addr = U1G_SFMA0_SIZE_1BIT;             /* Address Bit Size : 1 bit             */
    stt_transfer.b2_size_op_data = U1G_SFMA0_SIZE_1BIT;          /* Option Data Bit Size : 1 bit         */
    stt_transfer.b2_size_data = U1G_SFMA0_SIZE_1BIT;             /* Transfer Data Bit Size : 1 bit       */
    stt_transfer.b2_size_dmy_cycle = U1G_SFMA0_SIZE_1BIT;        /* Dummy Cycle Bit Size : 1 bit         */
    stt_transfer.u1_cmd = u8cmd;                                 /* Command : Device Reset               */
    stt_transfer.u1_opcmd = (uint8_t)0x00;                       /* Option Command : unused              */
    stt_transfer.u4_addr = (uint32_t)0x00000000;                 /* Address : unused                     */
    stt_transfer.au1_op_data[0] = (uint8_t)0x00;                 /* Option Data(OPD0) : unused           */
    stt_transfer.au1_op_data[1] = (uint8_t)0x00;                 /* Option Data(OPD1) : unused           */
    stt_transfer.au1_op_data[2] = (uint8_t)0x00;                 /* Option Data(OPD2) : unused           */
    stt_transfer.au1_op_data[3] = (uint8_t)0x00;                 /* Option Data(OPD3) : unused           */
    stt_transfer.au4_wdata[0] = (uint32_t)0x00000000;            /* Write Data(0) : unused               */
    stt_transfer.au4_wdata[1] = (uint32_t)0x00000000;            /* Write Data(1) : unused               */

    u1t_sfma0_ret = TYW_SFMA0_Transfer(&stt_transfer); /* Data Transfer                        */

    /* Transfer success */
    if (u1t_sfma0_ret == U1G_SFMA0_RET_OK)
    {
        *p32Data0 = stt_transfer.au4_rdata[0];
        *p32Data1 = stt_transfer.au4_rdata[1];
        u1t_ret = ERR_SPI_RET_OK;
    }
    /* Transfer fail */
    else
    {
        u1t_ret = ERR_SPI_RET_NG_SPI;
    }

    return u1t_ret;
}
uint8_t TYW_SFMA_SPIRead(uint8_t u8cmd, uint32_t *p32Data0, uint32_t *p32Data1, uint8_t readLen)
{
    st_SFMA0_Transfer stt_transfer; /* transfer data of SFMA0               */
    uint8_t u1t_sfma0_ret;          /* return value of SFMA0                */
    uint8_t u1t_ret;                /* return value                         */

    stt_transfer.b4_en_addr = U1G_SFMA0_EN_ADDR_DISABLE;       /* Address Enable : disabled            */
    stt_transfer.b4_en_op_data = U1G_SFMA0_EN_OP_DATA_DISABLE; /* Option Data Enable : disabled        */
    switch (readLen)
    {
    case 16:
        stt_transfer.b4_en_data = U1G_SFMA0_EN_DATA_16BIT; /* Transfer Data Enable : Not transferred */
        break;
    case 32:
        stt_transfer.b4_en_data = U1G_SFMA0_EN_DATA_32BIT; /* Transfer Data Enable : Not transferred */
        break;
    case 64:
        stt_transfer.b4_en_data = U1G_SFMA0_EN_DATA_64BIT; /* Transfer Data Enable : Not transferred */
        break;
    default:
        stt_transfer.b4_en_data = U1G_SFMA0_EN_DATA_DISABLE; /* Transfer Data Enable : Not transferred */
        break;
    }

    stt_transfer.b1_en_cmd = st_ON;                              /* Command Enable : enabled             */
    stt_transfer.b1_en_op_cmd = st_OFF;                          /* Optional Command Enable : disabled   */
    stt_transfer.b1_en_dmy_cycle = st_OFF;                        /* Dummy Cycle Enable : disabled        */
    stt_transfer.b1_en_write = st_OFF;                           /* Data Write Enable : disabled         */
    stt_transfer.b1_en_read = st_ON;                             /* Data Read Enable : enabled          */
    stt_transfer.b1_ddr_addr = st_OFF;                           /* Address DDR Enable : disabled        */
    stt_transfer.b1_ddr_op_data = st_OFF;                        /* Option Data DDR Enable : disabled    */
    stt_transfer.b1_ddr_data = st_OFF;                           /* Transfer Data DDR Enable : disabled  */
    stt_transfer.b1_keep_ssl = st_OFF;                           /* SPBSSL Signal Level Keep : disabled  */
    stt_transfer.b3_num_dmy_cycle = U1G_SFMA0_NUM_DUMMY_CYCLE_1; /* Number of Dummy Cycles : 1 cycle     */
    stt_transfer.b2_size_cmd = U1G_SFMA0_SIZE_1BIT;              /* Command Bit Size : 1 bit             */
    stt_transfer.b2_size_op_cmd = U1G_SFMA0_SIZE_1BIT;           /* Optional Command Bit Size : 1 bit    */
    stt_transfer.b2_size_addr = U1G_SFMA0_SIZE_1BIT;             /* Address Bit Size : 1 bit             */
    stt_transfer.b2_size_op_data = U1G_SFMA0_SIZE_1BIT;          /* Option Data Bit Size : 1 bit         */
    stt_transfer.b2_size_data = U1G_SFMA0_SIZE_1BIT;             /* Transfer Data Bit Size : 1 bit       */
    stt_transfer.b2_size_dmy_cycle = U1G_SFMA0_SIZE_1BIT;        /* Dummy Cycle Bit Size : 1 bit         */
    stt_transfer.u1_cmd = u8cmd;                                 /* Command : Device Reset               */
    stt_transfer.u1_opcmd = (uint8_t)0x00;                       /* Option Command : unused              */
    stt_transfer.u4_addr = (uint32_t)0x00000000;                 /* Address : unused                     */
    stt_transfer.au1_op_data[0] = (uint8_t)0x00;                 /* Option Data(OPD0) : unused           */
    stt_transfer.au1_op_data[1] = (uint8_t)0x00;                 /* Option Data(OPD1) : unused           */
    stt_transfer.au1_op_data[2] = (uint8_t)0x00;                 /* Option Data(OPD2) : unused           */
    stt_transfer.au1_op_data[3] = (uint8_t)0x00;                 /* Option Data(OPD3) : unused           */
    stt_transfer.au4_wdata[0] = (uint32_t)0x00000000;            /* Write Data(0) : unused               */
    stt_transfer.au4_wdata[1] = (uint32_t)0x00000000;            /* Write Data(1) : unused               */

    u1t_sfma0_ret = TYW_SFMA0_Transfer(&stt_transfer); /* Data Transfer                        */

    /* Transfer success */
    if (u1t_sfma0_ret == U1G_SFMA0_RET_OK)
    {
        *p32Data0 = stt_transfer.au4_rdata[0];
        *p32Data1 = stt_transfer.au4_rdata[1];
        u1t_ret = ERR_SPI_RET_OK;
    }
    /* Transfer fail */
    else
    {
        u1t_ret = ERR_SPI_RET_NG_SPI;
    }

    return u1t_ret;
}


uint8_t TYW_SFMA_SPIReadFlash(uint32_t u32Address, uint32_t u32Size, uint8_t *pu1t_buffer)
{
    st_SFMA0_Transfer stt_transfer;                             /* transfer data of SFMA0               */
    uint32_t u4t_loop;                                                /* loop counter                         */
    uint8_t u1t_fail;                                                /* fail                                 */
    uint8_t u1t_sfma0_ret;                                           /* return value of SFMA0                */
    uint8_t u1t_ret;                                                 /* return value                         */

    /*----------------------*/
    /* Transfer Except Data */
    /*----------------------*/
    stt_transfer.b4_en_addr = U1G_SFMA0_EN_ADDR_32BIT;          /* Address Enable : ADR[23:8]           */
    stt_transfer.b4_en_op_data = U1G_SFMA0_EN_OP_DATA_DISABLE;  /* Option Data Enable : disabled        */
    stt_transfer.b4_en_data = U1G_SFMA0_EN_DATA_DISABLE;        /* Transfer Data Enable : disabled      */
    stt_transfer.b1_en_cmd = st_ON;                                /* Command Enable : enabled             */
    stt_transfer.b1_en_op_cmd = st_OFF;                           /* Optional Command Enable : disabled   */
    stt_transfer.b1_en_dmy_cycle = st_OFF;                        /* Dummy Cycle Enable : enabled         */
    stt_transfer.b1_en_write = st_OFF;                            /* Data Write Enable : disabled         */
    stt_transfer.b1_en_read = st_OFF;                             /* Data Read Enable : disabled          */
    stt_transfer.b1_ddr_addr = st_OFF;                            /* Address DDR Enable : disabled        */
    stt_transfer.b1_ddr_op_data = st_OFF;                         /* Option Data DDR Enable : disabled    */
    stt_transfer.b1_ddr_data = st_OFF;                            /* Transfer Data DDR Enable : disabled  */
    stt_transfer.b1_keep_ssl = st_ON;                              /* SPBSSL Signal Level Keep : enabled   */
    stt_transfer.b3_num_dmy_cycle = U1G_SFMA0_NUM_DUMMY_CYCLE_1;          /* Number of Dummy Cycles : arg value   */
    stt_transfer.b2_size_cmd = U1G_SFMA0_SIZE_1BIT;             /* Command Bit Size : 1 bit             */
    stt_transfer.b2_size_op_cmd = U1G_SFMA0_SIZE_1BIT;          /* Optional Command Bit Size : 1 bit    */
    stt_transfer.b2_size_addr = U1G_SFMA0_SIZE_1BIT;            /* Address Bit Size : arg value         */
    stt_transfer.b2_size_op_data = U1G_SFMA0_SIZE_1BIT;         /* Option Data Bit Size : 1 bit         */
    stt_transfer.b2_size_data = U1G_SFMA0_SIZE_1BIT;            /* Transfer Data Bit Size : arg value   */
    stt_transfer.b2_size_dmy_cycle = U1G_SFMA0_SIZE_1BIT;    /* Dummy Cycle Bit Size : arg value     */
    stt_transfer.u1_cmd = 0x03;                              /* Command : arg value                  */
    stt_transfer.u1_opcmd = 0x00;                           /* Option Command : unused              */
    stt_transfer.au1_op_data[0] = 0x00;                     /* Option Data(OPD0) : unused           */
    stt_transfer.au1_op_data[1] = 0x00;                     /* Option Data(OPD1) : unused           */
    stt_transfer.au1_op_data[2] = 0x00;                     /* Option Data(OPD2) : unused           */
    stt_transfer.au1_op_data[3] = 0x00;                     /* Option Data(OPD3) : unused           */
    stt_transfer.au4_wdata[0] = 0x00000000;                 /* Write Data(0) : unused               */
    stt_transfer.au4_wdata[1] = 0x00000000;                 /* Write Data(1) : unused               */


    stt_transfer.u4_addr = u32Address;                  /* Address : used for dummy cycle       */

    u1t_sfma0_ret = TYW_SFMA0_Transfer(&stt_transfer);          /* Data Transfer                        */

    /* Transfer success */
    if (u1t_sfma0_ret == U1G_SFMA0_RET_OK)
    {
        u1t_fail = st_OFF;
    }
    /* Transfer fail */
    else
    {
        u1t_fail = st_ON;
        /* not abort to negate SPBSSL */
    }

    /*--------------------*/
    /* Transfer Only Data */
    /*--------------------*/
    stt_transfer.b4_en_addr = U1G_SFMA0_EN_ADDR_DISABLE;        /* Address Enable : disabled            */
    stt_transfer.b4_en_data = U1G_SFMA0_EN_DATA_64BIT;          /* Transfer Data Enable : 64bits transferred */
    stt_transfer.b1_en_cmd = st_OFF;                              /* Command Enable : disabled            */
    stt_transfer.b1_en_read = st_ON;                               /* Data Read Enable : enabled           */
    stt_transfer.b1_en_dmy_cycle = st_OFF;                        /* Dummy Cycle Enable : disabled        */
    stt_transfer.u1_cmd = (uint8_t)0x00;                             /* Command : unused                     */

    for (u4t_loop = (uint32_t)0; u4t_loop < u32Size; u4t_loop += 8)
    {
        /* Last transfer */
        if (u4t_loop == (u32Size - 8))
        {
            stt_transfer.b1_keep_ssl = st_OFF;                    /* SPBSSL Signal Level Keep : disabled  */
        }

        u1t_sfma0_ret = TYW_SFMA0_Transfer(&stt_transfer);      /* Data Transfer                        */

        /* Transfer success */
        if (u1t_sfma0_ret == U1G_SFMA0_RET_OK)
        {
            *(pu1t_buffer    ) = (uint8_t)((uint32_t)(stt_transfer.au4_rdata[0] >> 24) & (uint32_t)0x000000ff);
            *(pu1t_buffer + 1) = (uint8_t)((uint32_t)(stt_transfer.au4_rdata[0] >> 16) & (uint32_t)0x000000ff);
            *(pu1t_buffer + 2) = (uint8_t)((uint32_t)(stt_transfer.au4_rdata[0] >> 8) & (uint32_t)0x000000ff);
            *(pu1t_buffer + 3) = (uint8_t)((uint32_t)(stt_transfer.au4_rdata[0] >> 0) & (uint32_t)0x000000ff);
            *(pu1t_buffer + 4) = (uint8_t)((uint32_t)(stt_transfer.au4_rdata[1] >> 24) & (uint32_t)0x000000ff);
            *(pu1t_buffer + 5) = (uint8_t)((uint32_t)(stt_transfer.au4_rdata[1] >> 16) & (uint32_t)0x000000ff);
            *(pu1t_buffer + 6) = (uint8_t)((uint32_t)(stt_transfer.au4_rdata[1] >> 8) & (uint32_t)0x000000ff);
            *(pu1t_buffer + 7) = (uint8_t)((uint32_t)(stt_transfer.au4_rdata[1] >> 0) & (uint32_t)0x000000ff);

            pu1t_buffer += 8;
        }
        /* Transfer fail */
        else
        {
            u1t_fail = st_ON;
            /* not break to negate SPBSSL */
        }
    }

    /* All Transfer success */
    if (u1t_fail == st_OFF)
    {
        u1t_ret = 0;
    }
    /* Transfer fail */
    else
    {
        u1t_ret = 8;
    }

    return u1t_ret;
}

FLASH_MANUFACTURER_ID_t SPI_NOR_Init(void)
{
    uint32_t p32data0;
    uint32_t p32data1;
    uint8_t MF0 = 0;
    uint8_t ID0 = 0;
    uint8_t Status0 = 0;
    uint8_t Status1 = 0;
    FLASH_MANUFACTURER_ID_t FlashType;
    uint8_t WhileSaftyCnts = 0;

    FLASH_MANUFACTURER_ID_t Flash_ManuFacturer;
    TYW_SFMA_SPIReadID(0x90, &p32data0, &p32data1, 64);

    MF0 = (uint8_t)((p32data0 >> 8) & 0x000000fful);
    ID0 = (uint8_t)((p32data0 >> 0) & 0x000000fful);

    Flash_ManuFacturer = MF0;
    FlashType = Flash_ManuFacturer;
    switch (Flash_ManuFacturer)
    {

    case SPANSION:
         /*Reset Device*/
        TYW_SFMA_SPISendCmd(0xf0, 0x00, 0x00, 0x00, 0x00, 0);
        SFMA_Delay(50);/*the device will take approximately tRST=30us to reset*/
        do
        {
            /*Read Flash Status*/
            TYW_SFMA_SPIRead(0X05, &p32data0, &p32data1, 16);
            Status0 = (uint8_t)((p32data0 >> 24) & 0x000000fful);
            Status1 = (uint8_t)((p32data0 >> 16) & 0x000000fful);
            SFMA_Delay(50);
        }
        while (((Status0 & 0x03) != 0x00) && ((Status1 & 0x03) != 0x00));
        /*Read Flash Status*/
        TYW_SFMA_SPIRead(0x35, &p32data0, &p32data1, 16);
        Status0 = (uint8_t)((p32data0 >> 24) & 0x000000fful);
        Status1 = (uint8_t)((p32data0 >> 16) & 0x000000fful);
        if (((Status0 & 0x02) != 0x02) || ((Status1 & 0x02) != 0x02))
        {
            TYW_SFMA_SPISendCmd(0x06, 0x00, 0x00, 0x00, 0x00, 0);
            /*Enable QE*/
            TYW_SFMA_SPISendCmd(0x01, 0x02, 0x00, 0x00, 0x00, 1);
            SFMA_Delay(5);
        }
        break;
    case WINBOND:
        /*Reset Device*/
        TYW_SFMA_SPISendCmd(0x66, 0x00, 0x00, 0x00, 0x00, 0);
        TYW_SFMA_SPISendCmd(0x99, 0x00, 0x00, 0x00, 0x00, 0);
        SFMA_Delay(50);/*the device will take approximately tRST=30us to reset*/
        do
        {
            /*Read Flash Status*/
            TYW_SFMA_SPIRead(0X05, &p32data0, &p32data1, 16);
            Status0 = (uint8_t)((p32data0 >> 0) & 0x000000fful);
            SFMA_Delay(50);
        }
        while ((Status0 & 0x03) != 0x00);
        /*Read Flash Status*/
        TYW_SFMA_SPIRead(0x35, &p32data0, &p32data1, 16);
        Status0 = (uint8_t)((p32data0 >> 0) & 0x000000fful);

        if ((Status0 & 0x02) == 0x02)
        {
            ;
        }
        else
        {
            TYW_SFMA_SPISendCmd(0x06, 0x00, 0x00, 0x00, 0x00, 0);
            /*Enable QE*/
            TYW_SFMA_SPISendCmd(0x31, 0x02, 0x00, 0x00, 0x00, 1);
            SFMA_Delay(5);
            do
            {
                /*Read Flash Status*/
                TYW_SFMA_SPIRead(0X05, &p32data0, &p32data1, 16);
                Status0 = (uint8_t)((p32data0 >> 0) & 0x000000fful);
            }
            while ((Status0 & 0x03) != 0x00);

            TYW_SFMA_SPIRead(0x35, &p32data0, &p32data1, 16);
            Status0 = (uint8_t)((p32data0 >> 0) & 0x000000fful);
            while ((Status0 & 0x02) != 0x02)
            {
                TYW_SFMA_SPISendCmd(0x31, 0x02, 0x00, 0x00, 0x00, 1);
                SFMA_Delay(1);
                TYW_SFMA_SPIRead(0x35, &p32data0, &p32data1, 16);
                Status0 = (uint8_t)((p32data0 >> 0) & 0x000000fful);
                if (WhileSaftyCnts++ > 100) {
                    break;
                }
            }
        }
        break;
    case ISSI:
        /*Reset Device*/
        TYW_SFMA_SPISendCmd(0x06, 0x00, 0x00, 0x00, 0x00, 0);
        TYW_SFMA_SPISendCmd(0x66, 0x00, 0x00, 0x00, 0x00, 0);
        TYW_SFMA_SPISendCmd(0x99, 0x00, 0x00, 0x00, 0x00, 0);
        SFMA_Delay(100);/*the device will take approximately tRST=30us to reset*/
         /*Read Flash Status*/
        TYW_SFMA_SPIRead(0x05, &p32data0, &p32data1, 16);
        Status0 = (uint8_t)((p32data0 >> 24) & 0x000000fful);
        Status1 = (uint8_t)((p32data0 >> 16) & 0x000000fful);

        if (((Status0 & 0x40) == 0x40) && ((Status1 & 0x40) == 0x40))
        {
            do
            {
                /*Read Flash Status*/
                TYW_SFMA_SPIRead(0X05, &p32data0, &p32data1, 16);
                Status0 = (uint8_t)((p32data0 >> 24) & 0x000000fful);
                Status1 = (uint8_t)((p32data0 >> 16) & 0x000000fful);
            }
            while (((Status0 & 0x03) != 0x00) && ((Status1 & 0x03) != 0x00));


            TYW_SFMA_SPISendCmd(0x06, 0x00, 0x00, 0x00, 0x00, 0);
            TYW_SFMA_SPIRead(0x61, &p32data0, &p32data1, 16);
            Status0 = (uint8_t)((p32data0 >> 24) & 0x000000fful);
            Status1 = (uint8_t)((p32data0 >> 16) & 0x000000fful);
            do
            {
                /*write dummy cycle 7 to read register*/
                TYW_SFMA_SPISendCmd(0x65, 0x38, 0x00, 0x00, 0x00, 1);
                SFMA_Delay(1);
                TYW_SFMA_SPIRead(0x61, &p32data0, &p32data1, 16);
                Status0 = (uint8_t)((p32data0 >> 24) & 0x000000fful);
                Status1 = (uint8_t)((p32data0 >> 16) & 0x000000fful);
            }
            while (((Status0) != 0x38) && ((Status1) != 0x38));

            TYW_SFMA_SPISendCmd(0x06, 0x00, 0x00, 0x00, 0x00, 0);
            /*Enter 4Byte Addr Mode*/
            TYW_SFMA_SPISendCmd(0xB7, 0x00, 0x00, 0x00, 0x00, 0);/*EN4B*/
            SFMA_Delay(1);
            TYW_SFMA_SPIRead(0x16, &p32data0, &p32data1, 16);
            do
            {
                /*Enter 4Byte Addr Mode*/
                TYW_SFMA_SPISendCmd(0xB7, 0x00, 0x00, 0x00, 0x00, 0);/*EN4B*/
                SFMA_Delay(1);
                TYW_SFMA_SPIRead(0x16, &p32data0, &p32data1, 16);
                Status0 = (uint8_t)((p32data0 >> 24) & 0x000000fful);
                Status1 = (uint8_t)((p32data0 >> 16) & 0x000000fful);
            }
            while (((Status0 & 0x80) != 0x80) && ((Status1 & 0x80) != 0x80));
        }
        else
        {
            TYW_SFMA_SPISendCmd(0x06, 0x00, 0x00, 0x00, 0x00, 0);
            /*Enable QE*/
            TYW_SFMA_SPISendCmd(0x01, 0x40, 0x00, 0x00, 0x00, 1);
            SFMA_Delay(5);

            TYW_SFMA_SPIRead(0x05, &p32data0, &p32data1, 16);
            Status0 = (uint8_t)((p32data0 >> 24) & 0x000000fful);
            Status1 = (uint8_t)((p32data0 >> 16) & 0x000000fful);
            do
            {
                /*ensure QE enable*/
                TYW_SFMA_SPISendCmd(0x01, 0x40, 0x00, 0x00, 0x00, 1);
                SFMA_Delay(1);
                TYW_SFMA_SPIRead(0x05, &p32data0, &p32data1, 16);
                Status0 = (uint8_t)((p32data0 >> 24) & 0x000000fful);
                Status1 = (uint8_t)((p32data0 >> 16) & 0x000000fful);
            }
            while (((Status0 & 0x40) != 0x40) && ((Status1 & 0x40) != 0x40));

            TYW_SFMA_SPISendCmd(0x06, 0x00, 0x00, 0x00, 0x00, 0);
            TYW_SFMA_SPIRead(0x61, &p32data0, &p32data1, 16);
            Status0 = (uint8_t)((p32data0 >> 24) & 0x000000fful);
            Status1 = (uint8_t)((p32data0 >> 16) & 0x000000fful);
            do
            {
                /*write dummy cycle 7 to read register*/
                TYW_SFMA_SPISendCmd(0x65, 0x38, 0x00, 0x00, 0x00, 1);
                SFMA_Delay(1);
                TYW_SFMA_SPIRead(0x61, &p32data0, &p32data1, 16);
                Status0 = (uint8_t)((p32data0 >> 24) & 0x000000fful);
                Status1 = (uint8_t)((p32data0 >> 16) & 0x000000fful);
            }
            while (((Status0) != 0x38) && ((Status1) != 0x38));

            TYW_SFMA_SPIRead(0x81, &p32data0, &p32data1, 16);
            Status0 = (uint8_t)((p32data0 >> 24) & 0x000000fful);
            Status1 = (uint8_t)((p32data0 >> 16) & 0x000000fful);
            do
            {
                TYW_SFMA_SPISendCmd(0x85, 0xF0, 0x00, 0x00, 0x00, 1);
                SFMA_Delay(1);
                TYW_SFMA_SPIRead(0x81, &p32data0, &p32data1, 16);
                Status0 = (uint8_t)((p32data0 >> 24) & 0x000000fful);
                Status1 = (uint8_t)((p32data0 >> 16) & 0x000000fful);
            }
            while (((Status0) != 0xF0) && ((Status1) != 0xF0));

            TYW_SFMA_SPISendCmd(0x06, 0x00, 0x00, 0x00, 0x00, 0);
            /*Enter 4Byte Addr Mode*/
            TYW_SFMA_SPISendCmd(0xB7, 0x00, 0x00, 0x00, 0x00, 0);/*EN4B*/
            SFMA_Delay(1);
            TYW_SFMA_SPIRead(0x16, &p32data0, &p32data1, 16);
            do
            {
                /*Enter 4Byte Addr Mode*/
                TYW_SFMA_SPISendCmd(0xB7, 0x00, 0x00, 0x00, 0x00, 0);/*EN4B*/
                SFMA_Delay(1);
                TYW_SFMA_SPIRead(0x16, &p32data0, &p32data1, 16);
                Status0 = (uint8_t)((p32data0 >> 24) & 0x000000fful);
                Status1 = (uint8_t)((p32data0 >> 16) & 0x000000fful);
            }
            while (((Status0 & 0x80) != 0x80) && ((Status1 & 0x80) != 0x80));
        }
        break;
    default:
        break;
    }
    return FlashType;
}
