#include "SFMA_Driver.h"
#include "dr7f701401.dvf.h"
#include "r_dev_api.h"
#include "v800_ghs.h"
#include "r_typedefs.h"
#define U1_ON    (( uint8_t )0x01)
#define U1_OFF   (( uint8_t )0x00)
#define U1_HI    (( uint8_t )0x01)
#define U1_LO    (( uint8_t )0x00)
#define U1_TRUE  (( uint8_t )0x01)
#define U1_FALSE (( uint8_t )0x00)

/* Bit Value : CMNCR */
#define U1S_SFMA0_BIT_BSZ_MASK (( uint8_t )3)
#define U1S_SFMA0_BIT_BSZ_1MEM (( uint8_t )0)
#define U1S_SFMA0_BIT_BSZ_2MEM (( uint8_t )1)
/* Bit Position : SMCR */
#define U1S_SFMA0_BIT_SSLKP (( uint8_t )8)
#define U1S_SFMA0_BIT_SPIRE (( uint8_t )2)
#define U1S_SFMA0_BIT_SPIWE (( uint8_t )1)
#define U1S_SFMA0_BIT_SPIE  (( uint8_t )0)
/* Bit Position : SMCMR */
#define U1S_SFMA0_BIT_CMD  (( uint8_t )16)
#define U1S_SFMA0_BIT_OCMD (( uint8_t )0)
/* Bit Position : SMOPR */
#define U1S_SFMA0_BIT_OPD3 (( uint8_t )24)
#define U1S_SFMA0_BIT_OPD2 (( uint8_t )16)
#define U1S_SFMA0_BIT_OPD1 (( uint8_t )8)
#define U1S_SFMA0_BIT_OPD0 (( uint8_t )0)
/* Bit Position : SMENR */
#define U1S_SFMA0_BIT_CDB   (( uint8_t )30)
#define U1S_SFMA0_BIT_OCDB  (( uint8_t )28)
#define U1S_SFMA0_BIT_ADB   (( uint8_t )24)
#define U1S_SFMA0_BIT_OPDB  (( uint8_t )20)
#define U1S_SFMA0_BIT_SPIDB (( uint8_t )16)
#define U1S_SFMA0_BIT_DME   (( uint8_t )15)
#define U1S_SFMA0_BIT_CDE   (( uint8_t )14)
#define U1S_SFMA0_BIT_OCDE  (( uint8_t )12)
#define U1S_SFMA0_BIT_ADE   (( uint8_t )8)
#define U1S_SFMA0_BIT_OPDE  (( uint8_t )4)
#define U1S_SFMA0_BIT_SPIDE (( uint8_t )0)
/* Bit Position : SMDMCR */
#define U1S_SFMA0_BIT_DMDB  (( uint8_t )16)
#define U1S_SFMA0_BIT_DMCYC (( uint8_t )0)
/* Bit Position : SMDRENR */
#define U1S_SFMA0_BIT_ADDRE  (( uint8_t )8)
#define U1S_SFMA0_BIT_OPDRE  (( uint8_t )4)
#define U1S_SFMA0_BIT_SPIDRE (( uint8_t )0)

static uint8_t TYW_SFMA0_CheckTransferArg(const st_SFMA0_Transfer *pstt_transfer);

