/*
 * @file hv_cal_Qspi.h
 * @brief Header file of misc module.
 *
 * @verbatim
 * ==============================================================================
 *                        ##### How to use #####
 * ==============================================================================
 * (+) Use ()
 *
 * @endverbatim
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2023-06-19
 */


/** @file
 *  @brief HomeBus CAL APIs
*/

#ifndef _HV_CAL_QSPI_H
#define _HV_CAL_QSPI_H

#include "hv_comm_DataType.h"
#include "hv_comm_Define.h"
#include "hv_cal_Dma.h"

typedef enum _QspiRateMode
{
    QSPI_STANDARD = 0,
    SPI_DUAL,
    QSPI_QUAD,
} QspiRateMode;

typedef enum _QspiState
{
    /*!< QSPI not yet initialized or disabled           */
    QSPI_STATE_RESET = 0,
    /*!< QSPI initialized and ready for use             */
    QSPI_STATE_READY,
    /*!< QSPI process is ongoing                        */
    QSPI_STATE_BUSY,
    /*!< Data Transmission process is ongoing               */
    QSPI_STATE_BUSY_TX,
    /*!< Data Reception process is ongoing                  */
    QSPI_STATE_BUSY_RX,
    /*!< Data Transmission and Reception process is ongoing */
    QSPI_STATE_BUSY_TXRX,
    /*!< SPI error state                                    */
    QSPI_STATE_ERROR
} QspiState;

typedef enum _QspiDirection
{
    /*!< The DataSize for transmition is 8bits  */
    QSPI_DIRECTION_TXRX = 0,
    /*!< The DataSize for transmition is 16bits */
    QSPI_DIRECTION_TX,
    /*!< The DataSize for transmition is 32bits */
    QSPI_DIRECTION_RX,
} QspiDirection;

typedef enum _QspiError
{
    /*!< No error             */
    QSPI_ERROR_NONE = 0,
    /*!< MODF error           */
    QSPI_ERROR_MODF,
    /*!< Tx fifo empty when transmit start as slave*/
    QSPI_ERROR_TFEMPTY,
    /*!< OVR error            */
    QSPI_ERROR_OVR,
    /*!< DMA transfer error   */
    QSPI_ERROR_DMA,
    /*!< Flag: RXNE,TXE, BSY  */
    QSPI_ERROR_FLAG,
    /*!< SPI Timeout erro     */
    QSPI_ERROR_TIMEOUT
} QspiError;

typedef enum _QspiTransType
{
    QSPI_WRITE = 0,
    QSPI_READ,
} QspiTransType;

typedef enum _QspiPolarity
{
    QSPI_POLARITY_LOW = 0,
    QSPI_POLARITY_HIGH,
} QspiPolarity;

typedef enum _QspiPhase
{
    QSPI_PHASE_EDGE1 = 0,
    QSPI_PHASE_EDGE2,
} QspiPhase;

typedef enum _QspiBitWidth
{
    /*!< The DataSize for transmition is 8bits    */
    QSPI_BITWIDTH_8  = 0x07,
    /*!< The DataSize for transmition is 16bits */
    QSPI_BITWIDTH_16 = 0x0f,
    /*!< The DataSize for transmition is 24bits */
    QSPI_BITWIDTH_24 = 0x17,
    /*!< The DataSize for transmition is 32bits */
    QSPI_BITWIDTH_32 = 0x1f,
} QspiBitWidth;

typedef enum _QspiDivideRatio
{
    QSPI_DIVRATIO_2     = 1,
    QSPI_DIVRATIO_4     = 2,
    QSPI_DIVRATIO_8     = 4,
    QSPI_DIVRATIO_16    = 8,
    QSPI_DIVRATIO_32    = 16,
    QSPI_DIVRATIO_64    = 32,
    QSPI_DIVRATIO_128   = 64,
    QSPI_DIVRATIO_256   = 128,
    QSPI_DIVRATIO_512   = 256,
    QSPI_DIVRATIO_1024   = 512,
    QSPI_DIVRATIO_32768 = 16384,
    QSPI_DIVRATIO_65534 = 32767,
} QspiDivideRatio;

typedef enum _QspiInstruWidth
{
    QSPI_INSTRUWIDTH_0 = 0,
    QSPI_INSTRUWIDTH_4,
    QSPI_INSTRUWIDTH_8,
    QSPI_INSTRUWIDTH_16,
} QspiInstruWidth;

