From 0fc403c55a7aa76ef509dffd614ba99785010d1e Mon Sep 17 00:00:00 2001 From: gdisirio Date: Tue, 26 Mar 2013 15:02:45 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5506 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/SPC563Mxx/spc563m_registry.h | 19 ++ os/hal/platforms/SPC5xx/DSPI_v1/spc5_dspi.h | 10 +- os/hal/platforms/SPC5xx/DSPI_v1/spi_lld.c | 365 +++++++++++++++++++++++++- os/hal/platforms/SPC5xx/DSPI_v1/spi_lld.h | 211 ++++++++++++++- 4 files changed, 585 insertions(+), 20 deletions(-) (limited to 'os') diff --git a/os/hal/platforms/SPC563Mxx/spc563m_registry.h b/os/hal/platforms/SPC563Mxx/spc563m_registry.h index cc6050d9e..7d52e8e43 100644 --- a/os/hal/platforms/SPC563Mxx/spc563m_registry.h +++ b/os/hal/platforms/SPC563Mxx/spc563m_registry.h @@ -31,6 +31,25 @@ * @name SPC563Mxx capabilities * @{ */ +/* DSPI attribures.*/ +#define SPC5_HAS_DSPI0 FALSE +#define SPC5_HAS_DSPI1 TRUE +#define SPC5_HAS_DSPI2 TRUE +#define SPC5_HAS_DSPI3 FALSE +#define SPC5_DSPI_FIFO_DEPTH 16 +#define SPC5_DSPI1_TX_DMA_DEV_ID 12 +#define SPC5_DSPI1_RX_DMA_DEV_ID 13 +#define SPC5_DSPI2_TX_DMA_DEV_ID 14 +#define SPC5_DSPI2_RX_DMA_DEV_ID 15 +#define SPC5_DSPI1_EOQF_HANDLER vector132 +#define SPC5_DSPI1_EOQF_NUMBER 132 +#define SPC5_DSPI2_EOQF_HANDLER vector137 +#define SPC5_DSPI2_EOQF_NUMBER 137 +#define SPC5_DSPI1_ENABLE_CLOCK() +#define SPC5_DSPI1_DISABLE_CLOCK() +#define SPC5_DSPI2_ENABLE_CLOCK() +#define SPC5_DSPI2_DISABLE_CLOCK() + /* eDMA attributes.*/ #define SPC5_HAS_EDMAA TRUE #define SPC5_EDMA_NCHANNELS 32 diff --git a/os/hal/platforms/SPC5xx/DSPI_v1/spc5_dspi.h b/os/hal/platforms/SPC5xx/DSPI_v1/spc5_dspi.h index eec2f5809..7403c5550 100644 --- a/os/hal/platforms/SPC5xx/DSPI_v1/spc5_dspi.h +++ b/os/hal/platforms/SPC5xx/DSPI_v1/spc5_dspi.h @@ -254,19 +254,19 @@ struct spc5_dspi { * @{ */ #if SPC5_HAS_DSPI0 || defined(__DOXYGEN__) -#define SPC5_DSPI_0 (*(volatile struct spc5_dspi *)0xFFF90000UL) +#define SPC5_DSPI0 (*(struct spc5_dspi *)0xFFF90000UL) #endif #if SPC5_HAS_DSPI1 || defined(__DOXYGEN__) -#define SPC5_DSPI_1 (*(volatile struct spc5_dspi *)0xFFF94000UL) +#define SPC5_DSPI1 (*(struct spc5_dspi *)0xFFF94000UL) #endif -#if SPC5_HAS_DSP2 || defined(__DOXYGEN__) -#define SPC5_DSPI_2 (*(volatile struct spc5_dspi *)0xFFF98000UL) +#if SPC5_HAS_DSPI2 || defined(__DOXYGEN__) +#define SPC5_DSPI2 (*(struct spc5_dspi *)0xFFF98000UL) #endif #if SPC5_HAS_DSPI3 || defined(__DOXYGEN__) -#define SPC5_DSPI_3 (*(volatile struct spc5_dspi *)0xFFF9C000UL) +#define SPC5_DSPI3 (*(struct spc5_dspi *)0xFFF9C000UL) #endif /** @} */ diff --git a/os/hal/platforms/SPC5xx/DSPI_v1/spi_lld.c b/os/hal/platforms/SPC5xx/DSPI_v1/spi_lld.c index 738457ac6..db4865ffe 100644 --- a/os/hal/platforms/SPC5xx/DSPI_v1/spi_lld.c +++ b/os/hal/platforms/SPC5xx/DSPI_v1/spi_lld.c @@ -31,10 +31,40 @@ #if HAL_USE_SPI || defined(__DOXYGEN__) +/* Some forward declarations.*/ +static void spi_serve_rx_irq(edma_channel_t channel, void *p); +static void spi_serve_dma_error_irq(edma_channel_t channel, + void *p, + uint32_t esr); + /*===========================================================================*/ /* Driver local definitions. */ /*===========================================================================*/ +/* Enforced MCR bits.*/ +#define DSPI_MCR_ENFORCED_BITS (SPC5_MCR_MSTR) + +/* Excluded MCR bits.*/ +#define DSPI_MCR_EXCLUDED_BITS (SPC5_MCR_CONT_SCKE | \ + SPC5_MCR_DCONF_MASK | \ + SPC5_MCR_ROOE | \ + SPC5_MCR_MDIS | \ + SPC5_MCR_DIS_TXF | \ + SPC5_MCR_DIS_RXF | \ + SPC5_MCR_CLR_TXF | \ + SPC5_MCR_CLR_RXF | \ + SPC5_MCR_HALT) + +/* Excluded PUSHR bits.*/ +#define DSPI_PUSHR_EXCLUDED_BITS (SPC5_PUSHR_CTAS_MASK | \ + SPC5_PUSHR_EOQ | \ + SPC5_PUSHR_TXDATA_MASK) + +#define DSPI_PUSHR8_ADDRESS(spip) (((uint32_t)&(spip)->dspi->PUSHR.R) + 3) +#define DSPI_PUSHR16_ADDRESS(spip) (((uint32_t)&(spip)->dspi->PUSHR.R) + 2) +#define DSPI_POPR8_ADDRESS(spip) (((uint32_t)&(spip)->dspi->POPR.R) + 3) +#define DSPI_POPR16_ADDRESS(spip) (((uint32_t)&(spip)->dspi->POPR.R) + 2) + /*===========================================================================*/ /* Driver exported variables. */ /*===========================================================================*/ @@ -42,18 +72,203 @@ /** * @brief SPID1 driver identifier. */ -#if SPC5_SPI_USE_DSPI1 || defined(__DOXYGEN__) +#if SPC5_SPI_USE_DSPI0 || defined(__DOXYGEN__) SPIDriver SPID1; #endif +/** + * @brief SPID2 driver identifier. + */ +#if SPC5_SPI_USE_DSPI1 || defined(__DOXYGEN__) +SPIDriver SPID2; +#endif + +/** + * @brief SPID3 driver identifier. + */ +#if SPC5_SPI_USE_DSPI2 || defined(__DOXYGEN__) +SPIDriver SPID3; +#endif + +/** + * @brief SPID4 driver identifier. + */ +#if SPC5_SPI_USE_DSPI3 || defined(__DOXYGEN__) +SPIDriver SPID4; +#endif + /*===========================================================================*/ /* Driver local variables and types. */ /*===========================================================================*/ +#if SPC5_SPI_USE_DSPI0 || defined(__DOXYGEN__) +/** + * @brief DMA configuration for DSPI0 TX. + */ +static const edma_channel_config_t spi_dspi0_tx_dma_config = { + SPC5_DSPI0_TX_DMA_DEV_ID, SPC5_SPI_DSPI0_DMA_PRIO, SPC5_SPI_DSPI0_DMA_PRIO, + NULL, spi_serve_dma_error_irq, &SPID1 +}; + +/** + * @brief DMA configuration for DSPI0 RX. + */ +static const edma_channel_config_t spi_dspi0_rx_dma_config = { + SPC5_DSPI0_TX_DMA_DEV_ID, SPC5_SPI_DSPI0_DMA_PRIO, SPC5_SPI_DSPI0_DMA_PRIO, + spi_serve_rx_irq, spi_serve_dma_error_irq, &SPID1 +}; +#endif /* SPC5_SPI_USE_DSPI0 */ + +#if SPC5_SPI_USE_DSPI1 || defined(__DOXYGEN__) +/** + * @brief DMA configuration for DSPI1 TX. + */ +static const edma_channel_config_t spi_dspi1_tx_dma_config = { + SPC5_DSPI1_TX_DMA_DEV_ID, SPC5_SPI_DSPI1_DMA_PRIO, SPC5_SPI_DSPI1_DMA_PRIO, + NULL, spi_serve_dma_error_irq, &SPID2 +}; + +/** + * @brief DMA configuration for DSPI1 RX. + */ +static const edma_channel_config_t spi_dspi1_rx_dma_config = { + SPC5_DSPI1_TX_DMA_DEV_ID, SPC5_SPI_DSPI1_DMA_PRIO, SPC5_SPI_DSPI1_DMA_PRIO, + spi_serve_rx_irq, spi_serve_dma_error_irq, &SPID2 +}; +#endif /* SPC5_SPI_USE_DSPI1 */ + +#if SPC5_SPI_USE_DSPI2 || defined(__DOXYGEN__) +/** + * @brief DMA configuration for DSPI2 TX. + */ +static const edma_channel_config_t spi_dspi2_tx_dma_config = { + SPC5_DSPI2_TX_DMA_DEV_ID, SPC5_SPI_DSPI2_DMA_PRIO, SPC5_SPI_DSPI2_DMA_PRIO, + NULL, spi_serve_dma_error_irq, &SPID3 +}; + +/** + * @brief DMA configuration for DSPI2 RX. + */ +static const edma_channel_config_t spi_dspi2_rx_dma_config = { + SPC5_DSPI2_TX_DMA_DEV_ID, SPC5_SPI_DSPI2_DMA_PRIO, SPC5_SPI_DSPI2_DMA_PRIO, + spi_serve_rx_irq, spi_serve_dma_error_irq, &SPID3 +}; +#endif /* SPC5_SPI_USE_DSPI2 */ + +#if SPC5_SPI_USE_DSPI3 || defined(__DOXYGEN__) +/** + * @brief DMA configuration for DSPI3 TX. + */ +static const edma_channel_config_t spi_dspi3_tx_dma_config = { + SPC5_DSPI3_TX_DMA_DEV_ID, SPC5_SPI_DSPI3_DMA_PRIO, SPC5_SPI_DSPI3_DMA_PRIO, + NULL, spi_serve_dma_error_irq, &SPID4 +}; + +/** + * @brief DMA configuration for DSPI3 RX. + */ +static const edma_channel_config_t spi_dspi3_rx_dma_config = { + SPC5_DSPI3_TX_DMA_DEV_ID, SPC5_SPI_DSPI3_DMA_PRIO, SPC5_SPI_DSPI3_DMA_PRIO, + spi_serve_rx_irq, spi_serve_dma_error_irq, &SPID4 +}; +#endif /* SPC5_SPI_USE_DSPI3 */ + /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ +static void spi_start_dma_rx8(SPIDriver *spip, + size_t n, + uint8_t *rxbuf) { + + edmaChannelSetup(spip->rx_channel, /* channel. */ + DSPI_POPR8_ADDRESS(spip), /* src. */ + rxbuf, /* dst. */ + 0, /* soff, do not advance. */ + 1, /* doff, advance by one. */ + 0, /* ssize, 8 bits transfers. */ + 0, /* dsize, 8 bits transfers. */ + 1, /* nbytes, always one. */ + n, /* iter. */ + 0, /* slast. */ + 0, /* dlast. */ + EDMA_TCD_MODE_DREQ | EDMA_TCD_MODE_INT_END); /* mode.*/ + edmaChannelStart(spip->rx_channel); +} + +static void spi_start_dma_rx16(SPIDriver *spip, + size_t n, + uint16_t *rxbuf) { + + edmaChannelSetup(spip->rx_channel, /* channel. */ + DSPI_POPR16_ADDRESS(spip), /* src. */ + rxbuf, /* dst. */ + 0, /* soff, do not advance. */ + 2, /* doff, advance by two. */ + 1, /* ssize, 16 bits transfers.*/ + 1, /* dsize, 16 bits transfers.*/ + 2, /* nbytes, always two. */ + n, /* iter. */ + 0, /* slast, no source adjust. */ + 0, /* dlast. */ + EDMA_TCD_MODE_DREQ | EDMA_TCD_MODE_INT_END); /* mode.*/ + edmaChannelStart(spip->rx_channel); +} + +static void spi_start_dma_tx8(SPIDriver *spip, + size_t n, + const uint8_t *txbuf) { + + edmaChannelStart(spip->tx_channel); +} + +static void spi_start_dma_tx16(SPIDriver *spip, + size_t n, + const uint16_t *txbuf) { + + edmaChannelStart(spip->tx_channel); +} + +static void spi_tx_prefill8(SPIDriver *spip, + size_t n, + const uint8_t *txbuf) { + uint32_t cmd = spip->config->pushr & ~DSPI_PUSHR_EXCLUDED_BITS; + + do { + if (--n == 0) { + spip->dspi->PUSHR.R = SPC5_PUSHR_EOQ | cmd | (uint32_t)*txbuf; + break; + } + spip->dspi->PUSHR.R = cmd | (uint32_t)*txbuf; + txbuf++; + } while (TRUE); +} + +static void spi_tx_prefill16(SPIDriver *spip, + size_t n, + const uint16_t *txbuf) { + uint32_t cmd = spip->config->pushr & ~DSPI_PUSHR_EXCLUDED_BITS; + + do { + if (--n == 0) { + spip->dspi->PUSHR.R = SPC5_PUSHR_EOQ | cmd | (uint32_t)*txbuf; + break; + } + spip->dspi->PUSHR.R = cmd | (uint32_t)*txbuf; + txbuf++; + } while (TRUE); +} + +static void spi_serve_rx_irq(edma_channel_t channel, void *p) { + +} + +static void spi_serve_dma_error_irq(edma_channel_t channel, + void *p, + uint32_t esr) { + +} + /*===========================================================================*/ /* Driver interrupt handlers. */ /*===========================================================================*/ @@ -69,10 +284,51 @@ SPIDriver SPID1; */ void spi_lld_init(void) { -#if SPC5_SPI_USE_SPI1 + /* Enforcing low power mode for all DSPIs even if not used.*/ +#if SPC5_HAS_DSPI0 + SPC5_DSPI0.MCR.R = SPC5_MCR_MSTR | SPC5_MCR_MDIS; +#endif +#if SPC5_HAS_DSPI1 + SPC5_DSPI1.MCR.R = SPC5_MCR_MSTR | SPC5_MCR_MDIS; +#endif +#if SPC5_HAS_DSPI2 + SPC5_DSPI2.MCR.R = SPC5_MCR_MSTR | SPC5_MCR_MDIS; +#endif +#if SPC5_HAS_DSPI3 + SPC5_DSPI3.MCR.R = SPC5_MCR_MSTR | SPC5_MCR_MDIS; +#endif + +#if SPC5_SPI_USE_DSPI0 /* Driver initialization.*/ spiObjectInit(&SPID1); -#endif /* SPC5_SPI_USE_SPI1 */ + SPID1.dspi = &SPC5_DSPI0; + SPID1.tx_channel = EDMA_ERROR; + SPID1.rx_channel = EDMA_ERROR; +#endif /* SPC5_SPI_USE_DSPI0 */ + +#if SPC5_SPI_USE_DSPI1 + /* Driver initialization.*/ + spiObjectInit(&SPID2); + SPID2.dspi = &SPC5_DSPI1; + SPID2.tx_channel = EDMA_ERROR; + SPID2.rx_channel = EDMA_ERROR; +#endif /* SPC5_SPI_USE_DSPI1 */ + +#if SPC5_SPI_USE_DSPI2 + /* Driver initialization.*/ + spiObjectInit(&SPID3); + SPID3.dspi = &SPC5_DSPI2; + SPID3.tx_channel = EDMA_ERROR; + SPID3.rx_channel = EDMA_ERROR; +#endif /* SPC5_SPI_USE_DSPI2 */ + +#if SPC5_SPI_USE_DSPI03 + /* Driver initialization.*/ + spiObjectInit(&SPID4); + SPID4.dspi = &SPC5_DSPI3; + SPID4.tx_channel = EDMA_ERROR; + SPID4.rx_channel = EDMA_ERROR; +#endif /* SPC5_SPI_USE_DSPI3 */ } /** @@ -86,14 +342,45 @@ void spi_lld_start(SPIDriver *spip) { if (spip->state == SPI_STOP) { /* Enables the peripheral.*/ -#if SPC5_SPI_USE_SPI1 + +#if SPC5_SPI_USE_DSPI0 if (&SPID1 == spip) { + SPC5_DSPI0_ENABLE_CLOCK(); + spip->tx_channel = edmaChannelAllocate(&spi_dspi0_tx_dma_config); + spip->rx_channel = edmaChannelAllocate(&spi_dspi0_rx_dma_config); + } +#endif /* SPC5_SPI_USE_DSPI0 */ + +#if SPC5_SPI_USE_DSPI1 + if (&SPID2 == spip) { + SPC5_DSPI1_ENABLE_CLOCK(); + spip->tx_channel = edmaChannelAllocate(&spi_dspi1_tx_dma_config); + spip->rx_channel = edmaChannelAllocate(&spi_dspi1_rx_dma_config); + } +#endif /* SPC5_SPI_USE_DSPI1 */ +#if SPC5_SPI_USE_DSPI2 + if (&SPID3 == spip) { + SPC5_DSPI2_ENABLE_CLOCK(); + spip->tx_channel = edmaChannelAllocate(&spi_dspi2_tx_dma_config); + spip->rx_channel = edmaChannelAllocate(&spi_dspi2_rx_dma_config); } -#endif /* SPC5_SPI_USE_SPI1 */ +#endif /* SPC5_SPI_USE_DSPI2 */ + +#if SPC5_SPI_USE_DSPI3 + if (&SPID4 == spip) { + SPC5_DSPI3_ENABLE_CLOCK(); + spip->tx_channel = edmaChannelAllocate(&spi_dspi3_tx_dma_config); + spip->rx_channel = edmaChannelAllocate(&spi_dspi3_rx_dma_config); + } +#endif /* SPC5_SPI_USE_DSPI3 */ } /* Configures the peripheral.*/ - + spip->dspi->MCR.R = SPC5_MCR_MSTR | spip->config->mcr; + spip->dspi->CTAR[0].R = spip->config->ctar0; + spip->dspi->RSER.R = SPC5_RSER_EOQF_RE | SPC5_RSER_TFFF_DIRS | + SPC5_RSER_RFDF_DIRS; + spip->dspi->SR.R = spip->dspi->SR.R; } /** @@ -106,14 +393,40 @@ void spi_lld_start(SPIDriver *spip) { void spi_lld_stop(SPIDriver *spip) { if (spip->state == SPI_READY) { + /* Releases the allocated EDMA channels.*/ + edmaChannelRelease(spip->tx_channel); + edmaChannelRelease(spip->rx_channel); + /* Resets the peripheral.*/ + spip->dspi->CTAR[0].R = 0; + spip->dspi->RSER.R = 0; + spip->dspi->SR.R = spip->dspi->SR.R; + spip->dspi->MCR.R = SPC5_MCR_MSTR | SPC5_MCR_MDIS | + SPC5_MCR_CLR_TXF | SPC5_MCR_CLR_RXF; - /* Disables the peripheral.*/ -#if SPC5_SPI_USE_SPI1 +#if SPC5_SPI_USE_DSPI0 if (&SPID1 == spip) { + SPC5_DSPI0_DISABLE_CLOCK(); + } +#endif /* SPC5_SPI_USE_DSPI0 */ + +#if SPC5_SPI_USE_DSPI1 + if (&SPID2 == spip) { + SPC5_DSPI1_DISABLE_CLOCK(); + } +#endif /* SPC5_SPI_USE_DSPI1 */ + +#if SPC5_SPI_USE_DSPI2 + if (&SPID3 == spip) { + SPC5_DSPI2_DISABLE_CLOCK(); + } +#endif /* SPC5_SPI_USE_DSPI2 */ +#if SPC5_SPI_USE_DSPI3 + if (&SPID4 == spip) { + SPC5_DSPI3_DISABLE_CLOCK(); } -#endif /* SPC5_SPI_USE_SPI1 */ +#endif /* SPC5_SPI_USE_DSPI3 */ } } @@ -180,10 +493,36 @@ void spi_lld_ignore(SPIDriver *spip, size_t n) { void spi_lld_exchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf) { - (void)spip; - (void)n; - (void)txbuf; - (void)rxbuf; + /* DMAs require a different setup depending on the frame size.*/ + if (spip->dspi->CTAR[0].B.FMSZ < 8) { + /* Setting up the RX DMA channel.*/ + spi_start_dma_rx8(spip, n, rxbuf); + + if (n <= SPC5_DSPI_FIFO_DEPTH) { + /* If the total transfer size is smaller than the TX FIFO size then + the whole transmitted data is pushed here and the TX DMA is not + activated.*/ + spi_tx_prefill8(spip, n, txbuf); + } + else { + spi_start_dma_tx8(spip, n, txbuf); + } + } + else { + /* Setting up the RX DMA channel.*/ + spi_start_dma_rx16(spip, n, rxbuf); + + if (n <= SPC5_DSPI_FIFO_DEPTH) { + /* If the total transfer size is smaller than the TX FIFO size then + the whole transmitted data is pushed here and the TX DMA is not + activated.*/ + spi_tx_prefill16(spip, n, txbuf); + } + else { + spi_start_dma_tx16(spip, n, txbuf); + } + } + } diff --git a/os/hal/platforms/SPC5xx/DSPI_v1/spi_lld.h b/os/hal/platforms/SPC5xx/DSPI_v1/spi_lld.h index 1c61d8f03..7cf72047d 100644 --- a/os/hal/platforms/SPC5xx/DSPI_v1/spi_lld.h +++ b/os/hal/platforms/SPC5xx/DSPI_v1/spi_lld.h @@ -37,6 +37,73 @@ /* Driver constants. */ /*===========================================================================*/ +/** + * @name MCR register definitions + * @{ + */ +#define SPC5_MCR_MSTR (1U << 31) +#define SPC5_MCR_CONT_SCKE (1U << 30) +#define SPC5_MCR_DCONF_MASK (3U << 28) +#define SPC5_MCR_FRZ (1U << 27) +#define SPC5_MCR_MTFE (1U << 26) +#define SPC5_MCR_PCSSE (1U << 25) +#define SPC5_MCR_ROOE (1U << 24) +#define SPC5_MCR_PCSIS7 (1U << 23) +#define SPC5_MCR_PCSIS6 (1U << 22) +#define SPC5_MCR_PCSIS5 (1U << 21) +#define SPC5_MCR_PCSIS4 (1U << 20) +#define SPC5_MCR_PCSIS3 (1U << 19) +#define SPC5_MCR_PCSIS2 (1U << 18) +#define SPC5_MCR_PCSIS1 (1U << 17) +#define SPC5_MCR_PCSIS0 (1U << 16) +#define SPC5_MCR_DOZE (1U << 15) +#define SPC5_MCR_MDIS (1U << 14) +#define SPC5_MCR_DIS_TXF (1U << 13) +#define SPC5_MCR_DIS_RXF (1U << 12) +#define SPC5_MCR_CLR_TXF (1U << 11) +#define SPC5_MCR_CLR_RXF (1U << 10) +#define SPC5_MCR_SMPL_PT_MASK (3U << 8) +#define SPC5_MCR_SMPL_PT(n) ((n) << 8) +#define SPC5_MCR_FCPCS (1U << 2) +#define SPC5_MCR_PES (1U << 1) +#define SPC5_MCR_HALT (1U << 0) +/** @} */ + +/** + * @name RSER register definitions + * @{ + */ +#define SPC5_RSER_TCF_RE (1U << 31) +#define SPC5_RSER_DSITCF_RE (1U << 29) +#define SPC5_RSER_EOQF_RE (1U << 28) +#define SPC5_RSER_TFUF_RE (1U << 27) +#define SPC5_RSER_SPITCF_RE (1U << 26) +#define SPC5_RSER_TFFF_RE (1U << 25) +#define SPC5_RSER_TFFF_DIRS (1U << 24) +#define SPC5_RSER_DPEF_RE (1U << 22) +#define SPC5_RSER_SPEF_RE (1U << 21) +#define SPC5_RSER_DDIF_RE (1U << 20) +#define SPC5_RSER_RFOF_RE (1U << 19) +#define SPC5_RSER_RFDF_RE (1U << 17) +#define SPC5_RSER_RFDF_DIRS (1U << 16) +/** @} */ + +/** + * @name PUSHR register definitions + * @{ + */ +#define SPC5_PUSHR_CONT (1U << 31) +#define SPC5_PUSHR_CTAS_MASK (3U << 28) +#define SPC5_PUSHR_CTAS(n) ((n) << 29) +#define SPC5_PUSHR_EOQ (1U << 27) +#define SPC5_PUSHR_CTCNT (1U << 26) +#define SPC5_PUSHR_MASC (1U << 25) +#define SPC5_PUSHR_MCSC (1U << 24) +#define SPC5_PUSHR_PCS_MASK (255U << 16) +#define SPC5_PUSHR_PCS(n) ((1U << (n)) << 16) +#define SPC5_PUSHR_TXDATA_MASK (0xFFFFU << 0) +/** @} */ + /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ @@ -46,18 +113,118 @@ * @{ */ /** - * @brief SPI driver enable switch. + * @brief SPID1 driver enable switch. + * @details If set to @p TRUE the support for DSPI0 is included. + */ +#if !defined(SPC5_SPI_USE_DSPI0) || defined(__DOXYGEN__) +#define SPC5_SPI_USE_DSPI0 FALSE +#endif + +/** + * @brief SPID2 driver enable switch. * @details If set to @p TRUE the support for DSPI1 is included. */ #if !defined(SPC5_SPI_USE_DSPI1) || defined(__DOXYGEN__) #define SPC5_SPI_USE_DSPI1 FALSE #endif +/** + * @brief SPID3 driver enable switch. + * @details If set to @p TRUE the support for DSPI2 is included. + */ +#if !defined(SPC5_SPI_USE_DSPI2) || defined(__DOXYGEN__) +#define SPC5_SPI_USE_DSPI2 FALSE +#endif + +/** + * @brief SPID4 driver enable switch. + * @details If set to @p TRUE the support for DSPI3 is included. + */ +#if !defined(SPC5_SPI_USE_DSPI3) || defined(__DOXYGEN__) +#define SPC5_SPI_USE_DSPI3 FALSE +#endif + +/** + * @brief DSPI0 DMA priority. + */ +#if !defined(SPC5_SPI_DSPI0_DMA_PRIO) || defined(__DOXYGEN__) +#define SPC5_SPI_DSPI0_DMA_PRIO 10 +#endif + +/** + * @brief DSPI1 DMA priority. + */ +#if !defined(SPC5_SPI_DSPI1_DMA_PRIO) || defined(__DOXYGEN__) +#define SPC5_SPI_DSPI1_DMA_PRIO 10 +#endif + +/** + * @brief DSPI2 DMA priority. + */ +#if !defined(SPC5_SPI_DSPI2_DMA_PRIO) || defined(__DOXYGEN__) +#define SPC5_SPI_DSPI2_DMA_PRIO 10 +#endif + +/** + * @brief DSPI3 DMA priority. + */ +#if !defined(SPC5_SPI_DSPI3_DMA_PRIO) || defined(__DOXYGEN__) +#define SPC5_SPI_DSPI3_DMA_PRIO 10 +#endif + +/** + * @brief DSPI0 DMA IRQ priority. + */ +#if !defined(SPC5_SPI_DSPI0_DMA_IRQ_PRIO) || defined(__DOXYGEN__) +#define SPC5_SPI_DSPI0_DMA_IRQ_PRIO 10 +#endif + +/** + * @brief DSPI1 DMA IRQ priority. + */ +#if !defined(SPC5_SPI_DSPI1_DMA_IRQ_PRIO) || defined(__DOXYGEN__) +#define SPC5_SPI_DSPI1_DMA_IRQ_PRIO 10 +#endif + +/** + * @brief DSPI2 DMA IRQ priority. + */ +#if !defined(SPC5_SPI_DSPI2_DMA_IRQ_PRIO) || defined(__DOXYGEN__) +#define SPC5_SPI_DSPI2_DMA_IRQ_PRIO 10 +#endif + +/** + * @brief DSPI3 DMA IRQ priority. + */ +#if !defined(SPC5_SPI_DSPI3_DMA_IRQ_PRIO) || defined(__DOXYGEN__) +#define SPC5_SPI_DSPI3_DMA_IRQ_PRIO 10 +#endif /** @} */ /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ +#if SPC5_SPI_USE_DSPI0 && !SPC5_HAS_DSPI0 +#error "DSPI0 not present in the selected device" +#endif + +#if SPC5_SPI_USE_DSPI1 && !SPC5_HAS_DSPI1 +#error "DSPI1 not present in the selected device" +#endif + +#if SPC5_SPI_USE_DSPI2 && !SPC5_HAS_DSPI2 +#error "DSPI2 not present in the selected device" +#endif + +#if SPC5_SPI_USE_DSPI3 && !SPC5_HAS_DSPI3 +#error "DSPI3 not present in the selected device" +#endif + +#if !SPC5_SPI_USE_DSPI0 && !SPC5_SPI_USE_DSPI1 && \ + !SPC5_SPI_USE_DSPI2 && !SPC5_SPI_USE_DSPI3 +#error "SPI driver activated but no DSPI peripheral assigned" +#endif + /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ @@ -86,6 +253,22 @@ typedef struct { */ spicallback_t end_cb; /* End of the mandatory fields.*/ + /** + * @brief DSPI MCR value for this session. + * @note Some bits are ignored: CONT_SCKE, DCONF, ROOE, MDIS, DIS_TXF, + * DIS_RXF, CLR_TXF, CLR_RXF, HALT. + */ + uint32_t mcr; + /** + * @brief DSPI CTAR0 value for this session. + */ + uint32_t ctar0; + /** + * @brief DSPI PUSHR command for this session. + * @note Only CTAR0 can be referenced, the other CTARs are not + * initialized. The data part must be left to zero. + */ + uint32_t pushr; } SPIConfig; /** @@ -122,6 +305,18 @@ struct SPIDriver { SPI_DRIVER_EXT_FIELDS #endif /* End of the mandatory fields.*/ + /** + * @brief Pointer to the DSPI registers block. + */ + struct spc5_dspi *dspi; + /** + * @brief EDMA channel used for transmit. + */ + edma_channel_t tx_channel; + /** + * @brief EDMA channel used for receive. + */ + edma_channel_t rx_channel; }; /*===========================================================================*/ @@ -132,10 +327,22 @@ struct SPIDriver { /* External declarations. */ /*===========================================================================*/ -#if SPC5_SPI_USE_DSPI1 && !defined(__DOXYGEN__) +#if SPC5_SPI_USE_DSPI0 && !defined(__DOXYGEN__) extern SPIDriver SPID1; #endif +#if SPC5_SPI_USE_DSPI1 && !defined(__DOXYGEN__) +extern SPIDriver SPID2; +#endif + +#if SPC5_SPI_USE_DSPI2 && !defined(__DOXYGEN__) +extern SPIDriver SPID3; +#endif + +#if SPC5_SPI_USE_DSPI3 && !defined(__DOXYGEN__) +extern SPIDriver SPID4; +#endif + #ifdef __cplusplus extern "C" { #endif -- cgit v1.2.3