[rtems commit] bsp/mpc55xx: eDMA API changes

Sebastian Huber sebh at rtems.org
Mon Apr 8 14:37:39 UTC 2013


Module:    rtems
Branch:    master
Commit:    db21e1dd6c57614eee7ee6916373fea0c2406021
Changeset: http://git.rtems.org/rtems/commit/?id=db21e1dd6c57614eee7ee6916373fea0c2406021

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Wed Apr  3 12:05:49 2013 +0200

bsp/mpc55xx: eDMA API changes

---

 .../libbsp/powerpc/mpc55xxevb/network/smsc9218i.c  |   32 +--
 c/src/lib/libcpu/powerpc/mpc55xx/dspi/dspi.c       |  102 ++++---
 c/src/lib/libcpu/powerpc/mpc55xx/edma/edma.c       |  216 +++++++-------
 c/src/lib/libcpu/powerpc/mpc55xx/include/dspi.h    |   11 +-
 c/src/lib/libcpu/powerpc/mpc55xx/include/edma.h    |  307 ++++++++++++++++++-
 5 files changed, 485 insertions(+), 183 deletions(-)

diff --git a/c/src/lib/libbsp/powerpc/mpc55xxevb/network/smsc9218i.c b/c/src/lib/libbsp/powerpc/mpc55xxevb/network/smsc9218i.c
index 013447a..8a91986 100644
--- a/c/src/lib/libbsp/powerpc/mpc55xxevb/network/smsc9218i.c
+++ b/c/src/lib/libbsp/powerpc/mpc55xxevb/network/smsc9218i.c
@@ -146,8 +146,8 @@ typedef struct {
   smsc9218i_state state;
   rtems_id receive_task;
   rtems_id transmit_task;
-  mpc55xx_edma_channel_entry edma_receive;
-  mpc55xx_edma_channel_entry edma_transmit;
+  edma_channel_context edma_receive;
+  edma_channel_context edma_transmit;
   unsigned phy_interrupts;
   unsigned received_frames;
   unsigned receiver_errors;
@@ -205,12 +205,12 @@ typedef struct {
 static smsc9218i_receive_job_control smsc_rx_jc __attribute__((aligned (32)));
 
 static void smsc9218i_transmit_dma_done(
-  mpc55xx_edma_channel_entry *channel_entry,
+  edma_channel_context *ctx,
   uint32_t error_status
 );
 
 static void smsc9218i_receive_dma_done(
-  mpc55xx_edma_channel_entry *e,
+  edma_channel_context *ctx,
   uint32_t error_status
 );
 
@@ -219,14 +219,12 @@ static smsc9218i_driver_entry smsc9218i_driver_data = {
   .receive_task = RTEMS_ID_NONE,
   .transmit_task = RTEMS_ID_NONE,
   .edma_receive = {
-    .channel = SMSC9218I_EDMA_RX_CHANNEL,
-    .done = smsc9218i_receive_dma_done,
-    .id = RTEMS_ID_NONE
+    .edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(SMSC9218I_EDMA_RX_CHANNEL),
+    .done = smsc9218i_receive_dma_done
   },
   .edma_transmit = {
-    .channel = SMSC9218I_EDMA_TX_CHANNEL,
-    .done = smsc9218i_transmit_dma_done,
-    .id = RTEMS_ID_NONE
+    .edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(SMSC9218I_EDMA_TX_CHANNEL),
+    .done = smsc9218i_transmit_dma_done
   }
 };
 
@@ -604,7 +602,7 @@ static void smsc9218i_setup_receive_dma(
   jc->produce = p;
 
   if (last != NULL) {
-    volatile struct tcd_t *channel = &EDMA.TCD [e->edma_receive.channel];
+    volatile struct tcd_t *channel = e->edma_receive.edma_tcd;
 
     /* Setup last TCD */
     last->BMF.R = SMSC9218I_TCD_BMF_LAST;
@@ -625,7 +623,7 @@ static void smsc9218i_setup_receive_dma(
 }
 
 static void smsc9218i_receive_dma_done(
-  mpc55xx_edma_channel_entry *channel_entry,
+  edma_channel_context *ctx,
   uint32_t error_status
 )
 {
@@ -644,14 +642,14 @@ static void smsc9218i_receive_dma_done(
     ++e->receive_dma_errors;
   }
 
-  sc = rtems_bsdnet_event_send(channel_entry->id, SMSC9218I_EVENT_DMA);
+  sc = rtems_bsdnet_event_send(e->receive_task, SMSC9218I_EVENT_DMA);
   ASSERT_SC(sc);
 
   jc->done = jc->produce;
 }
 
 static void smsc9218i_transmit_dma_done(
-  mpc55xx_edma_channel_entry *channel_entry,
+  edma_channel_context *ctx,
   uint32_t error_status
 )
 {
@@ -668,7 +666,7 @@ static void smsc9218i_transmit_dma_done(
 
   ++e->transmit_dma_interrupts;
 
-  sc = rtems_bsdnet_event_send(channel_entry->id, event);
+  sc = rtems_bsdnet_event_send(e->transmit_task, event);
   ASSERT_SC(sc);
 }
 
@@ -866,7 +864,6 @@ static void smsc9218i_init_receive_jobs(
   int i = 0;
 
   /* Obtain receive eDMA channel */
-  e->edma_receive.id = e->receive_task;
   sc = mpc55xx_edma_obtain_channel(
     &e->edma_receive,
     MPC55XX_INTC_DEFAULT_PRIORITY
@@ -1270,7 +1267,7 @@ static void smsc9218i_transmit_do_jobs(
     }
 
     if (i > 0) {
-      volatile struct tcd_t *channel = &EDMA.TCD [e->edma_transmit.channel];
+      volatile struct tcd_t *channel = e->edma_transmit.edma_tcd;
       struct tcd_t *start = &jc->command_tcd_table [jc->transfer_index];
       struct tcd_t *last = &jc->data_tcd_table [last_index];
 
@@ -1427,7 +1424,6 @@ static void smsc9218i_transmit_task(void *arg)
   SMSC9218I_PRINTF("%s\n", __func__);
 
   /* Obtain transmit eDMA channel */
-  e->edma_transmit.id = e->transmit_task;
   sc = mpc55xx_edma_obtain_channel(
     &e->edma_transmit,
     MPC55XX_INTC_DEFAULT_PRIORITY
diff --git a/c/src/lib/libcpu/powerpc/mpc55xx/dspi/dspi.c b/c/src/lib/libcpu/powerpc/mpc55xx/dspi/dspi.c
index 0cba111..3e8aee4 100644
--- a/c/src/lib/libcpu/powerpc/mpc55xx/dspi/dspi.c
+++ b/c/src/lib/libcpu/powerpc/mpc55xx/dspi/dspi.c
@@ -113,8 +113,9 @@ static const mpc55xx_dspi_baudrate_scaler_entry mpc55xx_dspi_baudrate_scaler_tab
 	{ 229376, 3, 15 },
 };
 
-static void mpc55xx_dspi_edma_done( mpc55xx_edma_channel_entry *e, uint32_t error_status)
+static void mpc55xx_dspi_edma_done( edma_channel_context *ctx, uint32_t error_status)
 {
+	const mpc55xx_dspi_edma_entry *e = (const mpc55xx_dspi_edma_entry *) ctx;
 	rtems_semaphore_release( e->id);
 
 	if (error_status != 0) {
@@ -175,7 +176,7 @@ static rtems_status_code mpc55xx_dspi_init( rtems_libi2c_bus_t *bus)
 	);
 	RTEMS_CHECK_SC( sc, "create receive update semaphore");
 
-	sc = mpc55xx_edma_obtain_channel( &e->edma_receive, MPC55XX_INTC_DEFAULT_PRIORITY);
+	sc = mpc55xx_edma_obtain_channel( &e->edma_receive.edma, MPC55XX_INTC_DEFAULT_PRIORITY);
 	RTEMS_CHECK_SC( sc, "obtain receive eDMA channel");
 
 	/* eDMA transmit */
@@ -188,10 +189,10 @@ static rtems_status_code mpc55xx_dspi_init( rtems_libi2c_bus_t *bus)
 	);
 	RTEMS_CHECK_SC( sc, "create transmit update semaphore");
 
-	sc = mpc55xx_edma_obtain_channel( &e->edma_transmit, MPC55XX_INTC_DEFAULT_PRIORITY);
+	sc = mpc55xx_edma_obtain_channel( &e->edma_transmit.edma, MPC55XX_INTC_DEFAULT_PRIORITY);
 	RTEMS_CHECK_SC( sc, "obtain transmit eDMA channel");
 
-	sc = mpc55xx_edma_obtain_channel( &e->edma_push, MPC55XX_INTC_DEFAULT_PRIORITY);
+	sc = mpc55xx_edma_obtain_channel( &e->edma_push.edma, MPC55XX_INTC_DEFAULT_PRIORITY);
 	RTEMS_CHECK_SC( sc, "obtain push eDMA channel");
 
 	tcd_push.SADDR = mpc55xx_dspi_push_data_address( e);
@@ -204,7 +205,7 @@ static rtems_status_code mpc55xx_dspi_init( rtems_libi2c_bus_t *bus)
 	tcd_push.CDF.B.CITER = 1;
 	tcd_push.BMF.B.BITER = 1;
 
-	EDMA.TCD [e->edma_push.channel] = tcd_push;
+	*e->edma_push.edma.edma_tcd = tcd_push;
 
 	/* Module Control Register */
 	mcr.B.MSTR = e->master ? 1 : 0;
@@ -248,7 +249,7 @@ static rtems_status_code mpc55xx_dspi_init( rtems_libi2c_bus_t *bus)
 		e->regs->CTAR [i].R = ctar.R;
 	}
 
-        /* DMA/Interrupt Request Select and Enable Register */
+	/* DMA/Interrupt Request Select and Enable Register */
 	rser.B.TFFFRE = 1;
 	rser.B.TFFFDIRS = 1;
 	rser.B.RFDFRE = 1;
@@ -547,7 +548,8 @@ static int mpc55xx_dspi_read_write( rtems_libi2c_bus_t *bus, unsigned char *in,
 			tcd_transmit.CDF.B.CITER = n_c;
 			tcd_transmit.BMF.B.BITER = n_c;
 		} else {
-			EDMA.CDSBR.R = e->edma_transmit.channel;
+			unsigned push_channel = mpc55xx_edma_channel_by_tcd( e->edma_push.edma.edma_tcd);
+			mpc55xx_edma_clear_done( e->edma_transmit.edma.edma_tcd);
 			tcd_transmit.SADDR = (uint32_t) out_c;
 			tcd_transmit.SDF.B.SSIZE = 0;
 			tcd_transmit.SDF.B.SOFF = 1;
@@ -557,14 +559,14 @@ static int mpc55xx_dspi_read_write( rtems_libi2c_bus_t *bus, unsigned char *in,
 			tcd_transmit.NBYTES = 1;
 			tcd_transmit.CDF.B.CITERE_LINK = 1;
 			tcd_transmit.BMF.B.BITERE_LINK = 1;
-			tcd_transmit.BMF.B.MAJORLINKCH = e->edma_push.channel;
-			tcd_transmit.CDF.B.CITER = EDMA_TCD_LINK_AND_BITER( e->edma_push.channel, n_c);
-			tcd_transmit.BMF.B.BITER = EDMA_TCD_LINK_AND_BITER( e->edma_push.channel, n_c);
+			tcd_transmit.BMF.B.MAJORLINKCH = push_channel;
+			tcd_transmit.CDF.B.CITER = EDMA_TCD_LINK_AND_BITER( push_channel, n_c);
+			tcd_transmit.BMF.B.BITER = EDMA_TCD_LINK_AND_BITER( push_channel, n_c);
 			tcd_transmit.BMF.B.MAJORE_LINK = 1;
 		}
 		tcd_transmit.BMF.B.D_REQ = 1;
 		tcd_transmit.BMF.B.INT_MAJ = 1;
-		EDMA.TCD [e->edma_transmit.channel] = tcd_transmit;
+		*e->edma_transmit.edma.edma_tcd = tcd_transmit;
 
 		/* Set receive TCD */
 		if (in == NULL) {
@@ -583,7 +585,7 @@ static int mpc55xx_dspi_read_write( rtems_libi2c_bus_t *bus, unsigned char *in,
 		tcd_receive.BMF.B.INT_MAJ = 1;
 		tcd_receive.CDF.B.CITER = n_c;
 		tcd_receive.BMF.B.BITER = n_c;
-		EDMA.TCD [e->edma_receive.channel] = tcd_receive;
+		*e->edma_receive.edma.edma_tcd = tcd_receive;
 
 		/* Clear request flags */
 		sr.R = 0;
@@ -592,8 +594,8 @@ static int mpc55xx_dspi_read_write( rtems_libi2c_bus_t *bus, unsigned char *in,
 		status->R = sr.R;
 
 		/* Enable hardware requests */
-		mpc55xx_edma_enable_hardware_requests( e->edma_receive.channel, true);
-		mpc55xx_edma_enable_hardware_requests( e->edma_transmit.channel, true);
+		mpc55xx_edma_enable_hardware_requests( e->edma_receive.edma.edma_tcd);
+		mpc55xx_edma_enable_hardware_requests( e->edma_transmit.edma.edma_tcd);
 
 		/* Wait for transmit update */
 		sc = rtems_semaphore_obtain( e->edma_transmit.id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
@@ -676,18 +678,24 @@ mpc55xx_dspi_bus_entry mpc55xx_dspi_bus_table [MPC55XX_DSPI_NUMBER] = {
 		.master = true,
 		.push_data = MPC55XX_ZERO_FLAGS,
 		.edma_transmit = {
-			.channel = 32,
-			.done = mpc55xx_dspi_edma_done,
+			.edma = {
+				.edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(EDMA_DSPI_A_SR_TFFF),
+				.done = mpc55xx_dspi_edma_done
+			},
 			.id = RTEMS_ID_NONE
 		},
 		.edma_push = {
-			.channel = 43,
-			.done = mpc55xx_dspi_edma_done,
+			.edma = {
+				.edma_tcd = &EDMA.TCD [43],
+				.done = mpc55xx_dspi_edma_done
+			},
 			.id = RTEMS_ID_NONE
 		},
 		.edma_receive = {
-			.channel = 33,
-			.done = mpc55xx_dspi_edma_done,
+			.edma = {
+				.edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(EDMA_DSPI_A_SR_RFDF),
+				.done = mpc55xx_dspi_edma_done
+			},
 			.id = RTEMS_ID_NONE
 		},
 		.idle_char = 0xffffffff,
@@ -704,18 +712,24 @@ mpc55xx_dspi_bus_entry mpc55xx_dspi_bus_table [MPC55XX_DSPI_NUMBER] = {
 		.master = true,
 		.push_data = MPC55XX_ZERO_FLAGS,
 		.edma_transmit = {
-			.channel = 12,
-			.done = mpc55xx_dspi_edma_done,
+			.edma = {
+				.edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(EDMA_DSPI_B_SR_TFFF),
+				.done = mpc55xx_dspi_edma_done
+			},
 			.id = RTEMS_ID_NONE
 		},
 		.edma_push = {
-			.channel = 10,
-			.done = mpc55xx_dspi_edma_done,
+			.edma = {
+				.edma_tcd = &EDMA.TCD [10],
+				.done = mpc55xx_dspi_edma_done
+			},
 			.id = RTEMS_ID_NONE
 		},
 		.edma_receive = {
-			.channel = 13,
-			.done = mpc55xx_dspi_edma_done,
+			.edma = {
+				.edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(EDMA_DSPI_B_SR_RFDF),
+				.done = mpc55xx_dspi_edma_done
+			},
 			.id = RTEMS_ID_NONE
 		},
 		.idle_char = 0xffffffff,
@@ -732,18 +746,24 @@ mpc55xx_dspi_bus_entry mpc55xx_dspi_bus_table [MPC55XX_DSPI_NUMBER] = {
 		.master = true,
 		.push_data = MPC55XX_ZERO_FLAGS,
 		.edma_transmit = {
-			.channel = 14,
-			.done = mpc55xx_dspi_edma_done,
+			.edma = {
+				.edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(EDMA_DSPI_C_SR_TFFF),
+				.done = mpc55xx_dspi_edma_done
+			},
 			.id = RTEMS_ID_NONE
 		},
 		.edma_push = {
-			.channel = 11,
-			.done = mpc55xx_dspi_edma_done,
+			.edma = {
+				.edma_tcd = &EDMA.TCD [11],
+				.done = mpc55xx_dspi_edma_done
+			},
 			.id = RTEMS_ID_NONE
 		},
 		.edma_receive = {
-			.channel = 15,
-			.done = mpc55xx_dspi_edma_done,
+			.edma = {
+				.edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(EDMA_DSPI_C_SR_RFDF),
+				.done = mpc55xx_dspi_edma_done
+			},
 			.id = RTEMS_ID_NONE
 		},
 		.idle_char = 0xffffffff,
@@ -761,18 +781,24 @@ mpc55xx_dspi_bus_entry mpc55xx_dspi_bus_table [MPC55XX_DSPI_NUMBER] = {
 		.master = true,
 		.push_data = MPC55XX_ZERO_FLAGS,
 		.edma_transmit = {
-			.channel = 16,
-			.done = mpc55xx_dspi_edma_done,
+			.edma = {
+				.edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(EDMA_DSPI_D_SR_TFFF),
+				.done = mpc55xx_dspi_edma_done
+			},
 			.id = RTEMS_ID_NONE
 		},
 		.edma_push = {
-			.channel = 18,
-			.done = mpc55xx_dspi_edma_done,
+			.edma = {
+				.edma_tcd = &EDMA.TCD [18],
+				.done = mpc55xx_dspi_edma_done
+			},
 			.id = RTEMS_ID_NONE
 		},
 		.edma_receive = {
-			.channel = 17,
-			.done = mpc55xx_dspi_edma_done,
+			.edma = {
+				.edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(EDMA_DSPI_D_SR_RFDF),
+				.done = mpc55xx_dspi_edma_done
+			},
 			.id = RTEMS_ID_NONE
 		},
 		.idle_char = 0xffffffff,
diff --git a/c/src/lib/libcpu/powerpc/mpc55xx/edma/edma.c b/c/src/lib/libcpu/powerpc/mpc55xx/edma/edma.c
index 952e8a8..7b9eab4 100644
--- a/c/src/lib/libcpu/powerpc/mpc55xx/edma/edma.c
+++ b/c/src/lib/libcpu/powerpc/mpc55xx/edma/edma.c
@@ -7,10 +7,10 @@
  */
 
 /*
- * Copyright (c) 2008-2012 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2008-2013 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
- *  Obere Lagerstr. 30
+ *  Dornierstr. 4
  *  82178 Puchheim
  *  Germany
  *  <rtems at embedded-brains.de>
@@ -20,7 +20,6 @@
  * http://www.rtems.com/license/LICENSE.
  */
 
-#include <mpc55xx/regs.h>
 #include <mpc55xx/edma.h>
 #include <mpc55xx/mpc55xx.h>
 
@@ -29,48 +28,29 @@
 #include <bsp.h>
 #include <bsp/irq.h>
 
-#if MPC55XX_CHIP_FAMILY == 551
-  #define EDMA_CHANNEL_COUNT 16U
-#elif MPC55XX_CHIP_FAMILY == 564
-  #define EDMA_CHANNEL_COUNT 16U
-#elif MPC55XX_CHIP_FAMILY == 567
-  #define EDMA_CHANNEL_COUNT 96U
-#else
-  #define EDMA_CHANNEL_COUNT 64U
-#endif
-
 #define EDMA_CHANNELS_PER_GROUP 32U
 
-#define EDMA_CHANNELS_PER_MODULE 64U
-
 #define EDMA_GROUP_COUNT ((EDMA_CHANNEL_COUNT + 31U) / 32U)
 
-#define EDMA_MODULE_COUNT ((EDMA_CHANNEL_COUNT + 63U) / 64U)
-
-#define EDMA_INVALID_CHANNEL EDMA_CHANNEL_COUNT
-
-#define EDMA_IS_CHANNEL_INVALID(i) ((unsigned) (i) >= EDMA_CHANNEL_COUNT)
-
-#define EDMA_IS_CHANNEL_VALID(i) ((unsigned) (i) < EDMA_CHANNEL_COUNT)
-
 #define EDMA_GROUP_INDEX(channel) ((channel) / EDMA_CHANNELS_PER_GROUP)
 
 #define EDMA_GROUP_BIT(channel) (1U << ((channel) % EDMA_CHANNELS_PER_GROUP))
 
 #define EDMA_MODULE_INDEX(channel) ((channel) / EDMA_CHANNELS_PER_MODULE)
 
-#define EDMA_MODULE_BIT(channel) (1U << ((channel) % EDMA_CHANNELS_PER_MODULE))
-
 static uint32_t edma_channel_occupation [EDMA_GROUP_COUNT];
 
 static RTEMS_CHAIN_DEFINE_EMPTY(edma_channel_chain);
 
-static volatile struct EDMA_tag *edma_get_regs_by_channel(unsigned channel)
+static unsigned edma_channel_index_of_tcd(volatile struct tcd_t *edma_tcd)
 {
+  volatile struct EDMA_tag *edma = mpc55xx_edma_by_tcd(edma_tcd);
+  unsigned channel = edma_tcd - &edma->TCD[0];
+
 #if EDMA_MODULE_COUNT == 1
-  return &EDMA;
+  return channel;
 #elif EDMA_MODULE_COUNT == 2
-  return channel < EDMA_CHANNELS_PER_MODULE ? &EDMA_A : &EDMA_B;
+  return channel + (&EDMA_A == edma ? 0 : EDMA_CHANNELS_PER_MODULE);
 #else
   #error "unsupported module count"
 #endif
@@ -111,13 +91,11 @@ static uint32_t edma_bit_array_clear(unsigned channel, uint32_t *bit_array)
 
 static void edma_interrupt_handler(void *arg)
 {
-  mpc55xx_edma_channel_entry *e = arg;
-  unsigned channel = e->channel;
-  volatile struct EDMA_tag *edma = edma_get_regs_by_channel(channel);
+  edma_channel_context *ctx = arg;
 
-  edma->CIRQR.R = (uint8_t) channel;
+  mpc55xx_edma_clear_interrupts(ctx->edma_tcd);
 
-  e->done(e, 0);
+  (*ctx->done)(ctx, 0);
 }
 
 static void edma_interrupt_error_handler(void *arg)
@@ -155,47 +133,21 @@ static void edma_interrupt_error_handler(void *arg)
 #endif
 
   while (!rtems_chain_is_tail(chain, node)) {
-    mpc55xx_edma_channel_entry *e = (mpc55xx_edma_channel_entry *) node;
-    unsigned channel = e->channel;
-    unsigned group_index = EDMA_GROUP_INDEX(channel);
-    unsigned group_bit = EDMA_GROUP_BIT(channel);
+    edma_channel_context *ctx = (edma_channel_context *) node;
+    unsigned channel_index = edma_channel_index_of_tcd(ctx->edma_tcd);
+    unsigned group_index = EDMA_GROUP_INDEX(channel_index);
+    unsigned group_bit = EDMA_GROUP_BIT(channel_index);
 
     if ((error_channels [group_index] & group_bit) != 0) {
-      unsigned module_index = EDMA_MODULE_INDEX(channel);
+      unsigned module_index = EDMA_MODULE_INDEX(channel_index);
 
-      e->done(e, error_status [module_index]);
+      (*ctx->done)(ctx, error_status [module_index]);
     }
 
     node = rtems_chain_next(node);
   }
 }
 
-void mpc55xx_edma_enable_hardware_requests(unsigned channel, bool enable)
-{
-  volatile struct EDMA_tag *edma = edma_get_regs_by_channel(channel);
-
-  assert(EDMA_IS_CHANNEL_VALID(channel));
-
-  if (enable) {
-    edma->SERQR.R = (uint8_t) channel;
-  } else {
-    edma->CERQR.R = (uint8_t) channel;
-  }
-}
-
-void mpc55xx_edma_enable_error_interrupts(unsigned channel, bool enable)
-{
-  volatile struct EDMA_tag *edma = edma_get_regs_by_channel(channel);
-
-  assert(EDMA_IS_CHANNEL_VALID(channel));
-
-  if (enable) {
-    edma->SEEIR.R = (uint8_t) channel;
-  } else {
-    edma->CEEIR.R = (uint8_t) channel;
-  }
-}
-
 void mpc55xx_edma_init(void)
 {
   rtems_status_code sc = RTEMS_SUCCESSFUL;
@@ -252,75 +204,125 @@ void mpc55xx_edma_init(void)
   }
 }
 
-rtems_status_code mpc55xx_edma_obtain_channel(
-  mpc55xx_edma_channel_entry *e,
-  unsigned irq_priority
+rtems_status_code mpc55xx_edma_obtain_channel_by_tcd(
+  volatile struct tcd_t *edma_tcd
 )
 {
   rtems_status_code sc = RTEMS_SUCCESSFUL;
+  unsigned channel_index = edma_channel_index_of_tcd(edma_tcd);
   rtems_interrupt_level level;
-  unsigned channel = e->channel;
-  uint32_t channel_occupation = 0;
-
-  if (EDMA_IS_CHANNEL_INVALID(channel)) {
-    return RTEMS_INVALID_ID;
-  }
+  uint32_t channel_occupation;
 
   rtems_interrupt_disable(level);
   channel_occupation = edma_bit_array_set(
-    channel,
+    channel_index,
     &edma_channel_occupation [0]
   );
   rtems_interrupt_enable(level);
 
-  if ((channel_occupation & EDMA_GROUP_BIT(channel))) {
-    return RTEMS_RESOURCE_IN_USE;
-  }
-
-  sc = mpc55xx_interrupt_handler_install(
-    MPC55XX_IRQ_EDMA(channel),
-    "eDMA Channel",
-    RTEMS_INTERRUPT_SHARED,
-    irq_priority,
-    edma_interrupt_handler,
-    e
-  );
-  if (sc != RTEMS_SUCCESSFUL) {
-    rtems_interrupt_disable(level);
-    edma_bit_array_clear(channel, &edma_channel_occupation [0]);
-    rtems_interrupt_enable(level);
-
-    return RTEMS_IO_ERROR;
+  if ((channel_occupation & EDMA_GROUP_BIT(channel_index)) != 0) {
+    sc = RTEMS_RESOURCE_IN_USE;
   }
 
-  rtems_chain_prepend(&edma_channel_chain, &e->node);
-  mpc55xx_edma_enable_error_interrupts(channel, true);
-
-  return RTEMS_SUCCESSFUL;
+  return sc;
 }
 
-void mpc55xx_edma_release_channel(mpc55xx_edma_channel_entry *e)
+void mpc55xx_edma_release_channel_by_tcd(volatile struct tcd_t *edma_tcd)
 {
-  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  unsigned channel_index = edma_channel_index_of_tcd(edma_tcd);
   rtems_interrupt_level level;
-  unsigned channel = e->channel;
 
   rtems_interrupt_disable(level);
-  edma_bit_array_clear(channel, &edma_channel_occupation [0]);
+  edma_bit_array_clear(channel_index, &edma_channel_occupation [0]);
   rtems_interrupt_enable(level);
 
-  mpc55xx_edma_enable_hardware_requests(channel, false);
-  mpc55xx_edma_enable_error_interrupts(channel, false);
-  rtems_chain_extract(&e->node);
+  mpc55xx_edma_disable_hardware_requests(edma_tcd);
+  mpc55xx_edma_disable_error_interrupts(edma_tcd);
+}
+
+rtems_status_code mpc55xx_edma_obtain_channel(
+  edma_channel_context *ctx,
+  unsigned irq_priority
+)
+{
+  rtems_status_code sc = mpc55xx_edma_obtain_channel_by_tcd(ctx->edma_tcd);
+  if (sc == RTEMS_SUCCESSFUL) {
+    unsigned channel_index = edma_channel_index_of_tcd(ctx->edma_tcd);
+
+    sc = mpc55xx_interrupt_handler_install(
+      MPC55XX_IRQ_EDMA(channel_index),
+      "eDMA Channel",
+      RTEMS_INTERRUPT_SHARED,
+      irq_priority,
+      edma_interrupt_handler,
+      ctx
+    );
+    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)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  unsigned channel_index = edma_channel_index_of_tcd(ctx->edma_tcd);
+
+  mpc55xx_edma_release_channel_by_tcd(ctx->edma_tcd);
+  rtems_chain_extract(&ctx->node);
 
   sc = rtems_interrupt_handler_remove(
-    MPC55XX_IRQ_EDMA(e->channel),
+    MPC55XX_IRQ_EDMA(channel_index),
     edma_interrupt_handler,
-    e
+    ctx
   );
   if (sc != RTEMS_SUCCESSFUL) {
     mpc55xx_fatal(MPC55XX_FATAL_EDMA_IRQ_REMOVE);
   }
+}
+
+void mpc55xx_edma_copy(
+  volatile struct tcd_t *edma_tcd,
+  const struct tcd_t *source_tcd
+)
+{
+  /* Clear DONE flag */
+  edma_tcd->BMF.R = 0;
+
+  edma_tcd->SADDR = source_tcd->SADDR;
+  edma_tcd->SDF.R = source_tcd->SDF.R;
+  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->DLAST_SGA = source_tcd->DLAST_SGA;
+  edma_tcd->BMF.R = source_tcd->BMF.R;
+}
 
-  e->done(e, 0);
+void mpc55xx_edma_copy_and_enable_hardware_requests(
+  volatile struct tcd_t *edma_tcd,
+  const struct tcd_t *source_tcd
+)
+{
+  mpc55xx_edma_copy(edma_tcd, source_tcd);
+  mpc55xx_edma_enable_hardware_requests(edma_tcd);
+}
+
+void mpc55xx_edma_sg_link(
+  volatile struct tcd_t *edma_tcd,
+  const struct tcd_t *source_tcd
+)
+{
+  edma_tcd->DLAST_SGA = (int32_t) source_tcd;
+  edma_tcd->BMF.B.E_SG = 1;
+
+  if (!edma_tcd->BMF.B.E_SG) {
+    mpc55xx_edma_copy(edma_tcd, source_tcd);
+  }
 }
diff --git a/c/src/lib/libcpu/powerpc/mpc55xx/include/dspi.h b/c/src/lib/libcpu/powerpc/mpc55xx/include/dspi.h
index 38e1794..98bccc6 100644
--- a/c/src/lib/libcpu/powerpc/mpc55xx/include/dspi.h
+++ b/c/src/lib/libcpu/powerpc/mpc55xx/include/dspi.h
@@ -38,6 +38,11 @@ extern "C" {
 
 struct DSPI_tag;
 
+typedef struct {
+  edma_channel_context edma;
+  rtems_id id;
+} mpc55xx_dspi_edma_entry;
+
 /**
  * @brief LibI2C bus driver entry.
  */
@@ -79,21 +84,21 @@ typedef struct {
 	 *
 	 * The channel is fixed to a particular DSPI.
 	 */
-	mpc55xx_edma_channel_entry edma_transmit;
+	mpc55xx_dspi_edma_entry edma_transmit;
 
 	/**
 	 * @brief eDMA entry for push data generation.
 	 *
 	 * You can choose every available channel.
 	 */
-	mpc55xx_edma_channel_entry edma_push;
+	mpc55xx_dspi_edma_entry edma_push;
 
 	/**
 	 * @brief eDMA entry for receiving.
 	 *
 	 * The channel is fixed to a particular DSPI.
 	 */
-	mpc55xx_edma_channel_entry edma_receive;
+	mpc55xx_dspi_edma_entry edma_receive;
 
 	/**
 	 * @brief Idle character transmitted in read only mode.
diff --git a/c/src/lib/libcpu/powerpc/mpc55xx/include/edma.h b/c/src/lib/libcpu/powerpc/mpc55xx/include/edma.h
index 1e1b6a7..6669c56 100644
--- a/c/src/lib/libcpu/powerpc/mpc55xx/include/edma.h
+++ b/c/src/lib/libcpu/powerpc/mpc55xx/include/edma.h
@@ -7,12 +7,13 @@
  */
 
 /*
- * Copyright (c) 2008
- * Embedded Brains GmbH
- * Obere Lagerstr. 30
- * D-82178 Puchheim
- * Germany
- * rtems at embedded-brains.de
+ * Copyright (c) 2008-2013 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
  *
  * The license and distribution terms for this file may be
  * found in the file LICENSE in this distribution or at
@@ -22,8 +23,7 @@
 #ifndef LIBCPU_POWERPC_MPC55XX_EDMA_H
 #define LIBCPU_POWERPC_MPC55XX_EDMA_H
 
-#include <stdbool.h>
-#include <stdint.h>
+#include <mpc55xx/regs.h>
 
 #include <rtems.h>
 #include <rtems/chain.h>
@@ -32,22 +32,295 @@
 extern "C" {
 #endif /* __cplusplus */
 
-typedef struct mpc55xx_edma_channel_entry {
+#if MPC55XX_CHIP_FAMILY == 551
+  #define EDMA_CHANNEL_COUNT 16U
+#elif MPC55XX_CHIP_FAMILY == 564
+  #define EDMA_CHANNEL_COUNT 16U
+#elif MPC55XX_CHIP_FAMILY == 567
+  #define EDMA_CHANNEL_COUNT 96U
+#else
+  #define EDMA_CHANNEL_COUNT 64U
+#endif
+
+#define EDMA_MODULE_COUNT ((EDMA_CHANNEL_COUNT + 63U) / 64U)
+
+#define EDMA_CHANNELS_PER_MODULE 64U
+
+#if EDMA_MODULE_COUNT == 1
+  #define EDMA_TCD_BY_CHANNEL_INDEX(channel_index) \
+    (&EDMA.TCD[(channel_index)])
+#elif EDMA_MODULE_COUNT == 2
+  #define EDMA_TCD_BY_CHANNEL_INDEX(channel_index) \
+    ((channel_index) < EDMA_CHANNELS_PER_MODULE ? \
+      &EDMA_A.TCD[(channel_index)] \
+        : &EDMA_B.TCD[(channel_index) - EDMA_CHANNELS_PER_MODULE])
+#else
+  #error "unsupported module count"
+#endif
+
+/* FIXME: These values are only valid for the MPC5566 and MPC5674F */
+typedef enum {
+  EDMA_EQADC_A_FISR0_CFFF0 = 0,
+  EDMA_EQADC_A_FISR0_RFDF0 = 1,
+  EDMA_EQADC_A_FISR1_CFFF1 = 2,
+  EDMA_EQADC_A_FISR1_RFDF1 = 3,
+  EDMA_EQADC_A_FISR2_CFFF2 = 4,
+  EDMA_EQADC_A_FISR2_RFDF2 = 5,
+  EDMA_EQADC_A_FISR3_CFFF3 = 6,
+  EDMA_EQADC_A_FISR3_RFDF3 = 7,
+  EDMA_EQADC_A_FISR4_CFFF4 = 8,
+  EDMA_EQADC_A_FISR4_RFDF4 = 9,
+  EDMA_EQADC_A_FISR5_CFFF5 = 10,
+  EDMA_EQADC_A_FISR5_RFDF5 = 11,
+  EDMA_DSPI_B_SR_TFFF = 12,
+  EDMA_DSPI_B_SR_RFDF = 13,
+  EDMA_DSPI_C_SR_TFFF = 14,
+  EDMA_DSPI_C_SR_RFDF = 15,
+  EDMA_DSPI_D_SR_TFFF = 16,
+  EDMA_DSPI_D_SR_RFDF = 17,
+  EDMA_ESCI_A_COMBTX = 18,
+  EDMA_ESCI_A_COMBRX = 19,
+  EDMA_EMIOS_GFR_F0 = 20,
+  EDMA_EMIOS_GFR_F1 = 21,
+  EDMA_EMIOS_GFR_F2 = 22,
+  EDMA_EMIOS_GFR_F3 = 23,
+  EDMA_EMIOS_GFR_F4 = 24,
+  EDMA_EMIOS_GFR_F8 = 25,
+  EDMA_EMIOS_GFR_F9 = 26,
+  EDMA_ETPU_CDTRSR_A_DTRS0 = 27,
+  EDMA_ETPU_CDTRSR_A_DTRS1 = 28,
+  EDMA_ETPU_CDTRSR_A_DTRS2 = 29,
+  EDMA_ETPU_CDTRSR_A_DTRS14 = 30,
+  EDMA_ETPU_CDTRSR_A_DTRS15 = 31,
+  EDMA_DSPI_A_SR_TFFF = 32,
+  EDMA_DSPI_A_SR_RFDF = 33,
+  EDMA_ESCI_B_COMBTX = 34,
+  EDMA_ESCI_B_COMBRX = 35,
+  EDMA_EMIOS_GFR_F6 = 36,
+  EDMA_EMIOS_GFR_F7 = 37,
+  EDMA_EMIOS_GFR_F10 = 38,
+  EDMA_EMIOS_GFR_F11 = 39,
+  EDMA_EMIOS_GFR_F16 = 40,
+  EDMA_EMIOS_GFR_F17 = 41,
+  EDMA_EMIOS_GFR_F18 = 42,
+  EDMA_EMIOS_GFR_F19 = 43,
+  EDMA_ETPU_CDTRSR_A_DTRS12 = 44,
+  EDMA_ETPU_CDTRSR_A_DTRS13 = 45,
+  EDMA_ETPU_CDTRSR_A_DTRS28 = 46,
+  EDMA_ETPU_CDTRSR_A_DTRS29 = 47,
+  EDMA_SIU_EISR_EIF0 = 48,
+  EDMA_SIU_EISR_EIF1 = 49,
+  EDMA_SIU_EISR_EIF2 = 50,
+  EDMA_SIU_EISR_EIF3 = 51,
+  EDMA_ETPU_CDTRSR_B_DTRS0 = 52,
+  EDMA_ETPU_CDTRSR_B_DTRS1 = 53,
+  EDMA_ETPU_CDTRSR_B_DTRS2 = 54,
+  EDMA_ETPU_CDTRSR_B_DTRS3 = 55,
+  EDMA_ETPU_CDTRSR_B_DTRS12 = 56,
+  EDMA_ETPU_CDTRSR_B_DTRS13 = 57,
+  EDMA_ETPU_CDTRSR_B_DTRS14 = 58,
+  EDMA_ETPU_CDTRSR_B_DTRS15 = 59,
+  EDMA_ETPU_CDTRSR_B_DTRS28 = 60,
+  EDMA_ETPU_CDTRSR_B_DTRS29 = 61,
+  EDMA_ETPU_CDTRSR_B_DTRS30 = 62,
+  EDMA_ETPU_CDTRSR_B_DTRS31 = 63
+  #if MPC55XX_CHIP_FAMILY == 567
+    ,
+    EDMA_EQADC_B_FISR0_CFFF0 = 64 + 0,
+    EDMA_EQADC_B_FISR0_RFDF0 = 64 + 1,
+    EDMA_EQADC_B_FISR1_CFFF1 = 64 + 2,
+    EDMA_EQADC_B_FISR1_RFDF1 = 64 + 3,
+    EDMA_EQADC_B_FISR2_CFFF2 = 64 + 4,
+    EDMA_EQADC_B_FISR2_RFDF2 = 64 + 5,
+    EDMA_EQADC_B_FISR3_CFFF3 = 64 + 6,
+    EDMA_EQADC_B_FISR3_RFDF3 = 64 + 7,
+    EDMA_EQADC_B_FISR4_CFFF4 = 64 + 8,
+    EDMA_EQADC_B_FISR4_RFDF3 = 64 + 9,
+    EDMA_EQADC_B_FISR5_CFFF5 = 64 + 10,
+    EDMA_EQADC_B_FISR5_RFDF5 = 64 + 11,
+    EDMA_DECFILTER_A_IB = 64 + 12,
+    EDMA_DECFILTER_A_OB = 64 + 13,
+    EDMA_DECFILTER_B_IB = 64 + 14,
+    EDMA_DECFILTER_B_OB = 64 + 15,
+    EDMA_DECFILTER_C_IB = 64 + 16,
+    EDMA_DECFILTER_C_OB = 64 + 17,
+    EDMA_DECFILTER_D_IB = 64 + 18,
+    EDMA_DECFILTER_D_OB = 64 + 19,
+    EDMA_DECFILTER_E_IB = 64 + 20,
+    EDMA_DECFILTER_E_OB = 64 + 21,
+    EDMA_DECFILTER_F_IB = 64 + 22,
+    EDMA_DECFILTER_F_OB = 64 + 23,
+    EDMA_DECFILTER_G_IB = 64 + 24,
+    EDMA_DECFILTER_G_OB = 64 + 25,
+    EDMA_DECFILTER_H_IB = 64 + 26,
+    EDMA_DECFILTER_H_OB = 64 + 27
+  #endif
+} edma_channel;
+
+typedef struct edma_channel_context {
   rtems_chain_node node;
-  unsigned channel;
-  void (*done)( struct mpc55xx_edma_channel_entry *, uint32_t);
-  rtems_id id;
-} mpc55xx_edma_channel_entry;
+  volatile struct tcd_t *edma_tcd;
+  void (*done)(struct edma_channel_context *, uint32_t);
+} edma_channel_context;
 
 void mpc55xx_edma_init(void);
 
-rtems_status_code mpc55xx_edma_obtain_channel( mpc55xx_edma_channel_entry *e, unsigned irq_priority);
+/**
+ * @brief Obtains an eDMA channel.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_RESOURCE_IN_USE The channel is already in use.
+ */
+rtems_status_code mpc55xx_edma_obtain_channel_by_tcd(
+  volatile struct tcd_t *edma_tcd
+);
+
+void mpc55xx_edma_release_channel_by_tcd(volatile struct tcd_t *edma_tcd);
+
+/**
+ * @brief Obtains an eDMA channel and registers the channel context.
+ *
+ * The done handler of the channel context will be called
+ * - during minor or major loop completions if interrupts are enabled in the
+ *   corresponding TCD, or
+ * - in case a channel error occurs.
+ *
+ * An error status value not equal to zero indicates an error.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_RESOURCE_IN_USE The channel is already in use.
+ * @retval RTEMS_IO_ERROR Unable to install interrupt handler for this channel.
+ */
+rtems_status_code mpc55xx_edma_obtain_channel(
+  edma_channel_context *ctx,
+  unsigned irq_priority
+);
+
+void mpc55xx_edma_release_channel(edma_channel_context *ctx);
+
+/**
+ * @brief Copies a source TCD to an eDMA TCD.
+ *
+ * The DONE flag of the eDMA TCD is cleared before the actual copy operation.
+ * This enables the setting of channel link or scatter/gather options.
+ *
+ * This function can be used to start the channel if the START flags is
+ * set in the source TCD.
+ */
+void mpc55xx_edma_copy(
+  volatile struct tcd_t *edma_tcd,
+  const struct tcd_t *source_tcd
+);
+
+/**
+ * @brief Copies a source TCD to an eDMA TCD and enables hardware requests.
+ *
+ * The DONE flag of the eDMA TCD is cleared before the actual copy operation.
+ * This enables the setting of channel link or scatter/gather options.
+ */
+void mpc55xx_edma_copy_and_enable_hardware_requests(
+  volatile struct tcd_t *edma_tcd,
+  const struct tcd_t *source_tcd
+);
+
+void mpc55xx_edma_sg_link(
+  volatile struct tcd_t *edma_tcd,
+  const struct tcd_t *source_tcd
+);
+
+static inline volatile struct EDMA_tag *mpc55xx_edma_by_tcd(
+  volatile struct tcd_t *edma_tcd
+)
+{
+  return (volatile struct EDMA_tag *)
+    ((uintptr_t) edma_tcd & ~(uintptr_t) 0x1fff);
+}
+
+static inline unsigned mpc55xx_edma_channel_by_tcd(
+  volatile struct tcd_t *edma_tcd
+)
+{
+  volatile struct EDMA_tag *edma = mpc55xx_edma_by_tcd(edma_tcd);
+
+  return edma_tcd - &edma->TCD[0];
+}
+
+static inline void mpc55xx_edma_enable_hardware_requests(
+  volatile struct tcd_t *edma_tcd
+)
+{
+  volatile struct EDMA_tag *edma = mpc55xx_edma_by_tcd(edma_tcd);
+  unsigned channel = edma_tcd - &edma->TCD[0];
+
+  edma->SERQR.R = (uint8_t) channel;
+}
+
+static inline void mpc55xx_edma_disable_hardware_requests(
+  volatile struct tcd_t *edma_tcd
+)
+{
+  volatile struct EDMA_tag *edma = mpc55xx_edma_by_tcd(edma_tcd);
+  unsigned channel = edma_tcd - &edma->TCD[0];
+
+  edma->CERQR.R = (uint8_t) channel;
+}
+
+static inline void mpc55xx_edma_enable_error_interrupts(
+  volatile struct tcd_t *edma_tcd
+)
+{
+  volatile struct EDMA_tag *edma = mpc55xx_edma_by_tcd(edma_tcd);
+  unsigned channel = edma_tcd - &edma->TCD[0];
 
-void mpc55xx_edma_release_channel( mpc55xx_edma_channel_entry *e);
+  edma->SEEIR.R = (uint8_t) channel;
+}
+
+static inline void mpc55xx_edma_disable_error_interrupts(
+  volatile struct tcd_t *edma_tcd
+)
+{
+  volatile struct EDMA_tag *edma = mpc55xx_edma_by_tcd(edma_tcd);
+  unsigned channel = edma_tcd - &edma->TCD[0];
+
+  edma->CEEIR.R = (uint8_t) channel;
+}
+
+static inline void mpc55xx_edma_set_start(
+  volatile struct tcd_t *edma_tcd
+)
+{
+  volatile struct EDMA_tag *edma = mpc55xx_edma_by_tcd(edma_tcd);
+  unsigned channel = edma_tcd - &edma->TCD[0];
+
+  edma->SSBR.R = (uint8_t) channel;
+}
 
-void mpc55xx_edma_enable_hardware_requests( unsigned channel, bool enable);
+static inline void mpc55xx_edma_clear_done(
+  volatile struct tcd_t *edma_tcd
+)
+{
+  volatile struct EDMA_tag *edma = mpc55xx_edma_by_tcd(edma_tcd);
+  unsigned channel = edma_tcd - &edma->TCD[0];
 
-void mpc55xx_edma_enable_error_interrupts( unsigned channel, bool enable);
+  edma->CDSBR.R = (uint8_t) channel;
+}
+
+static inline void mpc55xx_edma_clear_interrupts(
+  volatile struct tcd_t *edma_tcd
+)
+{
+  volatile struct EDMA_tag *edma = mpc55xx_edma_by_tcd(edma_tcd);
+  unsigned channel = edma_tcd - &edma->TCD[0];
+
+  edma->CIRQR.R = (uint8_t) channel;
+}
+
+static inline bool mpc55xx_edma_is_done(
+  volatile struct tcd_t *edma_tcd
+)
+{
+  return edma_tcd->BMF.B.DONE;
+}
 
 #ifdef __cplusplus
 }




More information about the vc mailing list