Skip to content

Commit a35dd4b

Browse files
LucasTamborcarlescufi
authored andcommitted
drivers: dma: esp32s3: Add DMA support for esp32s3
Add GDMA support for esp32s3. Remove suspend/resume since they are optional and do the same as start/stop. Fix possible null pointer derreference. Signed-off-by: Lucas Tamborrino <[email protected]>
1 parent 4b31f8c commit a35dd4b

File tree

5 files changed

+163
-81
lines changed

5 files changed

+163
-81
lines changed

boards/xtensa/esp32s3_devkitm/doc/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ Current Zephyr's ESP32-S3-DevKitM board supports the following features:
104104
+------------+------------+-------------------------------------+
105105
| PCNT | on-chip | qdec |
106106
+------------+------------+-------------------------------------+
107+
| GDMA | on-chip | dma |
108+
+------------+------------+-------------------------------------+
107109

108110
Prerequisites
109111
-------------

boards/xtensa/esp32s3_devkitm/esp32s3_devkitm.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ supported:
1313
- watchdog
1414
- entropy
1515
- pwm
16+
- dma
1617
testing:
1718
ignore_tags:
1819
- net

drivers/dma/dma_esp32_gdma.c

Lines changed: 125 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,18 @@ LOG_MODULE_REGISTER(dma_esp32_gdma, CONFIG_DMA_LOG_LEVEL);
2020
#include <zephyr/kernel.h>
2121
#include <zephyr/drivers/dma.h>
2222
#include <zephyr/drivers/dma/dma_esp32.h>
23-
#include <zephyr/drivers/interrupt_controller/intc_esp32c3.h>
2423
#include <zephyr/drivers/clock_control.h>
24+
#ifndef CONFIG_SOC_ESP32C3
25+
#include <zephyr/drivers/interrupt_controller/intc_esp32.h>
26+
#else
27+
#include <zephyr/drivers/interrupt_controller/intc_esp32c3.h>
28+
#endif
29+
30+
#ifdef CONFIG_SOC_ESP32C3
31+
#define ISR_HANDLER isr_handler_t
32+
#else
33+
#define ISR_HANDLER intr_handler_t
34+
#endif
2535

2636
#define DMA_MAX_CHANNEL SOC_GDMA_PAIRS_PER_GROUP
2737

@@ -45,10 +55,15 @@ struct dma_esp32_channel {
4555
dma_descriptor_t desc;
4656
uint8_t *buf_temp;
4757
uint8_t *buf_original;
58+
#if defined(CONFIG_SOC_ESP32S3)
59+
struct intr_handle_data_t *intr_handle;
60+
#endif
4861
};
4962

5063
struct dma_esp32_config {
5164
int *irq_src;
65+
uint8_t irq_size;
66+
void **irq_handlers;
5267
uint8_t dma_channel_max;
5368
uint8_t sram_alignment;
5469
struct dma_esp32_channel dma_channel[DMA_MAX_CHANNEL * 2];
@@ -110,23 +125,58 @@ static void IRAM_ATTR dma_esp32_isr_handle(const struct device *dev, uint8_t rx_
110125
}
111126
}
112127

