Skip to content

Commit a11a103

Browse files
LucasTamborcarlescufi
authored andcommitted
drivers: spi: esp32/s2: add DMA support
Add SPI DMA support for esp32/s2. Signed-off-by: Lucas Tamborrino <[email protected]>
1 parent bea54c5 commit a11a103

File tree

5 files changed

+117
-6
lines changed

5 files changed

+117
-6
lines changed

drivers/spi/spi_esp32_spim.c

Lines changed: 91 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
LOG_MODULE_REGISTER(esp32_spi, CONFIG_SPI_LOG_LEVEL);
1515

1616
#include <soc.h>
17+
#include <soc/soc_memory_types.h>
1718
#include <zephyr/drivers/spi.h>
1819
#ifndef CONFIG_SOC_ESP32C3
1920
#include <zephyr/drivers/interrupt_controller/intc_esp32.h>
@@ -55,19 +56,48 @@ static inline void spi_esp32_complete(const struct device *dev,
5556
static int IRAM_ATTR spi_esp32_transfer(const struct device *dev)
5657
{
5758
struct spi_esp32_data *data = dev->data;
59+
const struct spi_esp32_config *cfg = dev->config;
5860
struct spi_context *ctx = &data->ctx;
5961
spi_hal_context_t *hal = &data->hal;
6062
spi_hal_dev_config_t *hal_dev = &data->dev_config;
6163
spi_hal_trans_config_t *hal_trans = &data->trans_config;
6264
size_t chunk_len = spi_context_max_continuous_chunk(&data->ctx);
6365
chunk_len = MIN(chunk_len, SOC_SPI_MAXIMUM_BUFFER_SIZE);
66+
size_t bit_len = chunk_len << 3;
67+
uint8_t *rx_temp = NULL;
68+
uint8_t *tx_temp = NULL;
69+
70+
if (cfg->dma_enabled) {
71+
/* bit_len needs to be at least one byte long when using DMA */
72+
bit_len = !bit_len ? 8 : bit_len;
73+
if (ctx->tx_buf && !esp_ptr_dma_capable((uint32_t *)&ctx->tx_buf[0])) {
74+
tx_temp = k_malloc(ctx->tx_len);
75+
if (!tx_temp) {
76+
LOG_ERR("Error allocating temp buffer Tx");
77+
return -ENOMEM;
78+
}
79+
memcpy(tx_temp, &ctx->tx_buf[0], ctx->tx_len);
80+
}
81+
if (ctx->rx_buf && (!esp_ptr_dma_capable((uint32_t *)&ctx->rx_buf[0]) ||
82+
((int)&ctx->rx_buf[0] % 4 != 0))) {
83+
/* The rx buffer need to be length of
84+
* multiples of 32 bits to avoid heap
85+
* corruption.
86+
*/
87+
rx_temp = k_calloc(((ctx->rx_len << 3) + 31) / 8, sizeof(uint8_t));
88+
if (!rx_temp) {
89+
LOG_ERR("Error allocating temp buffer Rx");
90+
return -ENOMEM;
91+
}
92+
}
93+
}
6494

6595
/* clean up and prepare SPI hal */
66-
memset((uint32_t *) hal->hw->data_buf, 0, sizeof(hal->hw->data_buf));
67-
hal_trans->send_buffer = (uint8_t *) ctx->tx_buf;
68-
hal_trans->rcv_buffer = ctx->rx_buf;
69-
hal_trans->tx_bitlen = chunk_len << 3;
70-
hal_trans->rx_bitlen = chunk_len << 3;
96+
memset((uint32_t *)hal->hw->data_buf, 0, sizeof(hal->hw->data_buf));
97+
hal_trans->send_buffer = tx_temp ? tx_temp : (uint8_t *)ctx->tx_buf;
98+
hal_trans->rcv_buffer = rx_temp ? rx_temp : ctx->rx_buf;
99+
hal_trans->tx_bitlen = bit_len;
100+
hal_trans->rx_bitlen = bit_len;
71101

72102
/* configure SPI */
73103
spi_hal_setup_trans(hal, hal_dev, hal_trans);
@@ -83,8 +113,21 @@ static int IRAM_ATTR spi_esp32_transfer(const struct device *dev)
83113

84114
/* read data */
85115
spi_hal_fetch_result(hal);
116+
117+
if (rx_temp) {
118+
memcpy(&ctx->rx_buf[0], rx_temp, chunk_len);
119+
}
120+
86121
spi_context_update_rx(&data->ctx, data->dfs, chunk_len);
87122

123+
if (tx_temp) {
124+
k_free(tx_temp);
125+
}
126+
127+
if (rx_temp) {
128+
k_free(rx_temp);
129+
}
130+
88131
return 0;
89132
}
90133

@@ -103,6 +146,42 @@ static void IRAM_ATTR spi_esp32_isr(void *arg)
103146
}
104147
#endif
105148

