mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-03 03:31:41 +03:00
spi_master: new segmented-configure-transfer mode
This commit is contained in:
@@ -1260,6 +1260,282 @@ static inline int spi_ll_get_slave_hd_dummy_bits(spi_line_mode_t line_mode)
|
||||
return 8;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Segmented-Configure-Transfer
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define SPI_LL_CONF_BUF_SET_BIT(_w, _m) ({ \
|
||||
(_w) |= (_m); \
|
||||
})
|
||||
#define SPI_LL_CONF_BUF_CLR_BIT(_w, _m) ({ \
|
||||
(_w) &= ~(_m); \
|
||||
})
|
||||
|
||||
#define SPI_LL_CONF_BUF_SET_FIELD(_w, _f, val) ({ \
|
||||
((_w) = (((_w) & ~((_f##_V) << (_f##_S))) | (((val) & (_f##_V))<<(_f##_S)))); \
|
||||
})
|
||||
|
||||
#define SPI_LL_CONF_BUF_GET_FIELD(_w, _f) ({ \
|
||||
(((_w) >> (_f##_S)) & (_f##_V)); \
|
||||
})
|
||||
|
||||
//This offset is 1, for bitmap
|
||||
#define SPI_LL_CONF_BUFFER_OFFSET (1)
|
||||
//bitmap must be the first
|
||||
#define SPI_LL_CONF_BITMAP_POS (0)
|
||||
|
||||
#define SPI_LL_ADDR_REG_POS (0)
|
||||
#define SPI_LL_CTRL_REG_POS (1)
|
||||
#define SPI_LL_CLOCK_REG_POS (2)
|
||||
#define SPI_LL_USER_REG_POS (3)
|
||||
#define SPI_LL_USER1_REG_POS (4)
|
||||
#define SPI_LL_USER2_REG_POS (5)
|
||||
#define SPI_LL_MS_DLEN_REG_POS (6)
|
||||
#define SPI_LL_MISC_REG_POS (7)
|
||||
#define SPI_LL_DIN_MODE_REG_POS (8)
|
||||
#define SPI_LL_DIN_NUM_REG_POS (9)
|
||||
#define SPI_LL_DOUT_MODE_REG_POS (10)
|
||||
#define SPI_LL_DMA_CONF_REG_POS (11)
|
||||
#define SPI_LL_DMA_INT_ENA_REG_POS (12)
|
||||
#define SPI_LL_DMA_INT_CLR_REG_POS (13)
|
||||
|
||||
#define SPI_LL_SCT_MAGIC_NUMBER (0x2)
|
||||
|
||||
/**
|
||||
* Update the conf buffer for conf phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX], bool is_end)
|
||||
{
|
||||
//user reg: usr_conf_nxt
|
||||
if (is_end) {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_CONF_NXT_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_CONF_NXT_M);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for prep phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param setup CS setup time
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_prep_phase_conf_buffer(spi_dev_t *hw, uint8_t setup, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: cs_setup
|
||||
if(setup) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_SETUP_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_SETUP_M);
|
||||
}
|
||||
|
||||
//user1 reg: cs_setup_time
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_SETUP_TIME, setup - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for cmd phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param cmd Command value
|
||||
* @param cmdlen Length of the cmd phase
|
||||
* @param lsbfirst Whether LSB first
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_cmd_phase_conf_buffer(spi_dev_t *hw, uint16_t cmd, int cmdlen, bool lsbfirst, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: usr_command
|
||||
if (cmdlen) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_M);
|
||||
}
|
||||
|
||||
//user2 reg: usr_command_bitlen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_BITLEN, cmdlen - 1);
|
||||
|
||||
//user2 reg: usr_command_value
|
||||
if (lsbfirst) {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_VALUE, cmd);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_VALUE, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for addr phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param addr Address to set
|
||||
* @param addrlen Length of the address phase
|
||||
* @param lsbfirst whether the LSB first feature is enabled.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_addr_phase_conf_buffer(spi_dev_t *hw, uint64_t addr, int addrlen, bool lsbfirst, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: usr_addr
|
||||
if (addrlen) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_M);
|
||||
}
|
||||
|
||||
//user1 reg: usr_addr_bitlen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_BITLEN, addrlen - 1);
|
||||
|
||||
//addr reg: addr
|
||||
if (lsbfirst) {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_ADDR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_VALUE, HAL_SWAP32(addr));
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_ADDR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_VALUE, (addr << (32 - addrlen)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for dummy phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param dummy_n Dummy cycles used. 0 to disable the dummy phase.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_dummy_phase_conf_buffer(spi_dev_t *hw, int dummy_n, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: usr_dummy
|
||||
if (dummy_n) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_DUMMY_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_DUMMY_M);
|
||||
}
|
||||
|
||||
//user1 reg: usr_dummy_cyclelen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_DUMMY_CYCLELEN, dummy_n - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for dout phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param bitlen output length, in bits.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_dout_phase_conf_buffer(spi_dev_t *hw, int bitlen, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
if (bitlen) {
|
||||
//user reg: usr_mosi
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MOSI_M);
|
||||
//dma_conf reg: dma_tx_ena
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_DMA_TX_ENA_M);
|
||||
//ms_dlen reg: ms_data_bitlen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_MS_DLEN_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_MS_DATA_BITLEN, bitlen - 1);
|
||||
} else {
|
||||
//user reg: usr_mosi
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MOSI_M);
|
||||
//dma_conf reg: dma_tx_ena
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_DMA_TX_ENA_M);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for din phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param bitlen input length, in bits.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_din_phase_conf_buffer(spi_dev_t *hw, int bitlen, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
if (bitlen) {
|
||||
//user reg: usr_miso
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MISO_M);
|
||||
//dma_conf reg: dma_rx_ena
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_DMA_RX_ENA_M);
|
||||
//ms_dlen reg: ms_data_bitlen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_MS_DLEN_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_MS_DATA_BITLEN, bitlen - 1);
|
||||
} else {
|
||||
//user reg: usr_miso
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MISO_M);
|
||||
//dma_conf reg: dma_rx_ena
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_DMA_RX_ENA_M);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for done phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param setup CS hold time
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_done_phase_conf_buffer(spi_dev_t *hw, int hold, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: cs_hold
|
||||
if(hold) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_HOLD_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_HOLD_M);
|
||||
}
|
||||
|
||||
//user1 reg: cs_hold_time
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_HOLD_TIME, hold);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the conf buffer:
|
||||
*
|
||||
* - init bitmap
|
||||
* - save all register values into the rest of the conf buffer words
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void spi_ll_init_conf_buffer(spi_dev_t *hw, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
conf_buffer[SPI_LL_CONF_BITMAP_POS] = 0x7FFF | (SPI_LL_SCT_MAGIC_NUMBER << 28);
|
||||
conf_buffer[SPI_LL_ADDR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->addr;
|
||||
conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->ctrl.val;
|
||||
conf_buffer[SPI_LL_CLOCK_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->clock.val;
|
||||
conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->user.val;
|
||||
conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->user1.val;
|
||||
conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->user2.val;
|
||||
conf_buffer[SPI_LL_MS_DLEN_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->ms_dlen.val;
|
||||
conf_buffer[SPI_LL_MISC_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->misc.val;
|
||||
conf_buffer[SPI_LL_DIN_MODE_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->din_mode.val;
|
||||
conf_buffer[SPI_LL_DIN_NUM_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->din_num.val;
|
||||
conf_buffer[SPI_LL_DOUT_MODE_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dout_mode.val;
|
||||
conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dma_conf.val;
|
||||
conf_buffer[SPI_LL_DMA_INT_ENA_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dma_int_ena.val;
|
||||
conf_buffer[SPI_LL_DMA_INT_CLR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dma_int_clr.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/Disable the conf phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param enable True: enable; False: disable
|
||||
*/
|
||||
static inline void spi_ll_conf_state_enable(spi_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->slave.usr_conf = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Segmented-Configure-Transfer required magic value
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param magic_value magic value
|
||||
*/
|
||||
static inline void spi_ll_set_magic_number(spi_dev_t *hw, uint8_t magic_value)
|
||||
{
|
||||
hw->slave.dma_seg_magic_value = magic_value;
|
||||
}
|
||||
|
||||
|
||||
#undef SPI_LL_RST_MASK
|
||||
#undef SPI_LL_UNUSED_INT_MASK
|
||||
|
||||
|
||||
@@ -1175,6 +1175,279 @@ static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw)
|
||||
return hw->slave1.last_addr;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Segmented-Configure-Transfer
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define SPI_LL_CONF_BUF_SET_BIT(_w, _m) ({ \
|
||||
(_w) |= (_m); \
|
||||
})
|
||||
#define SPI_LL_CONF_BUF_CLR_BIT(_w, _m) ({ \
|
||||
(_w) &= ~(_m); \
|
||||
})
|
||||
|
||||
#define SPI_LL_CONF_BUF_SET_FIELD(_w, _f, val) ({ \
|
||||
((_w) = (((_w) & ~((_f##_V) << (_f##_S))) | (((val) & (_f##_V))<<(_f##_S)))); \
|
||||
})
|
||||
|
||||
#define SPI_LL_CONF_BUF_GET_FIELD(_w, _f) ({ \
|
||||
(((_w) >> (_f##_S)) & (_f##_V)); \
|
||||
})
|
||||
|
||||
//This offset is 1, for bitmap
|
||||
#define SPI_LL_CONF_BUFFER_OFFSET (1)
|
||||
//bitmap must be the first
|
||||
#define SPI_LL_CONF_BITMAP_POS (0)
|
||||
|
||||
#define SPI_LL_ADDR_REG_POS (0)
|
||||
#define SPI_LL_CTRL_REG_POS (1)
|
||||
#define SPI_LL_CLOCK_REG_POS (2)
|
||||
#define SPI_LL_USER_REG_POS (3)
|
||||
#define SPI_LL_USER1_REG_POS (4)
|
||||
#define SPI_LL_USER2_REG_POS (5)
|
||||
#define SPI_LL_MS_DLEN_REG_POS (6)
|
||||
#define SPI_LL_MISC_REG_POS (7)
|
||||
#define SPI_LL_DIN_MODE_REG_POS (8)
|
||||
#define SPI_LL_DIN_NUM_REG_POS (9)
|
||||
#define SPI_LL_DOUT_MODE_REG_POS (10)
|
||||
#define SPI_LL_DMA_CONF_REG_POS (11)
|
||||
#define SPI_LL_DMA_INT_ENA_REG_POS (12)
|
||||
#define SPI_LL_DMA_INT_CLR_REG_POS (13)
|
||||
|
||||
#define SPI_LL_SCT_MAGIC_NUMBER (0x2)
|
||||
|
||||
/**
|
||||
* Update the conf buffer for conf phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX], bool is_end)
|
||||
{
|
||||
//user reg: usr_conf_nxt
|
||||
if (is_end) {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_CONF_NXT_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_CONF_NXT_M);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for prep phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param setup CS setup time
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_prep_phase_conf_buffer(spi_dev_t *hw, uint8_t setup, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: cs_setup
|
||||
if(setup) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_SETUP_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_SETUP_M);
|
||||
}
|
||||
|
||||
//user1 reg: cs_setup_time
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_SETUP_TIME, setup - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for cmd phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param cmd Command value
|
||||
* @param cmdlen Length of the cmd phase
|
||||
* @param lsbfirst Whether LSB first
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_cmd_phase_conf_buffer(spi_dev_t *hw, uint16_t cmd, int cmdlen, bool lsbfirst, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: usr_command
|
||||
if (cmdlen) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_M);
|
||||
}
|
||||
|
||||
//user2 reg: usr_command_bitlen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_BITLEN, cmdlen - 1);
|
||||
|
||||
//user2 reg: usr_command_value
|
||||
if (lsbfirst) {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_VALUE, cmd);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_VALUE, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for addr phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param addr Address to set
|
||||
* @param addrlen Length of the address phase
|
||||
* @param lsbfirst whether the LSB first feature is enabled.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_addr_phase_conf_buffer(spi_dev_t *hw, uint64_t addr, int addrlen, bool lsbfirst, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: usr_addr
|
||||
if (addrlen) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_M);
|
||||
}
|
||||
|
||||
//user1 reg: usr_addr_bitlen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_BITLEN, addrlen - 1);
|
||||
|
||||
//addr reg: addr
|
||||
if (lsbfirst) {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_ADDR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_VALUE, HAL_SWAP32(addr));
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_ADDR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_VALUE, (addr << (32 - addrlen)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for dummy phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param dummy_n Dummy cycles used. 0 to disable the dummy phase.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_dummy_phase_conf_buffer(spi_dev_t *hw, int dummy_n, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: usr_dummy
|
||||
if (dummy_n) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_DUMMY_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_DUMMY_M);
|
||||
}
|
||||
|
||||
//user1 reg: usr_dummy_cyclelen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_DUMMY_CYCLELEN, dummy_n - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for dout phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param bitlen output length, in bits.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_dout_phase_conf_buffer(spi_dev_t *hw, int bitlen, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
if (bitlen) {
|
||||
//user reg: usr_mosi
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MOSI_M);
|
||||
//dma_conf reg: dma_tx_ena
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_DMA_TX_ENA_M);
|
||||
//ms_dlen reg: ms_data_bitlen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_MS_DLEN_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_MS_DATA_BITLEN, bitlen - 1);
|
||||
} else {
|
||||
//user reg: usr_mosi
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MOSI_M);
|
||||
//dma_conf reg: dma_tx_ena
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_DMA_TX_ENA_M);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for din phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param bitlen input length, in bits.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_din_phase_conf_buffer(spi_dev_t *hw, int bitlen, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
if (bitlen) {
|
||||
//user reg: usr_miso
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MISO_M);
|
||||
//dma_conf reg: dma_rx_ena
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_DMA_RX_ENA_M);
|
||||
//ms_dlen reg: ms_data_bitlen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_MS_DLEN_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_MS_DATA_BITLEN, bitlen - 1);
|
||||
} else {
|
||||
//user reg: usr_miso
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MISO_M);
|
||||
//dma_conf reg: dma_rx_ena
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_DMA_RX_ENA_M);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for done phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param setup CS hold time
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_done_phase_conf_buffer(spi_dev_t *hw, int hold, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: cs_hold
|
||||
if(hold) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_HOLD_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_HOLD_M);
|
||||
}
|
||||
|
||||
//user1 reg: cs_hold_time
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_HOLD_TIME, hold);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the conf buffer:
|
||||
*
|
||||
* - init bitmap
|
||||
* - save all register values into the rest of the conf buffer words
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void spi_ll_init_conf_buffer(spi_dev_t *hw, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
conf_buffer[SPI_LL_CONF_BITMAP_POS] = 0x7FFF | (SPI_LL_SCT_MAGIC_NUMBER << 28);
|
||||
conf_buffer[SPI_LL_ADDR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->addr;
|
||||
conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->ctrl.val;
|
||||
conf_buffer[SPI_LL_CLOCK_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->clock.val;
|
||||
conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->user.val;
|
||||
conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->user1.val;
|
||||
conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->user2.val;
|
||||
conf_buffer[SPI_LL_MS_DLEN_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->ms_dlen.val;
|
||||
conf_buffer[SPI_LL_MISC_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->misc.val;
|
||||
conf_buffer[SPI_LL_DIN_MODE_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->din_mode.val;
|
||||
conf_buffer[SPI_LL_DIN_NUM_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->din_num.val;
|
||||
conf_buffer[SPI_LL_DOUT_MODE_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dout_mode.val;
|
||||
conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dma_conf.val;
|
||||
conf_buffer[SPI_LL_DMA_INT_ENA_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dma_int_ena.val;
|
||||
conf_buffer[SPI_LL_DMA_INT_CLR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dma_int_clr.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/Disable the conf phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param enable True: enable; False: disable
|
||||
*/
|
||||
static inline void spi_ll_conf_state_enable(spi_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->slave.usr_conf = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Segmented-Configure-Transfer required magic value
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param magic_value magic value
|
||||
*/
|
||||
static inline void spi_ll_set_magic_number(spi_dev_t *hw, uint8_t magic_value)
|
||||
{
|
||||
hw->slave.dma_seg_magic_value = magic_value;
|
||||
}
|
||||
|
||||
#undef SPI_LL_RST_MASK
|
||||
#undef SPI_LL_UNUSED_INT_MASK
|
||||
|
||||
|
||||
@@ -1166,6 +1166,281 @@ static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw)
|
||||
return hw->slave1.slv_last_addr;
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Segmented-Configure-Transfer
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define SPI_LL_CONF_BUF_SET_BIT(_w, _m) ({ \
|
||||
(_w) |= (_m); \
|
||||
})
|
||||
#define SPI_LL_CONF_BUF_CLR_BIT(_w, _m) ({ \
|
||||
(_w) &= ~(_m); \
|
||||
})
|
||||
|
||||
#define SPI_LL_CONF_BUF_SET_FIELD(_w, _f, val) ({ \
|
||||
((_w) = (((_w) & ~((_f##_V) << (_f##_S))) | (((val) & (_f##_V))<<(_f##_S)))); \
|
||||
})
|
||||
|
||||
#define SPI_LL_CONF_BUF_GET_FIELD(_w, _f) ({ \
|
||||
(((_w) >> (_f##_S)) & (_f##_V)); \
|
||||
})
|
||||
|
||||
//This offset is 1, for bitmap
|
||||
#define SPI_LL_CONF_BUFFER_OFFSET (1)
|
||||
//bitmap must be the first
|
||||
#define SPI_LL_CONF_BITMAP_POS (0)
|
||||
|
||||
#define SPI_LL_ADDR_REG_POS (0)
|
||||
#define SPI_LL_CTRL_REG_POS (1)
|
||||
#define SPI_LL_CLOCK_REG_POS (2)
|
||||
#define SPI_LL_USER_REG_POS (3)
|
||||
#define SPI_LL_USER1_REG_POS (4)
|
||||
#define SPI_LL_USER2_REG_POS (5)
|
||||
#define SPI_LL_MS_DLEN_REG_POS (6)
|
||||
#define SPI_LL_MISC_REG_POS (7)
|
||||
#define SPI_LL_DIN_MODE_REG_POS (8)
|
||||
#define SPI_LL_DIN_NUM_REG_POS (9)
|
||||
#define SPI_LL_DOUT_MODE_REG_POS (10)
|
||||
#define SPI_LL_DMA_CONF_REG_POS (11)
|
||||
#define SPI_LL_DMA_INT_ENA_REG_POS (12)
|
||||
#define SPI_LL_DMA_INT_CLR_REG_POS (13)
|
||||
|
||||
#define SPI_LL_SCT_MAGIC_NUMBER (0x2)
|
||||
|
||||
/**
|
||||
* Update the conf buffer for conf phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX], bool is_end)
|
||||
{
|
||||
//user reg: usr_conf_nxt
|
||||
if (is_end) {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_CONF_NXT_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_CONF_NXT_M);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for prep phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param setup CS setup time
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_prep_phase_conf_buffer(spi_dev_t *hw, uint8_t setup, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: cs_setup
|
||||
if(setup) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_SETUP_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_SETUP_M);
|
||||
}
|
||||
|
||||
//user1 reg: cs_setup_time
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_SETUP_TIME, setup - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for cmd phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param cmd Command value
|
||||
* @param cmdlen Length of the cmd phase
|
||||
* @param lsbfirst Whether LSB first
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_cmd_phase_conf_buffer(spi_dev_t *hw, uint16_t cmd, int cmdlen, bool lsbfirst, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: usr_command
|
||||
if (cmdlen) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_M);
|
||||
}
|
||||
|
||||
//user2 reg: usr_command_bitlen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_BITLEN, cmdlen - 1);
|
||||
|
||||
//user2 reg: usr_command_value
|
||||
if (lsbfirst) {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_VALUE, cmd);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_VALUE, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for addr phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param addr Address to set
|
||||
* @param addrlen Length of the address phase
|
||||
* @param lsbfirst whether the LSB first feature is enabled.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_addr_phase_conf_buffer(spi_dev_t *hw, uint64_t addr, int addrlen, bool lsbfirst, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: usr_addr
|
||||
if (addrlen) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_M);
|
||||
}
|
||||
|
||||
//user1 reg: usr_addr_bitlen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_BITLEN, addrlen - 1);
|
||||
|
||||
//addr reg: addr
|
||||
if (lsbfirst) {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_ADDR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_VALUE, HAL_SWAP32(addr));
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_ADDR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_VALUE, (addr << (32 - addrlen)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for dummy phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param dummy_n Dummy cycles used. 0 to disable the dummy phase.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_dummy_phase_conf_buffer(spi_dev_t *hw, int dummy_n, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: usr_dummy
|
||||
if (dummy_n) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_DUMMY_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_DUMMY_M);
|
||||
}
|
||||
|
||||
//user1 reg: usr_dummy_cyclelen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_DUMMY_CYCLELEN, dummy_n - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for dout phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param bitlen output length, in bits.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_dout_phase_conf_buffer(spi_dev_t *hw, int bitlen, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
if (bitlen) {
|
||||
//user reg: usr_mosi
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MOSI_M);
|
||||
//dma_conf reg: dma_tx_ena
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_DMA_TX_ENA_M);
|
||||
//ms_dlen reg: ms_data_bitlen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_MS_DLEN_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_MS_DATA_BITLEN, bitlen - 1);
|
||||
} else {
|
||||
//user reg: usr_mosi
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MOSI_M);
|
||||
//dma_conf reg: dma_tx_ena
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_DMA_TX_ENA_M);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for din phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param bitlen input length, in bits.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_din_phase_conf_buffer(spi_dev_t *hw, int bitlen, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
if (bitlen) {
|
||||
//user reg: usr_miso
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MISO_M);
|
||||
//dma_conf reg: dma_rx_ena
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_DMA_RX_ENA_M);
|
||||
//ms_dlen reg: ms_data_bitlen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_MS_DLEN_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_MS_DATA_BITLEN, bitlen - 1);
|
||||
} else {
|
||||
//user reg: usr_miso
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MISO_M);
|
||||
//dma_conf reg: dma_rx_ena
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_DMA_RX_ENA_M);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for done phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param setup CS hold time
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_done_phase_conf_buffer(spi_dev_t *hw, int hold, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: cs_hold
|
||||
if(hold) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_HOLD_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_HOLD_M);
|
||||
}
|
||||
|
||||
//user1 reg: cs_hold_time
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_HOLD_TIME, hold);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the conf buffer:
|
||||
*
|
||||
* - init bitmap
|
||||
* - save all register values into the rest of the conf buffer words
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void spi_ll_init_conf_buffer(spi_dev_t *hw, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
conf_buffer[SPI_LL_CONF_BITMAP_POS] = 0x7FFF | (SPI_LL_SCT_MAGIC_NUMBER << 28);
|
||||
conf_buffer[SPI_LL_ADDR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->addr;
|
||||
conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->ctrl.val;
|
||||
conf_buffer[SPI_LL_CLOCK_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->clock.val;
|
||||
conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->user.val;
|
||||
conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->user1.val;
|
||||
conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->user2.val;
|
||||
conf_buffer[SPI_LL_MS_DLEN_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->ms_dlen.val;
|
||||
conf_buffer[SPI_LL_MISC_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->misc.val;
|
||||
conf_buffer[SPI_LL_DIN_MODE_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->din_mode.val;
|
||||
conf_buffer[SPI_LL_DIN_NUM_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->din_num.val;
|
||||
conf_buffer[SPI_LL_DOUT_MODE_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dout_mode.val;
|
||||
conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dma_conf.val;
|
||||
conf_buffer[SPI_LL_DMA_INT_ENA_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dma_int_ena.val;
|
||||
conf_buffer[SPI_LL_DMA_INT_CLR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dma_int_clr.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/Disable the conf phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param enable True: enable; False: disable
|
||||
*/
|
||||
static inline void spi_ll_conf_state_enable(spi_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->slave.usr_conf = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Segmented-Configure-Transfer required magic value
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param magic_value magic value
|
||||
*/
|
||||
static inline void spi_ll_set_magic_number(spi_dev_t *hw, uint8_t magic_value)
|
||||
{
|
||||
hw->slave.dma_seg_magic_value = magic_value;
|
||||
}
|
||||
|
||||
|
||||
#undef SPI_LL_RST_MASK
|
||||
#undef SPI_LL_UNUSED_INT_MASK
|
||||
|
||||
|
||||
@@ -18,10 +18,13 @@
|
||||
#include <string.h>
|
||||
#include "esp_types.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_bit_defs.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "soc/spi_struct.h"
|
||||
#include "soc/spi_reg.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/lldesc.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/assert.h"
|
||||
#include "hal/misc.h"
|
||||
#include "hal/spi_types.h"
|
||||
@@ -308,7 +311,7 @@ static inline void spi_ll_user_start(spi_dev_t *hw)
|
||||
*/
|
||||
static inline uint32_t spi_ll_get_running_cmd(spi_dev_t *hw)
|
||||
{
|
||||
return hw->cmd.val;
|
||||
return hw->cmd.usr;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1017,7 +1020,6 @@ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, b
|
||||
* more straightly.
|
||||
*/
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1463,6 +1465,297 @@ static inline bool spi_ll_tx_get_empty_err(spi_dev_t *hw)
|
||||
return hw->dma_int_raw.outfifo_empty_err;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Segmented-Configure-Transfer
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define SPI_LL_CONF_BUF_SET_BIT(_w, _m) ({ \
|
||||
(_w) |= (_m); \
|
||||
})
|
||||
#define SPI_LL_CONF_BUF_CLR_BIT(_w, _m) ({ \
|
||||
(_w) &= ~(_m); \
|
||||
})
|
||||
|
||||
#define SPI_LL_CONF_BUF_SET_FIELD(_w, _f, val) ({ \
|
||||
((_w) = (((_w) & ~((_f##_V) << (_f##_S))) | (((val) & (_f##_V))<<(_f##_S)))); \
|
||||
})
|
||||
|
||||
#define SPI_LL_CONF_BUF_GET_FIELD(_w, _f) ({ \
|
||||
(((_w) >> (_f##_S)) & (_f##_V)); \
|
||||
})
|
||||
|
||||
//This offset is 1, for bitmap
|
||||
#define SPI_LL_CONF_BUFFER_OFFSET (1)
|
||||
//bitmap must be the first
|
||||
#define SPI_LL_CONF_BITMAP_POS (0)
|
||||
|
||||
#define SPI_LL_CMD_REG_POS (0)
|
||||
#define SPI_LL_ADDR_REG_POS (1)
|
||||
#define SPI_LL_CTRL_REG_POS (2)
|
||||
#define SPI_LL_CTRL1_REG_POS (3)
|
||||
#define SPI_LL_CTRL2_REG_POS (4)
|
||||
#define SPI_LL_CLOCK_REG_POS (5)
|
||||
#define SPI_LL_USER_REG_POS (6)
|
||||
#define SPI_LL_USER1_REG_POS (7)
|
||||
#define SPI_LL_USER2_REG_POS (8)
|
||||
#define SPI_LL_MOSI_DLEN_REG_POS (9)
|
||||
#define SPI_LL_MISO_DLEN_REG_POS (10)
|
||||
#define SPI_LL_MISC_REG_POS (11)
|
||||
#define SPI_LL_SLAVE_REG_POS (12)
|
||||
#define SPI_LL_FSM_REG_POS (13)
|
||||
#define SPI_LL_HOLD_REG_POS (14)
|
||||
#define SPI_LL_DMA_INT_ENA_REG_POS (15)
|
||||
#define SPI_LL_DMA_INT_RAW_REG_POS (16)
|
||||
#define SPI_LL_DMA_INT_CLR_REG_POS (17)
|
||||
#define SPI_LL_DIN_MODE_REG_POS (18)
|
||||
#define SPI_LL_DIN_NUM_REG_POS (19)
|
||||
#define SPI_LL_DOUT_MODE_REG_POS (20)
|
||||
#define SPI_LL_DOUT_NUM_REG_POS (21)
|
||||
#define SPI_LL_LCD_CTRL_REG_POS (22)
|
||||
#define SPI_LL_LCD_CTRL1_REG_POS (23)
|
||||
#define SPI_LL_LCD_CTRL2_REG_POS (24)
|
||||
#define SPI_LL_LCD_D_MODE_REG_POS (25)
|
||||
#define SPI_LL_LCD_D_NUM_REG_POS (26)
|
||||
|
||||
#define SPI_LL_SCT_MAGIC_NUMBER (0x2)
|
||||
|
||||
/**
|
||||
* Update the conf buffer for conf phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX], bool is_end)
|
||||
{
|
||||
//user reg: usr_conf_nxt
|
||||
if (is_end) {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_CONF_NXT_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_CONF_NXT_M);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for prep phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param setup CS setup time
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_prep_phase_conf_buffer(spi_dev_t *hw, uint8_t setup, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: cs_setup
|
||||
if(setup) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_SETUP_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_SETUP_M);
|
||||
}
|
||||
|
||||
//ctrl2 reg: cs_setup_time
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_CTRL2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_SETUP_TIME, setup - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for cmd phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param cmd Command value
|
||||
* @param cmdlen Length of the cmd phase
|
||||
* @param lsbfirst Whether LSB first
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_cmd_phase_conf_buffer(spi_dev_t *hw, uint16_t cmd, int cmdlen, bool lsbfirst, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: usr_command
|
||||
if (cmdlen) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_M);
|
||||
}
|
||||
|
||||
//user2 reg: usr_command_bitlen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_BITLEN, cmdlen - 1);
|
||||
|
||||
//user2 reg: usr_command_value
|
||||
if (lsbfirst) {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_VALUE, cmd);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_VALUE, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for addr phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param addr Address to set
|
||||
* @param addrlen Length of the address phase
|
||||
* @param lsbfirst whether the LSB first feature is enabled.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_addr_phase_conf_buffer(spi_dev_t *hw, uint64_t addr, int addrlen, bool lsbfirst, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: usr_addr
|
||||
if (addrlen) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_M);
|
||||
}
|
||||
|
||||
//user1 reg: usr_addr_bitlen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_BITLEN, addrlen - 1);
|
||||
|
||||
//addr reg: addr
|
||||
if (lsbfirst) {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_ADDR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_VALUE, HAL_SWAP32(addr));
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_ADDR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_VALUE, (addr << (32 - addrlen)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for dummy phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param dummy_n Dummy cycles used. 0 to disable the dummy phase.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_dummy_phase_conf_buffer(spi_dev_t *hw, int dummy_n, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: usr_dummy
|
||||
if (dummy_n) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_DUMMY_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_DUMMY_M);
|
||||
}
|
||||
|
||||
//user1 reg: usr_dummy_cyclelen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_DUMMY_CYCLELEN, dummy_n - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for dout phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param bitlen output length, in bits.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_dout_phase_conf_buffer(spi_dev_t *hw, int bitlen, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: usr_mosi
|
||||
if (bitlen) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MOSI_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MOSI_M);
|
||||
}
|
||||
|
||||
//mosi_dlen reg: usr_mosi_bit_len
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_MOSI_DLEN_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MOSI_DBITLEN, bitlen - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for din phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param bitlen input length, in bits.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_din_phase_conf_buffer(spi_dev_t *hw, int bitlen, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: usr_miso
|
||||
if (bitlen) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MISO_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MISO_M);
|
||||
}
|
||||
|
||||
//miso_dlen reg: usr_miso_bit_len
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_MISO_DLEN_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MISO_DBITLEN, bitlen - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for done phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param setup CS hold time
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_done_phase_conf_buffer(spi_dev_t *hw, int hold, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: cs_hold
|
||||
if(hold) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_HOLD_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_HOLD_M);
|
||||
}
|
||||
|
||||
//ctrl2 reg: cs_hold_time
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_CTRL2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_HOLD_TIME, hold);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the conf buffer:
|
||||
*
|
||||
* - init bitmap
|
||||
* - save all register values into the rest of the conf buffer words
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void spi_ll_init_conf_buffer(spi_dev_t *hw, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
conf_buffer[SPI_LL_CONF_BITMAP_POS] = 0x7FFFFFF | (SPI_LL_SCT_MAGIC_NUMBER << 28);
|
||||
conf_buffer[SPI_LL_CMD_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->cmd.val;
|
||||
conf_buffer[SPI_LL_ADDR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->addr;
|
||||
conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->ctrl.val;
|
||||
conf_buffer[SPI_LL_CTRL1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->ctrl1.val;
|
||||
conf_buffer[SPI_LL_CTRL2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->ctrl2.val;
|
||||
conf_buffer[SPI_LL_CLOCK_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->clock.val;
|
||||
conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->user.val;
|
||||
conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->user1.val;
|
||||
conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->user2.val;
|
||||
conf_buffer[SPI_LL_MOSI_DLEN_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->mosi_dlen.val;
|
||||
conf_buffer[SPI_LL_MISO_DLEN_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->miso_dlen.val;
|
||||
conf_buffer[SPI_LL_MISC_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->misc.val;
|
||||
conf_buffer[SPI_LL_SLAVE_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->slave.val;
|
||||
conf_buffer[SPI_LL_FSM_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->fsm.val;
|
||||
conf_buffer[SPI_LL_HOLD_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->hold.val;
|
||||
conf_buffer[SPI_LL_DMA_INT_ENA_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dma_int_ena.val;
|
||||
conf_buffer[SPI_LL_DMA_INT_RAW_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dma_int_raw.val;
|
||||
conf_buffer[SPI_LL_DMA_INT_CLR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dma_int_clr.val;
|
||||
conf_buffer[SPI_LL_DIN_MODE_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->din_mode.val;
|
||||
conf_buffer[SPI_LL_DIN_NUM_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->din_num.val;
|
||||
conf_buffer[SPI_LL_DOUT_MODE_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dout_mode.val;
|
||||
conf_buffer[SPI_LL_DOUT_NUM_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dout_num.val;
|
||||
conf_buffer[SPI_LL_LCD_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->lcd_ctrl.val;
|
||||
conf_buffer[SPI_LL_LCD_CTRL1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->lcd_ctrl1.val;
|
||||
conf_buffer[SPI_LL_LCD_CTRL2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->lcd_ctrl2.val;
|
||||
conf_buffer[SPI_LL_LCD_D_MODE_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->lcd_d_mode.val;
|
||||
conf_buffer[SPI_LL_LCD_D_NUM_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->lcd_d_num.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/Disable the conf phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param enable True: enable; False: disable
|
||||
*/
|
||||
static inline void spi_ll_conf_state_enable(spi_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->slv_rd_byte.usr_conf = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Segmented-Configure-Transfer required magic value
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param magic_value magic value
|
||||
*/
|
||||
static inline void spi_ll_set_magic_number(spi_dev_t *hw, uint8_t magic_value)
|
||||
{
|
||||
hw->slv_rd_byte.dma_seg_magic_value = magic_value;
|
||||
}
|
||||
|
||||
#undef SPI_LL_RST_MASK
|
||||
#undef SPI_LL_UNUSED_INT_MASK
|
||||
|
||||
|
||||
@@ -1195,6 +1195,280 @@ static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw)
|
||||
return hw->slave1.last_addr;
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Segmented-Configure-Transfer
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define SPI_LL_CONF_BUF_SET_BIT(_w, _m) ({ \
|
||||
(_w) |= (_m); \
|
||||
})
|
||||
#define SPI_LL_CONF_BUF_CLR_BIT(_w, _m) ({ \
|
||||
(_w) &= ~(_m); \
|
||||
})
|
||||
|
||||
#define SPI_LL_CONF_BUF_SET_FIELD(_w, _f, val) ({ \
|
||||
((_w) = (((_w) & ~((_f##_V) << (_f##_S))) | (((val) & (_f##_V))<<(_f##_S)))); \
|
||||
})
|
||||
|
||||
#define SPI_LL_CONF_BUF_GET_FIELD(_w, _f) ({ \
|
||||
(((_w) >> (_f##_S)) & (_f##_V)); \
|
||||
})
|
||||
|
||||
//This offset is 1, for bitmap
|
||||
#define SPI_LL_CONF_BUFFER_OFFSET (1)
|
||||
//bitmap must be the first
|
||||
#define SPI_LL_CONF_BITMAP_POS (0)
|
||||
|
||||
#define SPI_LL_ADDR_REG_POS (0)
|
||||
#define SPI_LL_CTRL_REG_POS (1)
|
||||
#define SPI_LL_CLOCK_REG_POS (2)
|
||||
#define SPI_LL_USER_REG_POS (3)
|
||||
#define SPI_LL_USER1_REG_POS (4)
|
||||
#define SPI_LL_USER2_REG_POS (5)
|
||||
#define SPI_LL_MS_DLEN_REG_POS (6)
|
||||
#define SPI_LL_MISC_REG_POS (7)
|
||||
#define SPI_LL_DIN_MODE_REG_POS (8)
|
||||
#define SPI_LL_DIN_NUM_REG_POS (9)
|
||||
#define SPI_LL_DOUT_MODE_REG_POS (10)
|
||||
#define SPI_LL_DMA_CONF_REG_POS (11)
|
||||
#define SPI_LL_DMA_INT_ENA_REG_POS (12)
|
||||
#define SPI_LL_DMA_INT_CLR_REG_POS (13)
|
||||
|
||||
#define SPI_LL_SCT_MAGIC_NUMBER (0x2)
|
||||
|
||||
/**
|
||||
* Update the conf buffer for conf phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX], bool is_end)
|
||||
{
|
||||
//user reg: usr_conf_nxt
|
||||
if (is_end) {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_CONF_NXT_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_CONF_NXT_M);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for prep phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param setup CS setup time
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_prep_phase_conf_buffer(spi_dev_t *hw, uint8_t setup, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: cs_setup
|
||||
if(setup) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_SETUP_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_SETUP_M);
|
||||
}
|
||||
|
||||
//user1 reg: cs_setup_time
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_SETUP_TIME, setup - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for cmd phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param cmd Command value
|
||||
* @param cmdlen Length of the cmd phase
|
||||
* @param lsbfirst Whether LSB first
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_cmd_phase_conf_buffer(spi_dev_t *hw, uint16_t cmd, int cmdlen, bool lsbfirst, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: usr_command
|
||||
if (cmdlen) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_M);
|
||||
}
|
||||
|
||||
//user2 reg: usr_command_bitlen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_BITLEN, cmdlen - 1);
|
||||
|
||||
//user2 reg: usr_command_value
|
||||
if (lsbfirst) {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_VALUE, cmd);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_COMMAND_VALUE, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for addr phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param addr Address to set
|
||||
* @param addrlen Length of the address phase
|
||||
* @param lsbfirst whether the LSB first feature is enabled.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_addr_phase_conf_buffer(spi_dev_t *hw, uint64_t addr, int addrlen, bool lsbfirst, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: usr_addr
|
||||
if (addrlen) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_M);
|
||||
}
|
||||
|
||||
//user1 reg: usr_addr_bitlen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_BITLEN, addrlen - 1);
|
||||
|
||||
//addr reg: addr
|
||||
if (lsbfirst) {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_ADDR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_VALUE, HAL_SWAP32(addr));
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_ADDR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_ADDR_VALUE, (addr << (32 - addrlen)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for dummy phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param dummy_n Dummy cycles used. 0 to disable the dummy phase.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_dummy_phase_conf_buffer(spi_dev_t *hw, int dummy_n, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: usr_dummy
|
||||
if (dummy_n) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_DUMMY_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_DUMMY_M);
|
||||
}
|
||||
|
||||
//user1 reg: usr_dummy_cyclelen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_DUMMY_CYCLELEN, dummy_n - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for dout phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param bitlen output length, in bits.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_dout_phase_conf_buffer(spi_dev_t *hw, int bitlen, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
if (bitlen) {
|
||||
//user reg: usr_mosi
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MOSI_M);
|
||||
//dma_conf reg: dma_tx_ena
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_DMA_TX_ENA_M);
|
||||
//ms_dlen reg: ms_data_bitlen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_MS_DLEN_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_MS_DATA_BITLEN, bitlen - 1);
|
||||
} else {
|
||||
//user reg: usr_mosi
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MOSI_M);
|
||||
//dma_conf reg: dma_tx_ena
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_DMA_TX_ENA_M);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for din phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param bitlen input length, in bits.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_din_phase_conf_buffer(spi_dev_t *hw, int bitlen, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
if (bitlen) {
|
||||
//user reg: usr_miso
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MISO_M);
|
||||
//dma_conf reg: dma_rx_ena
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_DMA_RX_ENA_M);
|
||||
//ms_dlen reg: ms_data_bitlen
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_MS_DLEN_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_MS_DATA_BITLEN, bitlen - 1);
|
||||
} else {
|
||||
//user reg: usr_miso
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_USR_MISO_M);
|
||||
//dma_conf reg: dma_rx_ena
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_DMA_RX_ENA_M);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the conf buffer for done phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param setup CS hold time
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
static inline void spi_ll_format_done_phase_conf_buffer(spi_dev_t *hw, int hold, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
//user reg: cs_hold
|
||||
if(hold) {
|
||||
SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_HOLD_M);
|
||||
} else {
|
||||
SPI_LL_CONF_BUF_CLR_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_HOLD_M);
|
||||
}
|
||||
|
||||
//user1 reg: cs_hold_time
|
||||
SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CS_HOLD_TIME, hold);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the conf buffer:
|
||||
*
|
||||
* - init bitmap
|
||||
* - save all register values into the rest of the conf buffer words
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param conf_buffer Conf buffer to be updated.
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void spi_ll_init_conf_buffer(spi_dev_t *hw, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
conf_buffer[SPI_LL_CONF_BITMAP_POS] = 0x7FFF | (SPI_LL_SCT_MAGIC_NUMBER << 28);
|
||||
conf_buffer[SPI_LL_ADDR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->addr;
|
||||
conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->ctrl.val;
|
||||
conf_buffer[SPI_LL_CLOCK_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->clock.val;
|
||||
conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->user.val;
|
||||
conf_buffer[SPI_LL_USER1_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->user1.val;
|
||||
conf_buffer[SPI_LL_USER2_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->user2.val;
|
||||
conf_buffer[SPI_LL_MS_DLEN_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->ms_dlen.val;
|
||||
conf_buffer[SPI_LL_MISC_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->misc.val;
|
||||
conf_buffer[SPI_LL_DIN_MODE_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->din_mode.val;
|
||||
conf_buffer[SPI_LL_DIN_NUM_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->din_num.val;
|
||||
conf_buffer[SPI_LL_DOUT_MODE_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dout_mode.val;
|
||||
conf_buffer[SPI_LL_DMA_CONF_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dma_conf.val;
|
||||
conf_buffer[SPI_LL_DMA_INT_ENA_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dma_int_ena.val;
|
||||
conf_buffer[SPI_LL_DMA_INT_CLR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->dma_int_clr.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/Disable the conf phase
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param enable True: enable; False: disable
|
||||
*/
|
||||
static inline void spi_ll_conf_state_enable(spi_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->slave.usr_conf = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Segmented-Configure-Transfer required magic value
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param magic_value magic value
|
||||
*/
|
||||
static inline void spi_ll_set_magic_number(spi_dev_t *hw, uint8_t magic_value)
|
||||
{
|
||||
hw->slave.dma_seg_magic_value = magic_value;
|
||||
}
|
||||
|
||||
#undef SPI_LL_RST_MASK
|
||||
#undef SPI_LL_UNUSED_INT_MASK
|
||||
|
||||
|
||||
@@ -48,6 +48,15 @@ typedef dma_descriptor_align4_t spi_dma_desc_t;
|
||||
typedef dma_descriptor_align8_t spi_dma_desc_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enum for DMA descriptor status
|
||||
*/
|
||||
typedef enum spi_hal_dma_desc_status_t {
|
||||
SPI_HAL_DMA_DESC_NULL = 0, ///< Null descriptos
|
||||
SPI_HAL_DMA_DESC_RUN_OUT = 1, ///< DMA descriptors are not enough for data
|
||||
SPI_HAL_DMA_DESC_LINKED = 2, ///< DMA descriptors are linked successfully
|
||||
} spi_hal_dma_desc_status_t;
|
||||
|
||||
/**
|
||||
* Input parameters to the ``spi_hal_cal_clock_conf`` to calculate the timing configuration
|
||||
*/
|
||||
@@ -103,6 +112,17 @@ typedef struct {
|
||||
/* Configured by driver at initialization, don't touch */
|
||||
spi_dev_t *hw; ///< Beginning address of the peripheral registers.
|
||||
bool dma_enabled; ///< Whether the DMA is enabled, do not update after initialization
|
||||
|
||||
#if SOC_SPI_SCT_SUPPORTED
|
||||
/* Segmented-Configure-Transfer required, configured by driver, don't touch */
|
||||
uint32_t tx_free_desc_num;
|
||||
uint32_t rx_free_desc_num;
|
||||
lldesc_t *cur_tx_seg_link; ///< Current TX DMA descriptor used for sct mode.
|
||||
lldesc_t *cur_rx_seg_link; ///< Current RX DMA descriptor used for sct mode.
|
||||
lldesc_t *tx_seg_link_tail; ///< Tail of the TX DMA descriptor link
|
||||
lldesc_t *rx_seg_link_tail; ///< Tail of the RX DMA descriptor link
|
||||
#endif //#if SOC_SPI_SCT_SUPPORTED
|
||||
|
||||
/* Internal parameters, don't touch */
|
||||
spi_hal_trans_config_t trans_config; ///< Transaction configuration
|
||||
} spi_hal_context_t;
|
||||
@@ -133,6 +153,32 @@ typedef struct {
|
||||
};//boolean configurations
|
||||
} spi_hal_dev_config_t;
|
||||
|
||||
#if SOC_SPI_SCT_SUPPORTED
|
||||
/**
|
||||
* SCT mode required configurations, per segment
|
||||
*/
|
||||
typedef struct {
|
||||
/* CONF State */
|
||||
bool seg_end; ///< True: this segment is the end; False: this segment isn't the end;
|
||||
/* PREP State */
|
||||
int cs_setup; ///< Setup time of CS active edge before the first SPI clock
|
||||
/* CMD State */
|
||||
uint16_t cmd; ///< Command value to be sent
|
||||
int cmd_bits; ///< Length (in bits) of the command phase
|
||||
/* ADDR State */
|
||||
uint64_t addr; ///< Address value to be sent
|
||||
int addr_bits; ///< Length (in bits) of the address phase
|
||||
/* DUMMY State */
|
||||
int dummy_bits; ///< Base length (in bits) of the dummy phase.
|
||||
/* DOUT State */
|
||||
int tx_bitlen; ///< TX length, in bits
|
||||
/* DIN State */
|
||||
int rx_bitlen; ///< RX length, in bits
|
||||
/* DONE State */
|
||||
int cs_hold; ///< Hold time of CS inactive edge after the last SPI clock
|
||||
} spi_hal_seg_config_t;
|
||||
#endif //#if SOC_SPI_SCT_SUPPORTED
|
||||
|
||||
/**
|
||||
* Init the peripheral and the context.
|
||||
*
|
||||
@@ -266,6 +312,125 @@ void spi_hal_cal_timing(int source_freq_hz, int eff_clk, bool gpio_is_used, int
|
||||
*/
|
||||
int spi_hal_get_freq_limit(bool gpio_is_used, int input_delay_ns);
|
||||
|
||||
#if SOC_SPI_SCT_SUPPORTED
|
||||
/*----------------------------------------------------------
|
||||
* Segmented-Configure-Transfer (SCT) Mode
|
||||
* ---------------------------------------------------------*/
|
||||
/**
|
||||
* Initialise SCT mode required registers and hal states
|
||||
*
|
||||
* @param hal Context of the HAL layer.
|
||||
*/
|
||||
void spi_hal_sct_init(spi_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* Initialise conf buffer, give it an initial value
|
||||
*
|
||||
* @param hal Context of the HAL layer.
|
||||
*/
|
||||
void spi_hal_sct_init_conf_buffer(spi_hal_context_t *hal, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX]);
|
||||
|
||||
/**
|
||||
* Format the conf buffer
|
||||
* According to the `spi_hal_seg_config_t`, update the conf buffer
|
||||
*
|
||||
* @param hal Context of the HAL layer.
|
||||
* @param config Conf buffer configuration, per segment. See `spi_hal_seg_config_t` to know what can be configured
|
||||
* @param conf_buffer Conf buffer
|
||||
*/
|
||||
void spi_hal_sct_format_conf_buffer(spi_hal_context_t *hal, const spi_hal_seg_config_t *config, const spi_hal_dev_config_t *dev, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX]);
|
||||
|
||||
/**
|
||||
* Format tx dma descriptor(s) for a SCT head
|
||||
*
|
||||
* @param hal Context of the HAL layer.
|
||||
* @param conf_buffer Conf buffer
|
||||
* @param send_buffer TX buffer
|
||||
* @param buf_len_bytes TX buffer length, in bytes
|
||||
* @param[out] trans_head SCT dma descriptor head
|
||||
* @param[out] used_desc_num After formatting, `used_desc_num` number of descriptors are used
|
||||
*
|
||||
* @return
|
||||
* - SPI_HAL_DMA_DESC_LINKED: Successfully format these dma descriptors, and link together
|
||||
* - SPI_HAL_DMA_DESC_RUN_OUT: Run out of dma descriptors, should alloc more, or wait until enough number of descriptors are recycled (by `spi_hal_sct_tx_dma_desc_recycle`)
|
||||
*/
|
||||
spi_hal_dma_desc_status_t spi_hal_sct_new_tx_dma_desc_head(spi_hal_context_t *hal, const uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX], const void *send_buffer, uint32_t buf_len_bytes, lldesc_t **trans_head, uint32_t *used_desc_num);
|
||||
|
||||
/**
|
||||
* Format tx dma descriptor(s) for a segment, and linked it to its previous segment
|
||||
*
|
||||
* @param hal Context of the HAL layer.
|
||||
* @param conf_buffer Conf buffer
|
||||
* @param send_buffer TX buffer
|
||||
* @param buf_len_bytes TX buffer length, in bytes
|
||||
* @param[out] used_desc_num After formatting, `used_desc_num` number of descriptors are used
|
||||
*
|
||||
* @return
|
||||
* - SPI_HAL_DMA_DESC_LINKED: Successfully format these dma descriptors, and link together
|
||||
* - SPI_HAL_DMA_DESC_RUN_OUT: Run out of dma descriptors, should alloc more, or wait until enough number of descriptors are recycled (by `spi_hal_sct_tx_dma_desc_recycle`)
|
||||
*/
|
||||
spi_hal_dma_desc_status_t spi_hal_sct_link_tx_seg_dma_desc(spi_hal_context_t *hal, const uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX], const void *send_buffer, uint32_t buf_len_bytes, uint32_t *used_desc_num);
|
||||
|
||||
/**
|
||||
* Recycle used tx dma descriptors (back to available state, NOT a memory free)
|
||||
*
|
||||
* @param hal Context of the HAL layer.
|
||||
* @param recycle_num Number of the to-be-recycled descriptors
|
||||
*/
|
||||
void spi_hal_sct_tx_dma_desc_recycle(spi_hal_context_t *hal, uint32_t recycle_num);
|
||||
|
||||
/**
|
||||
* Format rx dma descriptor(s) for a SCT head
|
||||
*
|
||||
* @param hal Context of the HAL layer.
|
||||
* @param recv_buffer RX buffer
|
||||
* @param buf_len_bytes RX buffer length, in bytes
|
||||
* @param[out] trans_head SCT dma descriptor head
|
||||
* @param[out] used_desc_num After formatting, `used_desc_num` number of descriptors are used
|
||||
*
|
||||
* @return
|
||||
* - SPI_HAL_DMA_DESC_LINKED: Successfully format these dma descriptors, and link together
|
||||
* - SPI_HAL_DMA_DESC_RUN_OUT: Run out of dma descriptors, should alloc more, or wait until enough number of descriptors are recycled (by `spi_hal_sct_tx_dma_desc_recycle`)
|
||||
*/
|
||||
spi_hal_dma_desc_status_t spi_hal_sct_new_rx_dma_desc_head(spi_hal_context_t *hal, const void *recv_buffer, uint32_t buf_len_bytes, lldesc_t **trans_head, uint32_t *used_desc_num);
|
||||
|
||||
/**
|
||||
* Format rx dma descriptor(s) for a segment, and linked it to its previous segment
|
||||
*
|
||||
* @param hal Context of the HAL layer.
|
||||
* @param send_buffer RX buffer
|
||||
* @param buf_len_bytes RX buffer length, in bytes
|
||||
* @param[out] used_desc_num After formatting, `used_desc_num` number of descriptors are used
|
||||
*
|
||||
* @return
|
||||
* - SPI_HAL_DMA_DESC_LINKED: Successfully format these dma descriptors, and link together
|
||||
* - SPI_HAL_DMA_DESC_RUN_OUT: Run out of dma descriptors, should alloc more, or wait until enough number of descriptors are recycled (by `spi_hal_sct_tx_dma_desc_recycle`)
|
||||
*/
|
||||
spi_hal_dma_desc_status_t spi_hal_sct_link_rx_seg_dma_desc(spi_hal_context_t *hal, const void *recv_buffer, uint32_t buf_len_bytes, uint32_t *used_desc_num);
|
||||
|
||||
/**
|
||||
* Recycle used rx dma descriptors (back to available state, NOT a memory free)
|
||||
*
|
||||
* @param hal Context of the HAL layer.
|
||||
* @param recycle_num Number of the to-be-recycled descriptors
|
||||
*/
|
||||
void spi_hal_sct_rx_dma_desc_recycle(spi_hal_context_t *hal, uint32_t recycle_num);
|
||||
|
||||
/**
|
||||
* Load dma descriptors to dma
|
||||
* Will do nothing to TX or RX dma, when `tx_seg_head` or `rx_seg_head` is NULL
|
||||
*
|
||||
* @param hal Context of the HAL layer.
|
||||
* @param rx_seg_head Head of the SCT RX dma descriptors
|
||||
* @param tx_seg_head Head of the SCT TX dma descriptors
|
||||
*/
|
||||
void spi_hal_sct_load_dma_link(spi_hal_context_t *hal, lldesc_t *rx_seg_head, lldesc_t *tx_seg_head);
|
||||
|
||||
/**
|
||||
* Deinit SCT mode related registers and hal states
|
||||
*/
|
||||
void spi_hal_sct_deinit(spi_hal_context_t *hal);
|
||||
#endif //#if SOC_SPI_SCT_SUPPORTED
|
||||
#endif //#if SOC_GPSPI_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -52,6 +52,34 @@ void spi_hal_deinit(spi_hal_context_t *hal)
|
||||
}
|
||||
}
|
||||
|
||||
#if SOC_SPI_SCT_SUPPORTED
|
||||
static void s_sct_reset_dma_link(spi_hal_context_t *hal)
|
||||
{
|
||||
hal->tx_free_desc_num = hal->dmadesc_n;
|
||||
hal->rx_free_desc_num = hal->dmadesc_n;
|
||||
hal->cur_tx_seg_link = hal->dmadesc_tx;
|
||||
hal->cur_rx_seg_link = hal->dmadesc_rx;
|
||||
hal->tx_seg_link_tail = NULL;
|
||||
hal->rx_seg_link_tail = NULL;
|
||||
}
|
||||
|
||||
void spi_hal_sct_init(spi_hal_context_t *hal)
|
||||
{
|
||||
s_sct_reset_dma_link(hal);
|
||||
spi_ll_conf_state_enable(hal->hw, true);
|
||||
spi_ll_set_magic_number(hal->hw, SPI_LL_SCT_MAGIC_NUMBER);
|
||||
spi_ll_enable_intr(hal->hw, SPI_LL_INTR_SEG_DONE);
|
||||
spi_ll_set_intr(hal->hw, SPI_LL_INTR_SEG_DONE);
|
||||
}
|
||||
|
||||
void spi_hal_sct_deinit(spi_hal_context_t *hal)
|
||||
{
|
||||
spi_ll_conf_state_enable(hal->hw, false);
|
||||
spi_ll_disable_intr(hal->hw, SPI_LL_INTR_SEG_DONE);
|
||||
spi_ll_clear_intr(hal->hw, SPI_LL_INTR_SEG_DONE);
|
||||
}
|
||||
#endif //#if SOC_SPI_SCT_SUPPORTED
|
||||
|
||||
esp_err_t spi_hal_cal_clock_conf(const spi_hal_timing_param_t *timing_param, spi_hal_timing_conf_t *timing_conf)
|
||||
{
|
||||
spi_hal_timing_conf_t temp_conf = {};
|
||||
|
||||
@@ -162,3 +162,177 @@ void spi_hal_fetch_result(const spi_hal_context_t *hal)
|
||||
spi_ll_read_buffer(hal->hw, trans->rcv_buffer, trans->rx_bitlen);
|
||||
}
|
||||
}
|
||||
|
||||
#if SOC_SPI_SCT_SUPPORTED
|
||||
/*------------------------------------------------------------------------------
|
||||
* Segmented-Configure-Transfer
|
||||
*----------------------------------------------------------------------------*/
|
||||
void spi_hal_sct_init_conf_buffer(spi_hal_context_t *hal, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
spi_ll_init_conf_buffer(hal->hw, conf_buffer);
|
||||
}
|
||||
|
||||
void spi_hal_sct_format_conf_buffer(spi_hal_context_t *hal, const spi_hal_seg_config_t *config, const spi_hal_dev_config_t *dev, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX])
|
||||
{
|
||||
spi_ll_format_prep_phase_conf_buffer(hal->hw, config->cs_setup, conf_buffer);
|
||||
spi_ll_format_cmd_phase_conf_buffer(hal->hw, config->cmd, config->cmd_bits, dev->tx_lsbfirst, conf_buffer);
|
||||
spi_ll_format_addr_phase_conf_buffer(hal->hw, config->addr, config->addr_bits, dev->rx_lsbfirst, conf_buffer);
|
||||
spi_ll_format_dummy_phase_conf_buffer(hal->hw, config->dummy_bits, conf_buffer);
|
||||
spi_ll_format_dout_phase_conf_buffer(hal->hw, config->tx_bitlen, conf_buffer);
|
||||
spi_ll_format_din_phase_conf_buffer(hal->hw, config->rx_bitlen, conf_buffer);
|
||||
spi_ll_format_done_phase_conf_buffer(hal->hw, config->cs_hold, conf_buffer);
|
||||
spi_ll_format_conf_phase_conf_buffer(hal->hw, conf_buffer, config->seg_end);
|
||||
}
|
||||
|
||||
void spi_hal_sct_load_dma_link(spi_hal_context_t *hal, lldesc_t *rx_seg_head, lldesc_t *tx_seg_head)
|
||||
{
|
||||
spi_ll_clear_intr(hal->hw, SPI_LL_INTR_SEG_DONE);
|
||||
|
||||
HAL_ASSERT(hal->dma_enabled);
|
||||
if (rx_seg_head) {
|
||||
spi_dma_ll_rx_reset(hal->dma_in, hal->rx_dma_chan);
|
||||
spi_ll_dma_rx_fifo_reset(hal->hw);
|
||||
spi_ll_infifo_full_clr(hal->hw);
|
||||
spi_ll_dma_rx_enable(hal->hw, 1);
|
||||
spi_dma_ll_rx_start(hal->dma_in, hal->rx_dma_chan, rx_seg_head);
|
||||
}
|
||||
|
||||
if (tx_seg_head) {
|
||||
spi_dma_ll_tx_reset(hal->dma_out, hal->tx_dma_chan);
|
||||
spi_ll_dma_tx_fifo_reset(hal->hw);
|
||||
spi_ll_outfifo_empty_clr(hal->hw);
|
||||
spi_ll_dma_tx_enable(hal->hw, 1);
|
||||
spi_dma_ll_tx_start(hal->dma_out, hal->tx_dma_chan, tx_seg_head);
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Below hal functions should be in the same spinlock
|
||||
*-----------------------------------------------------------*/
|
||||
/*-------------------------
|
||||
* TX
|
||||
*------------------------*/
|
||||
void spi_hal_sct_tx_dma_desc_recycle(spi_hal_context_t *hal, uint32_t recycle_num)
|
||||
{
|
||||
hal->tx_free_desc_num += recycle_num;
|
||||
}
|
||||
|
||||
static void s_sct_prepare_tx_seg(spi_hal_context_t *hal, const uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX], const void *send_buffer, uint32_t buf_len_bytes, lldesc_t **trans_head)
|
||||
{
|
||||
HAL_ASSERT(hal->tx_free_desc_num >= 1 + lldesc_get_required_num(buf_len_bytes));
|
||||
|
||||
*trans_head = hal->cur_tx_seg_link;
|
||||
lldesc_setup_link(hal->cur_tx_seg_link, conf_buffer, SOC_SPI_SCT_BUFFER_NUM_MAX * 4, false);
|
||||
lldesc_t *conf_buffer_link = hal->cur_tx_seg_link;
|
||||
hal->tx_free_desc_num -= 1;
|
||||
|
||||
hal->tx_seg_link_tail = hal->cur_tx_seg_link;
|
||||
hal->cur_tx_seg_link++;
|
||||
if (hal->cur_tx_seg_link == hal->dmadesc_tx + hal->dmadesc_n) {
|
||||
//As there is enough space, so we simply point this to the pool head
|
||||
hal->cur_tx_seg_link = hal->dmadesc_tx;
|
||||
}
|
||||
|
||||
if(send_buffer && buf_len_bytes) {
|
||||
lldesc_setup_link(hal->cur_tx_seg_link, send_buffer, buf_len_bytes, false);
|
||||
STAILQ_NEXT(conf_buffer_link, qe) = hal->cur_tx_seg_link;
|
||||
for (int i = 0; i < lldesc_get_required_num(buf_len_bytes); i++) {
|
||||
hal->tx_seg_link_tail = hal->cur_tx_seg_link;
|
||||
hal->cur_tx_seg_link++;
|
||||
if (hal->cur_tx_seg_link == hal->dmadesc_tx + hal->dmadesc_n) {
|
||||
//As there is enough space, so we simply point this to the pool head
|
||||
hal->cur_tx_seg_link = hal->dmadesc_tx;
|
||||
}
|
||||
}
|
||||
hal->tx_free_desc_num -= lldesc_get_required_num(buf_len_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
spi_hal_dma_desc_status_t spi_hal_sct_new_tx_dma_desc_head(spi_hal_context_t *hal, const uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX], const void *send_buffer, uint32_t buf_len_bytes, lldesc_t **trans_head, uint32_t *used_desc_num)
|
||||
{
|
||||
//1 desc for the conf_buffer, other for data.
|
||||
if (hal->tx_free_desc_num < 1 + lldesc_get_required_num(buf_len_bytes)) {
|
||||
return SPI_HAL_DMA_DESC_RUN_OUT;
|
||||
}
|
||||
|
||||
s_sct_prepare_tx_seg(hal, conf_buffer, send_buffer, buf_len_bytes, trans_head);
|
||||
*used_desc_num = 1 + lldesc_get_required_num(buf_len_bytes);
|
||||
|
||||
return SPI_HAL_DMA_DESC_LINKED;
|
||||
}
|
||||
|
||||
spi_hal_dma_desc_status_t spi_hal_sct_link_tx_seg_dma_desc(spi_hal_context_t *hal, const uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX], const void *send_buffer, uint32_t buf_len_bytes, uint32_t *used_desc_num)
|
||||
{
|
||||
//1 desc for the conf_buffer, other for data.
|
||||
if (hal->tx_free_desc_num < 1 + lldesc_get_required_num(buf_len_bytes)) {
|
||||
return SPI_HAL_DMA_DESC_RUN_OUT;
|
||||
}
|
||||
|
||||
if (hal->tx_seg_link_tail) {
|
||||
//Connect last segment to the current segment, as we're sure the `s_sct_prepare_tx_seg` next won't fail.
|
||||
STAILQ_NEXT(hal->tx_seg_link_tail, qe) = hal->cur_tx_seg_link;
|
||||
}
|
||||
|
||||
lldesc_t *internal_head = NULL;
|
||||
s_sct_prepare_tx_seg(hal, conf_buffer, send_buffer, buf_len_bytes, &internal_head);
|
||||
*used_desc_num = 1 + lldesc_get_required_num(buf_len_bytes);
|
||||
|
||||
return SPI_HAL_DMA_DESC_LINKED;
|
||||
}
|
||||
|
||||
/*-------------------------
|
||||
* RX
|
||||
*------------------------*/
|
||||
void spi_hal_sct_rx_dma_desc_recycle(spi_hal_context_t *hal, uint32_t recycle_num)
|
||||
{
|
||||
hal->rx_free_desc_num += recycle_num;
|
||||
}
|
||||
|
||||
static void s_sct_prepare_rx_seg(spi_hal_context_t *hal, const void *recv_buffer, uint32_t buf_len_bytes, lldesc_t **trans_head)
|
||||
{
|
||||
HAL_ASSERT(hal->rx_free_desc_num >= lldesc_get_required_num(buf_len_bytes));
|
||||
|
||||
*trans_head = hal->cur_rx_seg_link;
|
||||
lldesc_setup_link(hal->cur_rx_seg_link, recv_buffer, buf_len_bytes, true);
|
||||
for (int i = 0; i< lldesc_get_required_num(buf_len_bytes); i++) {
|
||||
hal->rx_seg_link_tail = hal->cur_rx_seg_link;
|
||||
hal->cur_rx_seg_link++;
|
||||
if (hal->cur_rx_seg_link == hal->dmadesc_rx + hal->dmadesc_n) {
|
||||
//As there is enough space, so we simply point this to the pool head
|
||||
hal->cur_rx_seg_link = hal->dmadesc_rx;
|
||||
}
|
||||
}
|
||||
|
||||
hal->rx_free_desc_num -= lldesc_get_required_num(buf_len_bytes);
|
||||
}
|
||||
|
||||
spi_hal_dma_desc_status_t spi_hal_sct_new_rx_dma_desc_head(spi_hal_context_t *hal, const void *recv_buffer, uint32_t buf_len_bytes, lldesc_t **trans_head, uint32_t *used_desc_num)
|
||||
{
|
||||
if (hal->rx_free_desc_num < lldesc_get_required_num(buf_len_bytes)) {
|
||||
return SPI_HAL_DMA_DESC_RUN_OUT;
|
||||
}
|
||||
|
||||
s_sct_prepare_rx_seg(hal, recv_buffer, buf_len_bytes, trans_head);
|
||||
*used_desc_num = lldesc_get_required_num(buf_len_bytes);
|
||||
|
||||
return SPI_HAL_DMA_DESC_LINKED;
|
||||
}
|
||||
|
||||
spi_hal_dma_desc_status_t spi_hal_sct_link_rx_seg_dma_desc(spi_hal_context_t *hal, const void *recv_buffer, uint32_t buf_len_bytes, uint32_t *used_desc_num)
|
||||
{
|
||||
if (hal->rx_free_desc_num < lldesc_get_required_num(buf_len_bytes)) {
|
||||
return SPI_HAL_DMA_DESC_RUN_OUT;
|
||||
}
|
||||
|
||||
if (hal->rx_seg_link_tail) {
|
||||
//Connect last segment to the current segment, as we're sure the `s_sct_prepare_tx_seg` next won't fail.
|
||||
STAILQ_NEXT(hal->rx_seg_link_tail, qe) = hal->cur_rx_seg_link;
|
||||
}
|
||||
|
||||
lldesc_t *internal_head = NULL;
|
||||
s_sct_prepare_rx_seg(hal, recv_buffer, buf_len_bytes, &internal_head);
|
||||
*used_desc_num = lldesc_get_required_num(buf_len_bytes);
|
||||
|
||||
return SPI_HAL_DMA_DESC_LINKED;
|
||||
}
|
||||
#endif //#if SOC_SPI_SCT_SUPPORTED
|
||||
|
||||
Reference in New Issue
Block a user