arch/xtensa/esp32s3: Add qspi/spi_slave/lcd DMA request return value.

Optimize DMA initialization for duplicate calls.
This commit is contained in:
nuttxs 2024-07-23 17:38:34 +08:00 committed by Xiang Xiao
parent 6edd1e3f7d
commit a83a569652
8 changed files with 84 additions and 124 deletions

View File

@ -61,7 +61,6 @@
static bool g_dma_chan_used[ESP32S3_DMA_CHAN_MAX];
static mutex_t g_dma_lock = NXMUTEX_INITIALIZER;
static int g_dma_ref;
/****************************************************************************
* Public Functions
@ -541,54 +540,10 @@ void esp32s3_dma_set_ext_memblk(int chan, bool tx,
void esp32s3_dma_init(void)
{
nxmutex_lock(&g_dma_lock);
modifyreg32(SYSTEM_PERIP_CLK_EN1_REG, 0, SYSTEM_DMA_CLK_EN_M);
modifyreg32(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST_M, 0);
if (!g_dma_ref)
{
modifyreg32(SYSTEM_PERIP_CLK_EN1_REG, 0, SYSTEM_DMA_CLK_EN_M);
modifyreg32(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST_M, 0);
/* enable DMA clock gating */
modifyreg32(DMA_MISC_CONF_REG, 0, DMA_CLK_EN_M);
}
g_dma_ref++;
nxmutex_unlock(&g_dma_lock);
}
/****************************************************************************
* Name: esp32s3_dma_deinit
*
* Description:
* Deinitialize DMA driver.
*
* Input Parameters:
* None
*
* Returned Value:
* None.
*
****************************************************************************/
void esp32s3_dma_deinit(void)
{
nxmutex_lock(&g_dma_lock);
g_dma_ref--;
if (!g_dma_ref)
{
/* Disable DMA clock gating */
modifyreg32(DMA_MISC_CONF_REG, DMA_CLK_EN_M, 0);
/* Disable DMA module by gating the clock and asserting the reset
* signal.
*/
modifyreg32(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN_M, 0);
modifyreg32(SYSTEM_PERIP_RST_EN1_REG, 0, SYSTEM_DMA_RST_M);
}
nxmutex_unlock(&g_dma_lock);
modifyreg32(DMA_MISC_CONF_REG, 0, DMA_CLK_EN_M);
}

View File

@ -293,22 +293,6 @@ void esp32s3_dma_set_ext_memblk(int chan, bool tx,
void esp32s3_dma_init(void);
/****************************************************************************
* Name: esp32s3_dma_deinit
*
* Description:
* Deinitialize DMA driver.
*
* Input Parameters:
* None
*
* Returned Value:
* None.
*
****************************************************************************/
void esp32s3_dma_deinit(void);
#ifdef __cplusplus
}
#endif

View File