149+
static int spi_esp32_init_dma(const struct device *dev)
150+
{
151+
const struct spi_esp32_config *cfg = dev->config;
152+
struct spi_esp32_data *data = dev->data;
153+
154+
LOG_ERR("DMA");
155+
if (clock_control_on(cfg->clock_dev, (clock_control_subsys_t)cfg->dma_clk_src)) {
156+
LOG_ERR("Could not enable DMA clock");
157+
return -EIO;
158+
}
159+
160+
#ifdef CONFIG_SOC_ESP32
161+
/*Connect SPI and DMA*/
162+
DPORT_SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 3, cfg->dma_host + 1,
163+
((cfg->dma_host + 1) * 2));
164+
#endif /* CONFIG_SOC_ESP32 */
165+
166+
data->hal_config.dma_in = (spi_dma_dev_t *)cfg->spi;
167+
data->hal_config.dma_out = (spi_dma_dev_t *)cfg->spi;
168+
data->hal_config.dma_enabled = true;
169+
data->hal_config.tx_dma_chan = cfg->dma_host + 1;
170+
data->hal_config.rx_dma_chan = cfg->dma_host + 1;
171+
data->hal_config.dmadesc_n = 1;
172+
data->hal_config.dmadesc_rx = &data->dma_desc_rx;
173+
data->hal_config.dmadesc_tx = &data->dma_desc_tx;
174+
175+
if (data->hal_config.dmadesc_tx == NULL || data->hal_config.dmadesc_rx == NULL) {
176+
k_free(data->hal_config.dmadesc_tx);
177+
k_free(data->hal_config.dmadesc_rx);
178+
return -ENOMEM;
179+
}
180+
181+
spi_hal_init(&data->hal, cfg->dma_host + 1, &data->hal_config);
182+
return 0;
183+
}
184+
106185
static int spi_esp32_init(const struct device *dev)
107186
{
108187
int err;
@@ -113,6 +192,10 @@ static int spi_esp32_init(const struct device *dev)
113192
return -EINVAL;
114193
}
115194

195+
if (cfg->dma_enabled) {
196+
spi_esp32_init_dma(dev);
197+
}
198+
116199
#ifdef CONFIG_SPI_ESP32_INTERRUPT
117200
data->irq_line = esp_intr_alloc(cfg->irq_source,
118201
0,
@@ -382,6 +465,9 @@ static const struct spi_driver_api spi_api = {
382465
.clock_subsys = \
383466
(clock_control_subsys_t)DT_INST_CLOCKS_CELL(idx, offset), \
384467
.use_iomux = DT_INST_PROP(idx, use_iomux), \
468+
.dma_enabled = DT_INST_PROP(idx, dma_enabled), \
469+
.dma_clk_src = DT_INST_PROP(idx, dma_clk), \
470+
.dma_host = DT_INST_PROP(idx, dma_host), \
385471
}; \
386472
\
387473
DEVICE_DT_INST_DEFINE(idx, &spi_esp32_init, \

drivers/spi/spi_esp32_spim.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define ZEPHYR_DRIVERS_SPI_ESP32_SPIM_H_
99

1010
#include <zephyr/drivers/pinctrl.h>
11+
#include <hal/spi_hal.h>
1112

1213
#define SPI_MASTER_FREQ_8M (APB_CLK_FREQ/10)
1314
#define SPI_MASTER_FREQ_9M (APB_CLK_FREQ/9) /* 8.89MHz */
@@ -29,16 +30,22 @@ struct spi_esp32_config {
2930
const struct pinctrl_dev_config *pcfg;
3031
clock_control_subsys_t clock_subsys;
3132
bool use_iomux;
33+
bool dma_enabled;
34+
int dma_clk_src;
35+
int dma_host;
3236
};
3337

3438
struct spi_esp32_data {
3539
struct spi_context ctx;
3640
spi_hal_context_t hal;
41+
spi_hal_config_t hal_config;
3742
spi_hal_timing_conf_t timing_config;
3843
spi_hal_dev_config_t dev_config;
3944
spi_hal_trans_config_t trans_config;
4045
uint8_t dfs;
4146
int irq_line;
47+
lldesc_t dma_desc_tx;
48+
lldesc_t dma_desc_rx;
4249
};
4350

4451
#endif /* ZEPHYR_DRIVERS_SPI_ESP32_SPIM_H_ */

dts/bindings/spi/espressif,esp32-spi.yaml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,21 @@ properties:
3838
3939
Use MOSI for both sending and receiving data
4040
41-
dma:
41+
dma-enabled:
4242
type: boolean
4343
required: false
4444
description: Enable SPI DMA support
4545

46+
dma-clk:
47+
type: int
48+
required: false
49+
description: DMA clock source
50+
51+
dma-host:
52+
type: int
53+
required: false
54+
description: DMA Host - 0 -> SPI2, 1 -> SPI3
55+
4656
clk-as-cs:
4757
type: boolean
4858
required: false

dts/xtensa/espressif/esp32.dtsi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,8 @@
288288
interrupts = <SPI2_INTR_SOURCE>;
289289
interrupt-parent = <&intc>;
290290
clocks = <&rtc ESP32_HSPI_MODULE>;
291+
dma-clk = <ESP32_SPI_DMA_MODULE>;
292+
dma-host = <0>;
291293
status = "disabled";
292294
};
293295

@@ -297,6 +299,8 @@
297299
interrupts = <SPI3_INTR_SOURCE>;
298300
interrupt-parent = <&intc>;
299301
clocks = <&rtc ESP32_VSPI_MODULE>;
302+
dma-clk = <ESP32_SPI_DMA_MODULE>;
303+
dma-host = <1>;
300304
status = "disabled";
301305
};
302306

dts/xtensa/espressif/esp32s2.dtsi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@
221221
interrupts = <SPI2_INTR_SOURCE>;
222222
interrupt-parent = <&intc>;
223223
clocks = <&rtc ESP32_FSPI_MODULE>;
224+
dma-clk = <ESP32_SPI2_DMA_MODULE>;
225+
dma-host = <0>;
224226
status = "disabled";
225227
};
226228

@@ -230,6 +232,8 @@
230232
interrupts = <SPI3_INTR_SOURCE>;
231233
interrupt-parent = <&intc>;
232234
clocks = <&rtc ESP32_HSPI_MODULE>;
235+
dma-clk = <ESP32_SPI3_DMA_MODULE>;
236+
dma-host = <1>;
233237
status = "disabled";
234238
};
235239

0 commit comments

Comments
 (0)