From 605ade6bc452d3801d4bb3864d99230f6b6c023c Mon Sep 17 00:00:00 2001 From: Lucien Zhao Date: Thu, 22 Aug 2024 15:09:00 +0800 Subject: [PATCH] drivers: dma: dma_mcux_edma: support EDMA IP in edma drivers Multi channels share one IRQ, add channels-shared-irq-mask on RT1180 attribution to describe the channel shared status, and add code implementation to register the handler function for each channel in different interrupts. Fix legacy building warning issue Signed-off-by: Lucien Zhao --- drivers/dma/dma_mcux_edma.c | 38 ++++++++++++++++++++++++++++- dts/bindings/dma/nxp,mcux-edma.yaml | 15 +++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/drivers/dma/dma_mcux_edma.c b/drivers/dma/dma_mcux_edma.c index 5575cb2a73f..ab818cd18ec 100644 --- a/drivers/dma/dma_mcux_edma.c +++ b/drivers/dma/dma_mcux_edma.c @@ -277,6 +277,28 @@ static void dma_mcux_edma_error_irq_handler(const struct device *dev) } #endif +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(channels_shared_irq_mask) +static void dma_mcux_edma_multi_channels_irq_handler(const struct device *dev, uint32_t idx, + uint32_t *buf, uint32_t mask_width) +{ + uint32_t *num = &buf[mask_width * idx]; + uint32_t count = 0; + + for (int _i = 0; _i < mask_width; _i++) { + uint32_t value = (*num); + + while (value > 0) { + if ((value & 0x1) == 1) { + dma_mcux_edma_irq_handler(dev, count); + } + value = value >> 1; + count++; + } + num++; + } +} +#endif + /* Configure a channel */ static int dma_mcux_edma_configure(const struct device *dev, uint32_t channel, struct dma_config *config) @@ -861,10 +883,22 @@ static int dma_mcux_edma_init(const struct device *dev) irq_enable(DT_INST_IRQ_BY_IDX(n, idx, irq)); \ } +#define EDMA_CHANNELS_MASK(n) static uint32_t edma_channel_mask_##n[] = \ + DT_PROP(DT_DRV_INST(n), channels_shared_irq_mask); + +#define GET_EDMA_CHANNEL_SHARED_IRQ_MASK_WIDTH(n) \ + (DT_INST_PROP(n, dma_channels) / 32) + +#define EDMA_CHANNELS_SHARED_REGISTER_IN_IRQ(dev, idx, n) \ + dma_mcux_edma_multi_channels_irq_handler(dev, idx, edma_channel_mask_##n, \ + GET_EDMA_CHANNEL_SHARED_IRQ_MASK_WIDTH(n)); + #define DMA_MCUX_EDMA_IRQ_DEFINE(idx, n) \ static void dma_mcux_edma_##n##_irq_##idx(const struct device *dev) \ { \ - dma_mcux_edma_irq_handler(dev, idx); \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, channels_shared_irq_mask), \ + (EDMA_CHANNELS_SHARED_REGISTER_IN_IRQ(dev, idx, n)), \ + (dma_mcux_edma_irq_handler(dev, idx);)) \ \ IF_ENABLED(UTIL_BOOL(DT_INST_PROP(n, irq_shared_offset)), \ (dma_mcux_edma_irq_handler(dev, \ @@ -877,6 +911,8 @@ static int dma_mcux_edma_init(const struct device *dev) IRQ_CONFIG(n, idx, dma_mcux_edma_##n##_irq_##idx) #define DMA_MCUX_EDMA_CONFIG_FUNC(n) \ + IF_ENABLED(DT_INST_NODE_HAS_PROP(n, channels_shared_irq_mask), \ + (EDMA_CHANNELS_MASK(n))) \ LISTIFY(NUM_IRQS_WITHOUT_ERROR_IRQ(n), DMA_MCUX_EDMA_IRQ_DEFINE, (), n) \ static void dma_imx_config_func_##n(const struct device *dev) \ { \ diff --git a/dts/bindings/dma/nxp,mcux-edma.yaml b/dts/bindings/dma/nxp,mcux-edma.yaml index 57e79378c04..17c8b3c3d22 100644 --- a/dts/bindings/dma/nxp,mcux-edma.yaml +++ b/dts/bindings/dma/nxp,mcux-edma.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2020, NXP +# Copyright (c) 2020,2024 NXP # SPDX-License-Identifier: Apache-2.0 description: NXP MCUX EDMA controller @@ -65,6 +65,19 @@ properties: description: | eDMA IP revision number. + channels-shared-irq-mask: + type: array + description: | + Describes channel enabled mask value on every IRQ. + The channel number is mapped to the bit value of array element value. + If the interrupt is shared on one channel number, the correspongding + bit is set to 1. + Please note each element of the array must be 32-bit. If there are more + than 32 channels, add one or more 32-bit elements in array(elements + should be contiguous). The software will determine the mask value of + several elements corresponding to the same interrupt according to the + number of channels. + "#dma-cells": type: int required: true