128+
#if defined(CONFIG_SOC_ESP32C3)
129+
static int dma_esp32_enable_interrupt(const struct device *dev,
130+
struct dma_esp32_channel *dma_channel)
131+
{
132+
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;
133+
134+
return esp_intr_enable(config->irq_src[dma_channel->channel_id]);
135+
}
136+
137+
static int dma_esp32_disable_interrupt(const struct device *dev,
138+
struct dma_esp32_channel *dma_channel)
139+
{
140+
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;
141+
142+
return esp_intr_disable(config->irq_src[dma_channel->channel_id]);
143+
}
144+
#else
145+
static int dma_esp32_enable_interrupt(const struct device *dev,
146+
struct dma_esp32_channel *dma_channel)
147+
{
148+
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;
149+
150+
return esp_intr_enable(dma_channel->intr_handle);
151+
}
152+
153+
static int dma_esp32_disable_interrupt(const struct device *dev,
154+
struct dma_esp32_channel *dma_channel)
155+
{
156+
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;
157+
158+
return esp_intr_disable(dma_channel->intr_handle);
159+
}
160+
161+
#endif
113162
static int dma_esp32_config_rx_descriptor(struct dma_esp32_channel *dma_channel,
114163
struct dma_block_config *block)
115164
{
116165
memset(&dma_channel->desc, 0, sizeof(dma_channel->desc));
117166
dma_channel->desc.buffer = (void *)block->dest_address;
118167
dma_channel->buf_original = (uint8_t *)block->dest_address;
168+
k_free(dma_channel->buf_temp);
169+
dma_channel->buf_temp = NULL;
119170
if (!esp_ptr_dma_capable((uint32_t *)block->dest_address)) {
120171
LOG_DBG("Rx buffer not in DMA capable memory: %p", (uint32_t *)block->dest_address);
121172
dma_channel->buf_temp = k_aligned_alloc(32, block->block_size);
122-
memset(dma_channel->buf_temp, 0, block->block_size);
123173
if (!dma_channel->buf_temp) {
124174
LOG_ERR("Not able to allocate mem");
125175
return -ENOMEM;
126176
}
177+
memset(dma_channel->buf_temp, 0, block->block_size);
127178
dma_channel->desc.buffer = dma_channel->buf_temp;
128179
}
129-
130180
dma_channel->desc.dw0.size = block->block_size;
131181
dma_channel->desc.dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
132182

@@ -174,6 +224,7 @@ static int dma_esp32_config_tx_descriptor(struct dma_esp32_channel *dma_channel,
174224
{
175225
memset(&dma_channel->desc, 0, sizeof(dma_channel->desc));
176226
dma_channel->desc.buffer = (void *)block->source_address;
227+
k_free(dma_channel->buf_temp);
177228
if (!esp_ptr_dma_capable((uint32_t *)block->source_address)) {
178229
LOG_DBG("Tx buffer not in DMA capable memory");
179230
dma_channel->buf_temp = k_malloc(block->block_size);
@@ -303,7 +354,7 @@ static int dma_esp32_start(const struct device *dev, uint32_t channel)
303354
return -EINVAL;
304355
}
305356

306-
if (esp_intr_enable(config->irq_src[dma_channel->channel_id])) {
357+
if (dma_esp32_enable_interrupt(dev, dma_channel)) {
307358
return -EINVAL;
308359
}
309360

@@ -338,31 +389,6 @@ static int dma_esp32_start(const struct device *dev, uint32_t channel)
338389
return 0;
339390
}
340391

341-
static int dma_esp32_suspend(const struct device *dev, uint32_t channel)
342-
{
343-
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;
344-
struct dma_esp32_data *data = (struct dma_esp32_data *const)(dev)->data;
345-
struct dma_esp32_channel *dma_channel = &config->dma_channel[channel];
346-
347-
if (channel >= config->dma_channel_max) {
348-
LOG_ERR("Unsupported channel");
349-
return -EINVAL;
350-
}
351-
352-
if (dma_channel->periph_id == SOC_GDMA_TRIG_PERIPH_M2M0) {
353-
gdma_ll_rx_stop(data->hal.dev, dma_channel->channel_id);
354-
gdma_ll_tx_stop(data->hal.dev, dma_channel->channel_id);
355-
}
356-
357-
if (dma_channel->dir == DMA_RX) {
358-
gdma_ll_rx_stop(data->hal.dev, dma_channel->channel_id);
359-
} else if (dma_channel->dir == DMA_TX) {
360-
gdma_ll_tx_stop(data->hal.dev, dma_channel->channel_id);
361-
}
362-
363-
return 0;
364-
}
365-
366392
static int dma_esp32_stop(const struct device *dev, uint32_t channel)
367393
{
368394
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;
@@ -374,34 +400,19 @@ static int dma_esp32_stop(const struct device *dev, uint32_t channel)
374400
return -EINVAL;
375401
}
376402

377-
if (esp_intr_disable(config->irq_src[dma_channel->channel_id])) {
378-
return -EINVAL;
379-
}
380-
381-
return dma_esp32_suspend(dev, channel);
382-
}
383-
384-
static int dma_esp32_resume(const struct device *dev, uint32_t channel)
385-
{
386-
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;
387-
struct dma_esp32_data *data = (struct dma_esp32_data *const)(dev)->data;
388-
struct dma_esp32_channel *dma_channel = &config->dma_channel[channel];
389-
390-
if (channel >= config->dma_channel_max) {
391-
LOG_ERR("Unsupported channel");
403+
if (dma_esp32_disable_interrupt(dev, dma_channel)) {
392404
return -EINVAL;
393405
}
394406

395407
if (dma_channel->periph_id == SOC_GDMA_TRIG_PERIPH_M2M0) {
396-
gdma_ll_rx_start(data->hal.dev, dma_channel->channel_id);
397-
gdma_ll_tx_start(data->hal.dev, dma_channel->channel_id);
398-
return 0;
408+
gdma_ll_rx_stop(data->hal.dev, dma_channel->channel_id);
409+
gdma_ll_tx_stop(data->hal.dev, dma_channel->channel_id);
399410
}
400411

401412
if (dma_channel->dir == DMA_RX) {
402-
gdma_ll_rx_start(data->hal.dev, dma_channel->channel_id);
413+
gdma_ll_rx_stop(data->hal.dev, dma_channel->channel_id);
403414
} else if (dma_channel->dir == DMA_TX) {
404-
gdma_ll_tx_start(data->hal.dev, dma_channel->channel_id);
415+
gdma_ll_tx_stop(data->hal.dev, dma_channel->channel_id);
405416
}
406417

407418
return 0;
@@ -439,7 +450,7 @@ static int dma_esp32_get_status(const struct device *dev, uint32_t channel,
439450
}
440451

441452
static int dma_esp32_reload(const struct device *dev, uint32_t channel, uint32_t src, uint32_t dst,
442-
size_t size)
453+
size_t size)
443454
{
444455
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;
445456
struct dma_esp32_data *data = (struct dma_esp32_data *const)(dev)->data;
@@ -475,6 +486,49 @@ static int dma_esp32_reload(const struct device *dev, uint32_t channel, uint32_t
475486
return 0;
476487
}
477488

489+
#if defined(CONFIG_SOC_ESP32C3)
490+
static int dma_esp32_configure_irq(const struct device *dev)
491+
{
492+
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;
493+
494+
for (uint8_t i = 0; i < config->irq_size; i++) {
495+
int ret = esp_intr_alloc(config->irq_src[i],
496+
0,
497+
(ISR_HANDLER)config->irq_handlers[i],
498+
(void *)dev,
499+
NULL);
500+
if (ret != 0) {
501+
LOG_ERR("Could not allocate interrupt handler");
502+
return ret;
503+
}
504+
}
505+
506+
return 0;
507+
}
508+
#else
509+
static int dma_esp32_configure_irq(const struct device *dev)
510+
{
511+
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;
512+
struct dma_esp32_data *data = (struct dma_esp32_data *)dev->data;
513+
struct dma_esp32_channel *dma_channel;
514+
515+
for (uint8_t i = 0; i < config->irq_size; i++) {
516+
dma_channel = &config->dma_channel[i];
517+
int ret = esp_intr_alloc(config->irq_src[i],
518+
0,
519+
(ISR_HANDLER)config->irq_handlers[i / 2],
520+
(void *)dev,
521+
&dma_channel->intr_handle);
522+
if (ret != 0) {
523+
LOG_ERR("Could not allocate interrupt handler");
524+
return ret;
525+
}
526+
}
527+
528+
return 0;
529+
}
530+
531+
#endif
478532
static int dma_esp32_init(const struct device *dev)
479533
{
480534
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;
@@ -493,7 +547,11 @@ static int dma_esp32_init(const struct device *dev)
493547
return ret;
494548
}
495549

496-
config->config_irq(dev);
550+
ret = dma_esp32_configure_irq(dev);
551+
if (ret < 0) {
552+
LOG_ERR("Could not configure IRQ (%d)", ret);
553+
return ret;
554+
}
497555

498556
for (uint8_t i = 0; i < DMA_MAX_CHANNEL * 2; i++) {
499557
dma_channel = &config->dma_channel[i];
@@ -515,18 +573,19 @@ static const struct dma_driver_api dma_esp32_api = {
515573
.config = dma_esp32_config,
516574
.start = dma_esp32_start,
517575
.stop = dma_esp32_stop,
518-
.suspend = dma_esp32_suspend,
519-
.resume = dma_esp32_resume,
520576
.get_status = dma_esp32_get_status,
521577
.reload = dma_esp32_reload,
522578
};
523579

524580
#define DMA_ESP32_DEFINE_IRQ_HANDLER(channel) \
525-
static void IRAM_ATTR dma_esp32_isr_##channel(const struct device *dev) \
581+
__attribute__((unused)) static void IRAM_ATTR dma_esp32_isr_##channel( \
582+
const struct device *dev) \
526583
{ \
527584
dma_esp32_isr_handle(dev, channel * 2, channel * 2 + 1); \
528585
}
529586

587+
#define ESP32_DMA_HANDLER(channel) dma_esp32_isr_##channel
588+
530589
DMA_ESP32_DEFINE_IRQ_HANDLER(0)
531590
DMA_ESP32_DEFINE_IRQ_HANDLER(1)
532591
DMA_ESP32_DEFINE_IRQ_HANDLER(2)
@@ -535,36 +594,25 @@ DMA_ESP32_DEFINE_IRQ_HANDLER(3)
535594
DMA_ESP32_DEFINE_IRQ_HANDLER(4)
536595
#endif
537596

538-
#define DMA_ESP32_CONNECT_IRQ(idx, channel, dev) \
539-
do { \
540-
esp_intr_alloc(DT_INST_IRQ_BY_IDX(idx, channel, irq), 0, \
541-
(isr_handler_t)dma_esp32_isr_##channel, (void *)dev, NULL); \
542-
esp_intr_disable(DT_INST_IRQ_BY_IDX(idx, channel, irq)); \
543-
} while (false)
544-
545-
#define DMA_ESP32_CONNECT_IRQ_COND(idx, channel, dev) \
546-
COND_CODE_1(DT_INST_IRQ_HAS_IDX(idx, channel), (DMA_ESP32_CONNECT_IRQ(idx, channel, dev)), \
547-
())
548-
549-
#define DMA_ESP32_DEFINE_IRQ_CONFIG(idx) \
550-
static void dma_esp32_config_irq_##idx(const struct device *dev) \
551-
{ \
552-
DMA_ESP32_CONNECT_IRQ_COND(idx, 0, dev); \
553-
DMA_ESP32_CONNECT_IRQ_COND(idx, 1, dev); \
554-
DMA_ESP32_CONNECT_IRQ_COND(idx, 2, dev); \
555-
DMA_ESP32_CONNECT_IRQ_COND(idx, 3, dev); \
556-
DMA_ESP32_CONNECT_IRQ_COND(idx, 4, dev); \
557-
}
597+
static void *irq_handlers[] = {
598+
ESP32_DMA_HANDLER(0),
599+
ESP32_DMA_HANDLER(1),
600+
ESP32_DMA_HANDLER(2),
601+
#if DMA_MAX_CHANNEL >= 5
602+
ESP32_DMA_HANDLER(3),
603+
ESP32_DMA_HANDLER(4),
604+
#endif
605+
};
558606

559607
#define DMA_ESP32_IRQ_NUM(node, prop, idx) DT_PROP_BY_IDX(node, interrupts, idx),
560608

561609
#define DMA_ESP32_INIT(idx) \
562-
DMA_ESP32_DEFINE_IRQ_CONFIG(idx) \
563610
static int irq_numbers[] = { \
564611
DT_INST_FOREACH_PROP_ELEM(idx, interrupts, DMA_ESP32_IRQ_NUM)}; \
565612
static struct dma_esp32_config dma_config_##idx = { \
566-
.config_irq = dma_esp32_config_irq_##idx, \
567613
.irq_src = irq_numbers, \
614+
.irq_size = ARRAY_SIZE(irq_numbers), \
615+
.irq_handlers = irq_handlers, \
568616
.dma_channel_max = DT_INST_PROP(idx, dma_channels), \
569617
.sram_alignment = DT_INST_PROP(idx, dma_buf_addr_alignment), \
570618
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(idx)), \
@@ -577,7 +625,7 @@ DMA_ESP32_DEFINE_IRQ_HANDLER(4)
577625
}, \
578626
}; \
579627
\
580-
DEVICE_DT_INST_DEFINE(idx, &dma_esp32_init, NULL, &dma_data_##idx, &dma_config_##idx, \
628+
DEVICE_DT_INST_DEFINE(idx, &dma_esp32_init, NULL, &dma_data_##idx, &dma_config_##idx, \
581629
PRE_KERNEL_1, CONFIG_DMA_INIT_PRIORITY, &dma_esp32_api);
582630

583631
DT_INST_FOREACH_STATUS_OKAY(DMA_ESP32_INIT)

dts/bindings/dma/espressif,esp32-gdma.yaml

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,30 @@ description: |
1313
1414
Every channel can be connected to different peripherals.
1515
16-
Peripherals with GDMA:
16+
ESP32C3's Peripherals with GDMA:
1717
* SPI2
1818
* UHCI0 (UART0/UART1)
19-
* I2S
20-
* AES
21-
* SHA
19+
* I2S (Not Supported yet)
20+
* AES (Not Supported yet)
21+
* SHA (Not Supported yet)
2222
* ADC
2323
24+
The GDMA controller in ESP32-S3 has ten independent channels,
25+
five transmit channels and five receive channels. Only six are
26+
supported, meaning three transmit and three receive channels.
27+
28+
ESP32S3's Peripherals with GDMA:
29+
* SPI2
30+
* SPI3
31+
* UHCI0
32+
* I2S0 (Not Supported yet)
33+
* I2S1 (Not Supported yet)
34+
* LCD/CAM (Not Supported yet)
35+
* AES (Not Supported yet)
36+
* SHA (Not Supported yet)
37+
* ADC (Not Supported yet)
38+
* RMT (Not Supported yet)
39+
2440
compatible: "espressif,esp32-gdma"
2541

2642
include: dma-controller.yaml

0 commit comments

Comments
 (0)