bsp/mpc55xx: eDMA API changes

This commit is contained in:
Sebastian Huber
2013-04-03 12:05:49 +02:00
parent 4e3deaf7c1
commit db21e1dd6c
5 changed files with 486 additions and 184 deletions

View File

@@ -146,8 +146,8 @@ typedef struct {
smsc9218i_state state; smsc9218i_state state;
rtems_id receive_task; rtems_id receive_task;
rtems_id transmit_task; rtems_id transmit_task;
mpc55xx_edma_channel_entry edma_receive; edma_channel_context edma_receive;
mpc55xx_edma_channel_entry edma_transmit; edma_channel_context edma_transmit;
unsigned phy_interrupts; unsigned phy_interrupts;
unsigned received_frames; unsigned received_frames;
unsigned receiver_errors; unsigned receiver_errors;
@@ -205,12 +205,12 @@ typedef struct {
static smsc9218i_receive_job_control smsc_rx_jc __attribute__((aligned (32))); static smsc9218i_receive_job_control smsc_rx_jc __attribute__((aligned (32)));
static void smsc9218i_transmit_dma_done( static void smsc9218i_transmit_dma_done(
mpc55xx_edma_channel_entry *channel_entry, edma_channel_context *ctx,
uint32_t error_status uint32_t error_status
); );
static void smsc9218i_receive_dma_done( static void smsc9218i_receive_dma_done(
mpc55xx_edma_channel_entry *e, edma_channel_context *ctx,
uint32_t error_status uint32_t error_status
); );
@@ -219,14 +219,12 @@ static smsc9218i_driver_entry smsc9218i_driver_data = {
.receive_task = RTEMS_ID_NONE, .receive_task = RTEMS_ID_NONE,
.transmit_task = RTEMS_ID_NONE, .transmit_task = RTEMS_ID_NONE,
.edma_receive = { .edma_receive = {
.channel = SMSC9218I_EDMA_RX_CHANNEL, .edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(SMSC9218I_EDMA_RX_CHANNEL),
.done = smsc9218i_receive_dma_done, .done = smsc9218i_receive_dma_done
.id = RTEMS_ID_NONE
}, },
.edma_transmit = { .edma_transmit = {
.channel = SMSC9218I_EDMA_TX_CHANNEL, .edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(SMSC9218I_EDMA_TX_CHANNEL),
.done = smsc9218i_transmit_dma_done, .done = smsc9218i_transmit_dma_done
.id = RTEMS_ID_NONE
} }
}; };
@@ -604,7 +602,7 @@ static void smsc9218i_setup_receive_dma(
jc->produce = p; jc->produce = p;
if (last != NULL) { 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 */ /* Setup last TCD */
last->BMF.R = SMSC9218I_TCD_BMF_LAST; last->BMF.R = SMSC9218I_TCD_BMF_LAST;
@@ -625,7 +623,7 @@ static void smsc9218i_setup_receive_dma(
} }
static void smsc9218i_receive_dma_done( static void smsc9218i_receive_dma_done(
mpc55xx_edma_channel_entry *channel_entry, edma_channel_context *ctx,
uint32_t error_status uint32_t error_status
) )
{ {
@@ -644,14 +642,14 @@ static void smsc9218i_receive_dma_done(
++e->receive_dma_errors; ++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); ASSERT_SC(sc);
jc->done = jc->produce; jc->done = jc->produce;
} }
static void smsc9218i_transmit_dma_done( static void smsc9218i_transmit_dma_done(
mpc55xx_edma_channel_entry *channel_entry, edma_channel_context *ctx,
uint32_t error_status uint32_t error_status
) )
{ {
@@ -668,7 +666,7 @@ static void smsc9218i_transmit_dma_done(
++e->transmit_dma_interrupts; ++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); ASSERT_SC(sc);
} }
@@ -866,7 +864,6 @@ static void smsc9218i_init_receive_jobs(
int i = 0; int i = 0;
/* Obtain receive eDMA channel */ /* Obtain receive eDMA channel */
e->edma_receive.id = e->receive_task;
sc = mpc55xx_edma_obtain_channel( sc = mpc55xx_edma_obtain_channel(
&e->edma_receive, &e->edma_receive,
MPC55XX_INTC_DEFAULT_PRIORITY MPC55XX_INTC_DEFAULT_PRIORITY
@@ -1270,7 +1267,7 @@ static void smsc9218i_transmit_do_jobs(
} }
if (i > 0) { 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 *start = &jc->command_tcd_table [jc->transfer_index];
struct tcd_t *last = &jc->data_tcd_table [last_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__); SMSC9218I_PRINTF("%s\n", __func__);
/* Obtain transmit eDMA channel */ /* Obtain transmit eDMA channel */
e->edma_transmit.id = e->transmit_task;
sc = mpc55xx_edma_obtain_channel( sc = mpc55xx_edma_obtain_channel(
&e->edma_transmit, &e->edma_transmit,
MPC55XX_INTC_DEFAULT_PRIORITY MPC55XX_INTC_DEFAULT_PRIORITY

View File

@@ -113,8 +113,9 @@ static const mpc55xx_dspi_baudrate_scaler_entry mpc55xx_dspi_baudrate_scaler_tab
{ 229376, 3, 15 }, { 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); rtems_semaphore_release( e->id);
if (error_status != 0) { 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"); 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"); RTEMS_CHECK_SC( sc, "obtain receive eDMA channel");
/* eDMA transmit */ /* 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"); 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"); 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"); RTEMS_CHECK_SC( sc, "obtain push eDMA channel");
tcd_push.SADDR = mpc55xx_dspi_push_data_address( e); 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.CDF.B.CITER = 1;
tcd_push.BMF.B.BITER = 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 */ /* Module Control Register */
mcr.B.MSTR = e->master ? 1 : 0; mcr.B.MSTR = e->master ? 1 : 0;
@@ -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.CDF.B.CITER = n_c;
tcd_transmit.BMF.B.BITER = n_c; tcd_transmit.BMF.B.BITER = n_c;
} else { } 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.SADDR = (uint32_t) out_c;
tcd_transmit.SDF.B.SSIZE = 0; tcd_transmit.SDF.B.SSIZE = 0;
tcd_transmit.SDF.B.SOFF = 1; 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.NBYTES = 1;
tcd_transmit.CDF.B.CITERE_LINK = 1; tcd_transmit.CDF.B.CITERE_LINK = 1;
tcd_transmit.BMF.B.BITERE_LINK = 1; tcd_transmit.BMF.B.BITERE_LINK = 1;
tcd_transmit.BMF.B.MAJORLINKCH = e->edma_push.channel; tcd_transmit.BMF.B.MAJORLINKCH = push_channel;
tcd_transmit.CDF.B.CITER = EDMA_TCD_LINK_AND_BITER( e->edma_push.channel, n_c); tcd_transmit.CDF.B.CITER = EDMA_TCD_LINK_AND_BITER( push_channel, n_c);
tcd_transmit.BMF.B.BITER = EDMA_TCD_LINK_AND_BITER( e->edma_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.MAJORE_LINK = 1;
} }
tcd_transmit.BMF.B.D_REQ = 1; tcd_transmit.BMF.B.D_REQ = 1;
tcd_transmit.BMF.B.INT_MAJ = 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 */ /* Set receive TCD */
if (in == NULL) { 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.BMF.B.INT_MAJ = 1;
tcd_receive.CDF.B.CITER = n_c; tcd_receive.CDF.B.CITER = n_c;
tcd_receive.BMF.B.BITER = 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 */ /* Clear request flags */
sr.R = 0; 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; status->R = sr.R;
/* Enable hardware requests */ /* Enable hardware requests */
mpc55xx_edma_enable_hardware_requests( e->edma_receive.channel, true); mpc55xx_edma_enable_hardware_requests( e->edma_receive.edma.edma_tcd);
mpc55xx_edma_enable_hardware_requests( e->edma_transmit.channel, true); mpc55xx_edma_enable_hardware_requests( e->edma_transmit.edma.edma_tcd);
/* Wait for transmit update */ /* Wait for transmit update */
sc = rtems_semaphore_obtain( e->edma_transmit.id, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 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, .master = true,
.push_data = MPC55XX_ZERO_FLAGS, .push_data = MPC55XX_ZERO_FLAGS,
.edma_transmit = { .edma_transmit = {
.channel = 32, .edma = {
.done = mpc55xx_dspi_edma_done, .edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(EDMA_DSPI_A_SR_TFFF),
.done = mpc55xx_dspi_edma_done
},
.id = RTEMS_ID_NONE .id = RTEMS_ID_NONE
}, },
.edma_push = { .edma_push = {
.channel = 43, .edma = {
.done = mpc55xx_dspi_edma_done, .edma_tcd = &EDMA.TCD [43],
.done = mpc55xx_dspi_edma_done
},
.id = RTEMS_ID_NONE .id = RTEMS_ID_NONE
}, },
.edma_receive = { .edma_receive = {
.channel = 33, .edma = {
.done = mpc55xx_dspi_edma_done, .edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(EDMA_DSPI_A_SR_RFDF),
.done = mpc55xx_dspi_edma_done
},
.id = RTEMS_ID_NONE .id = RTEMS_ID_NONE
}, },
.idle_char = 0xffffffff, .idle_char = 0xffffffff,
@@ -704,18 +712,24 @@ mpc55xx_dspi_bus_entry mpc55xx_dspi_bus_table [MPC55XX_DSPI_NUMBER] = {
.master = true, .master = true,
.push_data = MPC55XX_ZERO_FLAGS, .push_data = MPC55XX_ZERO_FLAGS,
.edma_transmit = { .edma_transmit = {
.channel = 12, .edma = {
.done = mpc55xx_dspi_edma_done, .edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(EDMA_DSPI_B_SR_TFFF),
.done = mpc55xx_dspi_edma_done
},
.id = RTEMS_ID_NONE .id = RTEMS_ID_NONE
}, },
.edma_push = { .edma_push = {
.channel = 10, .edma = {
.done = mpc55xx_dspi_edma_done, .edma_tcd = &EDMA.TCD [10],
.done = mpc55xx_dspi_edma_done
},
.id = RTEMS_ID_NONE .id = RTEMS_ID_NONE
}, },
.edma_receive = { .edma_receive = {
.channel = 13, .edma = {
.done = mpc55xx_dspi_edma_done, .edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(EDMA_DSPI_B_SR_RFDF),
.done = mpc55xx_dspi_edma_done
},
.id = RTEMS_ID_NONE .id = RTEMS_ID_NONE
}, },
.idle_char = 0xffffffff, .idle_char = 0xffffffff,
@@ -732,18 +746,24 @@ mpc55xx_dspi_bus_entry mpc55xx_dspi_bus_table [MPC55XX_DSPI_NUMBER] = {
.master = true, .master = true,
.push_data = MPC55XX_ZERO_FLAGS, .push_data = MPC55XX_ZERO_FLAGS,
.edma_transmit = { .edma_transmit = {
.channel = 14, .edma = {
.done = mpc55xx_dspi_edma_done, .edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(EDMA_DSPI_C_SR_TFFF),
.done = mpc55xx_dspi_edma_done
},
.id = RTEMS_ID_NONE .id = RTEMS_ID_NONE
}, },
.edma_push = { .edma_push = {
.channel = 11, .edma = {
.done = mpc55xx_dspi_edma_done, .edma_tcd = &EDMA.TCD [11],
.done = mpc55xx_dspi_edma_done
},
.id = RTEMS_ID_NONE .id = RTEMS_ID_NONE
}, },
.edma_receive = { .edma_receive = {
.channel = 15, .edma = {
.done = mpc55xx_dspi_edma_done, .edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(EDMA_DSPI_C_SR_RFDF),
.done = mpc55xx_dspi_edma_done
},
.id = RTEMS_ID_NONE .id = RTEMS_ID_NONE
}, },
.idle_char = 0xffffffff, .idle_char = 0xffffffff,
@@ -761,18 +781,24 @@ mpc55xx_dspi_bus_entry mpc55xx_dspi_bus_table [MPC55XX_DSPI_NUMBER] = {
.master = true, .master = true,
.push_data = MPC55XX_ZERO_FLAGS, .push_data = MPC55XX_ZERO_FLAGS,
.edma_transmit = { .edma_transmit = {
.channel = 16, .edma = {
.done = mpc55xx_dspi_edma_done, .edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(EDMA_DSPI_D_SR_TFFF),
.done = mpc55xx_dspi_edma_done
},
.id = RTEMS_ID_NONE .id = RTEMS_ID_NONE
}, },
.edma_push = { .edma_push = {
.channel = 18, .edma = {
.done = mpc55xx_dspi_edma_done, .edma_tcd = &EDMA.TCD [18],
.done = mpc55xx_dspi_edma_done
},
.id = RTEMS_ID_NONE .id = RTEMS_ID_NONE
}, },
.edma_receive = { .edma_receive = {
.channel = 17, .edma = {
.done = mpc55xx_dspi_edma_done, .edma_tcd = EDMA_TCD_BY_CHANNEL_INDEX(EDMA_DSPI_D_SR_RFDF),
.done = mpc55xx_dspi_edma_done
},
.id = RTEMS_ID_NONE .id = RTEMS_ID_NONE
}, },
.idle_char = 0xffffffff, .idle_char = 0xffffffff,

View File

@@ -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 * embedded brains GmbH
* Obere Lagerstr. 30 * Dornierstr. 4
* 82178 Puchheim * 82178 Puchheim
* Germany * Germany
* <rtems@embedded-brains.de> * <rtems@embedded-brains.de>
@@ -20,7 +20,6 @@
* http://www.rtems.com/license/LICENSE. * http://www.rtems.com/license/LICENSE.
*/ */
#include <mpc55xx/regs.h>
#include <mpc55xx/edma.h> #include <mpc55xx/edma.h>
#include <mpc55xx/mpc55xx.h> #include <mpc55xx/mpc55xx.h>
@@ -29,48 +28,29 @@
#include <bsp.h> #include <bsp.h>
#include <bsp/irq.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_GROUP 32U
#define EDMA_CHANNELS_PER_MODULE 64U
#define EDMA_GROUP_COUNT ((EDMA_CHANNEL_COUNT + 31U) / 32U) #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_INDEX(channel) ((channel) / EDMA_CHANNELS_PER_GROUP)
#define EDMA_GROUP_BIT(channel) (1U << ((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_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 uint32_t edma_channel_occupation [EDMA_GROUP_COUNT];
static RTEMS_CHAIN_DEFINE_EMPTY(edma_channel_chain); 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 #if EDMA_MODULE_COUNT == 1
return &EDMA; return channel;
#elif EDMA_MODULE_COUNT == 2 #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 #else
#error "unsupported module count" #error "unsupported module count"
#endif #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) static void edma_interrupt_handler(void *arg)
{ {
mpc55xx_edma_channel_entry *e = arg; edma_channel_context *ctx = arg;
unsigned channel = e->channel;
volatile struct EDMA_tag *edma = edma_get_regs_by_channel(channel);
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) static void edma_interrupt_error_handler(void *arg)
@@ -155,47 +133,21 @@ static void edma_interrupt_error_handler(void *arg)
#endif #endif
while (!rtems_chain_is_tail(chain, node)) { while (!rtems_chain_is_tail(chain, node)) {
mpc55xx_edma_channel_entry *e = (mpc55xx_edma_channel_entry *) node; edma_channel_context *ctx = (edma_channel_context *) node;
unsigned channel = e->channel; unsigned channel_index = edma_channel_index_of_tcd(ctx->edma_tcd);
unsigned group_index = EDMA_GROUP_INDEX(channel); unsigned group_index = EDMA_GROUP_INDEX(channel_index);
unsigned group_bit = EDMA_GROUP_BIT(channel); unsigned group_bit = EDMA_GROUP_BIT(channel_index);
if ((error_channels [group_index] & group_bit) != 0) { 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); 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) void mpc55xx_edma_init(void)
{ {
rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_status_code sc = RTEMS_SUCCESSFUL;
@@ -252,75 +204,125 @@ void mpc55xx_edma_init(void)
} }
} }
rtems_status_code mpc55xx_edma_obtain_channel( rtems_status_code mpc55xx_edma_obtain_channel_by_tcd(
mpc55xx_edma_channel_entry *e, volatile struct tcd_t *edma_tcd
unsigned irq_priority
) )
{ {
rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_status_code sc = RTEMS_SUCCESSFUL;
unsigned channel_index = edma_channel_index_of_tcd(edma_tcd);
rtems_interrupt_level level; rtems_interrupt_level level;
unsigned channel = e->channel; uint32_t channel_occupation;
uint32_t channel_occupation = 0;
if (EDMA_IS_CHANNEL_INVALID(channel)) {
return RTEMS_INVALID_ID;
}
rtems_interrupt_disable(level); rtems_interrupt_disable(level);
channel_occupation = edma_bit_array_set( channel_occupation = edma_bit_array_set(
channel, channel_index,
&edma_channel_occupation [0] &edma_channel_occupation [0]
); );
rtems_interrupt_enable(level); rtems_interrupt_enable(level);
if ((channel_occupation & EDMA_GROUP_BIT(channel))) { if ((channel_occupation & EDMA_GROUP_BIT(channel_index)) != 0) {
return RTEMS_RESOURCE_IN_USE; sc = RTEMS_RESOURCE_IN_USE;
} }
return sc;
}
void mpc55xx_edma_release_channel_by_tcd(volatile struct tcd_t *edma_tcd)
{
unsigned channel_index = 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]);
rtems_interrupt_enable(level);
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( sc = mpc55xx_interrupt_handler_install(
MPC55XX_IRQ_EDMA(channel), MPC55XX_IRQ_EDMA(channel_index),
"eDMA Channel", "eDMA Channel",
RTEMS_INTERRUPT_SHARED, RTEMS_INTERRUPT_SHARED,
irq_priority, irq_priority,
edma_interrupt_handler, edma_interrupt_handler,
e ctx
); );
if (sc != RTEMS_SUCCESSFUL) { if (sc == RTEMS_SUCCESSFUL) {
rtems_interrupt_disable(level); rtems_chain_prepend(&edma_channel_chain, &ctx->node);
edma_bit_array_clear(channel, &edma_channel_occupation [0]); mpc55xx_edma_enable_error_interrupts(ctx->edma_tcd);
rtems_interrupt_enable(level); } else {
mpc55xx_edma_release_channel_by_tcd(ctx->edma_tcd);
return RTEMS_IO_ERROR; sc = RTEMS_IO_ERROR;
}
} }
rtems_chain_prepend(&edma_channel_chain, &e->node); return sc;
mpc55xx_edma_enable_error_interrupts(channel, true);
return RTEMS_SUCCESSFUL;
} }
void mpc55xx_edma_release_channel(mpc55xx_edma_channel_entry *e) void mpc55xx_edma_release_channel(edma_channel_context *ctx)
{ {
rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_status_code sc = RTEMS_SUCCESSFUL;
rtems_interrupt_level level; unsigned channel_index = edma_channel_index_of_tcd(ctx->edma_tcd);
unsigned channel = e->channel;
rtems_interrupt_disable(level); mpc55xx_edma_release_channel_by_tcd(ctx->edma_tcd);
edma_bit_array_clear(channel, &edma_channel_occupation [0]); rtems_chain_extract(&ctx->node);
rtems_interrupt_enable(level);
mpc55xx_edma_enable_hardware_requests(channel, false);
mpc55xx_edma_enable_error_interrupts(channel, false);
rtems_chain_extract(&e->node);
sc = rtems_interrupt_handler_remove( sc = rtems_interrupt_handler_remove(
MPC55XX_IRQ_EDMA(e->channel), MPC55XX_IRQ_EDMA(channel_index),
edma_interrupt_handler, edma_interrupt_handler,
e ctx
); );
if (sc != RTEMS_SUCCESSFUL) { if (sc != RTEMS_SUCCESSFUL) {
mpc55xx_fatal(MPC55XX_FATAL_EDMA_IRQ_REMOVE); mpc55xx_fatal(MPC55XX_FATAL_EDMA_IRQ_REMOVE);
} }
}
e->done(e, 0);
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;
}
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);
}
} }

View File

@@ -38,6 +38,11 @@ extern "C" {
struct DSPI_tag; struct DSPI_tag;
typedef struct {
edma_channel_context edma;
rtems_id id;
} mpc55xx_dspi_edma_entry;
/** /**
* @brief LibI2C bus driver entry. * @brief LibI2C bus driver entry.
*/ */
@@ -79,21 +84,21 @@ typedef struct {
* *
* The channel is fixed to a particular DSPI. * 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. * @brief eDMA entry for push data generation.
* *
* You can choose every available channel. * You can choose every available channel.
*/ */
mpc55xx_edma_channel_entry edma_push; mpc55xx_dspi_edma_entry edma_push;
/** /**
* @brief eDMA entry for receiving. * @brief eDMA entry for receiving.
* *
* The channel is fixed to a particular DSPI. * 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. * @brief Idle character transmitted in read only mode.

View File

@@ -7,12 +7,13 @@
*/ */
/* /*
* Copyright (c) 2008 * Copyright (c) 2008-2013 embedded brains GmbH. All rights reserved.
* Embedded Brains GmbH *
* Obere Lagerstr. 30 * embedded brains GmbH
* D-82178 Puchheim * Dornierstr. 4
* 82178 Puchheim
* Germany * Germany
* rtems@embedded-brains.de * <rtems@embedded-brains.de>
* *
* The license and distribution terms for this file may be * The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at * found in the file LICENSE in this distribution or at
@@ -22,8 +23,7 @@
#ifndef LIBCPU_POWERPC_MPC55XX_EDMA_H #ifndef LIBCPU_POWERPC_MPC55XX_EDMA_H
#define LIBCPU_POWERPC_MPC55XX_EDMA_H #define LIBCPU_POWERPC_MPC55XX_EDMA_H
#include <stdbool.h> #include <mpc55xx/regs.h>
#include <stdint.h>
#include <rtems.h> #include <rtems.h>
#include <rtems/chain.h> #include <rtems/chain.h>
@@ -32,22 +32,295 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #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; rtems_chain_node node;
unsigned channel; volatile struct tcd_t *edma_tcd;
void (*done)( struct mpc55xx_edma_channel_entry *, uint32_t); void (*done)(struct edma_channel_context *, uint32_t);
rtems_id id; } edma_channel_context;
} mpc55xx_edma_channel_entry;
void mpc55xx_edma_init(void); 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( mpc55xx_edma_channel_entry *e); void mpc55xx_edma_release_channel_by_tcd(volatile struct tcd_t *edma_tcd);
void mpc55xx_edma_enable_hardware_requests( unsigned channel, bool enable); /**
* @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_enable_error_interrupts( unsigned channel, bool enable); 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];
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;
}
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];
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 #ifdef __cplusplus
} }