void TYW_SFMA0_Init(void)
{
    R_DEV_WRITE_PROT_REG(SYSPROTCMDD1, 0xfff85340, 0X02);
    while (0x02u != R_DEV_READ_REG(32, 0xFFF85348)) {}

    R_DEV_WRITE_PROT_REG(SYSPROTCMDD1, 0xfff85380, 0X03);
    while (0x03u != R_DEV_READ_REG(32, 0xfff85380)) {}
    SFMA0CKDLY = (uint32_t)0xA5040000; /* PROT_CKDLY[7:0] : write protection off */
    /* CKDLY_TS[1:0] : No shift             */
    /* CKDLYOC[2:0] :                       */
    /*      2 x [1/(2xfPHCLK)] - 1/fB phi   */
    /* CKDLYRX[2:0] : no sampling point shift */

    SFMA0SPODLY = ( uint32_t )0xA5000000; /* PROT_SPODLY[7:0] : write protection off */
    /* DLYOE1 : No output delay             */
    /* DLYO1 : No output delay              */
    /* DLYOE0 : No output delay             */
    /* DLYO0 : No output delay              */

    SFMA0CMNCR = ( uint32_t )0x00ff00fful; /* MD : SPI operating mode              */
    /* SFDE : Swapping is not performed     */
    /* MOIIO3[1:0] : Output value Hi-Z      */
    /* MOIIO2[1:0] : Output value Hi-Z      */
    /* MOIIO1[1:0] : Output value Hi-Z      */
    /* MOIIO0[1:0] : Output value Hi-Z      */
    /* IO3FV[1:0] : Output value 1          */
    /* IO2FV[1:0] : Output value Hi-Z       */
    /* IO0FV[1:0] : Output value Hi-Z       */
    /* CPHAT : Data transmission at even    */
    /*      edge during SDR transfer        */
    /* CPHAR : Data reception at even edge  */
    /*      during SDR transfer             */
    /* SSLP : Active low SPBSSL signal      */
    /* CPOL : SPBCLK output is 0 during     */
    /*      SPBSSL negation period          */
    /* BSZ[1:0] : 2 memories                */

    SFMA0SSLDR = ( uint32_t )0x00040000; /* SPNDL[2:0] : 5 SPBCLK cycle          */
    /* SLNDL[2:0] : 1.5 SPBCLK cycles       */
    /* SCKDL[2:0] : 1 SPBCLK cycle          */

    SFMA0SPBCR = ( uint32_t )0x00000100; /* SPBR[7:0] : 1                        */
    /* BRDV[1:0] : 0                        */
    /* <MEMO>                               */
    /* Bit rate = B phi / (2 * n * 2^N)     */
    /*          = 100MHz                    */
    /*   n : SPBR[7:0]                      */
    /*   N : BRDV[1:0]                      */
}

