xtensa/esp32: Refactor register access functions on SPI driver

This commit is contained in:
Gustavo Henrique Nihei
2021-03-25 18:22:53 -03:00
committed by Alan Carvalho de Assis
parent 5bff5dc971
commit 2d0e690803
+107 -130
View File
@@ -77,11 +77,14 @@
/* SPI Default speed (limited by clock divider) */ /* SPI Default speed (limited by clock divider) */
#define SPI_FREQ_DEFAULT 400000 #define SPI_FREQ_DEFAULT (400000)
#ifndef MIN /* Helper for applying the mask for a given register field.
# define MIN(a, b) (((a) < (b)) ? (a) : (b)) * Mask is determined by the macros suffixed with _V and _S from the
#endif * peripheral register description.
*/
#define VALUE_MASK(_val, _field) ((_val & (_field##_V)) << (_field##_S))
/**************************************************************************** /****************************************************************************
* Private Types * Private Types
@@ -91,7 +94,7 @@
struct esp32_spi_config_s struct esp32_spi_config_s
{ {
uint32_t reg_base; /* SPI register base address */ uint32_t id; /* SPI instance */
uint32_t clk_freq; /* SPI clock frequency */ uint32_t clk_freq; /* SPI clock frequency */
enum spi_mode_e mode; /* SPI default mode */ enum spi_mode_e mode; /* SPI default mode */
@@ -134,7 +137,7 @@ struct esp32_spi_priv_s
const struct esp32_spi_config_s *config; const struct esp32_spi_config_s *config;
int refs; /* Referernce count */ int refs; /* Reference count */
/* Held while chip is selected for mutual exclusion */ /* Held while chip is selected for mutual exclusion */
@@ -199,7 +202,7 @@ static void esp32_spi_deinit(FAR struct spi_dev_s *dev);
#ifdef CONFIG_ESP32_SPI2 #ifdef CONFIG_ESP32_SPI2
static const struct esp32_spi_config_s esp32_spi2_config = static const struct esp32_spi_config_s esp32_spi2_config =
{ {
.reg_base = REG_SPI_BASE(2), .id = 2,
.clk_freq = SPI_FREQ_DEFAULT, .clk_freq = SPI_FREQ_DEFAULT,
.mode = SPIDEV_MODE0, .mode = SPIDEV_MODE0,
.cs_pin = CONFIG_ESP32_SPI2_CSPIN, .cs_pin = CONFIG_ESP32_SPI2_CSPIN,
@@ -267,14 +270,14 @@ static struct esp32_spi_priv_s esp32_spi2_priv =
{ {
.ops = &esp32_spi2_ops .ops = &esp32_spi2_ops
}, },
.config = &esp32_spi2_config .config = &esp32_spi2_config
}; };
#endif /* CONFIG_ESP32_SPI2 */ #endif /* CONFIG_ESP32_SPI2 */
#ifdef CONFIG_ESP32_SPI3 #ifdef CONFIG_ESP32_SPI3
static const struct esp32_spi_config_s esp32_spi3_config = static const struct esp32_spi_config_s esp32_spi3_config =
{ {
.reg_base = REG_SPI_BASE(3), .id = 3,
.clk_freq = SPI_FREQ_DEFAULT, .clk_freq = SPI_FREQ_DEFAULT,
.mode = SPIDEV_MODE0, .mode = SPIDEV_MODE0,
.cs_pin = CONFIG_ESP32_SPI3_CSPIN, .cs_pin = CONFIG_ESP32_SPI3_CSPIN,
@@ -342,7 +345,7 @@ static struct esp32_spi_priv_s esp32_spi3_priv =
{ {
.ops = &esp32_spi3_ops .ops = &esp32_spi3_ops
}, },
.config = &esp32_spi3_config .config = &esp32_spi3_config
}; };
#endif /* CONFIG_ESP32_SPI3 */ #endif /* CONFIG_ESP32_SPI3 */
@@ -355,59 +358,14 @@ struct esp32_dmadesc_s s_dma_txdesc[SPI_DMA_CHANNEL_MAX][SPI_DMADESC_NUM];
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
/****************************************************************************
* Name: esp32_spi_set_reg
*
* Description:
* Set the contents of the SPI register at offset
*
* Input Parameters:
* priv - Private SPI device structure
* offset - Offset to the register of interest
* value - Value to be written
*
* Returned Value:
* None
*
****************************************************************************/
static inline void esp32_spi_set_reg(struct esp32_spi_priv_s *priv,
int offset,
uint32_t value)
{
putreg32(value, priv->config->reg_base + offset);
}
/****************************************************************************
* Name: esp32_spi_get_reg
*
* Description:
* Get the contents of the SPI register at offset
*
* Input Parameters:
* priv - Private SPI device structure
* offset - Offset to the register of interest
*
* Returned Value:
* The contents of the register
*
****************************************************************************/
static inline uint32_t esp32_spi_get_reg(struct esp32_spi_priv_s *priv,
int offset)
{
return getreg32(priv->config->reg_base + offset);
}
/**************************************************************************** /****************************************************************************
* Name: esp32_spi_set_regbits * Name: esp32_spi_set_regbits
* *
* Description: * Description:
* Set the bits of the SPI register at offset * Set the bits of the SPI register
* *
* Input Parameters: * Input Parameters:
* priv - Private SPI device structure * addr - Address of the register of interest
* offset - Offset to the register of interest
* bits - Bits to be set * bits - Bits to be set
* *
* Returned Value: * Returned Value:
@@ -415,23 +373,21 @@ static inline uint32_t esp32_spi_get_reg(struct esp32_spi_priv_s *priv,
* *
****************************************************************************/ ****************************************************************************/
static inline void esp32_spi_set_regbits(struct esp32_spi_priv_s *priv, static inline void esp32_spi_set_regbits(uint32_t addr, uint32_t bits)
int offset, uint32_t bits)
{ {
uint32_t tmp = getreg32(priv->config->reg_base + offset); uint32_t tmp = getreg32(addr);
putreg32(tmp | bits, priv->config->reg_base + offset); putreg32(tmp | bits, addr);
} }
/**************************************************************************** /****************************************************************************
* Name: esp32_spi_reset_regbits * Name: esp32_spi_reset_regbits
* *
* Description: * Description:
* Clear the bits of the SPI register at offset * Clear the bits of the SPI register
* *
* Input Parameters: * Input Parameters:
* priv - Private SPI device structure * addr - Address of the register of interest
* offset - Offset to the register of interest
* bits - Bits to be cleared * bits - Bits to be cleared
* *
* Returned Value: * Returned Value:
@@ -439,12 +395,11 @@ static inline void esp32_spi_set_regbits(struct esp32_spi_priv_s *priv,
* *
****************************************************************************/ ****************************************************************************/
static inline void esp32_spi_reset_regbits(struct esp32_spi_priv_s *priv, static inline void esp32_spi_reset_regbits(uint32_t addr, uint32_t bits)
int offset, uint32_t bits)
{ {
uint32_t tmp = getreg32(priv->config->reg_base + offset); uint32_t tmp = getreg32(addr);
putreg32(tmp & (~bits), priv->config->reg_base + offset); putreg32(tmp & (~bits), addr);
} }
/**************************************************************************** /****************************************************************************
@@ -466,7 +421,7 @@ static inline bool esp32_spi_iomux(struct esp32_spi_priv_s *priv)
bool mapped = false; bool mapped = false;
const struct esp32_spi_config_s *cfg = priv->config; const struct esp32_spi_config_s *cfg = priv->config;
if (REG_SPI_BASE(2) == cfg->reg_base) if (cfg->id == 2)
{ {
if (cfg->mosi_pin == SPI2_IOMUX_MOSIPIN && if (cfg->mosi_pin == SPI2_IOMUX_MOSIPIN &&
#ifndef CONFIG_ESP32_SPI_SWCS #ifndef CONFIG_ESP32_SPI_SWCS
@@ -478,7 +433,7 @@ static inline bool esp32_spi_iomux(struct esp32_spi_priv_s *priv)
mapped = true; mapped = true;
} }
} }
else if (REG_SPI_BASE(3) == cfg->reg_base) else if (cfg->id == 3)
{ {
if (cfg->mosi_pin == SPI3_IOMUX_MOSIPIN && if (cfg->mosi_pin == SPI3_IOMUX_MOSIPIN &&
#ifndef CONFIG_ESP32_SPI_SWCS #ifndef CONFIG_ESP32_SPI_SWCS
@@ -675,7 +630,7 @@ static uint32_t esp32_spi_setfrequency(FAR struct spi_dev_s *dev,
priv->frequency = frequency; priv->frequency = frequency;
esp32_spi_set_reg(priv, SPI_CLOCK_OFFSET, reg_val); putreg32(reg_val, SPI_CLOCK_REG(priv->config->id));
spiinfo("frequency=%d, actual=%d\n", priv->frequency, priv->actual); spiinfo("frequency=%d, actual=%d\n", priv->frequency, priv->actual);
@@ -741,24 +696,24 @@ static void esp32_spi_setmode(FAR struct spi_dev_s *dev,
return; return;
} }
esp32_spi_reset_regbits(priv, SPI_PIN_OFFSET, SPI_CK_IDLE_EDGE_M); const uint32_t id = priv->config->id;
esp32_spi_set_regbits(priv, SPI_PIN_OFFSET,
(ck_idle_edge << SPI_CK_IDLE_EDGE_S));
esp32_spi_reset_regbits(priv, SPI_USER_OFFSET, esp32_spi_reset_regbits(SPI_PIN_REG(id), SPI_CK_IDLE_EDGE_M);
SPI_CK_OUT_EDGE_M); esp32_spi_set_regbits(SPI_PIN_REG(id),
esp32_spi_set_regbits(priv, SPI_USER_OFFSET, VALUE_MASK(ck_idle_edge, SPI_CK_IDLE_EDGE));
(ck_out_edge << SPI_CK_OUT_EDGE_S));
esp32_spi_reset_regbits(priv, SPI_CTRL2_OFFSET, esp32_spi_reset_regbits(SPI_USER_REG(id), SPI_CK_OUT_EDGE_M);
esp32_spi_set_regbits(SPI_USER_REG(id),
VALUE_MASK(ck_out_edge, SPI_CK_OUT_EDGE));
esp32_spi_reset_regbits(SPI_CTRL2_REG(id),
SPI_MISO_DELAY_MODE_M | SPI_MISO_DELAY_MODE_M |
SPI_MISO_DELAY_NUM_M | SPI_MISO_DELAY_NUM_M |
SPI_MOSI_DELAY_NUM_M | SPI_MOSI_DELAY_NUM_M |
SPI_MOSI_DELAY_MODE_M); SPI_MOSI_DELAY_MODE_M);
esp32_spi_set_regbits(SPI_CTRL2_REG(id),
esp32_spi_set_regbits(priv, SPI_CTRL2_OFFSET, VALUE_MASK(delay_mode, SPI_MISO_DELAY_MODE) |
(delay_mode << SPI_MISO_DELAY_MODE_S) | VALUE_MASK(delay_mode, SPI_MOSI_DELAY_MODE));
(delay_mode << SPI_MOSI_DELAY_MODE_S));
priv->mode = mode; priv->mode = mode;
} }
@@ -846,11 +801,28 @@ static void esp32_spi_dma_exchange(FAR struct esp32_spi_priv_s *priv,
uint8_t *rp; uint8_t *rp;
uint32_t n; uint32_t n;
uint32_t regval; uint32_t regval;
struct esp32_dmadesc_s *dma_tx_desc;
struct esp32_dmadesc_s *dma_rx_desc;
#ifdef CONFIG_XTENSA_IMEM_USE_SEPARATE_HEAP #ifdef CONFIG_XTENSA_IMEM_USE_SEPARATE_HEAP
uint8_t *alloctp; uint8_t *alloctp;
uint8_t *allocrp; uint8_t *allocrp;
#endif #endif
/* Define these constants outside transfer loop to avoid wasting CPU time
* with register offset calculation.
*/
const uint32_t id = priv->config->id;
const uint8_t dma_desc_idx = priv->config->dma_chan - 1;
const uintptr_t spi_dma_in_link_reg = SPI_DMA_IN_LINK_REG(id);
const uintptr_t spi_dma_out_link_reg = SPI_DMA_OUT_LINK_REG(id);
const uintptr_t spi_slave_reg = SPI_SLAVE_REG(id);
const uintptr_t spi_dma_conf_reg = SPI_DMA_CONF_REG(id);
const uintptr_t spi_mosi_dlen_reg = SPI_MOSI_DLEN_REG(id);
const uintptr_t spi_miso_dlen_reg = SPI_MISO_DLEN_REG(id);
const uintptr_t spi_user_reg = SPI_USER_REG(id);
const uintptr_t spi_cmd_reg = SPI_CMD_REG(id);
DEBUGASSERT((txbuffer != NULL) || (rxbuffer != NULL)); DEBUGASSERT((txbuffer != NULL) || (rxbuffer != NULL));
/* If the buffer comes from PSRAM, allocate a new one from DRAM */ /* If the buffer comes from PSRAM, allocate a new one from DRAM */
@@ -887,59 +859,58 @@ static void esp32_spi_dma_exchange(FAR struct esp32_spi_priv_s *priv,
tp = rp; tp = rp;
} }
esp32_spi_reset_regbits(priv, SPI_SLAVE_OFFSET, SPI_TRANS_DONE_M); dma_tx_desc = s_dma_txdesc[dma_desc_idx];
esp32_spi_set_regbits(priv, SPI_SLAVE_OFFSET, SPI_INT_EN_M); dma_rx_desc = s_dma_rxdesc[dma_desc_idx];
esp32_spi_reset_regbits(spi_slave_reg, SPI_TRANS_DONE_M);
esp32_spi_set_regbits(spi_slave_reg, SPI_INT_EN_M);
while (bytes != 0) while (bytes != 0)
{ {
esp32_spi_set_reg(priv, SPI_DMA_IN_LINK_OFFSET, 0); putreg32(0, spi_dma_in_link_reg);
esp32_spi_set_reg(priv, SPI_DMA_OUT_LINK_OFFSET, 0); putreg32(0, spi_dma_out_link_reg);
esp32_spi_set_regbits(priv, SPI_SLAVE_OFFSET, SPI_SYNC_RESET_M); esp32_spi_set_regbits(spi_slave_reg, SPI_SYNC_RESET_M);
esp32_spi_reset_regbits(priv, SPI_SLAVE_OFFSET, SPI_SYNC_RESET_M); esp32_spi_reset_regbits(spi_slave_reg, SPI_SYNC_RESET_M);
esp32_spi_set_regbits(priv, SPI_DMA_CONF_OFFSET, SPI_DMA_RESET_MASK); esp32_spi_set_regbits(spi_dma_conf_reg, SPI_DMA_RESET_MASK);
esp32_spi_reset_regbits(priv, SPI_DMA_CONF_OFFSET, SPI_DMA_RESET_MASK); esp32_spi_reset_regbits(spi_dma_conf_reg, SPI_DMA_RESET_MASK);
n = esp32_dma_init(s_dma_txdesc[priv->config->dma_chan - 1], n = esp32_dma_init(dma_tx_desc, SPI_DMADESC_NUM, tp, bytes);
SPI_DMADESC_NUM, tp, bytes);
regval = (uintptr_t)s_dma_txdesc[priv->config->dma_chan - 1] & regval = VALUE_MASK((uintptr_t)dma_tx_desc, SPI_OUTLINK_ADDR);
SPI_OUTLINK_ADDR_V; regval |= SPI_OUTLINK_START_M;
esp32_spi_set_reg(priv, SPI_DMA_OUT_LINK_OFFSET, putreg32(regval, spi_dma_out_link_reg);
regval | SPI_OUTLINK_START_M); putreg32((n * 8 - 1), spi_mosi_dlen_reg);
esp32_spi_set_reg(priv, SPI_MOSI_DLEN_OFFSET, n * 8 - 1); esp32_spi_set_regbits(spi_user_reg, SPI_USR_MOSI_M);
esp32_spi_set_regbits(priv, SPI_USER_OFFSET, SPI_USR_MOSI_M);
tp += n; tp += n;
if (rp != NULL) if (rp != NULL)
{ {
esp32_dma_init(s_dma_rxdesc[priv->config->dma_chan - 1], esp32_dma_init(dma_rx_desc, SPI_DMADESC_NUM, rp, bytes);
SPI_DMADESC_NUM, rp, bytes);
regval = (uintptr_t)s_dma_rxdesc[priv->config->dma_chan - 1] & regval = VALUE_MASK((uintptr_t)dma_rx_desc, SPI_INLINK_ADDR);
SPI_INLINK_ADDR_V; regval |= SPI_INLINK_START_M;
esp32_spi_set_reg(priv, SPI_DMA_IN_LINK_OFFSET, putreg32(regval, spi_dma_in_link_reg);
regval | SPI_INLINK_START_M); putreg32((n * 8 - 1), spi_miso_dlen_reg);
esp32_spi_set_reg(priv, SPI_MISO_DLEN_OFFSET, n * 8 - 1); esp32_spi_set_regbits(spi_user_reg, SPI_USR_MISO_M);
esp32_spi_set_regbits(priv, SPI_USER_OFFSET, SPI_USR_MISO_M);
rp += n; rp += n;
} }
else else
{ {
esp32_spi_reset_regbits(priv, SPI_USER_OFFSET, SPI_USR_MISO_M); esp32_spi_reset_regbits(spi_user_reg, SPI_USR_MISO_M);
} }
esp32_spi_set_regbits(priv, SPI_CMD_OFFSET, SPI_USR_M); esp32_spi_set_regbits(spi_cmd_reg, SPI_USR_M);
esp32_spi_sem_waitdone(priv); esp32_spi_sem_waitdone(priv);
bytes -= n; bytes -= n;
} }
esp32_spi_reset_regbits(priv, SPI_SLAVE_OFFSET, SPI_INT_EN_M); esp32_spi_reset_regbits(spi_slave_reg, SPI_INT_EN_M);
#ifdef CONFIG_XTENSA_IMEM_USE_SEPARATE_HEAP #ifdef CONFIG_XTENSA_IMEM_USE_SEPARATE_HEAP
if (esp32_ptr_extram(rxbuffer)) if (esp32_ptr_extram(rxbuffer))
@@ -977,20 +948,24 @@ static uint32_t esp32_spi_poll_send(FAR struct esp32_spi_priv_s *priv,
uint32_t wd) uint32_t wd)
{ {
uint32_t val; uint32_t val;
const uintptr_t spi_miso_dlen_reg = SPI_MISO_DLEN_REG(priv->config->id);
const uintptr_t spi_mosi_dlen_reg = SPI_MOSI_DLEN_REG(priv->config->id);
const uintptr_t spi_w0_reg = SPI_W0_REG(priv->config->id);
const uintptr_t spi_cmd_reg = SPI_CMD_REG(priv->config->id);
esp32_spi_set_reg(priv, SPI_MISO_DLEN_OFFSET, (priv->nbits - 1)); putreg32((priv->nbits - 1), spi_miso_dlen_reg);
esp32_spi_set_reg(priv, SPI_MOSI_DLEN_OFFSET, (priv->nbits - 1)); putreg32((priv->nbits - 1), spi_mosi_dlen_reg);
esp32_spi_set_reg(priv, SPI_W0_OFFSET, wd); putreg32(wd, spi_w0_reg);
esp32_spi_set_regbits(priv, SPI_CMD_OFFSET, SPI_USR_M); esp32_spi_set_regbits(spi_cmd_reg, SPI_USR_M);
while (esp32_spi_get_reg(priv, SPI_CMD_OFFSET) & SPI_USR_M) while ((getreg32(spi_cmd_reg) & SPI_USR_M) != 0)
{ {
; ;
} }
val = esp32_spi_get_reg(priv, SPI_W0_OFFSET); val = getreg32(spi_w0_reg);
spiinfo("send=%x and recv=%x\n", wd, val); spiinfo("send=%x and recv=%x\n", wd, val);
@@ -1227,6 +1202,7 @@ static void esp32_spi_init(FAR struct spi_dev_s *dev)
{ {
FAR struct esp32_spi_priv_s *priv = (FAR struct esp32_spi_priv_s *)dev; FAR struct esp32_spi_priv_s *priv = (FAR struct esp32_spi_priv_s *)dev;
const struct esp32_spi_config_s *config = priv->config; const struct esp32_spi_config_s *config = priv->config;
uint32_t regval;
/* Initialize the SPI semaphore that enforces mutually exclusive access */ /* Initialize the SPI semaphore that enforces mutually exclusive access */
@@ -1277,18 +1253,18 @@ static void esp32_spi_init(FAR struct spi_dev_s *dev)
modifyreg32(DPORT_PERIP_CLK_EN_REG, 0, config->clk_bit); modifyreg32(DPORT_PERIP_CLK_EN_REG, 0, config->clk_bit);
modifyreg32(DPORT_PERIP_RST_EN_REG, config->rst_bit, 0); modifyreg32(DPORT_PERIP_RST_EN_REG, config->rst_bit, 0);
esp32_spi_set_reg(priv, SPI_USER_OFFSET, SPI_DOUTDIN_M | regval = SPI_DOUTDIN_M | SPI_USR_MISO_M | SPI_USR_MOSI_M | SPI_CS_HOLD_M;
SPI_USR_MISO_M | putreg32(regval, SPI_USER_REG(config->id));
SPI_USR_MOSI_M | putreg32(0, SPI_USER1_REG(config->id));
SPI_CS_HOLD_M); putreg32(0, SPI_SLAVE_REG(config->id));
esp32_spi_set_reg(priv, SPI_USER1_OFFSET, 0); putreg32(SPI_CS1_DIS_M | SPI_CS2_DIS_M, SPI_PIN_REG(config->id));
esp32_spi_set_reg(priv, SPI_SLAVE_OFFSET, 0);
esp32_spi_set_reg(priv, SPI_PIN_OFFSET, SPI_CS1_DIS_M | SPI_CS2_DIS_M);
#ifdef CONFIG_ESP32_SPI_SWCS #ifdef CONFIG_ESP32_SPI_SWCS
esp32_spi_set_regbits(priv, SPI_PIN_OFFSET, SPI_CS0_DIS_M); esp32_spi_set_regbits(SPI_PIN_REG(config->id), SPI_CS0_DIS_M);
#endif #endif
esp32_spi_set_reg(priv, SPI_CTRL_OFFSET, 0);
esp32_spi_set_reg(priv, SPI_CTRL2_OFFSET, (0 << SPI_HOLD_TIME_S)); putreg32(0, SPI_CTRL_REG(config->id));
putreg32(VALUE_MASK(0, SPI_HOLD_TIME), SPI_CTRL2_REG(config->id));
if (config->use_dma) if (config->use_dma)
{ {
@@ -1301,9 +1277,10 @@ static void esp32_spi_init(FAR struct spi_dev_s *dev)
modifyreg32(DPORT_SPI_DMA_CHAN_SEL_REG, 0, modifyreg32(DPORT_SPI_DMA_CHAN_SEL_REG, 0,
(config->dma_chan << config->dma_chan_s)); (config->dma_chan << config->dma_chan_s));
esp32_spi_set_reg(priv, SPI_DMA_CONF_OFFSET, SPI_OUT_DATA_BURST_EN_M | regval = SPI_OUT_DATA_BURST_EN_M |
SPI_INDSCR_BURST_EN_M | SPI_INDSCR_BURST_EN_M |
SPI_OUTDSCR_BURST_EN_M); SPI_OUTDSCR_BURST_EN_M;
putreg32(regval, SPI_DMA_CONF_REG(config->id));
} }
esp32_spi_setfrequency(dev, config->clk_freq); esp32_spi_setfrequency(dev, config->clk_freq);
@@ -1361,7 +1338,7 @@ static int esp32_spi_interrupt(int irq, void *context, FAR void *arg)
{ {
FAR struct esp32_spi_priv_s *priv = (FAR struct esp32_spi_priv_s *)arg; FAR struct esp32_spi_priv_s *priv = (FAR struct esp32_spi_priv_s *)arg;
esp32_spi_reset_regbits(priv, SPI_SLAVE_OFFSET, SPI_TRANS_DONE_M); esp32_spi_reset_regbits(SPI_SLAVE_REG(priv->config->id), SPI_TRANS_DONE_M);
nxsem_post(&priv->sem_isr); nxsem_post(&priv->sem_isr);
return 0; return 0;