Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dma: esp32c6: Added support to GDMA #75453

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions boards/espressif/esp32c6_devkitc/doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ Current Zephyr's ESP32-C6-DevKitC board supports the following features:
+------------+------------+-------------------------------------+
| SPI DMA | on-chip | spi |
+------------+------------+-------------------------------------+
| GDMA | on-chip | dma |
+------------+------------+-------------------------------------+

System requirements
*******************
Expand Down
1 change: 1 addition & 0 deletions boards/espressif/esp32c6_devkitc/esp32c6_devkitc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ supported:
- gpio
- watchdog
- uart
- dma
- spi
testing:
ignore_tags:
Expand Down
136 changes: 63 additions & 73 deletions drivers/dma/dma_esp32_gdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,24 @@ LOG_MODULE_REGISTER(dma_esp32_gdma, CONFIG_DMA_LOG_LEVEL);
#include <zephyr/drivers/dma.h>
#include <zephyr/drivers/dma/dma_esp32.h>
#include <zephyr/drivers/clock_control.h>
#ifndef CONFIG_SOC_SERIES_ESP32C3
#include <zephyr/drivers/interrupt_controller/intc_esp32.h>
#else
#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6)
#include <zephyr/drivers/interrupt_controller/intc_esp32c3.h>
#else
#include <zephyr/drivers/interrupt_controller/intc_esp32.h>
#endif

#ifdef CONFIG_SOC_SERIES_ESP32C3
#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6)
#define ISR_HANDLER isr_handler_t
#else
#define ISR_HANDLER intr_handler_t
#endif

#if defined(CONFIG_SOC_SERIES_ESP32C6)
#define DMA_MAX_CHANNEL SOC_GDMA_PAIRS_PER_GROUP_MAX
#else
#define DMA_MAX_CHANNEL SOC_GDMA_PAIRS_PER_GROUP
#endif

#define ESP_DMA_M2M_ON 0
#define ESP_DMA_M2M_OFF 1

Expand All @@ -55,9 +60,6 @@ struct dma_esp32_channel {
dma_callback_t cb;
void *user_data;
dma_descriptor_t desc;
#if defined(CONFIG_SOC_SERIES_ESP32S3)
struct intr_handle_data_t *intr_handle;
#endif
};

struct dma_esp32_config {
Expand Down Expand Up @@ -103,6 +105,7 @@ static void IRAM_ATTR dma_esp32_isr_handle_tx(const struct device *dev,
}
}

#if !defined(CONFIG_SOC_SERIES_ESP32C6) && !defined(CONFIG_SOC_SERIES_ESP32S3)
static void IRAM_ATTR dma_esp32_isr_handle(const struct device *dev, uint8_t rx_id, uint8_t tx_id)
{
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;
Expand All @@ -121,41 +124,8 @@ static void IRAM_ATTR dma_esp32_isr_handle(const struct device *dev, uint8_t rx_
dma_esp32_isr_handle_tx(dev, dma_channel_tx, intr_status);
}
}

#if defined(CONFIG_SOC_SERIES_ESP32C3)
static int dma_esp32_enable_interrupt(const struct device *dev,
struct dma_esp32_channel *dma_channel)
{
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;

return esp_intr_enable(config->irq_src[dma_channel->channel_id]);
}

static int dma_esp32_disable_interrupt(const struct device *dev,
struct dma_esp32_channel *dma_channel)
{
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;

return esp_intr_disable(config->irq_src[dma_channel->channel_id]);
}
#else
static int dma_esp32_enable_interrupt(const struct device *dev,
struct dma_esp32_channel *dma_channel)
{
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;

return esp_intr_enable(dma_channel->intr_handle);
}

static int dma_esp32_disable_interrupt(const struct device *dev,
struct dma_esp32_channel *dma_channel)
{
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;

return esp_intr_disable(dma_channel->intr_handle);
}

#endif

static int dma_esp32_config_rx_descriptor(struct dma_esp32_channel *dma_channel,
struct dma_block_config *block)
{
Expand Down Expand Up @@ -338,16 +308,17 @@ static int dma_esp32_start(const struct device *dev, uint32_t channel)
return -EINVAL;
}

if (dma_esp32_enable_interrupt(dev, dma_channel)) {
return -EINVAL;
}