/*------------------------------------------------------------------------------------------------------*/
/* Function Name : TYW_SFMA0_Transfer                                                                   */
/* Description   : Data transfer                                                                        */
/*                                                                                                      */
/* Arguments     : pstt_transfer : data transfer structure                                              */
/* Return Value  : result(U1G_SFMA0_RET_xxx)                                                            */
/* Note          : None                                                                                 */
/*------------------------------------------------------------------------------------------------------*/
uint8_t TYW_SFMA0_Transfer(st_SFMA0_Transfer *pstt_transfer)
{
    uint32_t u4t_regSMCR;    /* register value for SMCR              */
    uint32_t u4t_regSMCMR;   /* register value for SMCMR             */
    uint32_t u4t_regSMADR;   /* register value for SMADR             */
    uint32_t u4t_regSMOPR;   /* register value for SMOPR             */
    uint32_t u4t_regSMENR;   /* register value for SMENR             */
    uint32_t u4t_regSMWDR0;  /* register value for SMWDR0            */
    uint32_t u4t_regSMWDR1;  /* register value for SMWDR1            */
    uint32_t u4t_regSMDMCR;  /* register value for SMDMCR            */
    uint32_t u4t_regSMDRENR; /* register value for SMDRENR           */
    uint8_t  u1t_bitTEND;    /* bit value of TEND                    */
    uint8_t  u1t_check;      /* argment check result                 */
    uint8_t  u1t_ret;        /* return value                         */
    uint32_t i = 0;

    /* Parameter Check */
    u1t_check = TYW_SFMA0_CheckTransferArg(pstt_transfer);

    /* "Parameter Check" is OK */
    if ( u1t_check == U1G_SFMA0_RET_OK )
    {
        u1t_ret = U1G_SFMA0_RET_OK;

        /*-----------------------*/
        /* Create value for SMCR */
        /*-----------------------*/
        u4t_regSMCR = ( uint32_t )0x00000000; /* Initialize                           */
        u4t_regSMCR |= ( uint32_t )(pstt_transfer->b1_keep_ssl << U1S_SFMA0_BIT_SSLKP);
        /* SSLKP                                */
        u4t_regSMCR |= ( uint32_t )(pstt_transfer->b1_en_read << U1S_SFMA0_BIT_SPIRE);
        /* SPIRE                                */
        u4t_regSMCR |= ( uint32_t )(pstt_transfer->b1_en_write << U1S_SFMA0_BIT_SPIWE);
        /* SPIWE                                */

        /*------------------------*/
        /* Create value for SMCMR */
        /*------------------------*/
        u4t_regSMCMR = ( uint32_t )0x00000000; /* Initialize                           */
        u4t_regSMCMR |= ( uint32_t )(pstt_transfer->u1_cmd << U1S_SFMA0_BIT_CMD);
        /* CMD[7:0]                             */
        u4t_regSMCMR |= ( uint32_t )(pstt_transfer->u1_opcmd << U1S_SFMA0_BIT_OCMD);
        /* OCMD[7:0]                            */

        /*------------------------*/
        /* Create value for SMADR */
        /*------------------------*/
        if ( ( uint8_t )(SFMA0CMNCR & U1S_SFMA0_BIT_BSZ_MASK) == U1S_SFMA0_BIT_BSZ_2MEM )
        {
            u4t_regSMADR = ( uint32_t )(pstt_transfer->u4_addr >> 1); /* ADR[31:0] (address[32:1])            */
        }
        else
        {
            u4t_regSMADR = pstt_transfer->u4_addr; /* ADR[31:0] (address[31:0])            */
        }

        /*------------------------*/
        /* Create value for SMOPR */
        /*------------------------*/
        u4t_regSMOPR = ( uint32_t )0x00000000; /* Initialize                           */
        u4t_regSMOPR |= ( uint32_t )(pstt_transfer->au1_op_data [ 3 ] << U1S_SFMA0_BIT_OPD3);
        /* OPD3                                 */
        u4t_regSMOPR |= ( uint32_t )(pstt_transfer->au1_op_data [ 2 ] << U1S_SFMA0_BIT_OPD2);
        /* OPD2                                 */
        u4t_regSMOPR |= ( uint32_t )(pstt_transfer->au1_op_data [ 1 ] << U1S_SFMA0_BIT_OPD1);
        /* OPD1                                 */
        u4t_regSMOPR |= ( uint32_t )(pstt_transfer->au1_op_data [ 0 ] << U1S_SFMA0_BIT_OPD0);
        /* OPD0                                 */

        /*------------------------*/
        /* Create value for SMENR */
        /*------------------------*/
        u4t_regSMENR = ( uint32_t )0x00000000; /* Initialize                           */
        u4t_regSMENR |= ( uint32_t )(pstt_transfer->b2_size_cmd << U1S_SFMA0_BIT_CDB);
        /* CDB                                  */
        u4t_regSMENR |= ( uint32_t )(pstt_transfer->b2_size_op_cmd << U1S_SFMA0_BIT_OCDB);
        /* OCDB                                 */
        u4t_regSMENR |= ( uint32_t )(pstt_transfer->b2_size_addr << U1S_SFMA0_BIT_ADB);
        /* ADB                                  */
        u4t_regSMENR |= ( uint32_t )(pstt_transfer->b2_size_op_data << U1S_SFMA0_BIT_OPDB);
        /* OPDB                                 */
        u4t_regSMENR |= ( uint32_t )(pstt_transfer->b2_size_data << U1S_SFMA0_BIT_SPIDB);
        /* SPIDB                                */
        u4t_regSMENR |= ( uint32_t )(pstt_transfer->b1_en_dmy_cycle << U1S_SFMA0_BIT_DME);
        /* DME                                  */
        u4t_regSMENR |= ( uint32_t )(pstt_transfer->b1_en_cmd << U1S_SFMA0_BIT_CDE);
        /* CDE                                  */
        u4t_regSMENR |= ( uint32_t )(pstt_transfer->b1_en_op_cmd << U1S_SFMA0_BIT_OCDE);
        /* OCDE                                 */
        u4t_regSMENR |= ( uint32_t )(pstt_transfer->b4_en_addr << U1S_SFMA0_BIT_ADE);
        /* ADE                                  */
        u4t_regSMENR |= ( uint32_t )(pstt_transfer->b4_en_op_data << U1S_SFMA0_BIT_OPDE);
        /* OPDE                                 */
        u4t_regSMENR |= ( uint32_t )(pstt_transfer->b4_en_data << U1S_SFMA0_BIT_SPIDE);
        /* SPIDE                                */

        /*---------------------------------*/
        /* Create value for SMWDR0, SMWDR1 */
        /*---------------------------------*/
        u4t_regSMWDR0 = pstt_transfer->au4_wdata [ 0 ];
        u4t_regSMWDR1 = pstt_transfer->au4_wdata [ 1 ];

        /*-------------------------*/
        /* Create value for SMDMCR */
        /*-------------------------*/
        u4t_regSMDMCR = ( uint32_t )0x00000000; /* Initialize                           */
        u4t_regSMDMCR |= ( uint32_t )(pstt_transfer->b2_size_dmy_cycle << U1S_SFMA0_BIT_DMDB);
        /* DMDB                                 */
        u4t_regSMDMCR |= ( uint32_t )(pstt_transfer->b3_num_dmy_cycle << U1S_SFMA0_BIT_DMCYC);
        /* DMCYC                                */

        /*--------------------------*/
        /* Create value for SMDRENR */
        /*--------------------------*/
        u4t_regSMDRENR = ( uint32_t )0x00000000; /* Initialize                           */
        u4t_regSMDRENR |= ( uint32_t )(pstt_transfer->b1_ddr_addr << U1S_SFMA0_BIT_ADDRE);
        /* ADDRE                                */
        u4t_regSMDRENR |= ( uint32_t )(pstt_transfer->b1_ddr_op_data << U1S_SFMA0_BIT_OPDRE);
        /* OPDRE                                */
        u4t_regSMDRENR |= ( uint32_t )(pstt_transfer->b1_ddr_data << U1S_SFMA0_BIT_SPIDRE);
        /* SPIDRE                               */

        /*------------------------*/
        /* Set value to registers */
        /*------------------------*/
        SFMA0SMCR    = u4t_regSMCR;
        SFMA0SMCMR   = u4t_regSMCMR;
        SFMA0SMADR   = u4t_regSMADR;
        SFMA0SMOPR   = u4t_regSMOPR;
        SFMA0SMENR   = u4t_regSMENR;
        SFMA0SMWDR0  = u4t_regSMWDR0;
        SFMA0SMWDR1  = u4t_regSMWDR1;
        SFMA0SMDMCR  = u4t_regSMDMCR;
        SFMA0SMDRENR = u4t_regSMDRENR;

        /*----------------*/
        /* Start transfer */
        /*----------------*/
        u4t_regSMCR |= ( uint32_t )(( uint32_t )1 << U1S_SFMA0_BIT_SPIE);
        SFMA0SMCR = u4t_regSMCR;

        /*-----------------------*/
        /* Wait for end transfer */
        /*-----------------------*/
        do
        {
            u1t_bitTEND = (uint8_t)SFMA0TEND;
        }
        while (u1t_bitTEND == U1_OFF);

        for ( i = 100000; i > 0; i--) {
            asm("nop");
        }
        /*---------------*/
        /* Get read data */
        /*---------------*/
        pstt_transfer->au4_rdata [ 0 ] = SFMA0SMRDR0;
        pstt_transfer->au4_rdata [ 1 ] = SFMA0SMRDR1;
    }
    /* "Parameter Check" is NG */
    else
    {
        u1t_ret = U1G_SFMA0_RET_NG_PARAM;
    }

    return u1t_ret;
}

