#include "SFMA_Driver.h"
#include "dr7f701441.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                         */

    /* 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);

        /*---------------*/
        /* 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;
}
