diff options
Diffstat (limited to 'c/src/lib/libcpu/powerpc')
-rw-r--r-- | c/src/lib/libcpu/powerpc/mpc55xx/dspi/dspi.c | 102 | ||||
-rw-r--r-- | c/src/lib/libcpu/powerpc/mpc55xx/edma/edma.c | 216 | ||||
-rw-r--r-- | c/src/lib/libcpu/powerpc/mpc55xx/include/dspi.h | 11 | ||||
-rw-r--r-- | c/src/lib/libcpu/powerpc/mpc55xx/include/edma.h | 307 |
4 files changed, 471 insertions, 165 deletions
diff --git a/c/src/lib/libcpu/powerpc/mpc55xx/dspi/dspi.c b/c/src/lib/libcpu/powerpc/mpc55xx/dspi/dspi.c index 0cba1113dc..3e8aee44ad 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 952e8a8f38..7b9eab422a 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@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 38e1794670..98bccc606b 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 1e1b6a7e0b..6669c56a0e 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@embedded-brains.de + * Copyright (c) 2008-2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@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 } |