/*------------------------------------------------------------------------------------------------------*/
/* Internal function                                                                                    */
/*------------------------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------------------------*/
/* Function Name : TYW_SFMA0_CheckTransferArg                                                           */
/* Description   : Check transfer argment                                                               */
/*                                                                                                      */
/* Arguments     : pstt_transfer : data transfer structure                                              */
/* Return Value  : result(U1G_SFMA0_RET_xxx)                                                            */
/* Note          : None                                                                                 */
/*------------------------------------------------------------------------------------------------------*/
uint8_t TYW_SFMA0_CheckTransferArg(const st_SFMA0_Transfer *pstt_transfer)
{
    uint8_t u1t_ret; /* return value                         */

    /* Check NULL */
    if ( pstt_transfer == R_NULL )
    {
        u1t_ret = U1G_SFMA0_RET_NG_PARAM;
    }
    /* Check "Address Enable"(b4_en_addr) */
    else if ( (pstt_transfer->b4_en_addr != U1G_SFMA0_EN_ADDR_DISABLE) && (pstt_transfer->b4_en_addr != U1G_SFMA0_EN_ADDR_8BIT) && (pstt_transfer->b4_en_addr != U1G_SFMA0_EN_ADDR_16BIT) && (pstt_transfer->b4_en_addr != U1G_SFMA0_EN_ADDR_24BIT) && (pstt_transfer->b4_en_addr != U1G_SFMA0_EN_ADDR_32BIT) )
    {
        u1t_ret = U1G_SFMA0_RET_NG_PARAM;
    }
    /* Check "Option Data Enable"(b4_en_op_data) */
    else if ( (pstt_transfer->b4_en_op_data != U1G_SFMA0_EN_OP_DATA_DISABLE) && (pstt_transfer->b4_en_op_data != U1G_SFMA0_EN_OP_DATA_OPD3) && (pstt_transfer->b4_en_op_data != U1G_SFMA0_EN_OP_DATA_OPD3_OPD2) && (pstt_transfer->b4_en_op_data != U1G_SFMA0_EN_OP_DATA_OPD3_OPD1) && (pstt_transfer->b4_en_op_data != U1G_SFMA0_EN_OP_DATA_OPD3_OPD0) )
    {
        u1t_ret = U1G_SFMA0_RET_NG_PARAM;
    }
    /* Check "Transfer Data Enable"(b4_en_data) */
    else if ( (pstt_transfer->b4_en_data != U1G_SFMA0_EN_DATA_DISABLE) && (pstt_transfer->b4_en_data != U1G_SFMA0_EN_DATA_16BIT) && (pstt_transfer->b4_en_data != U1G_SFMA0_EN_DATA_32BIT) && (pstt_transfer->b4_en_data != U1G_SFMA0_EN_DATA_64BIT) )
    {
        u1t_ret = U1G_SFMA0_RET_NG_PARAM;
    }
    /* Check "Number of Dummy Cycles"(b3_num_dmy_cycle) */
    else if ( (pstt_transfer->b3_num_dmy_cycle != U1G_SFMA0_NUM_DUMMY_CYCLE_1) && (pstt_transfer->b3_num_dmy_cycle != U1G_SFMA0_NUM_DUMMY_CYCLE_2) && (pstt_transfer->b3_num_dmy_cycle != U1G_SFMA0_NUM_DUMMY_CYCLE_3) && (pstt_transfer->b3_num_dmy_cycle != U1G_SFMA0_NUM_DUMMY_CYCLE_4) && (pstt_transfer->b3_num_dmy_cycle != U1G_SFMA0_NUM_DUMMY_CYCLE_5) && (pstt_transfer->b3_num_dmy_cycle != U1G_SFMA0_NUM_DUMMY_CYCLE_6) && (pstt_transfer->b3_num_dmy_cycle != U1G_SFMA0_NUM_DUMMY_CYCLE_7) && (pstt_transfer->b3_num_dmy_cycle != U1G_SFMA0_NUM_DUMMY_CYCLE_8) )
    {
        u1t_ret = U1G_SFMA0_RET_NG_PARAM;
    }
    /* Check "Command Bit Size"(b2_size_cmd) */
    else if ( (pstt_transfer->b2_size_cmd != U1G_SFMA0_SIZE_1BIT) && (pstt_transfer->b2_size_cmd != U1G_SFMA0_SIZE_2BIT) && (pstt_transfer->b2_size_cmd != U1G_SFMA0_SIZE_4BIT) )
    {
        u1t_ret = U1G_SFMA0_RET_NG_PARAM;
    }
    /* Check "Optional Command Bit Size"(b2_size_op_cmd) */
    else if ( (pstt_transfer->b2_size_op_cmd != U1G_SFMA0_SIZE_1BIT) && (pstt_transfer->b2_size_op_cmd != U1G_SFMA0_SIZE_2BIT) && (pstt_transfer->b2_size_op_cmd != U1G_SFMA0_SIZE_4BIT) )
    {
        u1t_ret = U1G_SFMA0_RET_NG_PARAM;
    }
    /* Check "Address Bit Size"(b2_size_addr) */
    else if ( (pstt_transfer->b2_size_addr != U1G_SFMA0_SIZE_1BIT) && (pstt_transfer->b2_size_addr != U1G_SFMA0_SIZE_2BIT) && (pstt_transfer->b2_size_addr != U1G_SFMA0_SIZE_4BIT) )
    {
        u1t_ret = U1G_SFMA0_RET_NG_PARAM;
    }
    /* Check "Option Data Bit Size"(b2_size_op_data) */
    else if ( (pstt_transfer->b2_size_op_data != U1G_SFMA0_SIZE_1BIT) && (pstt_transfer->b2_size_op_data != U1G_SFMA0_SIZE_2BIT) && (pstt_transfer->b2_size_op_data != U1G_SFMA0_SIZE_4BIT) )
    {
        u1t_ret = U1G_SFMA0_RET_NG_PARAM;
    }
    /* Check "Transfer Data Bit Size"(b2_size_data) */
    else if ( (pstt_transfer->b2_size_data != U1G_SFMA0_SIZE_1BIT) && (pstt_transfer->b2_size_data != U1G_SFMA0_SIZE_2BIT) && (pstt_transfer->b2_size_data != U1G_SFMA0_SIZE_4BIT) )
    {
        u1t_ret = U1G_SFMA0_RET_NG_PARAM;
    }
    /* Check "Dummy Cycle Bit Size"(b2_size_dmy_cycle) */
    else if ( (pstt_transfer->b2_size_dmy_cycle != U1G_SFMA0_SIZE_1BIT) && (pstt_transfer->b2_size_dmy_cycle != U1G_SFMA0_SIZE_2BIT) && (pstt_transfer->b2_size_dmy_cycle != U1G_SFMA0_SIZE_4BIT) )
    {
        u1t_ret = U1G_SFMA0_RET_NG_PARAM;
    }
    /* Check result is OK */
    else
    {
        u1t_ret = U1G_SFMA0_RET_OK;
    }

    return u1t_ret;
}