@ -3053,10 +3053,6 @@ static int i2s_dma_setup(struct esp32s3_i2s_s *priv)
int ret;
int i2s_dma_dev;
/* Initialize GDMA controller */
esp32s3_dma_init();
if (priv->config->port == 0)
{
i2s_dma_dev = ESP32S3_DMA_PERIPH_I2S0;
@ -3072,7 +3068,6 @@ static int i2s_dma_setup(struct esp32s3_i2s_s *priv)
if (priv->dma_channel < 0)
{
i2serr("Failed to allocate GDMA channel\n");
return ERROR;
}

View File

@ -246,7 +246,7 @@ static int esp32s3_lcd_base_updatearea(struct fb_vtable_s *vtable,
/* Initialization ***********************************************************/
static void esp32s3_lcd_dmasetup(void);
static int esp32s3_lcd_dmasetup(void);
static void esp32s3_lcd_gpio_config(void);
static void esp32s3_lcd_disable(void);
static void esp32s3_lcd_enable(void);
@ -638,19 +638,22 @@ static int IRAM_ATTR lcd_interrupt(int irq, void *context, void *arg)
* None
*
* Returned Value:
* None
* Zero on success; a negated errno on failure
*
****************************************************************************/
static void esp32s3_lcd_dmasetup(void)
static int esp32s3_lcd_dmasetup(void)
{
struct esp32s3_lcd_s *priv = &g_lcd_priv;
esp32s3_dma_init();
priv->dma_channel = esp32s3_dma_request(ESP32S3_DMA_PERIPH_LCDCAM,
10, 1, true);
DEBUGASSERT(priv->dma_channel >= 0);
if (priv->dma_channel < 0)
{
spierr("Failed to allocate GDMA channel\n");
return ERROR;
}
esp32s3_dma_set_ext_memblk(priv->dma_channel,
true,
ESP32S3_DMA_EXT_MEMBLK_64B);
@ -669,6 +672,8 @@ static void esp32s3_lcd_dmasetup(void)
ESP32S3_LCD_FB_SIZE,
true, priv->dma_channel);
}
return OK;
}
/****************************************************************************
@ -758,11 +763,11 @@ static void esp32s3_lcd_enableclk(void)
* None
*
* Returned Value:
* None
* OK on success; A negated errno value on failure.
*
****************************************************************************/
static void esp32s3_lcd_config(void)
static int esp32s3_lcd_config(void)
{
uint32_t regval;
irqstate_t flags;
@ -830,7 +835,10 @@ static void esp32s3_lcd_config(void)
/* Set GDMA */
esp32s3_lcd_dmasetup();
if (esp32s3_lcd_dmasetup() != OK)
{
return ERROR;
}
/* Configure interrupt */
@ -851,6 +859,8 @@ static void esp32s3_lcd_config(void)
spin_unlock_irqrestore(&priv->lock, flags);
up_enable_irq(ESP32S3_IRQ_LCD_CAM);
return OK;
}
/****************************************************************************
@ -965,7 +975,10 @@ int up_fbinitialize(int display)
/* Configure LCD controller */
esp32s3_lcd_config();
if (esp32s3_lcd_config() != OK)
{
return ERROR;
}
/* And turn the LCD on */

View File