typedef enum _QspiAddrWidth
{
    QSPI_ADDRWIDTH_0   = 0,
    QSPI_ADDRWIDTH_4   = 1,
    QSPI_ADDRWIDTH_8   = 2,
    QSPI_ADDRWIDTH_16  = 4,
    QSPI_ADDRWIDTH_24  = 6,
    QSPI_ADDRWIDTH_32  = 8,
} QspiAddrWidth;

typedef enum _QspiInstruAddrType
{
    QSPI_INSTRU_STAND_ADDR_STAND = 0,
    QSPI_INSTRU_STAND_ADDR_MULTI,
    QSPI_INSTRU_MULTI_ADDR_MULTI,
} QspiInstruAddrType;

typedef enum _QspiDmaTxEn
{
    QSPI_DMATX_DISABLE = 0,
    QSPI_DMATX_ENABLE,
} QspiDmaTxEn;

typedef enum _QspiDmaRxEn
{
    QSPI_DMARX_DISABLE = 0,
    QSPI_DMARX_ENABLE,
} QspiDmaRxEn;

typedef enum _QspiTransComplete
{
    QSPI_TRANS_IN_PROCESS = 0,
    QSPI_TRANS_END,
} QspiTransComplete;

typedef enum _QspiCsSel
{
    QSPI_CS_HARDWARE_SELF = 0,
    QSPI_CS_BY_GPIO,
} QspiCsSel;

typedef Status (*Hv_Qspi_CpltCallback)(QspiTransType transType,void *arg);

typedef struct QspiInitParam
{
    /*!< Specifies the SPI speed mode.                  */
    QspiRateMode  RateMode;
    /*!< Specifies the SPI Directional mode state.      */
    QspiDirection Direction;
    /*!< Specifies the SPI data size.                   */
    QspiBitWidth  DataSize;
    /*!< Specifies the serial clock steady state.       */
    QspiPolarity  CLKPolarity;
    /*!< Specifies the clock active edge for capture.   */
    QspiPhase     CLKPhase;
    /*!< Specifies the Baud Rate prescaler value.       */
    QspiDivideRatio  BaudRatePrescaler;
	QspiCsSel    CsSel;
    /*!< Qspi transmit complete fuction.                */
    Hv_Qspi_CpltCallback QspiCpltCallback;
} QspiInitParam;

typedef struct  _QspiSelf  QspiSelf;

#define QSPI_TIMEOUT                             1000
#define QSPI_FIFO_DEPTH                          16
#define QSPI_DR_ADDR_RANGE_TOTAL                 34 * 4  /* Data Register  */

#define QSPI_DMA_TX_THRESHOLD                    8
#define QSPI_DMA_RX_THRESHOLD                    7

#define QSPI_SLAVE_SELECT_EN                     1
#define QSPI_XIP_STRU_EN                         1
#define QSPI_CONTINU_XFER_EN                     1

#define QSPI_FLAG_BUSY                           ((UINT32)0x00010001)
#define QSPI_FLAG_TFNF                           ((UINT32)0x00010002)
#define QSPI_FLAG_TFE                            ((UINT32)0x00010004)
#define QSPI_FLAG_RFNE                           ((UINT32)0x00010008)
#define QSPI_FLAG_RFF                            ((UINT32)0x00010010)
#define QSPI_FLAG_TXE                            ((UINT32)0x00010020)
#define QSPI_FLAG_DCOL                           ((UINT32)0x00010040)

#define QSPI_FLAG_TXEIR                          ((UINT32)0x00000001)
#define QSPI_FLAG_TXOIR                          ((UINT32)0x00000002)
#define QSPI_FLAG_RXUIR                          ((UINT32)0x00000004)
#define QSPI_FLAG_RXOIR                          ((UINT32)0x00000008)
#define QSPI_FLAG_RXFIR                          ((UINT32)0x00000010)
#define QSPI_FLAG_MSTIR                          ((UINT32)0x00000020)
#define QSPI_FLAG_MASK                           ((UINT32)0x0000007F)

/***************************************QSPI config API************************************/

void Hv_Cal_Qspi_SetFlashPoint(QspiSelf *pstSelf,void* pFlashPoint);

void* Hv_Cal_Qspi_GetFlashPoint(QspiSelf *pstSelf);

/** Tx and Rx Transfer completed callbacks
 *  @param self pointer to a QSPI structure that contains the configuration information.
 *  @param CallbackFunc callback defined by user.
 */