if (dma_channel->periph_id == SOC_GDMA_TRIG_PERIPH_M2M0) {
struct dma_esp32_channel *dma_channel_rx =
&config->dma_channel[dma_channel->channel_id * 2];
struct dma_esp32_channel *dma_channel_tx =
&config->dma_channel[(dma_channel->channel_id * 2) + 1];

gdma_ll_rx_enable_interrupt(data->hal.dev, dma_channel->channel_id,
UINT32_MAX, true);
gdma_ll_tx_enable_interrupt(data->hal.dev, dma_channel->channel_id,
GDMA_LL_EVENT_TX_EOF, true);

gdma_ll_rx_set_desc_addr(data->hal.dev, dma_channel->channel_id,
(int32_t)&dma_channel_rx->desc);
gdma_ll_rx_start(data->hal.dev, dma_channel->channel_id);
Expand All @@ -357,10 +328,14 @@ static int dma_esp32_start(const struct device *dev, uint32_t channel)
gdma_ll_tx_start(data->hal.dev, dma_channel->channel_id);
} else {
if (dma_channel->dir == DMA_RX) {
gdma_ll_rx_enable_interrupt(data->hal.dev, dma_channel->channel_id,
UINT32_MAX, true);
gdma_ll_rx_set_desc_addr(data->hal.dev, dma_channel->channel_id,
(int32_t)&dma_channel->desc);
gdma_ll_rx_start(data->hal.dev, dma_channel->channel_id);
} else if (dma_channel->dir == DMA_TX) {
gdma_ll_tx_enable_interrupt(data->hal.dev, dma_channel->channel_id,
GDMA_LL_EVENT_TX_EOF, true);
gdma_ll_tx_set_desc_addr(data->hal.dev, dma_channel->channel_id,
(int32_t)&dma_channel->desc);
gdma_ll_tx_start(data->hal.dev, dma_channel->channel_id);
Expand All @@ -384,18 +359,22 @@ static int dma_esp32_stop(const struct device *dev, uint32_t channel)
return -EINVAL;
}

if (dma_esp32_disable_interrupt(dev, dma_channel)) {
return -EINVAL;
}

if (dma_channel->periph_id == SOC_GDMA_TRIG_PERIPH_M2M0) {
gdma_ll_rx_enable_interrupt(data->hal.dev, dma_channel->channel_id,
UINT32_MAX, false);
gdma_ll_tx_enable_interrupt(data->hal.dev, dma_channel->channel_id,
GDMA_LL_EVENT_TX_EOF, false);
gdma_ll_rx_stop(data->hal.dev, dma_channel->channel_id);
gdma_ll_tx_stop(data->hal.dev, dma_channel->channel_id);
}

if (dma_channel->dir == DMA_RX) {
gdma_ll_rx_enable_interrupt(data->hal.dev, dma_channel->channel_id,
UINT32_MAX, false);
gdma_ll_rx_stop(data->hal.dev, dma_channel->channel_id);
} else if (dma_channel->dir == DMA_TX) {
gdma_ll_tx_enable_interrupt(data->hal.dev, dma_channel->channel_id,
GDMA_LL_EVENT_TX_EOF, false);
gdma_ll_tx_stop(data->hal.dev, dma_channel->channel_id);
}

Expand Down Expand Up @@ -470,7 +449,6 @@ static int dma_esp32_reload(const struct device *dev, uint32_t channel, uint32_t
return 0;
}

#if defined(CONFIG_SOC_SERIES_ESP32C3)
static int dma_esp32_configure_irq(const struct device *dev)
{
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;
Expand All @@ -489,30 +467,7 @@ static int dma_esp32_configure_irq(const struct device *dev)

return 0;
}
#else
static int dma_esp32_configure_irq(const struct device *dev)
{
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;
struct dma_esp32_data *data = (struct dma_esp32_data *)dev->data;
struct dma_esp32_channel *dma_channel;

for (uint8_t i = 0; i < config->irq_size; i++) {
dma_channel = &config->dma_channel[i];
int ret = esp_intr_alloc(config->irq_src[i],
0,
(ISR_HANDLER)config->irq_handlers[i / 2],
(void *)dev,
&dma_channel->intr_handle);
if (ret != 0) {
LOG_ERR("Could not allocate interrupt handler");
return ret;
}
}

return 0;
}

#endif
static int dma_esp32_init(const struct device *dev)
{
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;
Expand Down Expand Up @@ -559,14 +514,49 @@ static const struct dma_driver_api dma_esp32_api = {
.reload = dma_esp32_reload,
};

#if defined(CONFIG_SOC_SERIES_ESP32C6) || defined(CONFIG_SOC_SERIES_ESP32S3)

#define DMA_ESP32_DEFINE_IRQ_HANDLER(channel) \
__attribute__((unused)) static void IRAM_ATTR dma_esp32_isr_##channel##_rx( \
const struct device *dev) \
{ \
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config; \
struct dma_esp32_data *data = (struct dma_esp32_data *const)(dev)->data; \
uint32_t intr_status = gdma_ll_rx_get_interrupt_status(data->hal.dev, channel); \
if (intr_status) { \
dma_esp32_isr_handle_rx(dev, &config->dma_channel[channel * 2], \
intr_status); \
} \
} \
\
__attribute__((unused)) static void IRAM_ATTR dma_esp32_isr_##channel##_tx( \
const struct device *dev) \
{ \
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config; \
struct dma_esp32_data *data = (struct dma_esp32_data *const)(dev)->data; \
uint32_t intr_status = gdma_ll_tx_get_interrupt_status(data->hal.dev, channel); \
if (intr_status) { \
dma_esp32_isr_handle_tx(dev, &config->dma_channel[channel * 2 + 1], \
intr_status); \
} \
}

