summaryrefslogtreecommitdiffstats
path: root/bsps/shared/dev
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/shared/dev')
-rw-r--r--bsps/shared/dev/dma/fsl-edma.c349
1 files changed, 245 insertions, 104 deletions
diff --git a/bsps/shared/dev/dma/fsl-edma.c b/bsps/shared/dev/dma/fsl-edma.c
index c34624ed10..b3e1bb2fc5 100644
--- a/bsps/shared/dev/dma/fsl-edma.c
+++ b/bsps/shared/dev/dma/fsl-edma.c
@@ -1,33 +1,47 @@
/**
* @file
*
- * @ingroup RTEMSBSPsPowerPCMPC55XX
+ * @ingroup RTEMSBSPsSharedFslEDMA
*
- * @brief Enhanced Direct Memory Access (eDMA).
+ * @brief Freescale / NXP Enhanced Direct Memory Access (eDMA).
*/
/*
- * Copyright (c) 2008-2013 embedded brains GmbH. All rights reserved.
+ * Copyright (C) 2008-2020 embedded brains GmbH (http://www.embedded-brains.de)
*
- * embedded brains GmbH
- * Dornierstr. 4
- * 82178 Puchheim
- * Germany
- * <rtems@embedded-brains.de>
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
-#include <mpc55xx/edma.h>
-#include <mpc55xx/mpc55xx.h>
+#include <fsl/edma.h>
+#include <fsl/regs-edma.h>
#include <assert.h>
#include <bsp.h>
#include <bsp/fatal.h>
#include <bsp/irq.h>
+#ifdef LIBBSP_ARM_IMXRT_BSP_H
+#include <MIMXRT1052.h>
+#endif
#define EDMA_CHANNELS_PER_GROUP 32U
@@ -43,32 +57,67 @@ static uint32_t edma_channel_occupation [EDMA_GROUP_COUNT];
static RTEMS_CHAIN_DEFINE_EMPTY(edma_channel_chain);
-static unsigned edma_channel_index_of_tcd(volatile struct tcd_t *edma_tcd)
+volatile struct fsl_edma *edma_inst[EDMA_MODULE_COUNT] = {
+#ifdef LIBBSP_ARM_IMXRT_BSP_H
+ (volatile struct fsl_edma *) DMA0,
+#else /* ! LIBBSP_ARM_IMXRT_BSP_H */
+ #if EDMA_MODULE_COUNT == 1
+ (volatile struct fsl_edma *) &EDMA,
+ #elif EDMA_MODULE_COUNT == 2
+ (volatile struct fsl_edma *) &EDMA_A,
+ (volatile struct fsl_edma *) &EDMA_B,
+ #else
+ #error "unsupported module count"
+ #endif
+#endif /* LIBBSP_ARM_IMXRT_BSP_H */
+};
+
+unsigned fsl_edma_channel_index_of_tcd(
+ volatile struct fsl_edma_tcd *edma_tcd
+)
{
- volatile struct EDMA_tag *edma = mpc55xx_edma_by_tcd(edma_tcd);
+ volatile struct fsl_edma *edma = fsl_edma_by_tcd(edma_tcd);
unsigned channel = edma_tcd - &edma->TCD[0];
-#if EDMA_MODULE_COUNT == 1
- return channel;
-#elif EDMA_MODULE_COUNT == 2
- return channel + (&EDMA_A == edma ? 0 : EDMA_CHANNELS_PER_MODULE);
-#else
+#if EDMA_MODULE_COUNT == 2
+ if (edma_inst[1] == edma) {
+ channel += EDMA_CHANNELS_PER_MODULE;
+ }
+#elif EDMA_MODULE_COUNT > 2
#error "unsupported module count"
#endif
+
+ return channel;
}
-static volatile struct EDMA_tag *edma_get_regs_by_module(unsigned module)
+volatile struct fsl_edma_tcd *fsl_edma_tcd_of_channel_index(unsigned index)
{
-#if EDMA_MODULE_COUNT == 1
- return &EDMA;
-#elif EDMA_MODULE_COUNT == 2
- return module == 0 ? &EDMA_A : &EDMA_B;
-#else
- #error "unsupported module count"
-#endif
+ unsigned module = index / EDMA_CHANNELS_PER_MODULE;
+ unsigned channel = index % EDMA_CHANNELS_PER_MODULE;
+
+ return &edma_inst[module]->TCD[channel];
}
-static uint32_t edma_bit_array_set(unsigned channel, uint32_t *bit_array)
+static volatile struct fsl_edma *fsl_edma_get_regs_by_module(unsigned module)
+{
+ return edma_inst[module];
+}
+
+static uint32_t fsl_edma_bit_array_get_lowest_0(uint32_t *bit_array)
+{
+ unsigned array;
+
+ for (array = 0; array < EDMA_MODULE_COUNT; ++array) {
+ uint32_t first_0 = __builtin_ffs(~(bit_array[array]));
+ if (first_0 > 0) {
+ return (first_0 - 1) + array * 32;
+ }
+ }
+
+ return UINT32_MAX;
+}
+
+static uint32_t fsl_edma_bit_array_set(unsigned channel, uint32_t *bit_array)
{
unsigned array = channel / 32;
uint32_t bit = 1U << (channel % 32);
@@ -79,7 +128,7 @@ static uint32_t edma_bit_array_set(unsigned channel, uint32_t *bit_array)
return previous;
}
-static uint32_t edma_bit_array_clear(unsigned channel, uint32_t *bit_array)
+static uint32_t fsl_edma_bit_array_clear(unsigned channel, uint32_t *bit_array)
{
unsigned array = channel / 32;
uint32_t bit = 1U << (channel % 32);
@@ -90,11 +139,11 @@ static uint32_t edma_bit_array_clear(unsigned channel, uint32_t *bit_array)
return previous;
}
-static void edma_interrupt_handler(void *arg)
+static void fsl_edma_interrupt_handler(void *arg)
{
- edma_channel_context *ctx = arg;
+ fsl_edma_channel_context *ctx = arg;
- mpc55xx_edma_clear_interrupts(ctx->edma_tcd);
+ fsl_edma_clear_interrupts(ctx->edma_tcd);
(*ctx->done)(ctx, 0);
}
@@ -103,39 +152,40 @@ static void edma_interrupt_error_handler(void *arg)
{
rtems_chain_control *chain = &edma_channel_chain;
rtems_chain_node *node = rtems_chain_first(chain);
+
uint32_t error_channels [] = {
#if EDMA_GROUP_COUNT >= 1
- EDMA.ERL.R
+ edma_inst[0]->ERL,
#endif
#if EDMA_GROUP_COUNT >= 2
- , EDMA.ERH.R
+ edma_inst[0]->ERH,
#endif
#if EDMA_GROUP_COUNT >= 3
- , EDMA_B.ERL.R
+ edma_inst[1]->ERL,
#endif
};
uint32_t error_status [] = {
#if EDMA_GROUP_COUNT >= 1
- EDMA.ESR.R
+ edma_inst[0]->ESR,
#endif
#if EDMA_GROUP_COUNT >= 3
- , EDMA_B.ESR.R
+ edma_inst[1]->ESR,
#endif
};
#if EDMA_GROUP_COUNT >= 1
- EDMA.ERL.R = error_channels [0];
+ edma_inst[0]->ERL = error_channels [0];
#endif
#if EDMA_GROUP_COUNT >= 2
- EDMA.ERH.R = error_channels [1];
+ edma_inst[0]->ERH = error_channels [1];
#endif
#if EDMA_GROUP_COUNT >= 3
- EDMA_B.ERL.R = error_channels [2];
+ edma_inst[1]->ERL = error_channels [2];
#endif
while (!rtems_chain_is_tail(chain, node)) {
- edma_channel_context *ctx = (edma_channel_context *) node;
- unsigned channel_index = edma_channel_index_of_tcd(ctx->edma_tcd);
+ fsl_edma_channel_context *ctx = (fsl_edma_channel_context *) node;
+ unsigned channel_index = fsl_edma_channel_index_of_tcd(ctx->edma_tcd);
unsigned group_index = EDMA_GROUP_INDEX(channel_index);
unsigned group_bit = EDMA_GROUP_BIT(channel_index);
@@ -149,7 +199,7 @@ static void edma_interrupt_error_handler(void *arg)
}
}
-void mpc55xx_edma_init(void)
+void fsl_edma_init(void)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
unsigned channel_remaining = EDMA_CHANNEL_COUNT;
@@ -157,7 +207,7 @@ void mpc55xx_edma_init(void)
unsigned group = 0;
for (module = 0; module < EDMA_MODULE_COUNT; ++module) {
- volatile struct EDMA_tag *edma = edma_get_regs_by_module(module);
+ volatile struct fsl_edma *edma = fsl_edma_get_regs_by_module(module);
unsigned channel_count = channel_remaining < EDMA_CHANNELS_PER_MODULE ?
channel_remaining : EDMA_CHANNELS_PER_MODULE;
unsigned channel = 0;
@@ -165,32 +215,36 @@ void mpc55xx_edma_init(void)
channel_remaining -= channel_count;
/* Disable requests */
- edma->CERQR.B.CERQ = 0x40;
+ edma->CERQR = EDMA_CERQR_CAER;
/* Arbitration mode: group round robin, channel fixed */
- edma->CR.B.ERGA = 1;
- edma->CR.B.ERCA = 0;
+ edma->CR |= EDMA_CR_ERGA;
+ edma->CR &= ~EDMA_CR_ERCA;
+#if defined(BSP_FSL_EDMA_EMLM)
+ edma->CR |= EDMA_CR_EMLM;
+#endif
for (channel = 0; channel < channel_count; ++channel) {
- volatile struct tcd_t *tcd = &edma->TCD [channel];
- edma->CPR [channel].R = 0x80U | (channel & 0xfU);
+ volatile struct fsl_edma_tcd *tcd = &edma->TCD [channel];
+ edma->CPR [channel] = EDMA_CPR_ECP | EDMA_CPR_CHPRI(channel);
/* Initialize TCD, stop channel first */
- tcd->BMF.R = 0;
+ tcd->BMF = 0;
tcd->SADDR = 0;
- tcd->SDF.R = 0;
+ tcd->SDF = 0;
tcd->NBYTES = 0;
tcd->SLAST = 0;
tcd->DADDR = 0;
- tcd->CDF.R = 0;
+ tcd->CDF = 0;
tcd->DLAST_SGA = 0;
}
/* Clear interrupt requests */
- edma->CIRQR.B.CINT = 0x40;
- edma->CER.B.CERR = 0x40;
+ edma->CIRQR = EDMA_CIRQR_CAIR;
+ edma->CER = EDMA_CER_CAEI;
}
for (group = 0; group < EDMA_GROUP_COUNT; ++group) {
+#if defined(LIBBSP_POWERPC_MPC55XXEVB_BSP_H)
sc = mpc55xx_interrupt_handler_install(
MPC55XX_IRQ_EDMA_ERROR(group),
"eDMA Error",
@@ -199,23 +253,61 @@ void mpc55xx_edma_init(void)
edma_interrupt_error_handler,
NULL
);
+#elif defined(LIBBSP_ARM_IMXRT_BSP_H)
+ sc = rtems_interrupt_handler_install(
+ DMA_ERROR_IRQn,
+ "eDMA Error",
+ RTEMS_INTERRUPT_UNIQUE,
+ edma_interrupt_error_handler,
+ NULL
+ );
+#else
+ #error "Unknown chip"
+#endif
if (sc != RTEMS_SUCCESSFUL) {
bsp_fatal(MPC55XX_FATAL_EDMA_IRQ_INSTALL);
}
}
}
-rtems_status_code mpc55xx_edma_obtain_channel_by_tcd(
- volatile struct tcd_t *edma_tcd
+static rtems_status_code fsl_edma_obtain_next_free_channel_and_get_tcd(
+ volatile struct fsl_edma_tcd **edma_tcd
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ unsigned channel_index;
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+ channel_index = fsl_edma_bit_array_get_lowest_0(&edma_channel_occupation [0]);
+ if (channel_index > EDMA_CHANNEL_COUNT) {
+ sc = RTEMS_RESOURCE_IN_USE;
+ } else {
+ fsl_edma_bit_array_set(
+ channel_index,
+ &edma_channel_occupation [0]
+ );
+ }
+ rtems_interrupt_enable(level);
+
+ if (sc == RTEMS_SUCCESSFUL) {
+ *edma_tcd = fsl_edma_tcd_of_channel_index(channel_index);
+ }
+
+ return sc;
+}
+
+rtems_status_code fsl_edma_obtain_channel_by_tcd(
+ volatile struct fsl_edma_tcd *edma_tcd
)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
- unsigned channel_index = edma_channel_index_of_tcd(edma_tcd);
+ unsigned channel_index = fsl_edma_channel_index_of_tcd(edma_tcd);
rtems_interrupt_level level;
uint32_t channel_occupation;
rtems_interrupt_disable(level);
- channel_occupation = edma_bit_array_set(
+ channel_occupation = fsl_edma_bit_array_set(
channel_index,
&edma_channel_occupation [0]
);
@@ -228,59 +320,108 @@ rtems_status_code mpc55xx_edma_obtain_channel_by_tcd(
return sc;
}
-void mpc55xx_edma_release_channel_by_tcd(volatile struct tcd_t *edma_tcd)
+void fsl_edma_release_channel_by_tcd(volatile struct fsl_edma_tcd *edma_tcd)
{
- unsigned channel_index = edma_channel_index_of_tcd(edma_tcd);
+ unsigned channel_index = fsl_edma_channel_index_of_tcd(edma_tcd);
rtems_interrupt_level level;
rtems_interrupt_disable(level);
- edma_bit_array_clear(channel_index, &edma_channel_occupation [0]);
+ fsl_edma_bit_array_clear(channel_index, &edma_channel_occupation [0]);
rtems_interrupt_enable(level);
- mpc55xx_edma_disable_hardware_requests(edma_tcd);
- mpc55xx_edma_disable_error_interrupts(edma_tcd);
+ fsl_edma_disable_hardware_requests(edma_tcd);
+ fsl_edma_disable_error_interrupts(edma_tcd);
}
-rtems_status_code mpc55xx_edma_obtain_channel(
- edma_channel_context *ctx,
+static rtems_status_code fsl_edma_install_obtained_channel(
+ fsl_edma_channel_context *ctx,
unsigned irq_priority
)
{
- rtems_status_code sc = mpc55xx_edma_obtain_channel_by_tcd(ctx->edma_tcd);
+ unsigned channel_index = fsl_edma_channel_index_of_tcd(ctx->edma_tcd);
+ rtems_status_code sc;
+
+#if defined(LIBBSP_POWERPC_MPC55XXEVB_BSP_H)
+ sc = fsl_interrupt_handler_install(
+ MPC55XX_IRQ_EDMA(channel_index),
+ "eDMA Channel",
+ RTEMS_INTERRUPT_SHARED,
+ irq_priority,
+ fsl_edma_interrupt_handler,
+ ctx
+ );
+#elif defined(LIBBSP_ARM_IMXRT_BSP_H)
+ sc = rtems_interrupt_handler_install(
+ DMA0_DMA16_IRQn + (channel_index % 16),
+ "eDMA Channel",
+ RTEMS_INTERRUPT_SHARED,
+ fsl_edma_interrupt_handler,
+ ctx
+ );
+#else
+ #error "Unknown chip"
+#endif
if (sc == RTEMS_SUCCESSFUL) {
- unsigned channel_index = edma_channel_index_of_tcd(ctx->edma_tcd);
+ rtems_chain_prepend(&edma_channel_chain, &ctx->node);
+ fsl_edma_enable_error_interrupts(ctx->edma_tcd);
+ } else {
+ fsl_edma_release_channel_by_tcd(ctx->edma_tcd);
+ sc = RTEMS_IO_ERROR;
+ }
- sc = mpc55xx_interrupt_handler_install(
- MPC55XX_IRQ_EDMA(channel_index),
- "eDMA Channel",
- RTEMS_INTERRUPT_SHARED,
- irq_priority,
- edma_interrupt_handler,
- ctx
+ return sc;
+}
+
+rtems_status_code fsl_edma_obtain_channel(
+ fsl_edma_channel_context *ctx,
+ unsigned irq_priority
+)
+{
+ rtems_status_code sc = fsl_edma_obtain_channel_by_tcd(ctx->edma_tcd);
+ if (sc == RTEMS_SUCCESSFUL) {
+ sc = fsl_edma_install_obtained_channel(ctx, irq_priority);
+ }
+
+ return sc;
+}
+
+rtems_status_code fsl_edma_obtain_next_free_channel(
+ fsl_edma_channel_context *ctx
+)
+{
+ rtems_status_code sc;
+
+ sc = fsl_edma_obtain_next_free_channel_and_get_tcd(&ctx->edma_tcd);
+ if (sc == RTEMS_SUCCESSFUL) {
+ sc = fsl_edma_install_obtained_channel(ctx,
+#ifdef LIBBSP_POWERPC_MPC55XXEVB_BSP_H
+ MPC55XX_INTC_DEFAULT_PRIORITY
+#else
+ 0
+#endif
);
- if (sc == RTEMS_SUCCESSFUL) {
- rtems_chain_prepend(&edma_channel_chain, &ctx->node);
- mpc55xx_edma_enable_error_interrupts(ctx->edma_tcd);
- } else {
- mpc55xx_edma_release_channel_by_tcd(ctx->edma_tcd);
- sc = RTEMS_IO_ERROR;
- }
}
return sc;
}
-void mpc55xx_edma_release_channel(edma_channel_context *ctx)
+void fsl_edma_release_channel(fsl_edma_channel_context *ctx)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
- unsigned channel_index = edma_channel_index_of_tcd(ctx->edma_tcd);
+ unsigned channel_index = fsl_edma_channel_index_of_tcd(ctx->edma_tcd);
- mpc55xx_edma_release_channel_by_tcd(ctx->edma_tcd);
+ fsl_edma_release_channel_by_tcd(ctx->edma_tcd);
rtems_chain_extract(&ctx->node);
sc = rtems_interrupt_handler_remove(
+#if defined(LIBBSP_POWERPC_MPC55XXEVB_BSP_H)
MPC55XX_IRQ_EDMA(channel_index),
- edma_interrupt_handler,
+#elif defined(LIBBSP_ARM_IMXRT_BSP_H)
+ DMA0_DMA16_IRQn + (channel_index % 16),
+#else
+ #error "Unknown chip"
+#endif
+ fsl_edma_interrupt_handler,
ctx
);
if (sc != RTEMS_SUCCESSFUL) {
@@ -288,42 +429,42 @@ void mpc55xx_edma_release_channel(edma_channel_context *ctx)
}
}
-void mpc55xx_edma_copy(
- volatile struct tcd_t *edma_tcd,
- const struct tcd_t *source_tcd
+void fsl_edma_copy(
+ volatile struct fsl_edma_tcd *edma_tcd,
+ const struct fsl_edma_tcd *source_tcd
)
{
/* Clear DONE flag */
- edma_tcd->BMF.R = 0;
+ edma_tcd->BMF = 0;
edma_tcd->SADDR = source_tcd->SADDR;
- edma_tcd->SDF.R = source_tcd->SDF.R;
+ edma_tcd->SDF = source_tcd->SDF;
edma_tcd->NBYTES = source_tcd->NBYTES;
edma_tcd->SLAST = source_tcd->SLAST;
edma_tcd->DADDR = source_tcd->DADDR;
- edma_tcd->CDF.R = source_tcd->CDF.R;
+ edma_tcd->CDF = source_tcd->CDF;
edma_tcd->DLAST_SGA = source_tcd->DLAST_SGA;
- edma_tcd->BMF.R = source_tcd->BMF.R;
+ edma_tcd->BMF = source_tcd->BMF;
}
-void mpc55xx_edma_copy_and_enable_hardware_requests(
- volatile struct tcd_t *edma_tcd,
- const struct tcd_t *source_tcd
+void fsl_edma_copy_and_enable_hardware_requests(
+ volatile struct fsl_edma_tcd *edma_tcd,
+ const struct fsl_edma_tcd *source_tcd
)
{
- mpc55xx_edma_copy(edma_tcd, source_tcd);
- mpc55xx_edma_enable_hardware_requests(edma_tcd);
+ fsl_edma_copy(edma_tcd, source_tcd);
+ fsl_edma_enable_hardware_requests(edma_tcd);
}
-void mpc55xx_edma_sg_link(
- volatile struct tcd_t *edma_tcd,
- const struct tcd_t *source_tcd
+void fsl_edma_sg_link(
+ volatile struct fsl_edma_tcd *edma_tcd,
+ const struct fsl_edma_tcd *source_tcd
)
{
edma_tcd->DLAST_SGA = (int32_t) source_tcd;
- edma_tcd->BMF.B.E_SG = 1;
+ edma_tcd->BMF |= EDMA_TCD_BMF_E_SG;
- if (!edma_tcd->BMF.B.E_SG) {
- mpc55xx_edma_copy(edma_tcd, source_tcd);
+ if ((edma_tcd->BMF & EDMA_TCD_BMF_E_SG) == 0) {
+ fsl_edma_copy(edma_tcd, source_tcd);
}
}