void Hv_Cal_Qspi_SetCpltCallBack(QspiSelf *pstSelf, void * CallbackFunc);

QspiRateMode Hv_Cal_Qspi_GetRateMode(QspiSelf *pstSelf);

void Hv_Cal_Qspi_SetRateMode(QspiSelf *pstSelf, QspiRateMode RateMode);

/** Set transfer mode as direction
 *  @param self pointer to a QSPI structure that contains the configuration information.
 *  @param Direction 0x0(TX_AND_RX),0x1(TX_ONLY),0x2(RX_ONLY),0x3(EEPROM_READ).
 */
void Hv_Cal_Qspi_SetDirection(QspiSelf *pstSelf, QspiDirection Direction);

/** Set data frame size
 *  @param self Pointer to a QSPI structure that contains the configuration information.
 *  @param FrameWidth Indicates how many bits of data are serially transmitted in a frame.
 */
void Hv_Cal_Qspi_SetFrameBitsWidth(QspiSelf *pstSelf, QspiBitWidth FrameWidth);

/** Set TOP_QSPI_SPI_CTRLR0 register, contains SSIC_EN, INST_L, ADDR_L, WAIT_CYCLES
 *  @param self Pointer to a QSPI structure that contains the configuration information.
 *  @param instrWidth Dual/Quad/Octal mode instruction length in bits
 *  @param AddrWidth Defines length of address to be transmitted.
 *  @param waitCycle Wait cycles in dual/quad/octal mode between control frames transmit and
 *  data reception. Specified as number of SPI clock cycles.
 */
void Hv_Cal_Qspi_SetMultiIOCtrl(QspiSelf *pstSelf, QspiInstruAddrType transType,
                                UCHAR8 ucInstrWidth, UCHAR8 ucAddrWidth, UINT32 uiWaitCycle);

/** Set the length of address to be transmitted.
 *  @param self Pointer to a QSPI structure that contains the configuration information.
 *  @param AddrWidth Defines length of address to be transmitted.
 */
void Hv_Cal_Qspi_SetAddrBitsWidth(QspiSelf *pstSelf, UCHAR8 ucAddrWidth);

/** Set the baudrate
 *  @param self Pointer to a QSPI structure that contains the configuration information.
 *  @param BaudRate baudrate which will set as SSI Clock Divider.
 */
void Hv_Cal_Qspi_SetBaudRate(QspiSelf *pstSelf, QspiDivideRatio BaudRate);

/** Sets the number of data frames to be continuously received by the DWC_ssi.
 *  @param self Pointer to a QSPI structure that contains the configuration information.
 *  @param readDataNum number of data frames
 */
void Hv_Cal_Qspi_SetReadNumber(QspiSelf *pstSelf, UINT32 uiReadDataNum);


void Hv_Cal_Qspi_SetDmaTx(QspiSelf *pstSelf, DmaSelf *hdmaTx);
void Hv_Cal_Qspi_SetDmaRx(QspiSelf *pstSelf, DmaSelf *hdmaRx);

/***************************************QSPI Init API*******************************************/
/** Initializes the qspi flash peripheral according to the specified parameters.
 *  @param initParam pointer to the configuration information.
 *  @return qspi flash structure pointer
 */
QspiSelf* Hv_Cal_Qspi_Init( QspiInitParam *InitParam);

/** De-initialize qspi flash
 *  @param self qspi flash pointer
 *  @return result
 */
Status Hv_Cal_Qspi_Cleanup(QspiSelf *pstSelf);

/***************************************QSPI Tramsmit API***************************************/

/** Write data to qspi flash in blocking mode.
 *  @param self Pointer to a QSPI structure that contains the configuration information.
 *  @param pCmdAddr pointer to command data buffer
 *  @param pCmdSize command length
 *  @param pTxData pointer to data buffer to be transmited
 *  @param size amount of data to be sent
 *  @param timeout timeout duration
 *  @retval result
 */
Status Hv_Cal_Qspi_PollingWrite(QspiSelf *pstSelf, UCHAR8* pucCmdAddr, USHORT16 pusCmdSize,
                                UCHAR8* pucTxData, USHORT16 usDataSize, UINT32 uiTimeout);