#else

#define DMA_ESP32_DEFINE_IRQ_HANDLER(channel) \
__attribute__((unused)) static void IRAM_ATTR dma_esp32_isr_##channel( \
const struct device *dev) \
{ \
dma_esp32_isr_handle(dev, channel * 2, channel * 2 + 1); \
}

#endif

#if defined(CONFIG_SOC_SERIES_ESP32C6) || defined(CONFIG_SOC_SERIES_ESP32S3)
#define ESP32_DMA_HANDLER(channel) dma_esp32_isr_##channel##_rx, dma_esp32_isr_##channel##_tx
#else
#define ESP32_DMA_HANDLER(channel) dma_esp32_isr_##channel
#endif

DMA_ESP32_DEFINE_IRQ_HANDLER(0)
DMA_ESP32_DEFINE_IRQ_HANDLER(1)
Expand Down
14 changes: 14 additions & 0 deletions dts/riscv/espressif/esp32c6/esp32c6_common.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,20 @@
};
};

dma: dma@60080000 {
compatible = "espressif,esp32-gdma";
reg = <0x60080000 DT_SIZE_K(4)>;
#dma-cells = <1>;
interrupts = <DMA_IN_CH0_INTR_SOURCE DMA_OUT_CH0_INTR_SOURCE
DMA_IN_CH1_INTR_SOURCE DMA_OUT_CH1_INTR_SOURCE
DMA_IN_CH2_INTR_SOURCE DMA_OUT_CH2_INTR_SOURCE>;
interrupt-parent = <&intc>;
clocks = <&rtc ESP32_GDMA_MODULE>;
dma-channels = <6>;
dma-buf-addr-alignment = <4>;
status = "disabled";
};

gpio0: gpio@60091000 {
compatible = "espressif,esp32-gpio";
gpio-controller;
Expand Down
2 changes: 2 additions & 0 deletions tests/drivers/dma/loop_transfer/boards/esp32c6_devkitc.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CONFIG_DMA_LOOP_TRANSFER_CHANNEL_NR=4
CONFIG_DMA_LOOP_TRANSFER_SIZE=4094
11 changes: 11 additions & 0 deletions tests/drivers/dma/loop_transfer/boards/esp32c6_devkitc.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/

&dma {
status = "okay";
};

tst_dma0: &dma { };
2 changes: 2 additions & 0 deletions tests/drivers/uart/uart_async_api/boards/esp32c6_devkitc.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CONFIG_HEAP_MEM_POOL_SIZE=32768
CONFIG_DMA=y
31 changes: 31 additions & 0 deletions tests/drivers/uart/uart_async_api/boards/esp32c6_devkitc.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/

&pinctrl {
uart1_test: uart1_test {
group1 {
pinmux = <UART1_TX_GPIO2>;
input-enable; /* Connect GPIO2 and GPIO3 externally for testing */
};
group2 {
pinmux = <UART1_RX_GPIO3>;
output-enable; /* Connect GPIO2 and GPIO3 externally for testing */
};
};
};

dut: &uart1 {
status = "okay";
current-speed = <115200>;
pinctrl-0 = <&uart1_test>;
pinctrl-names = "default";
dmas = <&dma 0>, <&dma 1>;
dma-names = "rx", "tx";
};

&dma {
status = "okay";
};
2 changes: 1 addition & 1 deletion west.yml
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ manifest:
groups:
- hal
- name: hal_espressif
revision: 61b977fd2b033c656b1b2fa07b3137872236f710
revision: pull/300/head
path: modules/hal/espressif
west-commands: west/west-commands.yml
groups:
Expand Down
Loading