Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:54

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSBSPsPowerPCMPC55XX
0007  *
0008  * @brief Enhanced Direct Memory Access (eDMA).
0009  */
0010 
0011 /*
0012  * Copyright (C) 2008, 2013 embedded brains GmbH & Co. KG
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #ifndef LIBCPU_POWERPC_MPC55XX_EDMA_H
0037 #define LIBCPU_POWERPC_MPC55XX_EDMA_H
0038 
0039 #include <mpc55xx/regs.h>
0040 
0041 #include <rtems.h>
0042 #include <rtems/chain.h>
0043 
0044 #ifdef __cplusplus
0045 extern "C" {
0046 #endif /* __cplusplus */
0047 
0048 #if MPC55XX_CHIP_FAMILY == 551
0049   #define EDMA_CHANNEL_COUNT 16U
0050 #elif MPC55XX_CHIP_FAMILY == 564
0051   #define EDMA_CHANNEL_COUNT 16U
0052 #elif MPC55XX_CHIP_FAMILY == 567
0053   #define EDMA_CHANNEL_COUNT 96U
0054 #else
0055   #define EDMA_CHANNEL_COUNT 64U
0056 #endif
0057 
0058 #define EDMA_MODULE_COUNT ((EDMA_CHANNEL_COUNT + 63U) / 64U)
0059 
0060 #define EDMA_CHANNELS_PER_MODULE 64U
0061 
0062 #if EDMA_MODULE_COUNT == 1
0063   #define EDMA_TCD_BY_CHANNEL_INDEX(channel_index) \
0064     (&EDMA.TCD[(channel_index)])
0065 #elif EDMA_MODULE_COUNT == 2
0066   #define EDMA_TCD_BY_CHANNEL_INDEX(channel_index) \
0067     ((channel_index) < EDMA_CHANNELS_PER_MODULE ? \
0068       &EDMA_A.TCD[(channel_index)] \
0069         : &EDMA_B.TCD[(channel_index) - EDMA_CHANNELS_PER_MODULE])
0070 #else
0071   #error "unsupported module count"
0072 #endif
0073 
0074 /* FIXME: These values are only valid for the MPC5566 and MPC5674F */
0075 typedef enum {
0076   EDMA_EQADC_A_FISR0_CFFF0 = 0,
0077   EDMA_EQADC_A_FISR0_RFDF0 = 1,
0078   EDMA_EQADC_A_FISR1_CFFF1 = 2,
0079   EDMA_EQADC_A_FISR1_RFDF1 = 3,
0080   EDMA_EQADC_A_FISR2_CFFF2 = 4,
0081   EDMA_EQADC_A_FISR2_RFDF2 = 5,
0082   EDMA_EQADC_A_FISR3_CFFF3 = 6,
0083   EDMA_EQADC_A_FISR3_RFDF3 = 7,
0084   EDMA_EQADC_A_FISR4_CFFF4 = 8,
0085   EDMA_EQADC_A_FISR4_RFDF4 = 9,
0086   EDMA_EQADC_A_FISR5_CFFF5 = 10,
0087   EDMA_EQADC_A_FISR5_RFDF5 = 11,
0088   EDMA_DSPI_B_SR_TFFF = 12,
0089   EDMA_DSPI_B_SR_RFDF = 13,
0090   EDMA_DSPI_C_SR_TFFF = 14,
0091   EDMA_DSPI_C_SR_RFDF = 15,
0092   EDMA_DSPI_D_SR_TFFF = 16,
0093   EDMA_DSPI_D_SR_RFDF = 17,
0094   EDMA_ESCI_A_COMBTX = 18,
0095   EDMA_ESCI_A_COMBRX = 19,
0096   EDMA_EMIOS_GFR_F0 = 20,
0097   EDMA_EMIOS_GFR_F1 = 21,
0098   EDMA_EMIOS_GFR_F2 = 22,
0099   EDMA_EMIOS_GFR_F3 = 23,
0100   EDMA_EMIOS_GFR_F4 = 24,
0101   EDMA_EMIOS_GFR_F8 = 25,
0102   EDMA_EMIOS_GFR_F9 = 26,
0103   EDMA_ETPU_CDTRSR_A_DTRS0 = 27,
0104   EDMA_ETPU_CDTRSR_A_DTRS1 = 28,
0105   EDMA_ETPU_CDTRSR_A_DTRS2 = 29,
0106   EDMA_ETPU_CDTRSR_A_DTRS14 = 30,
0107   EDMA_ETPU_CDTRSR_A_DTRS15 = 31,
0108   EDMA_DSPI_A_SR_TFFF = 32,
0109   EDMA_DSPI_A_SR_RFDF = 33,
0110   EDMA_ESCI_B_COMBTX = 34,
0111   EDMA_ESCI_B_COMBRX = 35,
0112   EDMA_EMIOS_GFR_F6 = 36,
0113   EDMA_EMIOS_GFR_F7 = 37,
0114   EDMA_EMIOS_GFR_F10 = 38,
0115   EDMA_EMIOS_GFR_F11 = 39,
0116   EDMA_EMIOS_GFR_F16 = 40,
0117   EDMA_EMIOS_GFR_F17 = 41,
0118   EDMA_EMIOS_GFR_F18 = 42,
0119   EDMA_EMIOS_GFR_F19 = 43,
0120   EDMA_ETPU_CDTRSR_A_DTRS12 = 44,
0121   EDMA_ETPU_CDTRSR_A_DTRS13 = 45,
0122   EDMA_ETPU_CDTRSR_A_DTRS28 = 46,
0123   EDMA_ETPU_CDTRSR_A_DTRS29 = 47,
0124   EDMA_SIU_EISR_EIF0 = 48,
0125   EDMA_SIU_EISR_EIF1 = 49,
0126   EDMA_SIU_EISR_EIF2 = 50,
0127   EDMA_SIU_EISR_EIF3 = 51,
0128   EDMA_ETPU_CDTRSR_B_DTRS0 = 52,
0129   EDMA_ETPU_CDTRSR_B_DTRS1 = 53,
0130   EDMA_ETPU_CDTRSR_B_DTRS2 = 54,
0131   EDMA_ETPU_CDTRSR_B_DTRS3 = 55,
0132   EDMA_ETPU_CDTRSR_B_DTRS12 = 56,
0133   EDMA_ETPU_CDTRSR_B_DTRS13 = 57,
0134   EDMA_ETPU_CDTRSR_B_DTRS14 = 58,
0135   EDMA_ETPU_CDTRSR_B_DTRS15 = 59,
0136   EDMA_ETPU_CDTRSR_B_DTRS28 = 60,
0137   EDMA_ETPU_CDTRSR_B_DTRS29 = 61,
0138   EDMA_ETPU_CDTRSR_B_DTRS30 = 62,
0139   EDMA_ETPU_CDTRSR_B_DTRS31 = 63
0140   #if MPC55XX_CHIP_FAMILY == 567
0141     ,
0142     EDMA_EQADC_B_FISR0_CFFF0 = 64 + 0,
0143     EDMA_EQADC_B_FISR0_RFDF0 = 64 + 1,
0144     EDMA_EQADC_B_FISR1_CFFF1 = 64 + 2,
0145     EDMA_EQADC_B_FISR1_RFDF1 = 64 + 3,
0146     EDMA_EQADC_B_FISR2_CFFF2 = 64 + 4,
0147     EDMA_EQADC_B_FISR2_RFDF2 = 64 + 5,
0148     EDMA_EQADC_B_FISR3_CFFF3 = 64 + 6,
0149     EDMA_EQADC_B_FISR3_RFDF3 = 64 + 7,
0150     EDMA_EQADC_B_FISR4_CFFF4 = 64 + 8,
0151     EDMA_EQADC_B_FISR4_RFDF4 = 64 + 9,
0152     EDMA_EQADC_B_FISR5_CFFF5 = 64 + 10,
0153     EDMA_EQADC_B_FISR5_RFDF5 = 64 + 11,
0154     EDMA_DECFILTER_A_IB = 64 + 12,
0155     EDMA_DECFILTER_A_OB = 64 + 13,
0156     EDMA_DECFILTER_B_IB = 64 + 14,
0157     EDMA_DECFILTER_B_OB = 64 + 15,
0158     EDMA_DECFILTER_C_IB = 64 + 16,
0159     EDMA_DECFILTER_C_OB = 64 + 17,
0160     EDMA_DECFILTER_D_IB = 64 + 18,
0161     EDMA_DECFILTER_D_OB = 64 + 19,
0162     EDMA_DECFILTER_E_IB = 64 + 20,
0163     EDMA_DECFILTER_E_OB = 64 + 21,
0164     EDMA_DECFILTER_F_IB = 64 + 22,
0165     EDMA_DECFILTER_F_OB = 64 + 23,
0166     EDMA_DECFILTER_G_IB = 64 + 24,
0167     EDMA_DECFILTER_G_OB = 64 + 25,
0168     EDMA_DECFILTER_H_IB = 64 + 26,
0169     EDMA_DECFILTER_H_OB = 64 + 27
0170   #endif
0171 } edma_channel;
0172 
0173 typedef struct edma_channel_context {
0174   rtems_chain_node node;
0175   volatile struct tcd_t *edma_tcd;
0176   void (*done)(struct edma_channel_context *, uint32_t);
0177 } edma_channel_context;
0178 
0179 void mpc55xx_edma_init(void);
0180 
0181 /**
0182  * @brief Obtains an eDMA channel.
0183  *
0184  * @retval RTEMS_SUCCESSFUL Successful operation.
0185  * @retval RTEMS_RESOURCE_IN_USE The channel is already in use.
0186  */
0187 rtems_status_code mpc55xx_edma_obtain_channel_by_tcd(
0188   volatile struct tcd_t *edma_tcd
0189 );
0190 
0191 void mpc55xx_edma_release_channel_by_tcd(volatile struct tcd_t *edma_tcd);
0192 
0193 /**
0194  * @brief Obtains an eDMA channel and registers the channel context.
0195  *
0196  * The done handler of the channel context will be called
0197  * - during minor or major loop completions if interrupts are enabled in the
0198  *   corresponding TCD, or
0199  * - in case a channel error occurs.
0200  *
0201  * An error status value not equal to zero indicates an error.
0202  *
0203  * @retval RTEMS_SUCCESSFUL Successful operation.
0204  * @retval RTEMS_RESOURCE_IN_USE The channel is already in use.
0205  * @retval RTEMS_IO_ERROR Unable to install interrupt handler for this channel.
0206  */
0207 rtems_status_code mpc55xx_edma_obtain_channel(
0208   edma_channel_context *ctx,
0209   unsigned irq_priority
0210 );
0211 
0212 void mpc55xx_edma_release_channel(edma_channel_context *ctx);
0213 
0214 /**
0215  * @brief Copies a source TCD to an eDMA TCD.
0216  *
0217  * The DONE flag of the eDMA TCD is cleared before the actual copy operation.
0218  * This enables the setting of channel link or scatter/gather options.
0219  *
0220  * This function can be used to start the channel if the START flags is
0221  * set in the source TCD.
0222  */
0223 void mpc55xx_edma_copy(
0224   volatile struct tcd_t *edma_tcd,
0225   const struct tcd_t *source_tcd
0226 );
0227 
0228 /**
0229  * @brief Copies a source TCD to an eDMA TCD and enables hardware requests.
0230  *
0231  * The DONE flag of the eDMA TCD is cleared before the actual copy operation.
0232  * This enables the setting of channel link or scatter/gather options.
0233  */
0234 void mpc55xx_edma_copy_and_enable_hardware_requests(
0235   volatile struct tcd_t *edma_tcd,
0236   const struct tcd_t *source_tcd
0237 );
0238 
0239 void mpc55xx_edma_sg_link(
0240   volatile struct tcd_t *edma_tcd,
0241   const struct tcd_t *source_tcd
0242 );
0243 
0244 static inline volatile struct EDMA_tag *mpc55xx_edma_by_tcd(
0245   volatile struct tcd_t *edma_tcd
0246 )
0247 {
0248   return (volatile struct EDMA_tag *)
0249     ((uintptr_t) edma_tcd & ~(uintptr_t) 0x1fff);
0250 }
0251 
0252 static inline unsigned mpc55xx_edma_channel_by_tcd(
0253   volatile struct tcd_t *edma_tcd
0254 )
0255 {
0256   volatile struct EDMA_tag *edma = mpc55xx_edma_by_tcd(edma_tcd);
0257 
0258   return edma_tcd - &edma->TCD[0];
0259 }
0260 
0261 static inline void mpc55xx_edma_enable_hardware_requests(
0262   volatile struct tcd_t *edma_tcd
0263 )
0264 {
0265   volatile struct EDMA_tag *edma = mpc55xx_edma_by_tcd(edma_tcd);
0266   unsigned channel = edma_tcd - &edma->TCD[0];
0267 
0268   edma->SERQR.R = (uint8_t) channel;
0269 }
0270 
0271 static inline void mpc55xx_edma_disable_hardware_requests(
0272   volatile struct tcd_t *edma_tcd
0273 )
0274 {
0275   volatile struct EDMA_tag *edma = mpc55xx_edma_by_tcd(edma_tcd);
0276   unsigned channel = edma_tcd - &edma->TCD[0];
0277 
0278   edma->CERQR.R = (uint8_t) channel;
0279 }
0280 
0281 static inline void mpc55xx_edma_enable_error_interrupts(
0282   volatile struct tcd_t *edma_tcd
0283 )
0284 {
0285   volatile struct EDMA_tag *edma = mpc55xx_edma_by_tcd(edma_tcd);
0286   unsigned channel = edma_tcd - &edma->TCD[0];
0287 
0288   edma->SEEIR.R = (uint8_t) channel;
0289 }
0290 
0291 static inline void mpc55xx_edma_disable_error_interrupts(
0292   volatile struct tcd_t *edma_tcd
0293 )
0294 {
0295   volatile struct EDMA_tag *edma = mpc55xx_edma_by_tcd(edma_tcd);
0296   unsigned channel = edma_tcd - &edma->TCD[0];
0297 
0298   edma->CEEIR.R = (uint8_t) channel;
0299 }
0300 
0301 static inline void mpc55xx_edma_set_start(
0302   volatile struct tcd_t *edma_tcd
0303 )
0304 {
0305   volatile struct EDMA_tag *edma = mpc55xx_edma_by_tcd(edma_tcd);
0306   unsigned channel = edma_tcd - &edma->TCD[0];
0307 
0308   edma->SSBR.R = (uint8_t) channel;
0309 }
0310 
0311 static inline void mpc55xx_edma_clear_done(
0312   volatile struct tcd_t *edma_tcd
0313 )
0314 {
0315   volatile struct EDMA_tag *edma = mpc55xx_edma_by_tcd(edma_tcd);
0316   unsigned channel = edma_tcd - &edma->TCD[0];
0317 
0318   edma->CDSBR.R = (uint8_t) channel;
0319 }
0320 
0321 static inline void mpc55xx_edma_clear_interrupts(
0322   volatile struct tcd_t *edma_tcd
0323 )
0324 {
0325   volatile struct EDMA_tag *edma = mpc55xx_edma_by_tcd(edma_tcd);
0326   unsigned channel = edma_tcd - &edma->TCD[0];
0327 
0328   edma->CIRQR.R = (uint8_t) channel;
0329 }
0330 
0331 static inline bool mpc55xx_edma_is_done(
0332   volatile struct tcd_t *edma_tcd
0333 )
0334 {
0335   return edma_tcd->BMF.B.DONE;
0336 }
0337 
0338 #ifdef __cplusplus
0339 }
0340 #endif /* __cplusplus */
0341 
0342 #endif /* LIBCPU_POWERPC_MPC55XX_EDMA_H */