/** Write data to qspi flash in blocking mode.
 *  @param self Pointer to a QSPI structure that contains the configuration information.
 *  @param pCmdAddr pointer to command data buffer
 *  @param pCmdSize command length
 *  @param pTxData pointer to data buffer to be transmited
 *  @param size amount of data to be sent
 *  @param timeout timeout duration
 *  @retval result
 */
Status Hv_Cal_Qspi_MutiIoPollingWrite(QspiSelf *pstSelf, UCHAR8* pucCmdAddr, USHORT16 usCmdAddrSize,
                                      UCHAR8* pucTxData, USHORT16 usDataSize, UINT32 uiTimeout);

/** Read data from qspi flash in blocking mode.
 *  @param self Pointer to a QSPI structure that contains the configuration information.
 *  @param pCmdAddr pointer to command data buffer
 *  @param cmdAddrSize command length
 *  @param pRxData pointer to data buffer
 *  @param dataSize amount of data to be sent
 *  @param dSize the dummy size of receive
 *  @param timeout timeout duration
 *  @retval result
 */
Status Hv_Cal_Qspi_PollingRead(QspiSelf *pstSelf, UCHAR8 *pucCmdAddr, USHORT16 usCmdAddrSize,
                               UCHAR8 *pucRxData, USHORT16 usDataSize, UINT32 uiTimeout);

/** Read data from qspi flash in blocking mode.
 *  @param self Pointer to a QSPI structure that contains the configuration information.
 *  @param pCmdAddr pointer to command data buffer
 *  @param cmdAddrSize command length
 *  @param pRxData pointer to data buffer
 *  @param dataSize amount of data to be sent
 *  @param timeout timeout duration
 *  @retval result
 */
Status Hv_Cal_Qspi_MultiIoPollingRead(QspiSelf *pstSelf,  UCHAR8 *pucCmdAddr, USHORT16 usCmdAddrSize,
                                      UCHAR8 *pucRxData, USHORT16 usDataSize, UINT32 uiTimeout);

/** Write data to qspi flash with interrupt
 *  @param self Pointer to a QSPI structure that contains the configuration information.
 *  @param pCmdAddr pointer to command data buffer
 *  @param cmdAddrSize command length
 *  @param pTxData pointer to data buffer to be transmited
 *  @param size amount of data to be sent
 *  @retval result
 */
Status Hv_Cal_Qspi_IntWrite(QspiSelf *pstSelf, UCHAR8* pucCmdAddr, USHORT16 usCmdAddrSize,
                            UCHAR8* pucTxData, USHORT16 usDataSize);

/** Read data from qspi flash with interrupt
 *  @param self Pointer to a QSPI structure that contains the configuration information.
 *  @param pCmdAddr pointer to command data buffer
 *  @param cmdAddrSize command length
 *  @param pRxData pointer to data buffer
 *  @param dataSize amount of data to be sent
 *  @param dSize the dummy size of receive
 *  @retval result
 */
Status Hv_Cal_Qspi_IntRead(QspiSelf *pstSelf,  UCHAR8 *pucCmdAddr, USHORT16 usCmdAddrSize,
                           UCHAR8 *pucRxData, USHORT16 usDataSize);

/** Write data to qspi flash with DMA
 *  @param self Pointer to a QSPI structure that contains the configuration information.
 *  @param pTxData pointer to data buffer to be transmited
 *  @param size amount of data to be sent
 *  @retval result
 */
Status Hv_Cal_Qspi_DmaWrite(QspiSelf *pstSelf, UCHAR8* pucTxData, USHORT16 usDataSize);

/** Read data from qspi flash with DMA
 *  @param self Pointer to a QSPI structure that contains the configuration information.
 *  @param pCmdAddr pointer to command data buffer
 *  @param cmdAddrSize command length
 *  @param pRxData pointer to data buffer
 *  @param dataSize amount of data to be sent
 *  @retval result
 */
Status Hv_Cal_Qspi_DmaRead(QspiSelf *pstSelf,  UCHAR8 *pucCmdAddr, USHORT16 usCmdAddrSize,
                           UCHAR8* pRxData, USHORT16 usDataSize);

BOOL Hv_Cal_Qspi_TransferIsComplete(QspiSelf *pstSelf);

/* config wp to protect flash when not in fourline mode. */
VOID Hv_Cal_Qspi_WP_Init(VOID);
/** open or close hardware write protect.
 *  @param ucEnable enable or not.
 */
VOID Hv_Cal_Qspi_WP_Enable(UCHAR8 ucEnable);

#endif