@ -236,9 +236,9 @@ static void esp32s3_qspi_free(struct qspi_dev_s *dev, void *buffer);
#ifdef CONFIG_ESP32S3_SPI_DMA
static int esp32s3_qspi_interrupt(int irq, void *context, void *arg);
static int esp32s3_qspi_wait_sem(struct esp32s3_qspi_priv_s *priv);
static void esp32s3_qspi_init_dma(struct esp32s3_qspi_priv_s *priv);
static int esp32s3_qspi_init_dma(struct esp32s3_qspi_priv_s *priv);
#endif
static void esp32s3_qspi_init(struct esp32s3_qspi_priv_s *priv);
static int esp32s3_qspi_init(struct esp32s3_qspi_priv_s *priv);
static void esp32s3_qspi_deinit(struct esp32s3_qspi_priv_s *priv);
/****************************************************************************
@ -1171,12 +1171,12 @@ static int esp32s3_qspi_wait_sem(struct esp32s3_qspi_priv_s *priv)
* priv - QSPI private state data
*
* Returned Value:
* None.
* Zero on success; a negated errno on failure
*
****************************************************************************/
#ifdef CONFIG_ESP32S3_SPI_DMA
void esp32s3_qspi_init_dma(struct esp32s3_qspi_priv_s *priv)
static int esp32s3_qspi_init_dma(struct esp32s3_qspi_priv_s *priv)
{
const struct esp32s3_qspi_config_s *config = priv->config;
@ -1188,24 +1188,21 @@ void esp32s3_qspi_init_dma(struct esp32s3_qspi_priv_s *priv)
modifyreg32(SYSTEM_PERIP_RST_EN0_REG, config->dma_rst_bit, 0);
/* Initialize GDMA controller */
esp32s3_dma_init();
/* Request a GDMA channel for QSPI peripheral */
priv->dma_channel = esp32s3_dma_request(config->dma_periph, 1, 1, true);
if (priv->dma_channel < 0)
{
spierr("Failed to allocate GDMA channel\n");
DEBUGPANIC();
return ERROR;
}
/* Disable segment transaction mode for QSPI Master */
putreg32((SPI_SLV_RX_SEG_TRANS_CLR_EN_M | SPI_SLV_TX_SEG_TRANS_CLR_EN_M),
SPI_DMA_CONF_REG(config->id));
return OK;
}
/****************************************************************************
@ -1228,10 +1225,6 @@ void esp32s3_qspi_dma_deinit(struct esp32s3_qspi_priv_s *priv)
esp32s3_dma_release(priv->dma_channel);
/* Deinitialize DMA controller */
esp32s3_dma_deinit();
/* Disable DMA clock for the SPI peripheral */
modifyreg32(SYSTEM_PERIP_CLK_EN0_REG, priv->config->dma_clk_bit, 0);
@ -1368,11 +1361,11 @@ static void esp32s3_qspi_init_gpio(struct esp32s3_qspi_priv_s *priv)
* priv - QSPI private state data
*
* Returned Value:
* None.
* Zero on success; a negated errno on failure
*
****************************************************************************/
static void esp32s3_qspi_init(struct esp32s3_qspi_priv_s *priv)
static int esp32s3_qspi_init(struct esp32s3_qspi_priv_s *priv)
{
const struct esp32s3_qspi_config_s *config = priv->config;
uint8_t id = config->id;
@ -1394,12 +1387,19 @@ static void esp32s3_qspi_init(struct esp32s3_qspi_priv_s *priv)
putreg32(0, SPI_CTRL_REG(id));
#ifdef CONFIG_ESP32S3_SPI_DMA
esp32s3_qspi_init_dma(priv);
if (esp32s3_qspi_init_dma(priv) != OK)
{
modifyreg32(SYSTEM_PERIP_RST_EN0_REG, 0, priv->config->clk_bit);
modifyreg32(SYSTEM_PERIP_CLK_EN0_REG, priv->config->clk_bit, 0);
return ERROR;
}
#endif
esp32s3_qspi_setfrequency(&priv->spi_dev, QSPI_DEFAULT_FREQ);
esp32s3_qspi_setbits(&priv->spi_dev, QSPI_DEFAULT_WIDTH);
esp32s3_qspi_setmode(&priv->spi_dev, QSPI_DEFAULT_MODE);
return OK;
}
/****************************************************************************
@ -1603,7 +1603,18 @@ struct qspi_dev_s *esp32s3_qspibus_initialize(int port)
up_enable_irq(priv->config->irq);
#endif
esp32s3_qspi_init(priv);
if (esp32s3_qspi_init(priv) != OK)
{
#ifdef CONFIG_ESP32S3_SPI_DMA
up_disable_irq(priv->config->irq);
esp32s3_teardown_irq(priv->cpu, priv->config->periph, priv->cpuint);
irq_detach(priv->config->irq);
priv->cpuint = -ENOMEM;
#endif
nxmutex_unlock(&priv->lock);
return NULL;
}
priv->refs++;
nxmutex_unlock(&priv->lock);
return spi_dev;

View File

@ -1349,10 +1349,6 @@ static int esp32s3_spi_dma_init(struct spi_dev_s *dev)
modifyreg32(SYSTEM_PERIP_RST_EN0_REG, priv->config->dma_rst_bit, 0);
/* Initialize GDMA controller */
esp32s3_dma_init();
/* Request a GDMA channel for SPI peripheral */
priv->dma_channel = esp32s3_dma_request(priv->config->dma_periph, 1, 1,
@ -1360,8 +1356,6 @@ static int esp32s3_spi_dma_init(struct spi_dev_s *dev)
if (priv->dma_channel < 0)
{
spierr("Failed to allocate GDMA channel\n");
esp32s3_dma_deinit();
return ERROR;
}
@ -1395,10 +1389,6 @@ void esp32s3_spi_dma_deinit(struct spi_dev_s *dev)
esp32s3_dma_release(priv->dma_channel);
/* Deinitialize DMA controller */
esp32s3_dma_deinit();
/* Disable DMA clock for the SPI peripheral */
modifyreg32(SYSTEM_PERIP_CLK_EN0_REG, priv->config->dma_clk_bit, 0);

View File

@ -267,7 +267,7 @@ static void spislave_prepare_next_tx(struct spislave_priv_s *priv);
#else
static void spislave_write_tx_buffer(struct spislave_priv_s *priv);
#endif
static void spislave_initialize(struct spi_slave_ctrlr_s *ctrlr);
static int spislave_initialize(struct spi_slave_ctrlr_s *ctrlr);
static void spislave_deinitialize(struct spi_slave_ctrlr_s *ctrlr);
/* SPI Slave controller operations */
@ -1117,7 +1117,7 @@ static int spislave_periph_interrupt(int irq, void *context, void *arg)
****************************************************************************/
#ifdef CONFIG_ESP32S3_SPI_DMA
void spislave_dma_init(struct spislave_priv_s *priv)
static int spislave_dma_init(struct spislave_priv_s *priv)
{
/* Enable GDMA clock for the SPI peripheral */
@ -1127,10 +1127,6 @@ void spislave_dma_init(struct spislave_priv_s *priv)
resetbits(priv->config->dma_rst_bit, SYSTEM_PERIP_RST_EN0_REG);
/* Initialize GDMA controller */
esp32s3_dma_init();
/* Request a GDMA channel for SPI peripheral */
priv->dma_channel = esp32s3_dma_request(priv->config->dma_periph, 1, 1,
@ -1138,8 +1134,7 @@ void spislave_dma_init(struct spislave_priv_s *priv)
if (priv->dma_channel < 0)
{
spierr("Failed to allocate GDMA channel\n");
DEBUGPANIC();
return ERROR;
}
/* Disable segment transaction mode for SPI Slave */
@ -1149,6 +1144,8 @@ void spislave_dma_init(struct spislave_priv_s *priv)
/* Configure DMA In-Link EOF to be generated by trans_done */
resetbits(SPI_RX_EOF_EN_M, SPI_DMA_CONF_REG(priv->config->id));
return OK;
}
/****************************************************************************
@ -1171,10 +1168,6 @@ void spislave_dma_deinit(struct spislave_priv_s *priv)
esp32s3_dma_release(priv->dma_channel);
/* Deinitialize DMA controller */
esp32s3_dma_deinit();
/* Disable DMA clock for the SPI peripheral */
modifyreg32(SYSTEM_PERIP_CLK_EN0_REG, priv->config->dma_clk_bit, 0);
@ -1322,11 +1315,11 @@ static void spislave_gpio_initialize(struct spislave_priv_s *priv)
* ctrlr - SPI Slave controller interface instance
*
* Returned Value:
* None.
* Zero on success; a negated errno on failure
*
****************************************************************************/
static void spislave_initialize(struct spi_slave_ctrlr_s *ctrlr)
static int spislave_initialize(struct spi_slave_ctrlr_s *ctrlr)
{
uint32_t regval;
struct spislave_priv_s *priv = (struct spislave_priv_s *)ctrlr;
@ -1373,7 +1366,12 @@ static void spislave_initialize(struct spi_slave_ctrlr_s *ctrlr)
resetbits(SPI_INT_MASK, SPI_DMA_INT_ENA_REG(priv->config->id));
#ifdef CONFIG_ESP32S3_SPI_DMA
spislave_dma_init(priv);
if (spislave_dma_init(priv) != OK)
{
setbits(priv->config->clk_bit, SYSTEM_PERIP_RST_EN0_REG);
resetbits(priv->config->clk_bit, SYSTEM_PERIP_CLK_EN0_REG);
return ERROR;
}
#endif
esp32s3_gpioirqenable(ESP32S3_PIN2IRQ(config->cs_pin), RISING);
@ -1392,6 +1390,8 @@ static void spislave_initialize(struct spi_slave_ctrlr_s *ctrlr)
#endif
setbits(regval, SPI_DMA_INT_RAW_REG(priv->config->id));
setbits(regval, SPI_DMA_INT_ENA_REG(priv->config->id));
return OK;
}
/****************************************************************************
@ -1493,7 +1493,12 @@ static void spislave_bind(struct spi_slave_ctrlr_s *ctrlr,
priv->tx_length = 0;
priv->is_tx_enabled = false;
spislave_initialize(ctrlr);
if (spislave_initialize(ctrlr) != OK)
{
spierr("spislave_initialize failed!\n");
spin_unlock_irqrestore(&priv->lock, flags);
DEBUGPANIC();
}
spislave_setmode(ctrlr, mode);
spislave_setbits(ctrlr, nbits);

View File

@ -40,6 +40,7 @@
#include "esp32s3_rtc.h"
#include "esp32s3_spiram.h"
#include "esp32s3_wdt.h"
#include "esp32s3_dma.h"
#ifdef CONFIG_BUILD_PROTECTED
# include "esp32s3_userspace.h"
#endif
@ -409,6 +410,12 @@ noinstrument_function void noreturn_function IRAM_ATTR __esp32s3_start(void)
esp_setup_syscall_table();
#if defined(CONFIG_ESP32S3_DMA)
/* Initialize GDMA controller */
esp32s3_dma_init();
#endif
/* Initialize onboard resources */
esp32s3_board_initialize();