402 lines
11 KiB
C
402 lines
11 KiB
C
/****************************************************************************
|
|
|
|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
|
|
|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
|
be copied by any method or incorporated into another program without
|
|
the express written consent of Aerospace C.Power. This Information or any portion
|
|
thereof remains the property of Aerospace C.Power. The Information contained herein
|
|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
|
liability for its use in any way and conveys no license or title under
|
|
any patent or copyright and makes no representation or warranty that this
|
|
Information is free from patent or copyright infringement.
|
|
|
|
****************************************************************************/
|
|
#ifndef IOT_SPI_API_H
|
|
#define IOT_SPI_API_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/** \defgroup SPI_APIs SPI APIs
|
|
* @brief SPI APIs
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
|
|
/** @addtogroup SPI_APIs
|
|
* @{
|
|
*/
|
|
|
|
#define INCLUDE_DW_APB_SSI
|
|
|
|
#ifdef INCLUDE_DW_APB_SSI
|
|
|
|
/**
|
|
* @brief Poll mode Usage:
|
|
|
|
xfer_buf spi_tx, spi_rx;
|
|
|
|
iot_spi_cfg_t cfg = {0};
|
|
cfg.gpio.clk = xx;
|
|
cfg.gpio.cs = xx;
|
|
cfg.gpio.miso = xx;
|
|
cfg.gpio.mosi = xx;
|
|
cfg.port = xx; //see spi_device_list
|
|
iot_spi_module_init(&cfg);
|
|
|
|
iot_spi_dev_register(DEVICE_SPI0_MASTER, 1, 0, \
|
|
isr_func, INT_RXFIFO_FULL|INT_TXFIFO_EMPTY);
|
|
|
|
spi_tx.p_nt = &spi_rx; // Next buffer after this sent.
|
|
spi_tx.txbuf = spi_tx_buf;
|
|
spi_tx.rxbuf = NULL; // dummy data will be dropped.
|
|
spi_tx.size = SPI_SENT_SIZE; //To send SPI_SENT_SIZE byte from spi_tx_buf.
|
|
spi_rx.xfer_size =0;
|
|
|
|
spi_rx.p_nt = NULL;
|
|
spi_rx.rxbuf = spi_rx_buf;
|
|
spi_rx.txbuf = tmp_buf; // dummy data will be sent to slaver.
|
|
spi_rx.size = SPI_READ_SIZE; // To get SPI_READ_SIZE size of data.
|
|
spi_rx.xfer_size =0;
|
|
|
|
iot_spi_poll_transfer(DEVICE_SPI0_MASTER, &spi_tx);
|
|
|
|
...
|
|
|
|
*/
|
|
|
|
/**
|
|
* @brief SPI timing.
|
|
*/
|
|
struct timing_config
|
|
{
|
|
int scpol:1; /**< CLK stay in Low (0) or high (1) when idle */
|
|
int scph:1; /**< 0 - Data transmited on falling edge of CS,
|
|
captured on the 1ST edge of CLK
|
|
1 - Data transmited on the 1ST edge of CLK,
|
|
captured on the 2ND edge of CLK. */
|
|
int scph_tgl:1;
|
|
int sste:1; /**< scph_tgl=0 & sste=1 , CS toggled between frames and
|
|
CLK set default between frames .Else, CS stays LOW and CLK run
|
|
continuously alwaays */
|
|
int rev:28;
|
|
};
|
|
|
|
/**
|
|
* @brief SPI dma config.
|
|
*/
|
|
struct spi_dma_config
|
|
{
|
|
short rx_enable; /**< If to enable rx-DMA */
|
|
short tx_enable; /**< If to enable tx-DMA */
|
|
int rx_datalevel; /**< This bit field controls the level at which
|
|
a DMA request is made by the receive logic.The watermark level
|
|
= rx_datalevel+1 */
|
|
int tx_datalevel; /**< This bit field controls the level at which
|
|
a DMA request is made by the transmit logic.It is equal to the
|
|
watermark level */
|
|
};
|
|
|
|
/**
|
|
* @brief SPI device list.
|
|
*/
|
|
enum spi_device_list
|
|
{
|
|
DEVICE_SPI0_MASTER,
|
|
DEVICE_SPI1_MASTER,
|
|
DEVICE_SPI0_SLAVER,
|
|
DEVICE_SPI2_MASTER,
|
|
DEVICE_SPI_MAX
|
|
};
|
|
|
|
typedef struct _iot_spi_gpio_sel {
|
|
uint8_t clk;
|
|
uint8_t cs;
|
|
uint8_t miso;
|
|
uint8_t mosi;
|
|
} iot_spi_gpio_sel_t;
|
|
|
|
typedef struct _iot_spi_cfg {
|
|
uint8_t port;
|
|
iot_spi_gpio_sel_t gpio;
|
|
} iot_spi_cfg_t;
|
|
|
|
#define SPI_DFRAME_SIZE_8 8
|
|
#define SPI_DFRAME_SIZE_16 16
|
|
#define SPI_DFRAME_SIZE_32 32 /* NOT available for NOW */
|
|
|
|
#define DEVICE_SPI_CNT DEVICE_SPI_MAX
|
|
#define DEVICE_SPI_SYS_CLK 75*1000*1000 /* 75M */
|
|
#define DEVICE_SPI_DEFAULT_FREQUENCY 100*1000 /* 100K */
|
|
#define DEVICE_SPI_DEFAULT_RX_THRESHOULD 12
|
|
#define DEVICE_SPI_DEFAULT_TX_THRESHOULD 5
|
|
#define DEVICE_SPI_DEFAULT_CS_EN 1
|
|
|
|
|
|
/* Mask */
|
|
#define INT_RXFIFO_FULL BIT(4)
|
|
#define INT_RXFIFO_OVERFLOW BIT(3)
|
|
#define INT_RXFIFO_UNDERFLOW BIT(2)
|
|
#define INT_TXFIFO_EMPTY BIT(1)
|
|
#define INT_TXFIFO_OVERFLOW BIT(0)
|
|
#else
|
|
#error "No SPI device included !"
|
|
#endif
|
|
|
|
#define SPI_MASTER 0
|
|
#define SPI_SLAVER 1
|
|
|
|
/**
|
|
* We provide a new iot_spi_dev_open function to replace iot_spi_module_init.
|
|
* The macro definition here is for compatibility with previous programs.
|
|
*/
|
|
#define iot_spi_module_init(cfg) iot_spi_dev_open(cfg)
|
|
|
|
typedef void (*int_isr)(int);
|
|
typedef void (*dma_complete_cb_t)(int);
|
|
|
|
/**
|
|
* @brief SPI transerver mode.
|
|
*/
|
|
enum trans_mode
|
|
{
|
|
TMOD_TRANCIEVER = 0, /**< transmit and receive */
|
|
TMOD_TRANSMITER = 1, /**< transmit only */
|
|
TMOD_RECIEVER = 2, /**< receive only */
|
|
};
|
|
|
|
/**
|
|
* @brief SPI frame mode.
|
|
*/
|
|
enum frame_format
|
|
{
|
|
FRM_STD, /**< Only mode supported. */
|
|
FRM_DUAL,
|
|
FRM_QUAD,
|
|
FRM_OCTAL
|
|
};
|
|
|
|
/**
|
|
* @brief SPI config.
|
|
*/
|
|
typedef struct spi_config
|
|
{
|
|
/** Master or slaver */
|
|
int dev_type:2;
|
|
/** trans_mode */
|
|
int trs_mode:2;
|
|
/** frame_format */
|
|
int frm_fmt:2;
|
|
/** Data frame size, SPI_DFRAME_SIZE_8 suggested. */
|
|
int dfrm_sz:6;
|
|
/** slave select enable*/
|
|
int cs_en:1;
|
|
int rev:19;
|
|
/** Device frequency. Like DEVICE_SPI_DEFAULT_FREQUENCY */
|
|
int frq;
|
|
/**< Threshold for reviecing fifo. 0xF is max */
|
|
int rx_thd;
|
|
/**< Threshold for transmitting fifo. 0xF is max */
|
|
int tx_thd;
|
|
}spi_cfg;
|
|
|
|
/**
|
|
* @brief SPI xfer buffer.
|
|
*/
|
|
typedef struct spi_xfer_buf
|
|
{
|
|
struct spi_xfer_buf *p_nt;
|
|
/** bytes for recieving or for transmiting. */
|
|
int size;
|
|
/** bytes recieved or transmited */
|
|
int xfer_size;
|
|
char *rxbuf;
|
|
char *txbuf;
|
|
}xfer_buf;
|
|
|
|
typedef struct timing_config tm_cfg;
|
|
typedef struct spi_dma_config sdma_cfg;
|
|
|
|
/**
|
|
* @brief iot_spi_dev_register_detail() - Register a spi device.For detail using.
|
|
* @param dev: See enum spi_device_list.
|
|
* @param cfg: See spi_cfg, For spi config.
|
|
* @param tm: See struct timing_config, For timming config.
|
|
* @param dma_cfg: See sdma_cfg, For spi dma.
|
|
* @param isr: See int_isr, ISR for interrupts.
|
|
* @param int_mask: Interrupt mask. See #define INT_*.
|
|
* @see ERR_FAIL
|
|
* @see ERR_OK
|
|
* @return ERR_FAIL -- Operation failed.
|
|
* @return ERR_OK -- Operation Successful.
|
|
*/
|
|
int iot_spi_dev_register_detail
|
|
(int dev, spi_cfg * cfg, tm_cfg *tm,
|
|
sdma_cfg* dma_cfg, int_isr isr, int int_mask);
|
|
|
|
/**
|
|
* @brief iot_spi_dev_register_detail_dma() - Register a spi device in dma.
|
|
* @param dev: See enum spi_device_list.
|
|
* @param cfg: See spi_cfg, For spi config.
|
|
* @param tm: See struct timing_config, For timming config.
|
|
* @param dma_cfg: See sdma_cfg, For spi dma.
|
|
* @param isr: See int_isr, ISR for interrupts.
|
|
* @param int_mask: Interrupt mask. See #define INT_*.
|
|
* @param cb: Dma tansfer complete will call it
|
|
* @see ERR_FAIL
|
|
* @see ERR_OK
|
|
* @return ERR_FAIL -- Operation failed.
|
|
* @return ERR_OK -- Operation Successful.
|
|
*/
|
|
int iot_spi_dev_register_detail_dma(int dev, spi_cfg * cfg, tm_cfg *tm,
|
|
sdma_cfg* dma_cfg, dma_complete_cb_t cb);
|
|
|
|
/**
|
|
* @brief iot_spi_dev_register() - Register a spi device.
|
|
* @param dev: See enum spi_device_list.
|
|
* @param is_master: 0 for slaver, else master.
|
|
* @param is_dma: 0 for none-dma, else dma..
|
|
* @param isr: See int_isr, ISR for interrupts.
|
|
* @param int_mask: Interrupt mask. See #define INT_*.
|
|
* @param auto_cs: true - cs signal controled by hardware,
|
|
* false - cs signal controled by software. In this mode, cs signal
|
|
* also controled by iot_spi_poll_transfer() automatically.
|
|
* @see ERR_FAIL
|
|
* @see ERR_OK
|
|
* @return ERR_FAIL -- Operation failed.
|
|
* @return ERR_OK -- Operation Successful.
|
|
*/
|
|
int iot_spi_dev_register
|
|
(int dev, int is_master, int is_dma, int_isr isr, int int_mask, int auto_cs);
|
|
|
|
/**
|
|
* @brief iot_spi_clear_int_status() - Clear status of interrupts.
|
|
* @param dev: See enum spi_device_list.
|
|
* @see ERR_FAIL
|
|
* @see ERR_OK
|
|
* @return ERR_FAIL -- Operation failed.
|
|
* @return ERR_OK -- Operation Successful.
|
|
*/
|
|
int iot_spi_clear_int_status(int dev);
|
|
|
|
/**
|
|
* @brief iot_spi_set_int_enable() - Enable interrupts.
|
|
* @param dev: See enum spi_device_list.
|
|
* @param ena_msk: Interrupt mask. See #define INT_*.
|
|
* @see ERR_FAIL
|
|
* @see ERR_OK
|
|
* @return ERR_FAIL -- Operation failed.
|
|
* @return ERR_OK -- Operation Successful.
|
|
*/
|
|
int iot_spi_set_int_enable(int dev, int ena_msk);
|
|
|
|
/**
|
|
* @brief iot_spi_set_int_enable() - Disable interrupts.
|
|
* @param dev: See enum spi_device_list.
|
|
* @param dis_msk: Interrupt mask. See #define INT_*.
|
|
* @see ERR_FAIL
|
|
* @see ERR_OK
|
|
* @return ERR_FAIL -- Operation failed.
|
|
* @return ERR_OK -- Operation Successful.
|
|
*/
|
|
int iot_spi_set_int_disable(int dev, int dis_msk);
|
|
|
|
/**
|
|
* @brief iot_spi_get_rx_data_cnt() - Get recieved data counting..
|
|
* @param dev: See enum spi_device_list.
|
|
* @param *cnt: Pointer to return the counting.
|
|
* @see ERR_FAIL
|
|
* @see ERR_OK
|
|
* @return ERR_FAIL -- Operation failed.
|
|
* @return ERR_OK -- Operation Successful.
|
|
*/
|
|
int iot_spi_get_rx_data_cnt(int dev, int * cnt);
|
|
|
|
/**
|
|
* @brief iot_spi_get_tx_data_space_cnt() - Get data counting we can
|
|
still put into fifo.
|
|
* @param dev: See enum spi_device_list.
|
|
* @param *cnt: Pointer to return the counting.
|
|
* @see ERR_FAIL
|
|
* @see ERR_OK
|
|
* @return ERR_FAIL -- Operation failed.
|
|
* @return ERR_OK -- Operation Successful.
|
|
*/
|
|
int iot_spi_get_tx_data_space_cnt(int dev, int * cnt);
|
|
|
|
/**
|
|
* @brief iot_spi_read_data() - Get the data recieved.
|
|
* @param dev: See enum spi_device_list.
|
|
* @param *buf: Buffer to store the data.
|
|
* @param *rd_size: Size of data that wanna got.
|
|
* @return -- Size of data that got finally..
|
|
*/
|
|
int iot_spi_read_data(int dev, char *buf, int rd_size);
|
|
|
|
/**
|
|
* @brief iot_spi_write_data() - Transmit data.
|
|
* @param dev: See enum spi_device_list.
|
|
* @param *buf: Buffer to store the data.
|
|
* @param *wt_size: Size of data that wanna sent.
|
|
* @return -- Size of data that sent finally..
|
|
*/
|
|
int iot_spi_write_data(int dev, char *buf, int wt_size);
|
|
|
|
/**
|
|
* @brief iot_spi_poll_transfer() - Transceive data.
|
|
* @param dev: See enum spi_device_list.
|
|
* @param *buf: Buffer to tramsmit and recieve.
|
|
* @return ERR_FAIL -- Operation failed.
|
|
* @return ERR_OK -- Operation Successful.
|
|
*/
|
|
int iot_spi_poll_transfer(int dev, xfer_buf *buf);
|
|
|
|
/**
|
|
* @brief iot_spi_poll_transfer_by_dma() - Transceive data by dma.
|
|
* @param dev: See enum spi_device_list.
|
|
* @param *buf: Buffer to tramsmit and recieve, support single xfer_buf only
|
|
* @param flag: dma complete will set flag to 1
|
|
* @return ERR_FAIL -- Operation failed.
|
|
* @return ERR_OK -- Operation Successful.
|
|
*/
|
|
int iot_spi_poll_transfer_by_dma(int dev, xfer_buf *buf);
|
|
|
|
/**
|
|
* @brief iot_spi_dev_open() - open and initialize the specified SPI port .
|
|
* @param cfg: the pointer to spi initial config structure,
|
|
* cfg->port(see spi_device_list), cfg->gpio.clk, cfg->gpio.mosi,
|
|
* cfg->gpio.miso must be specified.
|
|
* @return ERR_FAIL -- Operation failed.
|
|
* @return ERR_OK -- Operation Successful.
|
|
*/
|
|
int iot_spi_dev_open(iot_spi_cfg_t *cfg);
|
|
|
|
/**
|
|
* @brief iot_spi_tx_fifo_empty_status() - check the tx fifo is empty or not.
|
|
* @return 0 -- tx fifo is NOT empty.
|
|
* @return 1 -- tx fifo is empty.
|
|
*/
|
|
int iot_spi_tx_fifo_empty_status(int dev);
|
|
|
|
/**
|
|
* @brief iot_spi_check_dev_invalidity() - check dev is invalid.
|
|
* @return 0 -- dev is valid
|
|
* @return 1 -- dev is invalid.
|
|
*/
|
|
int iot_spi_check_dev_invalidity(int dev);
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
#define DEVICE_SPI_PORT_INVALID(d) (iot_spi_check_dev_invalidity(d))
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|