diff --git a/arch/arm/src/imxrt/hardware/imxrt_edma.h b/arch/arm/src/imxrt/hardware/imxrt_edma.h index b46ddd5889..fd3da13e27 100644 --- a/arch/arm/src/imxrt/hardware/imxrt_edma.h +++ b/arch/arm/src/imxrt/hardware/imxrt_edma.h @@ -568,39 +568,6 @@ #define IMXRT_EDMA_DCHPRI30 (IMXRT_EDMA_BASE + IMXRT_EDMA_DCHPRI30_OFFSET) #define IMXRT_EDMA_DCHPRI31 (IMXRT_EDMA_BASE + IMXRT_EDMA_DCHPRI31_OFFSET) -#define IMXRT_EDMA_DCHPRI3_OFFSET 0x0100 /* Channel 3 Priority */ -#define IMXRT_EDMA_DCHPRI2_OFFSET 0x0101 /* Channel 2 Priority */ -#define IMXRT_EDMA_DCHPRI1_OFFSET 0x0102 /* Channel 1 Priority */ -#define IMXRT_EDMA_DCHPRI0_OFFSET 0x0103 /* Channel 0 Priority */ -#define IMXRT_EDMA_DCHPRI7_OFFSET 0x0104 /* Channel 7 Priority */ -#define IMXRT_EDMA_DCHPRI6_OFFSET 0x0105 /* Channel 6 Priority */ -#define IMXRT_EDMA_DCHPRI5_OFFSET 0x0106 /* Channel 5 Priority */ -#define IMXRT_EDMA_DCHPRI4_OFFSET 0x0107 /* Channel 4 Priority */ -#define IMXRT_EDMA_DCHPRI11_OFFSET 0x0108 /* Channel 11 Priority */ -#define IMXRT_EDMA_DCHPRI10_OFFSET 0x0109 /* Channel 10 Priority */ -#define IMXRT_EDMA_DCHPRI9_OFFSET 0x010a /* Channel 9 Priority */ -#define IMXRT_EDMA_DCHPRI8_OFFSET 0x010b /* Channel 8 Priority */ -#define IMXRT_EDMA_DCHPRI15_OFFSET 0x010c /* Channel 15 Priority */ -#define IMXRT_EDMA_DCHPRI14_OFFSET 0x010d /* Channel 14 Priority */ -#define IMXRT_EDMA_DCHPRI13_OFFSET 0x010e /* Channel 13 Priority */ -#define IMXRT_EDMA_DCHPRI12_OFFSET 0x010f /* Channel 12 Priority */ -#define IMXRT_EDMA_DCHPRI19_OFFSET 0x0110 /* Channel 19 Priority */ -#define IMXRT_EDMA_DCHPRI18_OFFSET 0x0111 /* Channel 18 Priority */ -#define IMXRT_EDMA_DCHPRI17_OFFSET 0x0112 /* Channel 17 Priority */ -#define IMXRT_EDMA_DCHPRI16_OFFSET 0x0113 /* Channel 16 Priority */ -#define IMXRT_EDMA_DCHPRI23_OFFSET 0x0114 /* Channel 23 Priority */ -#define IMXRT_EDMA_DCHPRI22_OFFSET 0x0115 /* Channel 22 Priority */ -#define IMXRT_EDMA_DCHPRI21_OFFSET 0x0116 /* Channel 21 Priority */ -#define IMXRT_EDMA_DCHPRI20_OFFSET 0x0117 /* Channel 20 Priority */ -#define IMXRT_EDMA_DCHPRI27_OFFSET 0x0118 /* Channel 27 Priority */ -#define IMXRT_EDMA_DCHPRI26_OFFSET 0x0119 /* Channel 26 Priority */ -#define IMXRT_EDMA_DCHPRI25_OFFSET 0x011a /* Channel 25 Priority */ -#define IMXRT_EDMA_DCHPRI24_OFFSET 0x011b /* Channel 24 Priority */ -#define IMXRT_EDMA_DCHPRI31_OFFSET 0x011c /* Channel 31 Priority */ -#define IMXRT_EDMA_DCHPRI30_OFFSET 0x011d /* Channel 30 Priority */ -#define IMXRT_EDMA_DCHPRI29_OFFSET 0x011e /* Channel 29 Priority */ -#define IMXRT_EDMA_DCHPRI28_OFFSET 0x011f /* Channel 28 Priority */ - /* Transfer Control Descriptor (TCD) */ #define IMXRT_EDMA_TCD_BASE(n) (IMXRT_EDMA_BASE + IMXRT_EDMA_TCD_OFFSET(n)) @@ -1113,7 +1080,6 @@ #define EDMA_CERR_NOP (1 << 7) /* Bit 7: No Op enable */ /* Clear Interrupt Request */ -#define EDMA_CINT_ #define EDMA_CINT_SHIFT (0) /* Bits 0-4: Clear Interrupt Request */ #define EDMA_CINT_MASK (0x1f << EDMA_CINT_SHIFT) @@ -1287,16 +1253,31 @@ struct imxrt_edmatcd_s { uint32_t saddr; /* Offset: 0x0000 TCD Source Address */ +#ifdef CONFIG_ENDIAN_BIG + uint16_t attr; /* Offset: 0x0004 TCD Transfer Attributes */ + uint16_t soff; /* Offset: 0x0006 TCD Signed Source Address Offset */ +#else uint16_t soff; /* Offset: 0x0004 TCD Signed Source Address Offset */ uint16_t attr; /* Offset: 0x0006 TCD Transfer Attributes */ +#endif uint32_t nbytes; /* Offset: 0x0008 TCD Signed Minor Loop Offset / Byte Count */ uint32_t slast; /* Offset: 0x000c TCD Last Source Address Adjustment */ uint32_t daddr; /* Offset: 0x0010 TCD Destination Address */ +#ifdef CONFIG_ENDIAN_BIG + uint16_t citer; /* Offset: 0x0014 TCD Current Minor Loop Link, Major Loop Count */ + uint16_t doff; /* Offset: 0x0016 TCD Signed Destination Address Offset */ +#else uint16_t doff; /* Offset: 0x0014 TCD Signed Destination Address Offset */ uint16_t citer; /* Offset: 0x0016 TCD Current Minor Loop Link, Major Loop Count */ +#endif uint32_t dlastsga; /* Offset: 0x0018 TCD Last Destination Address Adjustment/Scatter Gather Address */ +#ifdef CONFIG_ENDIAN_BIG + uint16_t biter; /* Offset: 0x001c TCD Beginning Minor Loop Link, Major Loop Count */ + uint16_t csr; /* Offset: 0x001e TCD Control and Status */ +#else uint16_t csr; /* Offset: 0x001c TCD Control and Status */ uint16_t biter; /* Offset: 0x001e TCD Beginning Minor Loop Link, Major Loop Count */ +#endif }; #endif /* __ARCH_ARM_SRC_IMXRT_HARDWARE_IMXRT_EDMA_H */ diff --git a/arch/arm/src/imxrt/imxrt_edma.h b/arch/arm/src/imxrt/imxrt_edma.h index 12813a8f12..41c114bd5b 100644 --- a/arch/arm/src/imxrt/imxrt_edma.h +++ b/arch/arm/src/imxrt/imxrt_edma.h @@ -139,22 +139,22 @@ enum imxrt_edma_xfrtype_e struct imxrt_edma_xfrconfig_s { - uint32_t saddr; /* Source data address. */ - uint32_t daddr; /* Destination data address. */ - int16_t soff; /* Sign-extended offset for current source address. */ - int16_t doff; /* Sign-extended offset for current destination address. */ - uint16_t iter; /* Major loop iteration count. */ - uint8_t flags; /* See EDMA_CONFIG_* definitions */ - uint8_t ssize; /* Source data transfer size (see TCD_ATTR_SIZE_* definitions in rdware/. */ - uint8_t dsize; /* Destination data transfer size. */ - uint8_t ttype; /* Transfer type (see enum imxrt_edma_xfrtype_e). */ + uint32_t saddr; /* Source data address. */ + uint32_t daddr; /* Destination data address. */ + int16_t soff; /* Sign-extended offset for current source address. */ + int16_t doff; /* Sign-extended offset for current destination address. */ + uint16_t iter; /* Major loop iteration count. */ + uint8_t flags; /* See EDMA_CONFIG_* definitions */ + uint8_t ssize; /* Source data transfer size (see TCD_ATTR_SIZE_* definitions in rdware/. */ + uint8_t dsize; /* Destination data transfer size. */ + uint8_t ttype; /* Transfer type (see enum imxrt_edma_xfrtype_e). */ #ifdef CONFIG_IMXRT_EDMA_EMLIM - uint16_t nbytes; /* Bytes to transfer in a minor loop */ + uint16_t nbytes; /* Bytes to transfer in a minor loop */ #else - uint32_t nbytes; /* Bytes to transfer in a minor loop */ + uint32_t nbytes; /* Bytes to transfer in a minor loop */ #endif #ifdef CONFIG_IMXRT_EDMA_ELINK - DMACH_HANDLE linkch; /* Link channel (With EDMA_CONFIG_LINKTYPE_* flags) */ + DMACH_HANDLE linkch; /* Link channel (With EDMA_CONFIG_LINKTYPE_* flags) */ #endif }; diff --git a/arch/arm/src/s32k1xx/Kconfig b/arch/arm/src/s32k1xx/Kconfig index 2d0b789891..5e7361f102 100644 --- a/arch/arm/src/s32k1xx/Kconfig +++ b/arch/arm/src/s32k1xx/Kconfig @@ -111,6 +111,10 @@ config S32K1XX_LPSPI menu "S32K1XX Peripheral Selection" +config S32K1XX_EDMA + bool "eDMA" + default n + config S32K1XX_LPUART0 bool "LPUART0" default n @@ -180,4 +184,85 @@ config S32K1XX_PORTEINTS endif endmenu # S32K1xx GPIO Interrupt Configuration +menu "eDMA Configuration" + depends on S32K1XX_EDMA + +config S32K1XX_EDMA_NTCD + int "Number of transfer descriptors" + default 0 + ---help--- + Number of pre-allocated transfer descriptors. Needed for scatter- + gather DMA. Make to be set to zero to disable in-memory TCDs in + which case only the TCD channel registers will be used and scatter- + will not be supported. + +config S32K1XX_EDMA_ELINK + bool "Channeling Linking" + default n + ---help--- + This option enables optional minor or major loop channel linking: + + Minor loop channel linking: As the channel completes the minor + loop, this flag enables linking to another channel. The link target + channel initiates a channel service request via an internal + mechanism that sets the TCDn_CSR[START] bit of the specified + channel. + + If minor loop channel linking is disabled, this link mechanism is + suppressed in favor of the major loop channel linking. + + Major loop channel linking: As the channel completes the minor + loop, this option enables the linking to another channel. The link + target channel initiates a channel service request via an internal + mechanism that sets the TCDn_CSR[START] bit of the linked channel. + +config S32K1XX_EDMA_ERCA + bool "Round Robin Channel Arbitration" + default n + ---help--- + Normally, a fixed priority arbitration is used for channel + selection. If this option is selected, round robin arbitration is + used for channel selection. + +config S32K1XX_EDMA_HOE + bool "Halt On Error" + default y + ---help--- + Any error causes the HALT bit to set. Subsequently, all service + requests are ignored until the HALT bit is cleared. + +config S32K1XX_EDMA_CLM + bool "Continuous Link Mode" + default n + ---help--- + By default, A minor loop channel link made to itself goes through + channel arbitration before being activated again. If this option is + selected, a minor loop channel link made to itself does not go + through channel arbitration before being activated again. Upon minor + loop completion, the channel activates again if that channel has a + minor loop channel link enabled and the link channel is itself. This + effectively applies the minor loop offsets and restarts the next + minor loop. + +config S32K1XX_EDMA_EMLIM + bool "Minor Loop Mapping" + default n + ---help--- + Normally TCD word 2 is a 32-bit NBYTES field. When this option is + enabled, TCD word 2 is redefined to include individual enable fields, + an offset field, and the NBYTES field. The individual enable fields + allow the minor loop offset to be applied to the source address, the + destination address, or both. The NBYTES field is reduced when either + offset is enabled. + +config S32K1XX_EDMA_EDBG + bool "Enable Debug" + default n + ---help--- + When in debug mode, the DMA stalls the start of a new channel. Executing + channels are allowed to complete. Channel execution resumes when the + system exits debug mode or the EDBG bit is cleared + +endmenu # eDMA Global Configuration + endif # ARCH_CHIP_S32K1XX diff --git a/arch/arm/src/s32k1xx/Make.defs b/arch/arm/src/s32k1xx/Make.defs index e74f6ed7ec..de6d4cb94d 100644 --- a/arch/arm/src/s32k1xx/Make.defs +++ b/arch/arm/src/s32k1xx/Make.defs @@ -64,8 +64,9 @@ ifeq ($(CONFIG_S32K1XX_GPIOIRQ),y) CHIP_CSRCS += s32k1xx_pinirq.c endif -ifeq ($(CONFIG_S32K1XX_DMA),y) +ifeq ($(CONFIG_S32K1XX_EDMA),y) CHIP_CSRCS += s32k1xx_pindma.c +CHIP_CSRCS += s32k1xx_edma.c endif ifeq ($(CONFIG_DEBUG_GPIO_INFO),y) diff --git a/arch/arm/src/s32k1xx/hardware/s32k1xx_edma.h b/arch/arm/src/s32k1xx/hardware/s32k1xx_edma.h new file mode 100644 index 0000000000..8fdca05381 --- /dev/null +++ b/arch/arm/src/s32k1xx/hardware/s32k1xx_edma.h @@ -0,0 +1,853 @@ +/**************************************************************************************************** + * arch/arm/src/s32k1xx/hardware/s32k1xx_edma.h + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_S32K1XX_HARDWARE_S32K1XX_EDMA_H +#define __ARCH_ARM_SRC_S32K1XX_HARDWARE_S32K1XX_EDMA_H + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ + +#include +#include "hardware/s32k1xx_memorymap.h" + +/**************************************************************************************************** + * Pre-processor Definitions + ****************************************************************************************************/ + +#if defined(CONFIG_ARCH_CHIP_S32K11X) +# define S32K1XX_EDMA_NCHANNELS 4 +#elif defined(CONFIG_ARCH_CHIP_S32K14x) +# define S32K1XX_EDMA_NCHANNELS 16 +#else +# error "Unknown number of DMA channels for this S32K1xx part" +#endif + +/* eDMA Register Offsets ****************************************************************************/ + +#define S32K1XX_EDMA_CR_OFFSET 0x0000 /* Control */ +#define S32K1XX_EDMA_ES_OFFSET 0x0004 /* Error Status */ +#define S32K1XX_EDMA_ERQ_OFFSET 0x000c /* Enable Request */ +#define S32K1XX_EDMA_EEI_OFFSET 0x0014 /* Enable Error Interrupt */ +#define S32K1XX_EDMA_CEEI_OFFSET 0x0018 /* Clear Enable Error Interrupt */ +#define S32K1XX_EDMA_SEEI_OFFSET 0x0019 /* Set Enable Error Interrupt */ +#define S32K1XX_EDMA_CERQ_OFFSET 0x001a /* Clear Enable Request */ +#define S32K1XX_EDMA_SERQ_OFFSET 0x001b /* Set Enable Request */ +#define S32K1XX_EDMA_CDNE_OFFSET 0x001c /* Clear DONE Status Bit */ +#define S32K1XX_EDMA_SSRT_OFFSET 0x001d /* Set START Bit */ +#define S32K1XX_EDMA_CERR_OFFSET 0x001e /* Clear Error */ +#define S32K1XX_EDMA_CINT_OFFSET 0x001f /* Clear Interrupt Request */ +#define S32K1XX_EDMA_INT_OFFSET 0x0024 /* Interrupt Request */ +#define S32K1XX_EDMA_ERR_OFFSET 0x002c /* Error */ +#define S32K1XX_EDMA_HRS_OFFSET 0x0034 /* Hardware Request Status */ +#define S32K1XX_EDMA_EARS_OFFSET 0x0044 /* Enable Asynchronous Request in Stop */ + +#define S32K1XX_EDMA_DCHPRI_OFFSET(n) (0x0100 + ((n) & ~3) + (3 - ((n) & 3))) + +#define S32K1XX_EDMA_DCHPRI3_OFFSET 0x0100 /* Channel 3 Priority */ +#define S32K1XX_EDMA_DCHPRI2_OFFSET 0x0101 /* Channel 2 Priority */ +#define S32K1XX_EDMA_DCHPRI1_OFFSET 0x0102 /* Channel 1 Priority */ +#define S32K1XX_EDMA_DCHPRI0_OFFSET 0x0103 /* Channel 0 Priority */ +#define S32K1XX_EDMA_DCHPRI7_OFFSET 0x0104 /* Channel 7 Priority */ +#define S32K1XX_EDMA_DCHPRI6_OFFSET 0x0105 /* Channel 6 Priority */ +#define S32K1XX_EDMA_DCHPRI5_OFFSET 0x0106 /* Channel 5 Priority */ +#define S32K1XX_EDMA_DCHPRI4_OFFSET 0x0107 /* Channel 4 Priority */ +#define S32K1XX_EDMA_DCHPRI11_OFFSET 0x0108 /* Channel 11 Priority */ +#define S32K1XX_EDMA_DCHPRI10_OFFSET 0x0109 /* Channel 10 Priority */ +#define S32K1XX_EDMA_DCHPRI9_OFFSET 0x010a /* Channel 9 Priority */ +#define S32K1XX_EDMA_DCHPRI8_OFFSET 0x010b /* Channel 8 Priority */ +#define S32K1XX_EDMA_DCHPRI15_OFFSET 0x010c /* Channel 15 Priority */ +#define S32K1XX_EDMA_DCHPRI14_OFFSET 0x010d /* Channel 14 Priority */ +#define S32K1XX_EDMA_DCHPRI13_OFFSET 0x010e /* Channel 13 Priority */ +#define S32K1XX_EDMA_DCHPRI12_OFFSET 0x010f /* Channel 12 Priority */ + +/* Transfer Control Descriptor (TCD) */ + +#define S32K1XX_EDMA_TCD_OFFSET(n) (0x1000 + ((n) << 5)) +#define S32K1XX_EDMA_TCD_SADDR_OFFSET 0x0000 /* TCD Source Address */ +#define S32K1XX_EDMA_TCD_SOFF_OFFSET 0x0004 /* TCD Signed Source Address Offset */ +#define S32K1XX_EDMA_TCD_ATTR_OFFSET 0x0006 /* TCD Transfer Attributes */ +#define S32K1XX_EDMA_TCD_NBYTES_ML_OFFSET 0x0008 /* TCD Signed Minor Loop Offset / Byte Count */ +#define S32K1XX_EDMA_TCD_SLAST_OFFSET 0x000c /* TCD Last Source Address Adjustment */ +#define S32K1XX_EDMA_TCD_DADDR_OFFSET 0x0010 /* TCD Destination Address */ +#define S32K1XX_EDMA_TCD_DOFF_OFFSET 0x0014 /* TCD Signed Destination Address Offset */ +#define S32K1XX_EDMA_TCD_CITER_ELINK_OFFSET 0x0016 /* TCD Current Minor Loop Link, Major Loop Count */ +#define S32K1XX_EDMA_TCD_DLASTSGA_OFFSET 0x0018 /* TCD Last Destination Address Adjustment/Scatter Gather Address */ +#define S32K1XX_EDMA_TCD_CSR_OFFSET 0x001c /* TCD Control and Status */ +#define S32K1XX_EDMA_TCD_BITER_ELINK_OFFSET 0x001e /* TCD Beginning Minor Loop Link, Major Loop Count */ + +#define S32K1XX_EDMA_TCD0_SADDR_OFFSET 0x1000 /* TCD Source Address */ +#define S32K1XX_EDMA_TCD0_SOFF_OFFSET 0x1004 /* TCD Signed Source Address Offset */ +#define S32K1XX_EDMA_TCD0_ATTR_OFFSET 0x1006 /* TCD Transfer Attributes */ +#define S32K1XX_EDMA_TCD0_NBYTES_ML_OFFSET 0x1008 /* TCD Signed Minor Loop Offset / Byte Count */ +#define S32K1XX_EDMA_TCD0_SLAST_OFFSET 0x100c /* TCD Last Source Address Adjustment */ +#define S32K1XX_EDMA_TCD0_DADDR_OFFSET 0x1010 /* TCD Destination Address */ +#define S32K1XX_EDMA_TCD0_DOFF_OFFSET 0x1014 /* TCD Signed Destination Address Offset */ +#define S32K1XX_EDMA_TCD0_CITER_ELINK_OFFSET 0x1016 /* TCD Current Minor Loop Link, Major Loop Count */ +#define S32K1XX_EDMA_TCD0_DLASTSGA_OFFSET 0x1018 /* TCD Last Destination Address Adjustment/Scatter Gather Address */ +#define S32K1XX_EDMA_TCD0_CSR_OFFSET 0x101c /* TCD Control and Status */ +#define S32K1XX_EDMA_TCD0_BITER_ELINK_OFFSET 0x101e /* TCD Beginning Minor Loop Link, Major Loop Count */ + +#define S32K1XX_EDMA_TCD1_SADDR_OFFSET 0x1020 /* TCD Source Address */ +#define S32K1XX_EDMA_TCD1_SOFF_OFFSET 0x1024 /* TCD Signed Source Address Offset */ +#define S32K1XX_EDMA_TCD1_ATTR_OFFSET 0x1026 /* TCD Transfer Attributes */ +#define S32K1XX_EDMA_TCD1_NBYTES_ML_OFFSET 0x1028 /* TCD Signed Minor Loop Offset / Byte Count */ +#define S32K1XX_EDMA_TCD1_SLAST_OFFSET 0x102c /* TCD Last Source Address Adjustment */ +#define S32K1XX_EDMA_TCD1_DADDR_OFFSET 0x1030 /* TCD Destination Address */ +#define S32K1XX_EDMA_TCD1_DOFF_OFFSET 0x1034 /* TCD Signed Destination Address Offset */ +#define S32K1XX_EDMA_TCD1_CITER_ELINK_OFFSET 0x1036 /* TCD Current Minor Loop Link, Major Loop Count */ +#define S32K1XX_EDMA_TCD1_DLASTSGA_OFFSET 0x1038 /* TCD Last Destination Address Adjustment/Scatter Gather Address */ +#define S32K1XX_EDMA_TCD1_CSR_OFFSET 0x103c /* TCD Control and Status */ +#define S32K1XX_EDMA_TCD1_BITER_ELINK_OFFSET 0x103e /* TCD Beginning Minor Loop Link, Major Loop Count */ + +#define S32K1XX_EDMA_TCD1_SADDR_OFFSET 0x1020 /* TCD Source Address */ +#define S32K1XX_EDMA_TCD1_SOFF_OFFSET 0x1024 /* TCD Signed Source Address Offset */ +#define S32K1XX_EDMA_TCD1_ATTR_OFFSET 0x1026 /* TCD Transfer Attributes */ +#define S32K1XX_EDMA_TCD1_NBYTES_ML_OFFSET 0x1028 /* TCD Signed Minor Loop Offset / Byte Count */ +#define S32K1XX_EDMA_TCD1_SLAST_OFFSET 0x102c /* TCD Last Source Address Adjustment */ +#define S32K1XX_EDMA_TCD1_DADDR_OFFSET 0x1030 /* TCD Destination Address */ +#define S32K1XX_EDMA_TCD1_DOFF_OFFSET 0x1034 /* TCD Signed Destination Address Offset */ +#define S32K1XX_EDMA_TCD1_CITER_ELINK_OFFSET 0x1036 /* TCD Current Minor Loop Link, Major Loop Count */ +#define S32K1XX_EDMA_TCD1_DLASTSGA_OFFSET 0x1038 /* TCD Last Destination Address Adjustment/Scatter Gather Address */ +#define S32K1XX_EDMA_TCD1_CSR_OFFSET 0x103c /* TCD Control and Status */ +#define S32K1XX_EDMA_TCD1_BITER_ELINK_OFFSET 0x103e /* TCD Beginning Minor Loop Link, Major Loop Count */ + +#define S32K1XX_EDMA_TCD2_SADDR_OFFSET 0x1040 /* TCD Source Address */ +#define S32K1XX_EDMA_TCD2_SOFF_OFFSET 0x1044 /* TCD Signed Source Address Offset */ +#define S32K1XX_EDMA_TCD2_ATTR_OFFSET 0x1046 /* TCD Transfer Attributes */ +#define S32K1XX_EDMA_TCD2_NBYTES_ML_OFFSET 0x1048 /* TCD Signed Minor Loop Offset / Byte Count */ +#define S32K1XX_EDMA_TCD2_SLAST_OFFSET 0x104c /* TCD Last Source Address Adjustment */ +#define S32K1XX_EDMA_TCD2_DADDR_OFFSET 0x1050 /* TCD Destination Address */ +#define S32K1XX_EDMA_TCD2_DOFF_OFFSET 0x1054 /* TCD Signed Destination Address Offset */ +#define S32K1XX_EDMA_TCD2_CITER_ELINK_OFFSET 0x1056 /* TCD Current Minor Loop Link, Major Loop Count */ +#define S32K1XX_EDMA_TCD2_DLASTSGA_OFFSET 0x1058 /* TCD Last Destination Address Adjustment/Scatter Gather Address */ +#define S32K1XX_EDMA_TCD2_CSR_OFFSET 0x105c /* TCD Control and Status */ +#define S32K1XX_EDMA_TCD2_BITER_ELINK_OFFSET 0x105e /* TCD Beginning Minor Loop Link, Major Loop Count */ + +#define S32K1XX_EDMA_TCD3_SADDR_OFFSET 0x1060 /* TCD Source Address */ +#define S32K1XX_EDMA_TCD3_SOFF_OFFSET 0x1064 /* TCD Signed Source Address Offset */ +#define S32K1XX_EDMA_TCD3_ATTR_OFFSET 0x1066 /* TCD Transfer Attributes */ +#define S32K1XX_EDMA_TCD3_NBYTES_ML_OFFSET 0x1068 /* TCD Signed Minor Loop Offset / Byte Count */ +#define S32K1XX_EDMA_TCD3_SLAST_OFFSET 0x106c /* TCD Last Source Address Adjustment */ +#define S32K1XX_EDMA_TCD3_DADDR_OFFSET 0x1070 /* TCD Destination Address */ +#define S32K1XX_EDMA_TCD3_DOFF_OFFSET 0x1074 /* TCD Signed Destination Address Offset */ +#define S32K1XX_EDMA_TCD3_CITER_ELINK_OFFSET 0x1076 /* TCD Current Minor Loop Link, Major Loop Count */ +#define S32K1XX_EDMA_TCD3_DLASTSGA_OFFSET 0x1078 /* TCD Last Destination Address Adjustment/Scatter Gather Address */ +#define S32K1XX_EDMA_TCD3_CSR_OFFSET 0x107c /* TCD Control and Status */ +#define S32K1XX_EDMA_TCD3_BITER_ELINK_OFFSET 0x107e /* TCD Beginning Minor Loop Link, Major Loop Count */ + +#define S32K1XX_EDMA_TCD4_SADDR_OFFSET 0x1080 /* TCD Source Address */ +#define S32K1XX_EDMA_TCD4_SOFF_OFFSET 0x1084 /* TCD Signed Source Address Offset */ +#define S32K1XX_EDMA_TCD4_ATTR_OFFSET 0x1086 /* TCD Transfer Attributes */ +#define S32K1XX_EDMA_TCD4_NBYTES_ML_OFFSET 0x1088 /* TCD Signed Minor Loop Offset / Byte Count */ +#define S32K1XX_EDMA_TCD4_SLAST_OFFSET 0x108c /* TCD Last Source Address Adjustment */ +#define S32K1XX_EDMA_TCD4_DADDR_OFFSET 0x1090 /* TCD Destination Address */ +#define S32K1XX_EDMA_TCD4_DOFF_OFFSET 0x1094 /* TCD Signed Destination Address Offset */ +#define S32K1XX_EDMA_TCD4_CITER_ELINK_OFFSET 0x1096 /* TCD Current Minor Loop Link, Major Loop Count */ +#define S32K1XX_EDMA_TCD4_DLASTSGA_OFFSET 0x1098 /* TCD Last Destination Address Adjustment/Scatter Gather Address */ +#define S32K1XX_EDMA_TCD4_CSR_OFFSET 0x109c /* TCD Control and Status */ +#define S32K1XX_EDMA_TCD4_BITER_ELINK_OFFSET 0x109e /* TCD Beginning Minor Loop Link, Major Loop Count */ + +#define S32K1XX_EDMA_TCD5_SADDR_OFFSET 0x10a0 /* TCD Source Address */ +#define S32K1XX_EDMA_TCD5_SOFF_OFFSET 0x10a4 /* TCD Signed Source Address Offset */ +#define S32K1XX_EDMA_TCD5_ATTR_OFFSET 0x10a6 /* TCD Transfer Attributes */ +#define S32K1XX_EDMA_TCD5_NBYTES_ML_OFFSET 0x10a8 /* TCD Signed Minor Loop Offset / Byte Count */ +#define S32K1XX_EDMA_TCD5_SLAST_OFFSET 0x10ac /* TCD Last Source Address Adjustment */ +#define S32K1XX_EDMA_TCD5_DADDR_OFFSET 0x10b0 /* TCD Destination Address */ +#define S32K1XX_EDMA_TCD5_DOFF_OFFSET 0x10b4 /* TCD Signed Destination Address Offset */ +#define S32K1XX_EDMA_TCD5_CITER_ELINK_OFFSET 0x10b6 /* TCD Current Minor Loop Link, Major Loop Count */ +#define S32K1XX_EDMA_TCD5_DLASTSGA_OFFSET 0x10b8 /* TCD Last Destination Address Adjustment/Scatter Gather Address */ +#define S32K1XX_EDMA_TCD5_CSR_OFFSET 0x10bc /* TCD Control and Status */ +#define S32K1XX_EDMA_TCD5_BITER_ELINK_OFFSET 0x10be /* TCD Beginning Minor Loop Link, Major Loop Count */ + +#define S32K1XX_EDMA_TCD6_SADDR_OFFSET 0x10c0 /* TCD Source Address */ +#define S32K1XX_EDMA_TCD6_SOFF_OFFSET 0x10c4 /* TCD Signed Source Address Offset */ +#define S32K1XX_EDMA_TCD6_ATTR_OFFSET 0x10c6 /* TCD Transfer Attributes */ +#define S32K1XX_EDMA_TCD6_NBYTES_ML_OFFSET 0x10c8 /* TCD Signed Minor Loop Offset / Byte Count */ +#define S32K1XX_EDMA_TCD6_SLAST_OFFSET 0x10cc /* TCD Last Source Address Adjustment */ +#define S32K1XX_EDMA_TCD6_DADDR_OFFSET 0x10d0 /* TCD Destination Address */ +#define S32K1XX_EDMA_TCD6_DOFF_OFFSET 0x10d4 /* TCD Signed Destination Address Offset */ +#define S32K1XX_EDMA_TCD6_CITER_ELINK_OFFSET 0x10d6 /* TCD Current Minor Loop Link, Major Loop Count */ +#define S32K1XX_EDMA_TCD6_DLASTSGA_OFFSET 0x10d8 /* TCD Last Destination Address Adjustment/Scatter Gather Address */ +#define S32K1XX_EDMA_TCD6_CSR_OFFSET 0x10dc /* TCD Control and Status */ +#define S32K1XX_EDMA_TCD6_BITER_ELINK_OFFSET 0x10de /* TCD Beginning Minor Loop Link, Major Loop Count */ + +#define S32K1XX_EDMA_TCD7_SADDR_OFFSET 0x10e0 /* TCD Source Address */ +#define S32K1XX_EDMA_TCD7_SOFF_OFFSET 0x10e4 /* TCD Signed Source Address Offset */ +#define S32K1XX_EDMA_TCD7_ATTR_OFFSET 0x10e6 /* TCD Transfer Attributes */ +#define S32K1XX_EDMA_TCD7_NBYTES_ML_OFFSET 0x10e8 /* TCD Signed Minor Loop Offset / Byte Count */ +#define S32K1XX_EDMA_TCD7_SLAST_OFFSET 0x10ec /* TCD Last Source Address Adjustment */ +#define S32K1XX_EDMA_TCD7_DADDR_OFFSET 0x10f0 /* TCD Destination Address */ +#define S32K1XX_EDMA_TCD7_DOFF_OFFSET 0x10f4 /* TCD Signed Destination Address Offset */ +#define S32K1XX_EDMA_TCD7_CITER_ELINK_OFFSET 0x10f6 /* TCD Current Minor Loop Link, Major Loop Count */ +#define S32K1XX_EDMA_TCD7_DLASTSGA_OFFSET 0x10f8 /* TCD Last Destination Address Adjustment/Scatter Gather Address */ +#define S32K1XX_EDMA_TCD7_CSR_OFFSET 0x10fc /* TCD Control and Status */ +#define S32K1XX_EDMA_TCD7_BITER_ELINK_OFFSET 0x10fe /* TCD Beginning Minor Loop Link, Major Loop Count */ + +#define S32K1XX_EDMA_TCD8_SADDR_OFFSET 0x1100 /* TCD Source Address */ +#define S32K1XX_EDMA_TCD8_SOFF_OFFSET 0x1104 /* TCD Signed Source Address Offset */ +#define S32K1XX_EDMA_TCD8_ATTR_OFFSET 0x1106 /* TCD Transfer Attributes */ +#define S32K1XX_EDMA_TCD8_NBYTES_ML_OFFSET 0x1108 /* TCD Signed Minor Loop Offset / Byte Count */ +#define S32K1XX_EDMA_TCD8_SLAST_OFFSET 0x110c /* TCD Last Source Address Adjustment */ +#define S32K1XX_EDMA_TCD8_DADDR_OFFSET 0x1110 /* TCD Destination Address */ +#define S32K1XX_EDMA_TCD8_DOFF_OFFSET 0x1114 /* TCD Signed Destination Address Offset */ +#define S32K1XX_EDMA_TCD8_CITER_ELINK_OFFSET 0x1116 /* TCD Current Minor Loop Link, Major Loop Count */ +#define S32K1XX_EDMA_TCD8_DLASTSGA_OFFSET 0x1118 /* TCD Last Destination Address Adjustment/Scatter Gather Address */ +#define S32K1XX_EDMA_TCD8_CSR_OFFSET 0x111c /* TCD Control and Status */ +#define S32K1XX_EDMA_TCD8_BITER_ELINK_OFFSET 0x111e /* TCD Beginning Minor Loop Link, Major Loop Count */ + +#define S32K1XX_EDMA_TCD9_SADDR_OFFSET 0x1120 /* TCD Source Address */ +#define S32K1XX_EDMA_TCD9_SOFF_OFFSET 0x1124 /* TCD Signed Source Address Offset */ +#define S32K1XX_EDMA_TCD9_ATTR_OFFSET 0x1126 /* TCD Transfer Attributes */ +#define S32K1XX_EDMA_TCD9_NBYTES_ML_OFFSET 0x1128 /* TCD Signed Minor Loop Offset / Byte Count */ +#define S32K1XX_EDMA_TCD9_SLAST_OFFSET 0x112c /* TCD Last Source Address Adjustment */ +#define S32K1XX_EDMA_TCD9_DADDR_OFFSET 0x1130 /* TCD Destination Address */ +#define S32K1XX_EDMA_TCD9_DOFF_OFFSET 0x1134 /* TCD Signed Destination Address Offset */ +#define S32K1XX_EDMA_TCD9_CITER_ELINK_OFFSET 0x1136 /* TCD Current Minor Loop Link, Major Loop Count */ +#define S32K1XX_EDMA_TCD9_DLASTSGA_OFFSET 0x1138 /* TCD Last Destination Address Adjustment/Scatter Gather Address */ +#define S32K1XX_EDMA_TCD9_CSR_OFFSET 0x113c /* TCD Control and Status */ +#define S32K1XX_EDMA_TCD9_BITER_ELINK_OFFSET 0x113e /* TCD Beginning Minor Loop Link, Major Loop Count */ + +#define S32K1XX_EDMA_TCD10_SADDR_OFFSET 0x1140 /* TCD Source Address */ +#define S32K1XX_EDMA_TCD10_SOFF_OFFSET 0x1144 /* TCD Signed Source Address Offset */ +#define S32K1XX_EDMA_TCD10_ATTR_OFFSET 0x1146 /* TCD Transfer Attributes */ +#define S32K1XX_EDMA_TCD10_NBYTES_ML_OFFSET 0x1148 /* TCD Signed Minor Loop Offset / Byte Count */ +#define S32K1XX_EDMA_TCD10_SLAST_OFFSET 0x114c /* TCD Last Source Address Adjustment */ +#define S32K1XX_EDMA_TCD10_DADDR_OFFSET 0x1150 /* TCD Destination Address */ +#define S32K1XX_EDMA_TCD10_DOFF_OFFSET 0x1154 /* TCD Signed Destination Address Offset */ +#define S32K1XX_EDMA_TCD10_CITER_ELINK_OFFSET 0x1156 /* TCD Current Minor Loop Link, Major Loop Count */ +#define S32K1XX_EDMA_TCD10_DLASTSGA_OFFSET 0x1158 /* TCD Last Destination Address Adjustment/Scatter Gather Address */ +#define S32K1XX_EDMA_TCD10_CSR_OFFSET 0x115c /* TCD Control and Status */ +#define S32K1XX_EDMA_TCD10_BITER_ELINK_OFFSET 0x115e /* TCD Beginning Minor Loop Link, Major Loop Count */ + +#define S32K1XX_EDMA_TCD11_SADDR_OFFSET 0x1160 /* TCD Source Address */ +#define S32K1XX_EDMA_TCD11_SOFF_OFFSET 0x1164 /* TCD Signed Source Address Offset */ +#define S32K1XX_EDMA_TCD11_ATTR_OFFSET 0x1166 /* TCD Transfer Attributes */ +#define S32K1XX_EDMA_TCD11_NBYTES_ML_OFFSET 0x1168 /* TCD Signed Minor Loop Offset / Byte Count */ +#define S32K1XX_EDMA_TCD11_SLAST_OFFSET 0x116c /* TCD Last Source Address Adjustment */ +#define S32K1XX_EDMA_TCD11_DADDR_OFFSET 0x1170 /* TCD Destination Address */ +#define S32K1XX_EDMA_TCD11_DOFF_OFFSET 0x1174 /* TCD Signed Destination Address Offset */ +#define S32K1XX_EDMA_TCD11_CITER_ELINK_OFFSET 0x1176 /* TCD Current Minor Loop Link, Major Loop Count */ +#define S32K1XX_EDMA_TCD11_DLASTSGA_OFFSET 0x1178 /* TCD Last Destination Address Adjustment/Scatter Gather Address */ +#define S32K1XX_EDMA_TCD11_CSR_OFFSET 0x117c /* TCD Control and Status */ +#define S32K1XX_EDMA_TCD11_BITER_ELINK_OFFSET 0x117e /* TCD Beginning Minor Loop Link, Major Loop Count */ + +#define S32K1XX_EDMA_TCD12_SADDR_OFFSET 0x1180 /* TCD Source Address */ +#define S32K1XX_EDMA_TCD12_SOFF_OFFSET 0x1184 /* TCD Signed Source Address Offset */ +#define S32K1XX_EDMA_TCD12_ATTR_OFFSET 0x1186 /* TCD Transfer Attributes */ +#define S32K1XX_EDMA_TCD12_NBYTES_ML_OFFSET 0x1188 /* TCD Signed Minor Loop Offset / Byte Count */ +#define S32K1XX_EDMA_TCD12_SLAST_OFFSET 0x118c /* TCD Last Source Address Adjustment */ +#define S32K1XX_EDMA_TCD12_DADDR_OFFSET 0x1190 /* TCD Destination Address */ +#define S32K1XX_EDMA_TCD12_DOFF_OFFSET 0x1194 /* TCD Signed Destination Address Offset */ +#define S32K1XX_EDMA_TCD12_CITER_ELINK_OFFSET 0x1196 /* TCD Current Minor Loop Link, Major Loop Count */ +#define S32K1XX_EDMA_TCD12_DLASTSGA_OFFSET 0x1198 /* TCD Last Destination Address Adjustment/Scatter Gather Address */ +#define S32K1XX_EDMA_TCD12_CSR_OFFSET 0x119c /* TCD Control and Status */ +#define S32K1XX_EDMA_TCD12_BITER_ELINK_OFFSET 0x119e /* TCD Beginning Minor Loop Link, Major Loop Count */ + +#define S32K1XX_EDMA_TCD13_SADDR_OFFSET 0x11a0 /* TCD Source Address */ +#define S32K1XX_EDMA_TCD13_SOFF_OFFSET 0x11a4 /* TCD Signed Source Address Offset */ +#define S32K1XX_EDMA_TCD13_ATTR_OFFSET 0x11a6 /* TCD Transfer Attributes */ +#define S32K1XX_EDMA_TCD13_NBYTES_ML_OFFSET 0x11a8 /* TCD Signed Minor Loop Offset / Byte Count */ +#define S32K1XX_EDMA_TCD13_SLAST_OFFSET 0x11ac /* TCD Last Source Address Adjustment */ +#define S32K1XX_EDMA_TCD13_DADDR_OFFSET 0x11b0 /* TCD Destination Address */ +#define S32K1XX_EDMA_TCD13_DOFF_OFFSET 0x11b4 /* TCD Signed Destination Address Offset */ +#define S32K1XX_EDMA_TCD13_CITER_ELINK_OFFSET 0x11b6 /* TCD Current Minor Loop Link, Major Loop Count */ +#define S32K1XX_EDMA_TCD13_DLASTSGA_OFFSET 0x11b8 /* TCD Last Destination Address Adjustment/Scatter Gather Address */ +#define S32K1XX_EDMA_TCD13_CSR_OFFSET 0x11bc /* TCD Control and Status */ +#define S32K1XX_EDMA_TCD13_BITER_ELINK_OFFSET 0x11be /* TCD Beginning Minor Loop Link, Major Loop Count */ + +#define S32K1XX_EDMA_TCD14_SADDR_OFFSET 0x11c0 /* TCD Source Address */ +#define S32K1XX_EDMA_TCD14_SOFF_OFFSET 0x11c4 /* TCD Signed Source Address Offset */ +#define S32K1XX_EDMA_TCD14_ATTR_OFFSET 0x11c6 /* TCD Transfer Attributes */ +#define S32K1XX_EDMA_TCD14_NBYTES_ML_OFFSET 0x11c8 /* TCD Signed Minor Loop Offset / Byte Count */ +#define S32K1XX_EDMA_TCD14_SLAST_OFFSET 0x11cc /* TCD Last Source Address Adjustment */ +#define S32K1XX_EDMA_TCD14_DADDR_OFFSET 0x11d0 /* TCD Destination Address */ +#define S32K1XX_EDMA_TCD14_DOFF_OFFSET 0x11d4 /* TCD Signed Destination Address Offset */ +#define S32K1XX_EDMA_TCD14_CITER_ELINK_OFFSET 0x11d6 /* TCD Current Minor Loop Link, Major Loop Count */ +#define S32K1XX_EDMA_TCD14_DLASTSGA_OFFSET 0x11d8 /* TCD Last Destination Address Adjustment/Scatter Gather Address */ +#define S32K1XX_EDMA_TCD14_CSR_OFFSET 0x11dc /* TCD Control and Status */ +#define S32K1XX_EDMA_TCD14_BITER_ELINK_OFFSET 0x11de /* TCD Beginning Minor Loop Link, Major Loop Count */ + +#define S32K1XX_EDMA_TCD15_SADDR_OFFSET 0x11e0 /* TCD Source Address */ +#define S32K1XX_EDMA_TCD15_SOFF_OFFSET 0x11e4 /* TCD Signed Source Address Offset */ +#define S32K1XX_EDMA_TCD15_ATTR_OFFSET 0x11e6 /* TCD Transfer Attributes */ +#define S32K1XX_EDMA_TCD15_NBYTES_ML_OFFSET 0x11e8 /* TCD Signed Minor Loop Offset / Byte Count */ +#define S32K1XX_EDMA_TCD15_SLAST_OFFSET 0x11ec /* TCD Last Source Address Adjustment */ +#define S32K1XX_EDMA_TCD15_DADDR_OFFSET 0x11f0 /* TCD Destination Address */ +#define S32K1XX_EDMA_TCD15_DOFF_OFFSET 0x11f4 /* TCD Signed Destination Address Offset */ +#define S32K1XX_EDMA_TCD15_CITER_ELINK_OFFSET 0x11f6 /* TCD Current Minor Loop Link, Major Loop Count */ +#define S32K1XX_EDMA_TCD15_DLASTSGA_OFFSET 0x11f8 /* TCD Last Destination Address Adjustment/Scatter Gather Address */ +#define S32K1XX_EDMA_TCD15_CSR_OFFSET 0x11fc /* TCD Control and Status */ +#define S32K1XX_EDMA_TCD15_BITER_ELINK_OFFSET 0x11fe /* TCD Beginning Minor Loop Link, Major Loop Count */ + +/* eDMA Register Addresses **************************************************************************/ + +#define S32K1XX_EDMA_CR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_CR_OFFSET) +#define S32K1XX_EDMA_ES (S32K1XX_EDMA_BASE + S32K1XX_EDMA_ES_OFFSET) +#define S32K1XX_EDMA_ERQ (S32K1XX_EDMA_BASE + S32K1XX_EDMA_ERQ_OFFSET) +#define S32K1XX_EDMA_EEI (S32K1XX_EDMA_BASE + S32K1XX_EDMA_EEI_OFFSET) +#define S32K1XX_EDMA_CEEI (S32K1XX_EDMA_BASE + S32K1XX_EDMA_CEEI_OFFSET) +#define S32K1XX_EDMA_SEEI (S32K1XX_EDMA_BASE + S32K1XX_EDMA_SEEI_OFFSET) +#define S32K1XX_EDMA_CERQ (S32K1XX_EDMA_BASE + S32K1XX_EDMA_CERQ_OFFSET) +#define S32K1XX_EDMA_SERQ (S32K1XX_EDMA_BASE + S32K1XX_EDMA_SERQ_OFFSET) +#define S32K1XX_EDMA_CDNE (S32K1XX_EDMA_BASE + S32K1XX_EDMA_CDNE_OFFSET) +#define S32K1XX_EDMA_SSRT (S32K1XX_EDMA_BASE + S32K1XX_EDMA_SSRT_OFFSET) +#define S32K1XX_EDMA_CERR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_CERR_OFFSET) +#define S32K1XX_EDMA_CINT (S32K1XX_EDMA_BASE + S32K1XX_EDMA_CINT_OFFSET) +#define S32K1XX_EDMA_INT (S32K1XX_EDMA_BASE + S32K1XX_EDMA_INT_OFFSET) +#define S32K1XX_EDMA_ERR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_ERR_OFFSET) +#define S32K1XX_EDMA_HRS (S32K1XX_EDMA_BASE + S32K1XX_EDMA_HRS_OFFSET) +#define S32K1XX_EDMA_EARS (S32K1XX_EDMA_BASE + S32K1XX_EDMA_EARS_OFFSET) + +#define S32K1XX_EDMA_DCHPRI(n) (S32K1XX_EDMA_BASE + S32K1XX_EDMA_DCHPRI_OFFSET(n)) + +#define S32K1XX_EDMA_DCHPRI0 (S32K1XX_EDMA_BASE + S32K1XX_EDMA_DCHPRI0_OFFSET) +#define S32K1XX_EDMA_DCHPRI1 (S32K1XX_EDMA_BASE + S32K1XX_EDMA_DCHPRI1_OFFSET) +#define S32K1XX_EDMA_DCHPRI2 (S32K1XX_EDMA_BASE + S32K1XX_EDMA_DCHPRI2_OFFSET) +#define S32K1XX_EDMA_DCHPRI3 (S32K1XX_EDMA_BASE + S32K1XX_EDMA_DCHPRI3_OFFSET) +#define S32K1XX_EDMA_DCHPRI4 (S32K1XX_EDMA_BASE + S32K1XX_EDMA_DCHPRI4_OFFSET) +#define S32K1XX_EDMA_DCHPRI5 (S32K1XX_EDMA_BASE + S32K1XX_EDMA_DCHPRI5_OFFSET) +#define S32K1XX_EDMA_DCHPRI6 (S32K1XX_EDMA_BASE + S32K1XX_EDMA_DCHPRI6_OFFSET) +#define S32K1XX_EDMA_DCHPRI7 (S32K1XX_EDMA_BASE + S32K1XX_EDMA_DCHPRI7_OFFSET) +#define S32K1XX_EDMA_DCHPRI8 (S32K1XX_EDMA_BASE + S32K1XX_EDMA_DCHPRI8_OFFSET) +#define S32K1XX_EDMA_DCHPRI9 (S32K1XX_EDMA_BASE + S32K1XX_EDMA_DCHPRI9_OFFSET) +#define S32K1XX_EDMA_DCHPRI10 (S32K1XX_EDMA_BASE + S32K1XX_EDMA_DCHPRI10_OFFSET) +#define S32K1XX_EDMA_DCHPRI11 (S32K1XX_EDMA_BASE + S32K1XX_EDMA_DCHPRI11_OFFSET) +#define S32K1XX_EDMA_DCHPRI12 (S32K1XX_EDMA_BASE + S32K1XX_EDMA_DCHPRI12_OFFSET) +#define S32K1XX_EDMA_DCHPRI13 (S32K1XX_EDMA_BASE + S32K1XX_EDMA_DCHPRI13_OFFSET) +#define S32K1XX_EDMA_DCHPRI14 (S32K1XX_EDMA_BASE + S32K1XX_EDMA_DCHPRI14_OFFSET) +#define S32K1XX_EDMA_DCHPRI15 (S32K1XX_EDMA_BASE + S32K1XX_EDMA_DCHPRI15_OFFSET) + +/* Transfer Control Descriptor (TCD) */ + +#define S32K1XX_EDMA_TCD_BASE(n) (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD_OFFSET(n)) +#define S32K1XX_EDMA_TCD_SADDR(n) (S32K1XX_EDMA_TCD_BASE(n) + S32K1XX_EDMA_TCD_SADDR_OFFSET) +#define S32K1XX_EDMA_TCD_SOFF(n) (S32K1XX_EDMA_TCD_BASE(n) + S32K1XX_EDMA_TCD_SOFF_OFFSET) +#define S32K1XX_EDMA_TCD_ATTR(n) (S32K1XX_EDMA_TCD_BASE(n) + S32K1XX_EDMA_TCD_ATTR_OFFSET) +#define S32K1XX_EDMA_TCD_NBYTES_ML(n) (S32K1XX_EDMA_TCD_BASE(n) + S32K1XX_EDMA_TCD_NBYTES_ML_OFFSET) +#define S32K1XX_EDMA_TCD_SLAST(n) (S32K1XX_EDMA_TCD_BASE(n) + S32K1XX_EDMA_TCD_SLAST_OFFSET) +#define S32K1XX_EDMA_TCD_DADDR(n) (S32K1XX_EDMA_TCD_BASE(n) + S32K1XX_EDMA_TCD_DADDR_OFFSET) +#define S32K1XX_EDMA_TCD_DOFF(n) (S32K1XX_EDMA_TCD_BASE(n) + S32K1XX_EDMA_TCD_DOFF_OFFSET) +#define S32K1XX_EDMA_TCD_CITER_ELINK(n) (S32K1XX_EDMA_TCD_BASE(n) + S32K1XX_EDMA_TCD_CITER_ELINK_OFFSET) +#define S32K1XX_EDMA_TCD_DLASTSGA(n) (S32K1XX_EDMA_TCD_BASE(n) + S32K1XX_EDMA_TCD_DLASTSGA_OFFSET) +#define S32K1XX_EDMA_TCD_CSR(n) (S32K1XX_EDMA_TCD_BASE(n) + S32K1XX_EDMA_TCD_CSR_OFFSET) +#define S32K1XX_EDMA_TCD_BITER_ELINK(n) (S32K1XX_EDMA_TCD_BASE(n) + S32K1XX_EDMA_TCD_BITER_ELINK_OFFSET) + +#define S32K1XX_EDMA_TCD0_SADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD0_SADDR_OFFSET) +#define S32K1XX_EDMA_TCD0_SOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD0_SOFF_OFFSET) +#define S32K1XX_EDMA_TCD0_ATTR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD0_ATTR_OFFSET) +#define S32K1XX_EDMA_TCD0_NBYTES_ML (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD0_NBYTES_ML_OFFSET) +#define S32K1XX_EDMA_TCD0_SLAST (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD0_SLAST_OFFSET) +#define S32K1XX_EDMA_TCD0_DADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD0_DADDR_OFFSET) +#define S32K1XX_EDMA_TCD0_DOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD0_DOFF_OFFSET) +#define S32K1XX_EDMA_TCD0_CITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD0_CITER_ELINK_OFFSET) +#define S32K1XX_EDMA_TCD0_DLASTSGA (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD0_DLASTSGA_OFFSET) +#define S32K1XX_EDMA_TCD0_CSR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD0_CSR_OFFSET) +#define S32K1XX_EDMA_TCD0_BITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD0_BITER_ELINK_OFFSET) + +#define S32K1XX_EDMA_TCD1_SADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD1_SADDR_OFFSET) +#define S32K1XX_EDMA_TCD1_SOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD1_SOFF_OFFSET) +#define S32K1XX_EDMA_TCD1_ATTR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD1_ATTR_OFFSET) +#define S32K1XX_EDMA_TCD1_NBYTES_ML (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD1_NBYTES_ML_OFFSET) +#define S32K1XX_EDMA_TCD1_SLAST (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD1_SLAST_OFFSET) +#define S32K1XX_EDMA_TCD1_DADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD1_DADDR_OFFSET) +#define S32K1XX_EDMA_TCD1_DOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD1_DOFF_OFFSET) +#define S32K1XX_EDMA_TCD1_CITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD1_CITER_ELINK_OFFSET) +#define S32K1XX_EDMA_TCD1_DLASTSGA (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD1_DLASTSGA_OFFSET) +#define S32K1XX_EDMA_TCD1_CSR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD1_CSR_OFFSET) +#define S32K1XX_EDMA_TCD1_BITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD1_BITER_ELINK_OFFSET) + +#define S32K1XX_EDMA_TCD2_SADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD2_SADDR_OFFSET) +#define S32K1XX_EDMA_TCD2_SOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD2_SOFF_OFFSET) +#define S32K1XX_EDMA_TCD2_ATTR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD2_ATTR_OFFSET) +#define S32K1XX_EDMA_TCD2_NBYTES_ML (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD2_NBYTES_ML_OFFSET) +#define S32K1XX_EDMA_TCD2_SLAST (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD2_SLAST_OFFSET) +#define S32K1XX_EDMA_TCD2_DADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD2_DADDR_OFFSET) +#define S32K1XX_EDMA_TCD2_DOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD2_DOFF_OFFSET) +#define S32K1XX_EDMA_TCD2_CITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD2_CITER_ELINK_OFFSET) +#define S32K1XX_EDMA_TCD2_DLASTSGA (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD2_DLASTSGA_OFFSET) +#define S32K1XX_EDMA_TCD2_CSR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD2_CSR_OFFSET) +#define S32K1XX_EDMA_TCD2_BITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD2_BITER_ELINK_OFFSET) + +#define S32K1XX_EDMA_TCD3_SADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD3_SADDR_OFFSET) +#define S32K1XX_EDMA_TCD3_SOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD3_SOFF_OFFSET) +#define S32K1XX_EDMA_TCD3_ATTR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD3_ATTR_OFFSET) +#define S32K1XX_EDMA_TCD3_NBYTES_ML (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD3_NBYTES_ML_OFFSET) +#define S32K1XX_EDMA_TCD3_SLAST (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD3_SLAST_OFFSET) +#define S32K1XX_EDMA_TCD3_DADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD3_DADDR_OFFSET) +#define S32K1XX_EDMA_TCD3_DOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD3_DOFF_OFFSET) +#define S32K1XX_EDMA_TCD3_CITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD3_CITER_ELINK_OFFSET) +#define S32K1XX_EDMA_TCD3_DLASTSGA (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD3_DLASTSGA_OFFSET) +#define S32K1XX_EDMA_TCD3_CSR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD3_CSR_OFFSET) +#define S32K1XX_EDMA_TCD3_BITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD3_BITER_ELINK_OFFSET) + +#define S32K1XX_EDMA_TCD4_SADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD4_SADDR_OFFSET) +#define S32K1XX_EDMA_TCD4_SOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD4_SOFF_OFFSET) +#define S32K1XX_EDMA_TCD4_ATTR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD4_ATTR_OFFSET) +#define S32K1XX_EDMA_TCD4_NBYTES_ML (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD4_NBYTES_ML_OFFSET) +#define S32K1XX_EDMA_TCD4_SLAST (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD4_SLAST_OFFSET) +#define S32K1XX_EDMA_TCD4_DADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD4_DADDR_OFFSET) +#define S32K1XX_EDMA_TCD4_DOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD4_DOFF_OFFSET) +#define S32K1XX_EDMA_TCD4_CITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD4_CITER_ELINK_OFFSET) +#define S32K1XX_EDMA_TCD4_DLASTSGA (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD4_DLASTSGA_OFFSET) +#define S32K1XX_EDMA_TCD4_CSR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD4_CSR_OFFSET) +#define S32K1XX_EDMA_TCD4_BITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD4_BITER_ELINK_OFFSET) + +#define S32K1XX_EDMA_TCD5_SADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD5_SADDR_OFFSET) +#define S32K1XX_EDMA_TCD5_SOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD5_SOFF_OFFSET) +#define S32K1XX_EDMA_TCD5_ATTR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD5_ATTR_OFFSET) +#define S32K1XX_EDMA_TCD5_NBYTES_ML (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD5_NBYTES_ML_OFFSET) +#define S32K1XX_EDMA_TCD5_SLAST (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD5_SLAST_OFFSET) +#define S32K1XX_EDMA_TCD5_DADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD5_DADDR_OFFSET) +#define S32K1XX_EDMA_TCD5_DOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD5_DOFF_OFFSET) +#define S32K1XX_EDMA_TCD5_CITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD5_CITER_ELINK_OFFSET) +#define S32K1XX_EDMA_TCD5_DLASTSGA (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD5_DLASTSGA_OFFSET) +#define S32K1XX_EDMA_TCD5_CSR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD5_CSR_OFFSET) +#define S32K1XX_EDMA_TCD5_BITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD5_BITER_ELINK_OFFSET) + +#define S32K1XX_EDMA_TCD6_SADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD6_SADDR_OFFSET) +#define S32K1XX_EDMA_TCD6_SOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD6_SOFF_OFFSET) +#define S32K1XX_EDMA_TCD6_ATTR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD6_ATTR_OFFSET) +#define S32K1XX_EDMA_TCD6_NBYTES_ML (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD6_NBYTES_ML_OFFSET) +#define S32K1XX_EDMA_TCD6_SLAST (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD6_SLAST_OFFSET) +#define S32K1XX_EDMA_TCD6_DADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD6_DADDR_OFFSET) +#define S32K1XX_EDMA_TCD6_DOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD6_DOFF_OFFSET) +#define S32K1XX_EDMA_TCD6_CITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD6_CITER_ELINK_OFFSET) +#define S32K1XX_EDMA_TCD6_DLASTSGA (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD6_DLASTSGA_OFFSET) +#define S32K1XX_EDMA_TCD6_CSR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD6_CSR_OFFSET) +#define S32K1XX_EDMA_TCD6_BITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD6_BITER_ELINK_OFFSET) + +#define S32K1XX_EDMA_TCD7_SADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD7_SADDR_OFFSET) +#define S32K1XX_EDMA_TCD7_SOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD7_SOFF_OFFSET) +#define S32K1XX_EDMA_TCD7_ATTR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD7_ATTR_OFFSET) +#define S32K1XX_EDMA_TCD7_NBYTES_ML (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD7_NBYTES_ML_OFFSET) +#define S32K1XX_EDMA_TCD7_SLAST (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD7_SLAST_OFFSET) +#define S32K1XX_EDMA_TCD7_DADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD7_DADDR_OFFSET) +#define S32K1XX_EDMA_TCD7_DOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD7_DOFF_OFFSET) +#define S32K1XX_EDMA_TCD7_CITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD7_CITER_ELINK_OFFSET) +#define S32K1XX_EDMA_TCD7_DLASTSGA (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD7_DLASTSGA_OFFSET) +#define S32K1XX_EDMA_TCD7_CSR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD7_CSR_OFFSET) +#define S32K1XX_EDMA_TCD7_BITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD7_BITER_ELINK_OFFSET) + +#define S32K1XX_EDMA_TCD8_SADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD8_SADDR_OFFSET) +#define S32K1XX_EDMA_TCD8_SOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD8_SOFF_OFFSET) +#define S32K1XX_EDMA_TCD8_ATTR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD8_ATTR_OFFSET) +#define S32K1XX_EDMA_TCD8_NBYTES_ML (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD8_NBYTES_ML_OFFSET) +#define S32K1XX_EDMA_TCD8_SLAST (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD8_SLAST_OFFSET) +#define S32K1XX_EDMA_TCD8_DADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD8_DADDR_OFFSET) +#define S32K1XX_EDMA_TCD8_DOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD8_DOFF_OFFSET) +#define S32K1XX_EDMA_TCD8_CITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD8_CITER_ELINK_OFFSET) +#define S32K1XX_EDMA_TCD8_DLASTSGA (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD8_DLASTSGA_OFFSET) +#define S32K1XX_EDMA_TCD8_CSR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD8_CSR_OFFSET) +#define S32K1XX_EDMA_TCD8_BITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD8_BITER_ELINK_OFFSET) + +#define S32K1XX_EDMA_TCD9_SADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD9_SADDR_OFFSET) +#define S32K1XX_EDMA_TCD9_SOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD9_SOFF_OFFSET) +#define S32K1XX_EDMA_TCD9_ATTR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD9_ATTR_OFFSET) +#define S32K1XX_EDMA_TCD9_NBYTES_ML (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD9_NBYTES_ML_OFFSET) +#define S32K1XX_EDMA_TCD9_SLAST (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD9_SLAST_OFFSET) +#define S32K1XX_EDMA_TCD9_DADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD9_DADDR_OFFSET) +#define S32K1XX_EDMA_TCD9_DOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD9_DOFF_OFFSET) +#define S32K1XX_EDMA_TCD9_CITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD9_CITER_ELINK_OFFSET) +#define S32K1XX_EDMA_TCD9_DLASTSGA (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD9_DLASTSGA_OFFSET) +#define S32K1XX_EDMA_TCD9_CSR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD9_CSR_OFFSET) +#define S32K1XX_EDMA_TCD9_BITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD9_BITER_ELINK_OFFSET) + +#define S32K1XX_EDMA_TCD10_SADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD10_SADDR_OFFSET) +#define S32K1XX_EDMA_TCD10_SOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD10_SOFF_OFFSET) +#define S32K1XX_EDMA_TCD10_ATTR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD10_ATTR_OFFSET) +#define S32K1XX_EDMA_TCD10_NBYTES_ML (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD10_NBYTES_ML_OFFSET) +#define S32K1XX_EDMA_TCD10_SLAST (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD10_SLAST_OFFSET) +#define S32K1XX_EDMA_TCD10_DADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD10_DADDR_OFFSET) +#define S32K1XX_EDMA_TCD10_DOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD10_DOFF_OFFSET) +#define S32K1XX_EDMA_TCD10_CITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD10_CITER_ELINK_OFFSET) +#define S32K1XX_EDMA_TCD10_DLASTSGA (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD10_DLASTSGA_OFFSET) +#define S32K1XX_EDMA_TCD10_CSR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD10_CSR_OFFSET) +#define S32K1XX_EDMA_TCD10_BITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD10_BITER_ELINK_OFFSET) + +#define S32K1XX_EDMA_TCD11_SADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD11_SADDR_OFFSET) +#define S32K1XX_EDMA_TCD11_SOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD11_SOFF_OFFSET) +#define S32K1XX_EDMA_TCD11_ATTR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD11_ATTR_OFFSET) +#define S32K1XX_EDMA_TCD11_NBYTES_ML (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD11_NBYTES_ML_OFFSET) +#define S32K1XX_EDMA_TCD11_SLAST (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD11_SLAST_OFFSET) +#define S32K1XX_EDMA_TCD11_DADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD11_DADDR_OFFSET) +#define S32K1XX_EDMA_TCD11_DOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD11_DOFF_OFFSET) +#define S32K1XX_EDMA_TCD11_CITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD11_CITER_ELINK_OFFSET) +#define S32K1XX_EDMA_TCD11_DLASTSGA (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD11_DLASTSGA_OFFSET) +#define S32K1XX_EDMA_TCD11_CSR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD11_CSR_OFFSET) +#define S32K1XX_EDMA_TCD11_BITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD11_BITER_ELINK_OFFSET) + +#define S32K1XX_EDMA_TCD12_SADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD12_SADDR_OFFSET) +#define S32K1XX_EDMA_TCD12_SOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD12_SOFF_OFFSET) +#define S32K1XX_EDMA_TCD12_ATTR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD12_ATTR_OFFSET) +#define S32K1XX_EDMA_TCD12_NBYTES_ML (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD12_NBYTES_ML_OFFSET) +#define S32K1XX_EDMA_TCD12_SLAST (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD12_SLAST_OFFSET) +#define S32K1XX_EDMA_TCD12_DADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD12_DADDR_OFFSET) +#define S32K1XX_EDMA_TCD12_DOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD12_DOFF_OFFSET) +#define S32K1XX_EDMA_TCD12_CITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD12_CITER_ELINK_OFFSET) +#define S32K1XX_EDMA_TCD12_DLASTSGA (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD12_DLASTSGA_OFFSET) +#define S32K1XX_EDMA_TCD12_CSR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD12_CSR_OFFSET) +#define S32K1XX_EDMA_TCD12_BITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD12_BITER_ELINK_OFFSET) + +#define S32K1XX_EDMA_TCD13_SADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD13_SADDR_OFFSET) +#define S32K1XX_EDMA_TCD13_SOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD13_SOFF_OFFSET) +#define S32K1XX_EDMA_TCD13_ATTR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD13_ATTR_OFFSET) +#define S32K1XX_EDMA_TCD13_NBYTES_ML (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD13_NBYTES_ML_OFFSET) +#define S32K1XX_EDMA_TCD13_SLAST (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD13_SLAST_OFFSET) +#define S32K1XX_EDMA_TCD13_DADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD13_DADDR_OFFSET) +#define S32K1XX_EDMA_TCD13_DOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD13_DOFF_OFFSET) +#define S32K1XX_EDMA_TCD13_CITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD13_CITER_ELINK_OFFSET) +#define S32K1XX_EDMA_TCD13_DLASTSGA (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD13_DLASTSGA_OFFSET) +#define S32K1XX_EDMA_TCD13_CSR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD13_CSR_OFFSET) +#define S32K1XX_EDMA_TCD13_BITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD13_BITER_ELINK_OFFSET) + +#define S32K1XX_EDMA_TCD14_SADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD14_SADDR_OFFSET) +#define S32K1XX_EDMA_TCD14_SOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD14_SOFF_OFFSET) +#define S32K1XX_EDMA_TCD14_ATTR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD14_ATTR_OFFSET) +#define S32K1XX_EDMA_TCD14_NBYTES_ML (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD14_NBYTES_ML_OFFSET) +#define S32K1XX_EDMA_TCD14_SLAST (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD14_SLAST_OFFSET) +#define S32K1XX_EDMA_TCD14_DADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD14_DADDR_OFFSET) +#define S32K1XX_EDMA_TCD14_DOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD14_DOFF_OFFSET) +#define S32K1XX_EDMA_TCD14_CITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD14_CITER_ELINK_OFFSET) +#define S32K1XX_EDMA_TCD14_DLASTSGA (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD14_DLASTSGA_OFFSET) +#define S32K1XX_EDMA_TCD14_CSR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD14_CSR_OFFSET) +#define S32K1XX_EDMA_TCD14_BITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD14_BITER_ELINK_OFFSET) + +#define S32K1XX_EDMA_TCD15_SADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD15_SADDR_OFFSET) +#define S32K1XX_EDMA_TCD15_SOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD15_SOFF_OFFSET) +#define S32K1XX_EDMA_TCD15_ATTR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD15_ATTR_OFFSET) +#define S32K1XX_EDMA_TCD15_NBYTES_ML (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD15_NBYTES_ML_OFFSET) +#define S32K1XX_EDMA_TCD15_SLAST (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD15_SLAST_OFFSET) +#define S32K1XX_EDMA_TCD15_DADDR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD15_DADDR_OFFSET) +#define S32K1XX_EDMA_TCD15_DOFF (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD15_DOFF_OFFSET) +#define S32K1XX_EDMA_TCD15_CITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD15_CITER_ELINK_OFFSET) +#define S32K1XX_EDMA_TCD15_DLASTSGA (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD15_DLASTSGA_OFFSET) +#define S32K1XX_EDMA_TCD15_CSR (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD15_CSR_OFFSET) +#define S32K1XX_EDMA_TCD15_BITER_ELINK (S32K1XX_EDMA_BASE + S32K1XX_EDMA_TCD15_BITER_ELINK_OFFSET) + +/* eDMA Bit-Field Definitions ***********************************************************************/ + +/* Control */ + /* Bit 0: Reserved */ +#define EDMA_CR_EDBG (1 << 1) /* Bit 1: Enable Debug */ +#define EDMA_CR_ERCA (1 << 2) /* Bit 2: Enable Round Robin Channel Arbitration */ + /* Bit 3: Reserved */ +#define EDMA_CR_HOE (1 << 4) /* Bit 4: Halt On Error */ +#define EDMA_CR_HALT (1 << 5) /* Bit 5: Halt DMA Operations */ +#define EDMA_CR_CLM (1 << 6) /* Bit 6: Continuous Link Mode */ +#define EDMA_CR_EMLM (1 << 7) /* Bit 7: Enable Minor Loop Mapping */ + /* Bit 8-15: Reserved */ +#define EDMA_CR_ECX (1 << 16) /* Bit 16: Error Cancel Transfer */ +#define EDMA_CR_CX (1 << 17) /* Bit 17: Cancel Transfer */ + /* Bits 18-23: Reserved */ + /* Bits 24-30: eDMA version number (reserved) */ +#define EDMA_CR_ACTIVE (1 << 31) /* Bit 31: DMA Active Status */ + +/* Error Status */ + +#define EDMA_ES_DBE (1 << 0) /* Bit 0: Destination Bus Error */ +#define EDMA_ES_SBE (1 << 1) /* Bit 1: Source Bus Error */ +#define EDMA_ES_SGE (1 << 2) /* Bit 2: Scatter/Gather Configuration Error */ +#define EDMA_ES_NCE (1 << 3) /* Bit 3: NBYTES/CITER Configuration Error */ +#define EDMA_ES_DOE (1 << 4) /* Bit 4: Destination Offset Error */ +#define EDMA_ES_DAE (1 << 5) /* Bit 5: Destination Address Error */ +#define EDMA_ES_SOE (1 << 6) /* Bit 6: Source Offset Error */ +#define EDMA_ES_SAE (1 << 7) /* Bit 7: Source Address Error */ +#define EDMA_ES_ERRCHN_SHIFT (8) /* Bits 8-11: Error Channel Number or + * Canceled Channel Number */ +#define EDMA_ES_ERRCHN_MASK (15 << EDMA_ES_ERRCHN_SHIFT) + /* Bits 23-13: Reserved */ +#define EDMA_ES_CPE (1 << 14) /* Bit 14: Channel Priority Error */ + /* Bit 15: Reserved */ +#define EDMA_ES_ECX (1 << 16) /* Bit 16: Transfer Canceled */ + /* Bits 17-30: Reserved */ +#define EDMA_ES_VLD (1 << 31) /* Bit 31: Logical OR of all ERR status bits */ + +/* Enable Request */ + +#define EDMA_ERQ(n) ((uint32_t)1 << (n)) /* Bit n: Enable DMA request n */ + +/* Enable Error Interrupt */ + +#define EDMA_EEI(n) ((uint32_t)1 << (n)) /* Bit n: Enable error interrupt n */ + +/* Clear Enable Error Interrupt */ + +#define EDMA_CEEI_SHIFT (0) /* Bits 0-3: Clear Enable Error Interrupt */ +#define EDMA_CEEI_MASK (15 << EDMA_CEEI_SHIFT) +# define EDMA_CEEI(n) ((uint32_t)(n) << EDMA_CEEI_SHIFT) + /* Bit 54-: Reserved */ +#define EDMA_CEEI_CAEE (1 << 6) /* Bit 6: Clear All Enable Error Interrupts */ +#define EDMA_CEEI_NOP (1 << 7) /* Bit 7: No Op enable */ + +/* Set Enable Error Interrupt */ + +#define EDMA_SEEI_SHIFT (0) /* Bits 0-3: Set Enable Error Interrupt */ +#define EDMA_SEEI_MASK (15 << EDMA_SEEI_SHIFT) +# define EDMA_SEEI(n) ((uint32_t)(n) << EDMA_SEEI_SHIFT) + /* Bit 54-: Reserved */ +#define EDMA_SEEI_SAEE (1 << 6) /* Bit 6: Set All Enable Error Interrupts */ +#define EDMA_SEEI_NOP (1 << 7) /* Bit 7: No Op enable */ + +/* Clear Enable Request */ + +#define EDMA_CERQ_SHIFT (0) /* Bits 0-3: Clear Enable Request */ +#define EDMA_CERQ_MASK (15 << EDMA_CERQ_SHIFT) +# define EDMA_CERQ(n) ((uint32_t)(n) << EDMA_CERQ_SHIFT) + /* Bit 4-5: Reserved */ +#define EDMA_CERQ_CAER (1 << 6) /* Bit 6: Clear All Enable Requests */ +#define EDMA_CERQ_NOP (1 << 7) /* Bit 7: No Op enable */ + +/* Set Enable Request */ + +#define EDMA_SERQ_SHIFT (0) /* Bits 0-3: Set Enable Request */ +#define EDMA_SERQ_MASK (15 << EDMA_SERQ_SHIFT) +# define EDMA_SERQ(n) ((uint32_t)(n) << EDMA_SERQ_SHIFT) + /* Bit 4-5: Reserved */ +#define EDMA_SERQ_SAER (1 << 6) /* Bit 6: Set All Enable Requests */ +#define EDMA_SERQ_NOP (1 << 7) /* Bit 7: No Op enable */ + +/* Clear DONE Status Bit */ + +#define EDMA_CDNE_SHIFT (0) /* Bits 0-3: Clear DONE Bit */ +#define EDMA_CDNE_MASK (15 << EDMA_CDNE_SHIFT) +# define EDMA_CDNE(n) ((uint32_t)(n) << EDMA_CDNE_SHIFT) + /* Bit 4-5: Reserved */ +#define EDMA_CDNE_CADN (1 << 6) /* Bit 6: Clears All DONE Bits */ +#define EDMA_CDNE_NOP (1 << 7) /* Bit 7: No Op enable */ + +/* Set START Bit */ + +#define EDMA_SSRT_SHIFT (0) /* Bits 0-3: Set START Bit */ +#define EDMA_SSRT_MASK (15 << EDMA_SSRT_SHIFT) +# define EDMA_SSRT(n) ((uint32_t)(n) << EDMA_SSRT_SHIFT) + /* Bit 4-5: Reserved */ +#define EDMA_SSRT_SAST (1 << 6) /* Bit 6: Set All START Bits (activates all channels) */ +#define EDMA_SSRT_NOP (1 << 7) /* Bit 7: No Op enable */ + +/* Clear Error */ + +#define EDMA_CERR_SHIFT (0) /* Bits 0-3: Clear Error Indicator */ +#define EDMA_CERR_MASK (15 << EDMA_CERR_SHIFT) +# define EDMA_CERR(n) ((uint32_t)(n) << EDMA_CERR_SHIFT) + /* Bit 4-5: Reserved */ +#define EDMA_CERR_CAEI (1 << 6) /* Bit 6: Clear All Error Indicators */ +#define EDMA_CERR_NOP (1 << 7) /* Bit 7: No Op enable */ + +/* Clear Interrupt Request */ + +#define EDMA_CINT_SHIFT (0) /* Bits 0-3: Clear Interrupt Request */ +#define EDMA_CINT_MASK (15 << EDMA_CINT_SHIFT) +# define EDMA_CINT(n) ((uint32_t)(n) << EDMA_CINT_SHIFT) + /* Bit 4-5: Reserved */ +#define EDMA_CINT_CAIR (1 << 6) /* Bit 6: Clear All Interrupt Requests */ +#define EDMA_CINT_NOP (1 << 7) /* Bit 7: No Op enable */ + +/* Interrupt Request */ + +#define EDMA_INT(n) ((uint32_t)1 << (n)) /* Bit n: Interrupt Request n */ + +/* Error */ + +#define EDMA_ERR(n) ((uint32_t)1 << (n)) /* Bit n: Error In Channel n */ + +/* Hardware Request Status */ + +#define EDMA_HRS(n) ((uint32_t)1 << (n)) /* Bit n: Hardware Request Status + * Channel n */ +/* Enable Asynchronous Request in Stop */ + +#define EDMA_EARS(n) ((uint32_t)1 << (n)) /* Bit n: Enable asynchronous DMA + * request in stop mode for channel n */ +/* Channel n Priority */ + +#define EDMA_DCHPRI_CHPRI_SHIFT (0) /* Bits 0-3: Channel n Arbitration Priority */ +#define EDMA_DCHPRI_CHPRI_MASK (15 << EDMA_DCHPRI_CHPRI_SHIFT) +# define EDMA_DCHPRI_CHPRI(n) ((uint32_t)(n) << EDMA_DCHPRI_CHPRI_SHIFT) + /* Bit 4-5: Reserved */ +#define EDMA_DCHPRI_DPA (1 << 6) /* Bit 6: Disable Preempt Ability */ +#define EDMA_DCHPRI_ECP (1 << 7) /* Bit 7: Enable Channel Preemption */ + +/* TCD Source Address (32-bit address) */ +/* TCD Signed Source Address Offset (16-bit offset) */ + +/* TCD Transfer Attributes */ + +#define TCD_ATTR_SIZE_8BIT (0) /* 8-bit */ +#define TCD_ATTR_SIZE_16BIT (1) /* 16-bit */ +#define TCD_ATTR_SIZE_32BIT (2) /* 32-bit */ +#define TCD_ATTR_SIZE_64BIT (3) /* 64-bit */ +#define TCD_ATTR_SIZE_256BIT (5) /* 32-byte burst (4 beats of 64 bits) */ + +#define EDMA_TCD_ATTR_DSIZE_SHIFT (0) /* Bits 0-2: Destination data transfer size */ +#define EDMA_TCD_ATTR_DSIZE_MASK (7 << EDMA_TCD_ATTR_DSIZE_SHIFT) +# define EDMA_TCD_ATTR_DSIZE(n) ((uint32_t)(n) << EDMA_TCD_ATTR_DSIZE_SHIFT) /* 8-bit */ +# define EDMA_TCD_ATTR_DSIZE_8BIT (TCD_ATTR_SIZE_8BIT << EDMA_TCD_ATTR_DSIZE_SHIFT) /* 8-bit */ +# define EDMA_TCD_ATTR_DSIZE_16BIT (TCD_ATTR_SIZE_16BIT << EDMA_TCD_ATTR_DSIZE_SHIFT) /* 16-bit */ +# define EDMA_TCD_ATTR_DSIZE_32BIT (TCD_ATTR_SIZE_32BIT << EDMA_TCD_ATTR_DSIZE_SHIFT) /* 32-bit */ +# define EDMA_TCD_ATTR_DSIZE_64BIT (TCD_ATTR_SIZE_64BIT << EDMA_TCD_ATTR_DSIZE_SHIFT) /* 64-bit */ +# define EDMA_TCD_ATTR_DSIZE_256BIT (TCD_ATTR_SIZE_256BIT << EDMA_TCD_ATTR_DSIZE_SHIFT) /* 32-byte burst */ +#define EDMA_TCD_ATTR_DMOD_SHIFT (3) /* Bits 3-7: Destination Address Modulo */ +#define EDMA_TCD_ATTR_DMOD_MASK (31 << EDMA_TCD_ATTR_DMOD_SHIFT) +# define EDMA_TCD_ATTR_DMOD(n) ((uint32_t)(n) << EDMA_TCD_ATTR_DMOD_SHIFT) +#define EDMA_TCD_ATTR_SSIZE_SHIFT (8) /* Bits 8-10: Source data transfer size */ +#define EDMA_TCD_ATTR_SSIZE_MASK (7 << EDMA_TCD_ATTR_SSIZE_SHIFT) +# define EDMA_TCD_ATTR_SSIZE(n) ((uint32_t)(n) << EDMA_TCD_ATTR_SSIZE_SHIFT) /* 8-bit */ +# define EDMA_TCD_ATTR_SSIZE_8BIT (TCD_ATTR_SIZE_8BIT << EDMA_TCD_ATTR_SSIZE_SHIFT) /* 8-bit */ +# define EDMA_TCD_ATTR_SSIZE_16BIT (TCD_ATTR_SIZE_16BIT << EDMA_TCD_ATTR_SSIZE_SHIFT) /* 16-bit */ +# define EDMA_TCD_ATTR_SSIZE_32BIT (TCD_ATTR_SIZE_32BIT << EDMA_TCD_ATTR_SSIZE_SHIFT) /* 32-bit */ +# define EDMA_TCD_ATTR_SSIZE_64BIT (TCD_ATTR_SIZE_64BIT << EDMA_TCD_ATTR_SSIZE_SHIFT) /* 64-bit */ +# define EDMA_TCD_ATTR_SSIZE_256BIT (TCD_ATTR_SIZE_256BIT << EDMA_TCD_ATTR_SSIZE_SHIFT) /* 32-byte burst */ +#define EDMA_TCD_ATTR_SMOD_SHIFT (11) /* Bits 11-15: Source Address Modulo */ +#define EDMA_TCD_ATTR_SMOD_MASK (31 << EDMA_TCD_ATTR_SMOD_SHIFT) +# define EDMA_TCD_ATTR_SMOD(n) ((uint32_t)(n) << EDMA_TCD_ATTR_SMOD_SHIFT) + +/* TCD Signed Minor Loop Offset / Byte Count */ +/* Minor Byte Count (Minor Loop Mapping Disabled -- 32-bit byte count) */ + +/* TCD Signed Minor Loop Offset / Byte Count */ +/* Minor Byte Count (Minor Loop Mapping Enabled, offset disabled) */ + +#define EDMA_TCD_NBYTES_ML_NBYTES_SHIFT (0) /* Bits 0-29: Minor Byte Transfer Count */ +#define EDMA_TCD_NBYTES_ML_NBYTES_MASK (0x3fffffff << EDMA_TCD_NBYTES_ML_NBYTES_SHIFT) +# define EDMA_TCD_NBYTES_ML_NBYTES(n) ((uint32_t)(n) << EDMA_TCD_NBYTES_ML_NBYTES_SHIFT) +#define EDMA_TCD_NBYTES_ML_DMLOE (1 << 30) /* Bit 30: Destination Minor Loop Offset enable */ +#define EDMA_TCD_NBYTES_ML_SMLOE (1 << 31) /* Bit 31: Source Minor Loop Offset Enable */ + +/* TCD Signed Minor Loop Offset / Byte Count */ +/* Minor Byte Count (Minor Loop Mapping Enabled, offset enabled) */ + +#define EDMA_TCD_NBYTES_MLOFF_NBYTES_SHIFT (0) /* Bits 0-9: Minor Byte Transfer Count */ +#define EDMA_TCD_NBYTES_MLOFF_NBYTES_MASK (0x3ff << EDMA_TCD_NBYTES_MLOFF_NBYTES_SHIFT) +# define EDMA_TCD_NBYTES_MLOFF_NBYTES(n) ((uint32_t)(n) << EDMA_TCD_NBYTES_MLOFF_NBYTES_SHIFT) +#define EDMA_TCD_NBYTES_MLOFF_MLOFF_SHIFT (10) /* Bits 10-29: Minor Byte Transfer Count */ +#define EDMA_TCD_NBYTES_MLOFF_MLOFF_MASK (0xfffff << EDMA_TCD_NBYTES_MLOFF_MLOFF_SHIFT) +# define EDMA_TCD_NBYTES_MLOFF_MLOFF(n) ((uint32_t)(n) << EDMA_TCD_NBYTES_MLOFF_MLOFF_SHIFT) +#define EDMA_TCD_NBYTES_MLOFF_DMLOE (1 << 30) /* Bit 30: Destination Minor Loop Offset enable */ +#define EDMA_TCD_NBYTES_MLOFF_SMLOE (1 << 31) /* Bit 31: Source Minor Loop Offset Enable */ + +/* TCD Last Source Address Adjustment (32-bit address adjustment) */ +/* TCD Destination Address (32-bit address) */ +/* TCD Signed Destination Address Offset (16-bit signed address offset) */ + +/* TCD Current Minor Loop Link, Major Loop Count (Channel linking disabled) */ + +#define EDMA_TCD_CITER_CITER_SHIFT (0) /* Bit 0-14: Starting Major Iteration Count */ +#define EDMA_TCD_CITER_CITER_MASK (0x7fff << EDMA_TCD_CITER_CITER_SHIFT) +# define EDMA_TCD_CITER_CITER(n) ((uint32_t)(n) << EDMA_TCD_CITER_CITER_SHIFT) +#define EDMA_TCD_CITER_ELINK (1 << 15) /* Bit 15: Enable channel-to-channel linking + * on minor-loop complete */ + +/* TCD Current Minor Loop Link, Major Loop Count (Channel linking enabled) */ + +#define EDMA_TCD_CITER_ELINK_CITER_SHIFT (0) /* Bit 0-8: Current major iteration count */ +#define EDMA_TCD_CITER_ELINK_CITER_MASK (0x1ff << EDMA_TCD_CITER_ELINK_CITER_SHIFT) +# define EDMA_TCD_CITER_ELINK_CITER(n) ((uint32_t)(n) << EDMA_TCD_CITER_ELINK_CITER_SHIFT) +#define EDMA_TCD_CITER_ELINK_LINKCH_SHIFT (9) /* Bit 9-12: Minor Loop Link Channel Number */ +#define EDMA_TCD_CITER_ELINK_LINKCH_MASK (15 << EDMA_TCD_CITER_ELINK_LINKCH_SHIFT) +# define EDMA_TCD_CITER_ELINK_LINKCH(n) ((uint32_t)(n) << EDMA_TCD_CITER_ELINK_LINKCH_SHIFT) + /* Bit 13-14: Reserved */ +#define EDMA_TCD_CITER_ELINK_ELINK (1 << 15) /* Bit 15: Enable channel-to-channel linking + * on minor-loop complete */ + +/* TCD Last Destination Address Adjustment/Scatter Gather Address (32-bit address) */ + +/* TCD Control and Status */ + +#define EDMA_TCD_CSR_START (1 << 0) /* Bit 0: Channel Start */ +#define EDMA_TCD_CSR_INTMAJOR (1 << 1) /* Bit 1: Enable an interrupt when major + * iteration count completes */ +#define EDMA_TCD_CSR_INTHALF (1 << 2) /* Bit 2: Enable an interrupt when major + * counter is half complete */ +#define EDMA_TCD_CSR_DREQ (1 << 3) /* Bit 3: Disable Request */ +#define EDMA_TCD_CSR_ESG (1 << 4) /* Bit 4: Enable Scatter/Gather Processing */ +#define EDMA_TCD_CSR_MAJORELINK (1 << 5) /* Bit 5: Enable channel-to-channel linking + * on major loop complete */ +#define EDMA_TCD_CSR_ACTIVE (1 << 6) /* Bit 6: Channel Active */ +#define EDMA_TCD_CSR_DONE (1 << 7) /* Bit 7: Channel Done */ +#define EDMA_TCD_CSR_MAJORLINKCH_SHIFT (8) /* Bits 8-11: Major Loop Link Channel Number */ +#define EDMA_TCD_CSR_MAJORLINKCH_MASK (15 << EDMA_TCD_CSR_MAJORLINKCH_SHIFT) +# define EDMA_TCD_CSR_MAJORLINKCH(n) ((uint32_t)(n) << EDMA_TCD_CSR_MAJORLINKCH_SHIFT) + /* Bit 112-3: Reserved */ +#define EDMA_TCD_CSR_BWC_SHIFT (14) /* Bits 14-15: Bandwidth Control */ +#define EDMA_TCD_CSR_BWC_MASK (3 << EDMA_TCD_CSR_BWC_SHIFT) +# define EDMA_TCD_CSR_BWC_NONE (0 << EDMA_TCD_CSR_BWC_SHIFT) /* No eDMA engine stalls */ +# define EDMA_TCD_CSR_BWC_4CYCLES (2 << EDMA_TCD_CSR_BWC_SHIFT) /* eDMA engine stalls for 4 + * cycles after each R/W */ +# define EDMA_TCD_CSR_BWC_8CYCLES (3 << EDMA_TCD_CSR_BWC_SHIFT) /* eDMA engine stalls for 8 + * cycles after each R/W */ + +/* TCD Beginning Minor Loop Link, Major Loop Count (Channel linking disabled) */ + +#define EDMA_TCD_BITER_BITER_SHIFT (0) /* Bit 0-14: Starting Major Iteration Count */ +#define EDMA_TCD_BITER_BITER_MASK (0x7fff << EDMA_TCD_BITER_BITER_SHIFT) +# define EDMA_TCD_BITER_BITER(n) ((uint32_t)(n) << EDMA_TCD_BITER_BITER_SHIFT) +#define EDMA_TCD_BITER_ELINK (1 << 15) /* Bit 15: Enable channel-to-channel linking + * on minor-loop complete */ + +/* TCD Beginning Minor Loop Link, Major Loop Count (Channel linking enabled) */ + +#define EDMA_TCD_BITER_ELINK_BITER_SHIFT (0) /* Bit 0-8: Current major iteration count */ +#define EDMA_TCD_BITER_ELINK_BITER_MASK (0x1ff << EDMA_TCD_BITER_ELINK_BITER_SHIFT) +# define EDMA_TCD_BITER_ELINK_BITER(n) ((uint32_t)(n) << EDMA_TCD_BITER_ELINK_BITER_SHIFT) +#define EDMA_TCD_BITER_ELINK_LINKCH_SHIFT (9) /* Bit 9-12: Link Channel Number */ +#define EDMA_TCD_BITER_ELINK_LINKCH_MASK (15 << EDMA_TCD_BITER_ELINK_LINKCH_SHIFT) +# define EDMA_TCD_BITER_ELINK_LINKCH(n) ((uint32_t)(n) << EDMA_TCD_BITER_ELINK_LINKCH_SHIFT) + /* Bit 13-4: Reserved */ +#define EDMA_TCD_BITER_ELINK_ELINK (1 << 15) /* Bit 15: Enable channel-to-channel linking + * on minor-loop complete */ + +/**************************************************************************************************** + * Public Types + ****************************************************************************************************/ + +/* In-memory representation of the 32-byte Transfer Control Descriptor (TCD) */ + +struct s32k1xx_edmatcd_s +{ + uint32_t saddr; /* Offset: 0x0000 TCD Source Address */ + uint16_t soff; /* Offset: 0x0004 TCD Signed Source Address Offset */ + uint16_t attr; /* Offset: 0x0006 TCD Transfer Attributes */ + uint32_t nbytes; /* Offset: 0x0008 TCD Signed Minor Loop Offset / Byte Count */ + uint32_t slast; /* Offset: 0x000c TCD Last Source Address Adjustment */ + uint32_t daddr; /* Offset: 0x0010 TCD Destination Address */ + uint16_t doff; /* Offset: 0x0014 TCD Signed Destination Address Offset */ + uint16_t citer; /* Offset: 0x0016 TCD Current Minor Loop Link, Major Loop Count */ + uint32_t dlastsga; /* Offset: 0x0018 TCD Last Destination Address Adjustment/Scatter Gather Address */ + uint16_t csr; /* Offset: 0x001c TCD Control and Status */ + uint16_t biter; /* Offset: 0x001e TCD Beginning Minor Loop Link, Major Loop Count */ +}; + +#endif /* __ARCH_ARM_SRC_S32K1XX_HARDWARE_S32K1XX_EDMA_H */ diff --git a/arch/arm/src/s32k1xx/s32k1xx_edma.c b/arch/arm/src/s32k1xx/s32k1xx_edma.c new file mode 100644 index 0000000000..bba1308601 --- /dev/null +++ b/arch/arm/src/s32k1xx/s32k1xx_edma.c @@ -0,0 +1,1453 @@ +/**************************************************************************** + * arch/arm/src/s32k1xx/s32k1xx_edma.c + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * This file was leveraged from the NuttX i.MXRT port. Portions of that eDMA logic + * derived from NXP sample code which has a compatible BSD 3-clause license: + * + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "up_arch.h" +#include "up_internal.h" +#include "sched/sched.h" + +#include "chip.h" +#include "hardware/s32k1xx_edma.h" +#include "hardware/s32k1xx_dmamux.h" +#include "s32k1xx_edma.h" + +#ifdef CONFIG_S32K1XX_EDMA + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* TCD Alignment. + * + * eDMA TCDs must be aligned with the D-Cache line boundaries to facilitate + * cache operations on the TCDs when the D-Cache is enabled. + * + * NOTE: The TCDs are 32-bytes in length. We implicitly assume that the + * D-Cache line size is also 32-bits. Otherwise, padding would be required + * at the ends of the TCDS and buffers to protect data after the end of from + * invalidation. + */ + +#ifdef CONFIG_ARMV7M_DCACHE +/* Align to the cache line size which we assume is >= 8 */ + +# define EDMA_ALIGN ARMV7M_DCACHE_LINESIZE +# define EDMA_ALIGN_MASK (EDMA_ALIGN-1) +# define EDMA_ALIGN_UP(n) (((n) + EDMA_ALIGN_MASK) & ~EDMA_ALIGN_MASK) + +#else +/* Special alignment is not required in this case, but we will align to 8-bytes */ + +# define EDMA_ALIGN 8 +# define EDMA_ALIGN_MASK 7 +# define EDMA_ALIGN_UP(n) (((n) + 7) & ~7) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* State of a DMA channel */ + +enum s32k1xx_dmastate_e +{ + S32K1XX_DMA_IDLE = 0, /* No DMA in progress */ + S32K1XX_DMA_CONFIGURED, /* DMA configured, but not yet started */ + S32K1XX_DMA_ACTIVE /* DMA has been started and is in progress */ +}; + +/* This structure describes one DMA channel */ + +struct s32k1xx_dmach_s +{ + uint8_t chan; /* DMA channel number (0-S32K1XX_EDMA_NCHANNELS) */ + bool inuse; /* true: The DMA channel is in use */ + uint8_t ttype; /* Transfer type: M2M, M2P, P2M, or P2P */ + uint8_t state; /* Channel state. See enum s32k1xx_dmastate_e */ + uint32_t flags; /* DMA channel flags */ + edma_callback_t callback; /* Callback invoked when the DMA completes */ + void *arg; /* Argument passed to callback function */ + +#if CONFIG_S32K1XX_EDMA_NTCD > 0 + /* That TCD list is linked through the DLAST SGA field. The first transfer + * to be performed is at the head of the list. Subsequent TCDs are added at + * the tail of the list. + */ + + struct s32k1xx_edmatcd_s *head; /* First TCD in the list */ + struct s32k1xx_edmatcd_s *tail; /* Last TCD in the list */ +#endif +}; + +/* This structure describes the state of the eDMA controller */ + +struct s32k1xx_edma_s +{ + /* These semaphores protect the DMA channel and descriptor tables */ + + sem_t chsem; /* Protects channel table */ +#if CONFIG_S32K1XX_EDMA_NTCD > 0 + sem_t dsem; /* Supports wait for free descriptors */ +#endif + + /* This array describes each DMA channel */ + + struct s32k1xx_dmach_s dmach[S32K1XX_EDMA_NCHANNELS]; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The state of the eDMA */ + +static struct s32k1xx_edma_s g_edma; + +#if CONFIG_S32K1XX_EDMA_NTCD > 0 +/* This is a singly-linked list of free TCDs */ + +static sq_queue_t g_tcd_free; + +/* This is a pool of pre-allocated TCDs */ + +static struct s32k1xx_edmatcd_s g_tcd_pool[CONFIG_S32K1XX_EDMA_NTCD] + __attribute__((aligned(EDMA_ALIGN))); +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: s32k1xx_takechsem() and s32k1xx_givechsem() + * + * Description: + * Used to get exclusive access to the DMA channel table for channel + * allocation. + * + ****************************************************************************/ + +static void s32k1xx_takechsem(void) +{ + int ret; + + do + { + /* Take the semaphore (perhaps waiting) */ + + ret = nxsem_wait(&g_edma.chsem); + + /* The only case that an error should occur here is if the wait was + * awakened by a signal. + */ + + DEBUGASSERT(ret == OK || ret == -EINTR || ret == -ECANCELED); + } + while (ret == -EINTR); +} + +static inline void s32k1xx_givechsem(void) +{ + (void)nxsem_post(&g_edma.chsem); +} + +/**************************************************************************** + * Name: s32k1xx_takedsem() and s32k1xx_givedsem() + * + * Description: + * Used to wait for availability of descriptors in the descriptor table. + * + ****************************************************************************/ + +#if CONFIG_S32K1XX_EDMA_NTCD > 0 +static void s32k1xx_takedsem(void) +{ + int ret; + + do + { + /* Take the semaphore (perhaps waiting) */ + + ret = nxsem_wait(&g_edma.dsem); + + /* The only case that an error should occur here is if the wait was + * awakened by a signal. + */ + + DEBUGASSERT(ret == OK || ret == -EINTR || ret == -ECANCELED); + } + while (ret == -EINTR); +} + +static inline void s32k1xx_givedsem(void) +{ + (void)nxsem_post(&g_edma.dsem); +} +#endif + +/**************************************************************************** + * Name: s32k1xx_tcd_alloc + * + * Description: + * Allocate an in-memory, TCD + * + ****************************************************************************/ + +#if CONFIG_S32K1XX_EDMA_NTCD > 0 +static struct s32k1xx_edmatcd_s *s32k1xx_tcd_alloc(void) +{ + struct s32k1xx_edmatcd_s *tcd; + irqstate_t flags; + + /* Take the 'dsem'. When we hold the the 'dsem', then we know that one + * TCD is reserved for us in the free list. + * + * NOTE: We use a critical section here because we may block waiting for + * the 'dsem'. The critical section will be suspended while we are + * waiting. + */ + + flags = enter_critical_section(); + s32k1xx_takedsem(); + + /* Now there should be a TCD in the free list reserved just for us */ + + tcd = (struct s32k1xx_edmatcd_s *)sq_remfirst(&g_tcd_free); + DEBUGASSERT(tcd != NULL); + + leave_critical_section(flags); + return tcd; +} +#endif + +/**************************************************************************** + * Name: s32k1xx_tcd_free + * + * Description: + * Free an in-memory, TCD + * + ****************************************************************************/ + +#if CONFIG_S32K1XX_EDMA_NTCD > 0 +static void s32k1xx_tcd_free(struct s32k1xx_edmatcd_s *tcd) +{ + irqstate_t flags; + + /* Add the the TCD to the end of the free list and post the 'dsem', + * possibly waking up another thread that might be waiting for + * a TCD. + */ + + flags = spin_lock_irqsave(); + sq_addlast((sq_entry_t *)tcd, &g_tcd_free); + (void)s32k1xx_givedsem(); + spin_unlock_irqrestore(flags); +} +#endif + +/**************************************************************************** + * Name: s32k1xx_tcd_initialize() + * + * Description: + * Initialize the TCD free list from the pool of pre-allocated TCDs. + * + * Assumptions: + * Called early in the initialization sequence so no special protection is + * necessary. + * + ****************************************************************************/ + +#if CONFIG_S32K1XX_EDMA_NTCD > 0 +static inline void s32k1xx_tcd_initialize(void) +{ + sq_entry_t *tcd; + int i; + + /* Add each pre-allocated TCD to the tail of the TCD free list */ + + sq_init(&g_tcd_free); + for (i = 0; i < CONFIG_S32K1XX_EDMA_NTCD; i++) + { + tcd = (sq_entry_t *)&g_tcd_pool[i]; + sq_addlast(tcd, &g_tcd_free); + } +} +#endif + +/************************************************************************************ + * Name: s32k1xx_tcd_chanlink + * + * Description: + * This function configures either a minor link or a major link. The minor link + * means the channel link is triggered every time CITER decreases by 1. The major + * link means that the channel link is triggered when the CITER is exhausted. + * + * NOTE: Users should ensure that DONE flag is cleared before calling this + * interface, or the configuration is invalid. + * + * Input Parameters: + * tcd - Point to the TCD structure. + * type - Channel link type. + * chan - The linked channel number. + * + * Returned Value: + * None + * + ************************************************************************************/ + +#ifdef CONFIG_S32K1XX_EDMA_ELINK +static inline void s32k1xx_tcd_chanlink(uint8_t flags, struct s32k1xx_dmach_s *linkch, + struct s32k1xx_edmatcd_s *tcd) +{ + uint16_t regval16; + + flags &= EDMA_CONFIG_LINKTYPE_MASK; + + if (linkch == NULL || flags == EDMA_CONFIG_LINKTYPE_LINKNONE) + { +#if 0 /* Already done */ + /* No link or no link channel provided */ + + /* Disable minor links */ + + tcd->citer &= ~EDMA_TCD_CITER_ELINK; + tcd->biter &= ~EDMA_TCD_BITER_ELINK; + + /* Disable major link */ + + tcd->csr &= ~EDMA_TCD_CSR_MAJORELINK; +#endif + } + else if (flags == EDMA_CONFIG_LINKTYPE_MINORLINK) /* Minor link config */ + { + /* Enable minor link */ + + tcd->citer |= EDMA_TCD_CITER_ELINK_ELINK; + tcd->biter |= EDMA_TCD_BITER_ELINK_ELINK; + + /* Set linked channel */ + + regval16 = tcd->citer; + regval16 &= ~EDMA_TCD_CITER_ELINK_LINKCH_MASK; + regval16 |= EDMA_TCD_CITER_ELINK_LINKCH(linkch->chan); + tcd->citer = regval16; + + regval16 = tcd->biter; + regval16 &= ~EDMA_TCD_BITER_ELINK_LINKCH_MASK; + regval16 |= EDMA_TCD_BITER_ELINK_LINKCH(linkch->chan); + tcd->biter = regval16; + } + else /* if (flags == EDMA_CONFIG_LINKTYPE_MAJORLINK) Major link config */ + { + /* Enable major link */ + + regval16 = tcd->csr; + regval16 |= EDMA_TCD_CSR_MAJORELINK; + tcd->csr = regval16; + + /* Set major linked channel */ + + regval16 &= ~EDMA_TCD_CSR_MAJORLINKCH_MASK; + regval16 |= EDMA_TCD_CSR_MAJORLINKCH(linkch->chan); + tcd->csr = regval16; + } +} +#endif + +/**************************************************************************** + * Name: s32k1xx_tcd_configure + * + * Description: + * Configure all TCD registers to the specified values. 'tcd' is an + * 'overlay' that may refer either to either the TCD register set or to an + * in-memory TCD structure. + * + ****************************************************************************/ + +static inline void s32k1xx_tcd_configure(struct s32k1xx_edmatcd_s *tcd, + const struct s32k1xx_edma_xfrconfig_s *config) +{ + tcd->saddr = config->saddr; + tcd->soff = config->soff; + tcd->attr = EDMA_TCD_ATTR_SSIZE(config->ssize) | /* Transfer Attributes */ + EDMA_TCD_ATTR_DSIZE(config->dsize); + tcd->nbytes = config->nbytes; + tcd->slast = tcd->slast; + tcd->daddr = config->daddr; + tcd->doff = config->doff; + tcd->citer = config->iter & EDMA_TCD_CITER_CITER_MASK; + tcd->biter = config->iter & EDMA_TCD_BITER_BITER_MASK; + tcd->csr = EDMA_TCD_CSR_DREQ; /* Assume last transfer */ + tcd->dlastsga = 0; + + /* And special case flags */ + +#ifdef CONFIG_S32K1XX_EDMA_ELINK + /* Configure major/minor link mapping */ + + s32k1xx_tcd_chanlink(config->flags, (struct s32k1xx_dmach_s *)config->linkch, + tcd); +#endif +} + +/**************************************************************************** + * Name: s32k1xx_tcd_instantiate + * + * Description: + * Copy an in-memory TCD into eDMA channel TCD registers + * + ****************************************************************************/ + +#if CONFIG_S32K1XX_EDMA_NTCD > 0 +static void s32k1xx_tcd_instantiate(struct s32k1xx_dmach_s *dmach, + const struct s32k1xx_edmatcd_s *tcd) +{ + uintptr_t base = S32K1XX_EDMA_TCD_BASE(dmach->chan); + + /* Push tcd into hardware TCD register */ + + putreg32(tcd->saddr, base + S32K1XX_EDMA_TCD_SADDR_OFFSET); + putreg16(tcd->soff, base + S32K1XX_EDMA_TCD_SOFF_OFFSET); + putreg16(tcd->attr, base + S32K1XX_EDMA_TCD_ATTR_OFFSET); + putreg32(tcd->nbytes, base + S32K1XX_EDMA_TCD_NBYTES_ML_OFFSET); + putreg32(tcd->slast, base + S32K1XX_EDMA_TCD_SLAST_OFFSET); + putreg32(tcd->daddr, base + S32K1XX_EDMA_TCD_DADDR_OFFSET); + putreg16(tcd->doff, base + S32K1XX_EDMA_TCD_DOFF_OFFSET); + putreg16(tcd->citer, base + S32K1XX_EDMA_TCD_CITER_ELINK_OFFSET); + putreg32(tcd->dlastsga, base + S32K1XX_EDMA_TCD_DLASTSGA_OFFSET); + + /* Clear DONE bit first, otherwise ESG cannot be set */ + + putreg16(0, base + S32K1XX_EDMA_TCD_CSR_OFFSET); + putreg16(tcd->csr, base + S32K1XX_EDMA_TCD_CSR_OFFSET); + + putreg16(tcd->biter, base + S32K1XX_EDMA_TCD_BITER_ELINK_OFFSET); +} +#endif + +/**************************************************************************** + * Name: s32k1xx_dmaterminate + * + * Description: + * Terminate the DMA transfer and disable the DMA channel + * + ****************************************************************************/ + +static void s32k1xx_dmaterminate(struct s32k1xx_dmach_s *dmach, int result) +{ +#if CONFIG_S32K1XX_EDMA_NTCD > 0 + struct s32k1xx_edmatcd_s *tcd; + struct s32k1xx_edmatcd_s *next; +#endif + uintptr_t regaddr; + uint8_t regval8; + uint8_t chan; + + /* Disable channel ERROR interrupts */ + + chan = dmach->chan; + regval8 = EDMA_CEEI(chan); + putreg8(regval8, S32K1XX_EDMA_CEEI); + + /* Disable channel IRQ requests */ + + regval8 = EDMA_CERQ(chan); + putreg8(regval8, S32K1XX_EDMA_CERQ); + + /* Clear CSR to disable channel. Because if the given channel started, + * transfer CSR will be not zero. Because if it is the last transfer, DREQ + * will be set. If not, ESG will be set. + */ + + regaddr = S32K1XX_EDMA_TCD_CSR(chan); + putreg16(0, regaddr); + + /* Cancel next TCD transfer. */ + + regaddr = S32K1XX_EDMA_TCD_DLASTSGA(chan); + putreg16(0, regaddr); + +#if CONFIG_S32K1XX_EDMA_NTCD > 0 + /* Return all allocated TCDs to the free list */ + + for (tcd = dmach->head; tcd != NULL; tcd = next) + { + next = (struct s32k1xx_edmatcd_s *)tcd->dlastsga; + s32k1xx_tcd_free(tcd); + } + + dmach->head = NULL; + dmach->tail = NULL; +#endif + + /* Check for an Rx (memory-to-peripheral/memory-to-memory) DMA transfer */ + + if (dmach->ttype == EMDA_MEM2MEM || dmach->ttype == EMDA_PERIPH2MEM) + { + /* Invalidate the cache to force reloads from memory. */ + +#warning Missing logic + } + + /* Perform the DMA complete callback */ + + if (dmach->callback) + { + dmach->callback((DMACH_HANDLE)dmach, dmach->arg, true, result); + } + + dmach->callback = NULL; + dmach->arg = NULL; + dmach->state = S32K1XX_DMA_IDLE; +} + +/**************************************************************************** + * Name: s32k1xx_edma_interrupt + * + * Description: + * DMA interrupt handler. This function clears the channel major + * interrupt flag and calls the callback function if it is not NULL. + * + * NOTE: For the case using TCD queue, when the major iteration count is + * exhausted, additional operations are performed. These include the + * final address adjustments and reloading of the BITER field into the + * CITER. Assertion of an optional interrupt request also occurs at this + * time, as does a possible fetch of a new TCD from memory using the + * scatter/gather address pointer included in the descriptor (if scatter/ + * gather is enabled). + * + ****************************************************************************/ + +static int s32k1xx_edma_interrupt(int irq, void *context, FAR void *arg) +{ + struct s32k1xx_dmach_s *dmach; + uintptr_t regaddr; + uint32_t regval32; + uint16_t regval16; + uint8_t regval8; + uint8_t chan; + int result; + + /* 'arg' should the DMA channel instance. */ + + dmach = (struct s32k1xx_dmach_s *)arg; + DEBUGASSERT(dmach != NULL); + + chan = dmach->chan; + DEBUGASSERT(chan < S32K1XX_EDMA_NCHANNELS && dmach == &g_edma.dmach[chan]); + + /* Check for an eDMA pending interrupt on this channel */ + + regval32 = getreg32(S32K1XX_EDMA_INT); + if ((regval32 & EDMA_INT(chan)) != 0) + { + /* An interrupt is pending. This should only happen if the channel is + * active. + */ + + DEBUGASSERT(dmach->state == S32K1XX_DMA_ACTIVE); + + /* Clear the pending eDMA channel interrupt */ + + regval8 = EDMA_CINT(chan); + putreg32(regval8, S32K1XX_EDMA_CINT); + + /* Get the eDMA TCD Control and Status register value. */ + + regaddr = S32K1XX_EDMA_TCD_CSR(chan); + regval16 = getreg16(regaddr); + + /* Check if transfer has finished. */ + + if ((regval16 & EDMA_TCD_CSR_DONE) != 0) + { + /* Clear the pending DONE interrupt status. */ + + regval8 = EDMA_CDNE(chan); + putreg8(regval8, S32K1XX_EDMA_CDNE); + result = OK; + } + else + { +#if CONFIG_S32K1XX_EDMA_NTCD > 0 + /* Perform the end-of-major-cycle DMA callback */ + + if (dmach->callback != NULL) + { + dmach->callback((DMACH_HANDLE)dmach, dmach->arg, + false, OK); + } + + return; +#else + /* Otherwise the interrupt was not expected! */ + + DEBUGPANIC(); + result = -EPIPE; +#endif + } + + /* Terminate the transfer when it is done. */ + + s32k1xx_dmaterminate(dmach, result); + } +} + +/**************************************************************************** + * Name: s32k1xx_error_interrupt + * + * Description: + * DMA error interrupt handler + * + ****************************************************************************/ + +static int s32k1xx_error_interrupt(int irq, void *context, FAR void *arg) +{ + uint32_t errstatus; + uint32_t errmask; + uint8_t regval8; + unsigned int chan; + + /* Get the set of pending error interrupts */ + + errstatus = getreg32(S32K1XX_EDMA_ERR); + + /* Check for an error on each channel */ + + for (chan = 0; chan < S32K1XX_EDMA_NCHANNELS && errstatus != 0; chan++) + { + /* Check for a pending error interrupt on each channel */ + + errmask = EDMA_ERR(chan); + if ((errstatus & errmask) != 0) + { + dmaerr("ERROR: DMACH%u ES=%08lx\n", + chan, (unsigned long)getreg32(S32K1XX_EDMA_ES)); + + /* Clear the pending error interrupt status. */ + + regval8 = EDMA_CERR(chan); + putreg32(regval8, S32K1XX_EDMA_CERR); + + /* Remove the bit from the sample ERR register so that perhaps we + * can exit this loop early. + */ + + errstatus &= ~errmask; + + /* Terminate the transfer on any error */ + + s32k1xx_dmaterminate(&g_edma.dmach[chan], -EIO); + } + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_dma_initialize + * + * Description: + * Initialize the DMA subsystem + * + * NOTE: This assumes that board-specific logic has enabled clocking to + * the DMA module as part of the clock initialization logic. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void weak_function up_dma_initialize(void) +{ + uintptr_t regaddr; + uint32_t regval; + int i; + + dmainfo("Initialize eDMA\n"); + + /* Configure the eDMA controller */ + + regval = getreg32(S32K1XX_EDMA_CR); + regval &= ~(EDMA_CR_EDBG | EDMA_CR_ERCA | EDMA_CR_HOE | EDMA_CR_CLM | + EDMA_CR_EMLM); + +#ifdef CONFIG_S32K1XX_EDMA_EDBG + regval |= EDMA_CR_EDBG; /* Enable Debug */ +#endif +#ifdef CONFIG_S32K1XX_EDMA_ERCA + regval |= EDMA_CR_ERCA; /* Enable Round Robin Channel Arbitration */ +#endif +#ifdef CONFIG_S32K1XX_EDMA_HOE + regval |= EDMA_CR_HOE; /* Halt On Error */ +#endif +#ifdef CONFIG_S32K1XX_EDMA_CLM + regval |= EDMA_CR_CLM; /* Continuous Link Mode */ +#endif +#ifdef CONFIG_S32K1XX_EDMA_EMLIM + regval |= EDMA_CR_EMLM; /* Enable Minor Loop Mapping */ +#endif + + putreg32(regval, S32K1XX_EDMA_CR); + + /* Initialize data structures */ + + memset(&g_edma, 0, sizeof(struct s32k1xx_edma_s)); + for (i = 0; i < S32K1XX_EDMA_NCHANNELS; i++) + { + g_edma.dmach[i].chan = i; + } + + /* Initialize semaphores */ + + nxsem_init(&g_edma.chsem, 0, 1); +#if CONFIG_S32K1XX_EDMA_NTCD > 0 + nxsem_init(&g_edma.dsem, 0, CONFIG_S32K1XX_EDMA_NTCD); + + /* The 'dsem' is used for signaling rather than mutual exclusion and, + * hence, should not have priority inheritance enabled. + */ + + nxsem_setprotocol(&g_edma.dsem, SEM_PRIO_NONE); + + /* Initialize the list of of free TCDs from the pool of pre-allocated TCDs. */ + + s32k1xx_tcd_initialize(); +#endif + + /* Attach DMA interrupt vectors. */ + + (void)irq_attach(S32K1XX_IRQ_DMACH0, s32k1xx_edma_interrupt, &g_edma.dmach[0]); + (void)irq_attach(S32K1XX_IRQ_DMACH1, s32k1xx_edma_interrupt, &g_edma.dmach[1]); + (void)irq_attach(S32K1XX_IRQ_DMACH2, s32k1xx_edma_interrupt, &g_edma.dmach[2]); + (void)irq_attach(S32K1XX_IRQ_DMACH3, s32k1xx_edma_interrupt, &g_edma.dmach[3]); +#if S32K1XX_EDMA_NCHANNELS > 4 + (void)irq_attach(S32K1XX_IRQ_DMACH4, s32k1xx_edma_interrupt, &g_edma.dmach[4]); + (void)irq_attach(S32K1XX_IRQ_DMACH5, s32k1xx_edma_interrupt, &g_edma.dmach[5]); + (void)irq_attach(S32K1XX_IRQ_DMACH6, s32k1xx_edma_interrupt, &g_edma.dmach[6]); + (void)irq_attach(S32K1XX_IRQ_DMACH7, s32k1xx_edma_interrupt, &g_edma.dmach[7]); + (void)irq_attach(S32K1XX_IRQ_DMACH8, s32k1xx_edma_interrupt, &g_edma.dmach[8]); + (void)irq_attach(S32K1XX_IRQ_DMACH9, s32k1xx_edma_interrupt, &g_edma.dmach[9]); + (void)irq_attach(S32K1XX_IRQ_DMACH10, s32k1xx_edma_interrupt, &g_edma.dmach[10]); + (void)irq_attach(S32K1XX_IRQ_DMACH11, s32k1xx_edma_interrupt, &g_edma.dmach[11]); + (void)irq_attach(S32K1XX_IRQ_DMACH12, s32k1xx_edma_interrupt, &g_edma.dmach[12]); + (void)irq_attach(S32K1XX_IRQ_DMACH13, s32k1xx_edma_interrupt, &g_edma.dmach[13]); + (void)irq_attach(S32K1XX_IRQ_DMACH14, s32k1xx_edma_interrupt, &g_edma.dmach[14]); + (void)irq_attach(S32K1XX_IRQ_DMACH15, s32k1xx_edma_interrupt, &g_edma.dmach[15]); +#endif + /* Attach the DMA error interrupt vector */ + + (void)irq_attach(S32K1XX_IRQ_DMACH_ERR, s32k1xx_error_interrupt, NULL); + + /* Disable and clear all error interrupts */ + + putreg32(0, S32K1XX_EDMA_EEI); + putreg32(0xffffffff, S32K1XX_EDMA_ERR); + + /* Disable all DMA channel interrupts at the eDMA controller */ + + for (i = 0; i < S32K1XX_EDMA_NCHANNELS; i++) + { + /* Disable all DMA channels and DMA channel interrupts */ + + regaddr = S32K1XX_EDMA_TCD_CSR(i); + putreg16(0, regaddr); + } + + /* Clear all pending DMA channel interrupts */ + + putreg32(0xffffffff, S32K1XX_EDMA_INT); + + /* Enable the channel interrupts at the NVIC (still disabled at the eDMA + * controller). + */ + + up_enable_irq(S32K1XX_IRQ_DMACH0); + up_enable_irq(S32K1XX_IRQ_DMACH1); + up_enable_irq(S32K1XX_IRQ_DMACH2); + up_enable_irq(S32K1XX_IRQ_DMACH3); +#if S32K1XX_EDMA_NCHANNELS > 4 + up_enable_irq(S32K1XX_IRQ_DMACH4); + up_enable_irq(S32K1XX_IRQ_DMACH5); + up_enable_irq(S32K1XX_IRQ_DMACH6); + up_enable_irq(S32K1XX_IRQ_DMACH7); + up_enable_irq(S32K1XX_IRQ_DMACH8); + up_enable_irq(S32K1XX_IRQ_DMACH9); + up_enable_irq(S32K1XX_IRQ_DMACH10); + up_enable_irq(S32K1XX_IRQ_DMACH11); + up_enable_irq(S32K1XX_IRQ_DMACH12); + up_enable_irq(S32K1XX_IRQ_DMACH13); + up_enable_irq(S32K1XX_IRQ_DMACH14); + up_enable_irq(S32K1XX_IRQ_DMACH15); +#endif + + /* Enable the DMA error interrupt */ + + up_enable_irq(S32K1XX_IRQ_DMACH_ERR); +} + +/**************************************************************************** + * Name: s32k1xx_dmach_alloc + * + * Allocate a DMA channel. This function sets aside a DMA channel, + * initializes the DMAMUX for the channel, then gives the caller exclusive + * access to the DMA channel. + * + * Input Parameters: + * dmamux - DMAMUX configuration see DMAMUX channel configuration register + * bit-field definitions in hardware/s32k1xx_dmamux.h. Settings include: + * + * DMAMUX_CHCFG_SOURCE Chip-specific DMA source (required) + * DMAMUX_CHCFG_AON DMA Channel Always Enable (optional) + * DMAMUX_CHCFG_TRIG DMA Channel Trigger Enable (optional) + * DMAMUX_CHCFG_ENBL DMA Mux Channel Enable (required) + * + * A value of zero will disable the DMAMUX channel. + * dchpri - DCHPRI channel priority configuration. See DCHPRI channel + * configuration register bit-field definitions in + * hardware/s32k1xx_edma.h. Meaningful settings include: + * + * EDMA_DCHPRI_CHPRI Channel Arbitration Priority + * DCHPRI_DPA Disable Preempt Ability + * DCHPRI_ECP Enable Channel Preemption + * + * The power-on default, 0x05, is a reasonable choice. + * + * Returned Value: + * If a DMA channel is available, this function returns a non-NULL, void* + * DMA channel handle. NULL is returned on any failure. + * + ****************************************************************************/ + +DMACH_HANDLE s32k1xx_dmach_alloc(uint32_t dmamux, uint8_t dchpri) +{ + struct s32k1xx_dmach_s *dmach; + unsigned int chndx; + + /* Search for an available DMA channel */ + + dmach = NULL; + s32k1xx_takechsem(); + for (chndx = 0; chndx < S32K1XX_EDMA_NCHANNELS; chndx++) + { + struct s32k1xx_dmach_s *candidate = &g_edma.dmach[chndx]; + uintptr_t regaddr; + uint8_t regval8; + + if (!candidate->inuse) + { + dmach = candidate; + dmach->inuse = true; + dmach->state = S32K1XX_DMA_IDLE; + + /* Clear any pending interrupts on the channel */ + + DEBUGASSERT(chndx == dmach->chan); + regaddr = S32K1XX_EDMA_TCD_CSR(chndx); + putreg16(0, regaddr); + + /* Make sure that the channel is disabled. */ + + regval8 = EDMA_CERQ(chndx); + putreg8(regval8, S32K1XX_EDMA_CERQ); + + /* Set the DMAMUX register associated with this channel */ + + regaddr = S32K1XX_DMAMUX_CHCFG(chndx); + putreg32(dmamux, regaddr); + break; + } + } + + s32k1xx_givechsem(); + + /* Show the result of the allocation */ + + if (dmach != NULL) + { + dmainfo("CH%d: returning dmach: %p\n", dmach->chan, dmach); + } + else + { + dmaerr("ERROR: Failed allocate eDMA channel\n"); + } + + return (DMACH_HANDLE)dmach; +} + +/**************************************************************************** + * Name: s32k1xx_dmach_free + * + * Description: + * Release a DMA channel. NOTE: The 'handle' used in this argument must + * NEVER be used again until s32k1xx_dmach_alloc() is called again to re-gain + * a valid handle. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void s32k1xx_dmach_free(DMACH_HANDLE handle) +{ + struct s32k1xx_dmach_s *dmach = (struct s32k1xx_dmach_s *)handle; + uintptr_t regaddr; + uint8_t regval8; + + dmainfo("dmach: %p\n", dmach); + DEBUGASSERT(dmach != NULL && dmach->inuse && dmach->state != S32K1XX_DMA_ACTIVE); + + /* Mark the channel no longer in use. Clearing the inuse flag is an atomic + * operation and so should be safe. + */ + + dmach->flags = 0; + dmach->inuse = false; /* No longer in use */ + dmach->state = S32K1XX_DMA_IDLE; /* Better not be active! */ + + /* Make sure that the channel is disabled. */ + + regval8 = EDMA_CERQ(dmach->chan); + putreg8(regval8, S32K1XX_EDMA_CERQ); + + /* Disable the associated DMAMUX */ + + regaddr = S32K1XX_DMAMUX_CHCFG(dmach->chan); + putreg32(0, regaddr); +} + +/**************************************************************************** + * Name: s32k1xx_dmach_xfrsetup + * + * Description: + * This function adds the eDMA transfer to the DMA sequence. The request + * is setup according to the content of the transfer configuration + * structure. For "normal" DMA, s32k1xx_dmach_xfrsetup is called only once. + * Scatter/gather DMA is accomplished by calling this function repeatedly, + * once for each transfer in the sequence. Scatter/gather DMA processing + * is enabled automatically when the second transfer configuration is received. + * + * This function may be called multiple times to handle multiple, + * discontinuous transfers (scatter-gather) + * + * Input Parameters: + * handle - DMA channel handle created by s32k1xx_dmach_alloc() + * config - A DMA transfer configuration instance, populated by the + * The content of 'config' describes the transfer + * + * Returned Value + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +int s32k1xx_dmach_xfrsetup(DMACH_HANDLE *handle, + const struct s32k1xx_edma_xfrconfig_s *config) +{ + struct s32k1xx_dmach_s *dmach = (struct s32k1xx_dmach_s *)handle; +#if CONFIG_S32K1XX_EDMA_NTCD > 0 + struct s32k1xx_edmatcd_s *tcd; + struct s32k1xx_edmatcd_s *prev; +#endif + uintptr_t regaddr; + uint16_t regval16; + + DEBUGASSERT(dmach != NULL); + dmainfo("dmach%u: %p config: %p\n", dmach, config); + +#if CONFIG_S32K1XX_EDMA_NTCD > 0 + /* Scatter/gather DMA is supported */ + + /* Allocate a TCD, waiting if necessary */ + + tcd = s32k1xx_tcd_alloc(); + + /* Configure current TCD block transfer. */ + + s32k1xx_tcd_configure(tcd, config); + + /* Enable the interrupt when the major iteration count completes for this + * TCD. For "normal" DMAs, this will correspond to the DMA DONE + * interrupt; for scatter gather DMAs, multiple interrupts will be + * generated with the final being the DONE interrupt. + */ + + tcd->csr |= EDMA_TCD_CSR_INTMAJOR; + + /* Is this the first descriptor in the list? */ + + if (dmach->head == NULL) + { + /* Yes.. add it to the list */ + + dmach->head = tcd; + dmach->tail = tcd; + dmach->ttype = config->ttype; + + /* And instantiate the first TCD in the DMA channel TCD registers. */ + + s32k1xx_tcd_instantiate(dmach, tcd); + } + else + { + /* Cannot mix transfer types (only because of cache-related operations. + * this restriction could be removed with some effort). + */ + + if (dmach->ttype != config->ttype) + { + s32k1xx_tcd_free(tcd); + return -EINVAL; + } + + /* Chain from previous descriptor in the list. */ + + /* Enable scatter/gather feature in the previous TCD. */ + + prev = dmach->tail; + regval16 = prev->csr; + regval16 &= ~EDMA_TCD_CSR_DREQ; + regval16 |= EDMA_TCD_CSR_ESG; + prev->csr = regval16; + + prev->dlastsga = (uint32_t)tcd; + dmach->tail = tcd; + + /* Clean cache associated with the previous TCD memory */ + + up_clean_dcache((uintptr_t)prev, + (uintptr_t)prev + sizeof(struct s32k1xx_edmatcd_s)); + + /* Check if the TCD block in the DMA channel registers is the same as + * the previous previous TCD. This can happen if the previous TCD was + * the first TCD and has already be loaded into the TCD registers. + */ + + if (dmach->head == prev) + { + /* Enable scatter/gather also in the TCD registers. */ + + regaddr = S32K1XX_EDMA_TCD_CSR(dmach->chan); + regval16 = getreg16(regaddr); + regval16 &= ~EDMA_TCD_CSR_DREQ; + regval16 |= EDMA_TCD_CSR_ESG; + putreg16(regval16, regaddr); + + regaddr = S32K1XX_EDMA_TCD_DLASTSGA(dmach->chan); + putreg32((uint32_t)tcd, regaddr); + } + } + + /* Clean cache associated with the TCD memory */ + + up_clean_dcache((uintptr_t)tcd, + (uintptr_t)tcd + sizeof(struct s32k1xx_edmatcd_s)); +#else + /* Scatter/gather DMA is NOT supported */ + + /* Check if eDMA is busy: if the channel has started transfer, CSR will be + * non-zero. + */ + + regaddr = S32K1XX_EDMA_TCD_CSR(dmach->chan); + regval16 = getreg16(regaddr); + + if (regval16 != 0 && (regval16 & EDMA_TCD_CSR_DONE) == 0) + { + return -EBUSY; + } + + /* Configure channel TCD registers to the values specified in config. */ + + s32k1xx_tcd_configure((struct s32k1xx_edmatcd_s *)S32K1XX_EDMA_TCD_BASE(dmach->chan), + config); + + /* Enable the DONE interrupt when the major iteration count completes. */ + + regaddr = S32K1XX_EDMA_TCD_CSR(dmach->chan); + modifyreg16(regaddr, 0, EDMA_TCD_CSR_INTMAJOR); +#endif + + /* Check for an Rx (memory-to-peripheral/memory-to-memory) DMA transfer */ + + if (dmach->ttype == EMDA_MEM2MEM || dmach->ttype == EMDA_PERIPH2MEM) + { + /* Invalidate caches associated with the destination DMA memory. + * REVISIT: nbytes is the number of bytes transferred on each + * minor loop. The following is only valid when the major loop + * is one. + */ + + up_invalidate_dcache((uintptr_t)config->daddr, + (uintptr_t)config->daddr + config->nbytes); + } + + /* Check for an Tx (peripheral-to-memory/memory-to-memory) DMA transfer */ + + if (dmach->ttype == EMDA_MEM2MEM || dmach->ttype == EMDA_MEM2PERIPH) + { + /* Clean caches associated with the source DMA memory. + * REVISIT: nbytes is the number of bytes transferred on each + * minor loop. The following is only valid when the major loop + * is one. + */ +#warning Missing logic + + up_clean_dcache((uintptr_t)config->saddr, + (uintptr_t)config->saddr + config->nbytes); + } + + dmach->state = S32K1XX_DMA_CONFIGURED; + return OK; +} + +/************************************************************************************ + * Name: s32k1xx_dmach_start + * + * Description: + * Start the DMA transfer. This function should be called after the final call + * to s32k1xx_dmach_xfrsetup() in order to avoid race conditions. + * + * At the conclusion of each major DMA loop, a callback to the user-provided + * function is made: |For "normal" DMAs, this will correspond to the DMA DONE + * interrupt; for scatter gather DMAs, multiple interrupts will be generated + * with the final being the DONE interrupt. + * + * At the conclusion of the DMA, the DMA channel is reset, all TCDs are freed, and + * the callback function is called with the the success/fail result of the DMA. + * + * NOTE: On Rx DMAs (peripheral-to-memory or memory-to-memory), it is necessary + * to invalidate the destination memory. That is not done automatically by the + * DMA module. Invalidation of the destination memory regions is the + * responsibility of the caller. + * + * Input Parameters: + * handle - DMA channel handle created by s32k1xx_dmach_alloc() + * callback - The callback to be invoked when the DMA is completes or is aborted. + * arg - An argument that accompanies the callback + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + ************************************************************************************/ + +int s32k1xx_dmach_start(DMACH_HANDLE handle, edma_callback_t callback, void *arg) +{ + struct s32k1xx_dmach_s *dmach = (struct s32k1xx_dmach_s *)handle; + irqstate_t flags; + uint8_t regval8; + uint8_t chan; + + DEBUGASSERT(dmach != NULL && dmach->state == S32K1XX_DMA_CONFIGURED); + chan = dmach->chan; + dmainfo("dmach%u: %p callback: %p arg: %p\n", dmach, chan, callback, arg); + + /* Save the callback info. This will be invoked when the DMA completes */ + + flags = spin_lock_irqsave(); + dmach->callback = callback; + dmach->arg = arg; + dmach->state = S32K1XX_DMA_ACTIVE; + +#if CONFIG_S32K1XX_EDMA_NTCD > 0 + /* Although it is not recommended, it might be possible to call this function + * multiple times while adding TCDs on the fly. + */ + + if (dmach->state != S32K1XX_DMA_ACTIVE) +#endif + { + /* Enable channel ERROR interrupts */ + + regval8 = EDMA_SEEI(chan); + putreg8(regval8, S32K1XX_EDMA_SEEI); + + /* Enable the DMA request for this channel */ + + regval8 = EDMA_SERQ(chan); + putreg8(regval8, S32K1XX_EDMA_SERQ_OFFSET); + } + + spin_unlock_irqrestore(flags); + return OK; +} + +/************************************************************************************ + * Name: s32k1xx_dmach_stop + * + * Description: + * Cancel the DMA. After s32k1xx_dmach_stop() is called, the DMA channel is reset, + * all TCDs are freed, and s32k1xx_dmarx/txsetup() must be called before + * s32k1xx_dmach_start() can be called again + * + * Input Parameters: + * handle - DMA channel handle created by s32k1xx_dmach_alloc() + * + * Returned Value: + * None. + * + ************************************************************************************/ + +void s32k1xx_dmach_stop(DMACH_HANDLE handle) +{ + struct s32k1xx_dmach_s *dmach = (struct s32k1xx_dmach_s *)handle; + irqstate_t flags; + + dmainfo("dmach: %p\n", dmach); + DEBUGASSERT(dmach != NULL); + + flags = spin_lock_irqsave(); + s32k1xx_dmaterminate(dmach, -EINTR); + spin_unlock_irqrestore(flags); +} + +/**************************************************************************** + * Name: s32k1xx_dmach_getcount + * + * Description: + * This function checks the TCD (Task Control Descriptor) status for a + * specified eDMA channel and returns the the number of major loop counts + * that have not finished. + * + * NOTES: + * 1. This function can only be used to get unfinished major loop count of + * transfer without the next TCD, or it might be inaccuracy. + * 2. The unfinished/remaining transfer bytes cannot be obtained directly + * from registers while the channel is running. + * + * Because to calculate the remaining bytes, the initial NBYTES configured + * in DMA_TCDn_NBYTES_MLNO register is needed while the eDMA IP does not + * support getting it while a channel is active. In another words, the + * NBYTES value reading is always the actual (decrementing) NBYTES value + * the dma_engine is working with while a channel is running. + * Consequently, to get the remaining transfer bytes, a software-saved + * initial value of NBYTES (for example copied before enabling the channel) + * is needed. The formula to calculate it is shown below: + * + * RemainingBytes = RemainingMajorLoopCount * NBYTES(initially configured) + * + * Input Parameters: + * handle - DMA channel handle created by s32k1xx_dmach_alloc() + * + * Returned Value: + * Major loop count which has not been transferred yet for the current TCD. + * + ****************************************************************************/ + +unsigned int s32k1xx_dmach_getcount(DMACH_HANDLE *handle) +{ + struct s32k1xx_dmach_s *dmach = (struct s32k1xx_dmach_s *)handle; + unsigned int remaining = 0; + uintptr_t regaddr; + uint16_t regval16; + + DEBUGASSERT(dmach != NULL); + + /* If the DMA is done, then the remaining count is zero */ + + regaddr = S32K1XX_EDMA_TCD_CSR(dmach->chan); + regval16 = getreg16(regaddr); + + if ((regval16 & EDMA_TCD_CSR_DONE) == 0) + { + /* Calculate the unfinished bytes */ + + regaddr = S32K1XX_EDMA_TCD_CITER_ELINK(dmach->chan); + regval16 = getreg16(regaddr); + + if ((regval16 & EDMA_TCD_CITER_ELINK) != 0) + { + remaining = (regval16 & EDMA_TCD_CITER_ELINK_CITER_MASK) >> + EDMA_TCD_CITER_ELINK_CITER_SHIFT; + } + else + { + remaining = (regval16 & EDMA_TCD_CITER_CITER_MASK) >> + EDMA_TCD_CITER_CITER_SHIFT; + } + } + + return remaining; +} + +/**************************************************************************** + * Name: s32k1xx_dmasample + * + * Description: + * Sample DMA register contents + * + * Assumptions: + * - DMA handle allocated by s32k1xx_dmach_alloc() + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA +void s32k1xx_dmasample(DMACH_HANDLE handle, struct s32k1xx_dmaregs_s *regs) +{ + struct s32k1xx_dmach_s *dmach = (struct s32k1xx_dmach_s *)handle; + uintptr_t regaddr; + unsigned int chan; + irqstate_t flags; + + DEBUGASSERT(dmach != NULL && regs != NULL); + chan = dmach->chan; + regs->chan = chan; + + /* eDMA Global Registers */ + + flags = spin_lock_irqsave(); + + regs->cr = getreg32(S32K1XX_EDMA_CR); /* Control */ + regs->es = getreg32(S32K1XX_EDMA_ES); /* Error Status */ + regs->erq = getreg32(S32K1XX_EDMA_ERQ); /* Enable Request */ + regs->req = getreg32(S32K1XX_EDMA_INT); /* Interrupt Request */ + regs->err = getreg32(S32K1XX_EDMA_ERR); /* Error */ + regs->hrs = getreg32(S32K1XX_EDMA_HRS); /* Hardware Request Status */ + regs->ears = getreg32(S32K1XX_EDMA_EARS); /* Enable Asynchronous Request in Stop */ + + /* eDMA Channel registers */ + + regaddr = S32K1XX_EDMA_DCHPRI(chan); + regs->dchpri = getreg8(regaddr); /* Channel priority */ + + /* eDMA TCD */ + + base = S32K1XX_EDMA_TCD_BASE(chan); + regs->saddr = getreg32(base + S32K1XX_EDMA_TCD_SADDR_OFFSET); + regs->soff = getreg16(base + S32K1XX_EDMA_TCD_SOFF_OFFSET); + regs->attr = getreg16(base + S32K1XX_EDMA_TCD_ATTR_OFFSET); + regs->nbml = getreg32(base + S32K1XX_EDMA_TCD_NBYTES_ML_OFFSET); + regs->slast = getreg32(base + S32K1XX_EDMA_TCD_SLAST_OFFSET); + regs->daddr = getreg32(base + S32K1XX_EDMA_TCD_DADDR_OFFSET); + regs->doff = getreg16(base + S32K1XX_EDMA_TCD_DOFF_OFFSET); + regs->citer = getreg16(base + S32K1XX_EDMA_TCD_CITER_ELINK_OFFSET); + regs->dlastsga = getreg32(base + S32K1XX_EDMA_TCD_DLASTSGA_OFFSET); + regs->csr = getreg16(base + S32K1XX_EDMA_TCD_CSR_OFFSET); + regs->biter = getreg16(base + S32K1XX_EDMA_TCD_BITER_ELINK_OFFSET); + + /* DMAMUX registers */ + + regaddr = S32K1XX_DMAMUX_CHCFG(chan); + regs->dmamux = getreg32(regaddr); /* Channel configuration */ + + spin_unlock_irqrestore(flags); +} +#endif /* CONFIG_DEBUG_DMA */ + +/**************************************************************************** + * Name: s32k1xx_dmadump + * + * Description: + * Dump previously sampled DMA register contents + * + * Assumptions: + * - DMA handle allocated by s32k1xx_dmach_alloc() + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA +void s32k1xx_dmadump(const struct s32k1xx_dmaregs_s *regs, const char *msg) +{ + unsigned int chan; + + DEBUGASSERT(regs != NULL && msg != NULL); + + chan = regs->chan; + DEBUGASSERT(chan < S32K1XX_EDMA_NCHANNELS); + + dmainfo("%s\n", msg); + dmainfo(" eDMA Global Registers:\n"); + dmainfo(" CR: %08x\n", regs->cr); + dmainfo(" ES: %08x\n", regs->es); + dmainfo(" ERQ: %08x\n", regs->erq); + dmainfo(" INT: %08x\n", regs->req); + dmainfo(" ERR: %08x\n", regs->err); + dmainfo(" EARS: %08x\n", regs->hrs); + + /* eDMA Channel registers */ + + dmainfo(" eDMA Channel %u Registers:\n", chan); + dmainfo(" DCHPRI: %02x\n", regs->dchpri); + + /* eDMA TCD */ + + dmainfo(" eDMA Channel %u TCD Registers:\n", chan); + dmainfo(" SADDR: %08x\n", regs->saddr); + dmainfo(" SOFF: %04x\n", regs->soff); + dmainfo(" ATTR: %04x\n", regs->attr); + dmainfo(" NBML: %05x\n", regs->nbml); + dmainfo(" SLAST: %05x\n", regs->slast); + dmainfo(" DADDR: %05x\n", regs->daddr); + dmainfo(" DOFF: %04x\n", regs->doff); + dmainfo(" CITER: %04x\n", regs->citer); + dmainfo(" DLASTSGA: %08x\n", regs->dlastsga); + dmainfo(" CSR: %04x\n", regs->csr); + dmainfo(" BITER: %04x\n", regs->biter); + + /* DMAMUX registers */ + + dmainfo(" DMAMUX Channel %u Registers:\n", chan); + dmainfo(" DMAMUX: %08x\n", regs->dmamux); +} +#endif /* CONFIG_DEBUG_DMA */ +#endif /* CONFIG_S32K1XX_EDMA */ diff --git a/arch/arm/src/s32k1xx/s32k1xx_edma.h b/arch/arm/src/s32k1xx/s32k1xx_edma.h new file mode 100644 index 0000000000..5cfcdab07c --- /dev/null +++ b/arch/arm/src/s32k1xx/s32k1xx_edma.h @@ -0,0 +1,423 @@ +/************************************************************************************ + * arch/arm/src/s32k1xx/s32k1xx_dmac.h + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * This file was leveraged from the NuttX i.MXRT port. Portions of that eDMA logic + * derived from NXP sample code which has a compatible BSD 3-clause license: + * + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_S32K1XX_S32K1XX_EDMAC_H +#define __ARCH_ARM_SRC_S32K1XX_S32K1XX_EDMAC_H + +/* General Usage: + * + * 1. Allocate a DMA channel + * + * DMACH_HANDLE handle; + * handle = edma_dmach_alloc(dmamux, dchpri); + * + * Where 'dmamux' is the channel DMAMUX configuration register setting and + * 'dchpri' is the channel DCHPRIO priority register setting. + * + * 2. Create the transfer configuration: + * + * struct s32k1xx_edma_xfrconfig_s config; + * config.saddr = ..; + * config.daddr = ..; + * etc. + * + * 3. Setup the transfer in hardware: + * + * int ret; + * ret = s32k1xx_dmach_xfrsetup(handle, &config); + * + * 4. If you are setting up a scatter gather DMA (with CONFIG_S32K1XX_EDMA_NTCD > 0), + * then repeat steps 2 and 3 for each segment of the transfer. + * + * 5. Start the DMA: + * + * ret = s32k1xx_dmach_start(handle, my_callback_func, priv); + * + * Where my_callback_func() is called when the DMA completes or an error occurs. + * 'priv' represents some internal driver state that will be provided with the + * callback. + * + * 6. If you need to stop the DMA and free resources (such as if a timeout occurs), + * then: + * + * i mxrt_dmach_stop(handle); + * + * 7. The callback will be received when the DMA completes (or an error occurs). + * After that, you may free the DMA channel, or re-use it on subsequent DMAs. + * + * s32k1xx_dmach_free(handle); + * + * Almost non-invasive debug instrumentation is available. You may call + * s32k1xx_dmasample() to save the current state of the eDMA registers at any given + * point in time. At some later, postmortem analysis, you can dump the content of + * the buffered registers with s32k1xx_dmadump(). s32k1xx_dmasample() is also + * available for monitoring DMA progress. + */ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include "hardware/s32k1xx_edma.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Configuration flags. + * + * REVISIT: Many missing options that should be represented as flags: + * 1. Bandwidth + * 2. Source/Destination modulo + */ + +#define EDMA_CONFIG_LINKTYPE_SHIFT (0) /* Bits 0-1: Link type */ +#define EDMA_CONFIG_LINKTYPE_MASK (3 << EDMA_CONFIG_LINKTYPE_SHIFT) +# define EDMA_CONFIG_LINKTYPE_LINKNONE (0 << EDMA_CONFIG_LINKTYPE_SHIFT) /* No channel link */ +# define EDMA_CONFIG_LINKTYPE_MINORLINK (1 << EDMA_CONFIG_LINKTYPE_SHIFT) /* Channel link after each minor loop */ +# define EDMA_CONFIG_LINKTYPE_MAJORLINK (2 << EDMA_CONFIG_LINKTYPE_SHIFT) /* Channel link when major loop count exhausted */ + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +typedef FAR void *DMACH_HANDLE; +typedef void (*edma_callback_t)(DMACH_HANDLE handle, void *arg, bool done, int result); + +/* eDMA transfer type */ + +enum s32k1xx_edma_xfrtype_e +{ + EDMA_MEM2MEM = 0, /* Transfer from memory to memory */ + EDMA_PERIPH2MEM, /* Transfer from peripheral to memory */ + EDMA_MEM2PERIPH, /* Transfer from memory to peripheral */ +}; + +/* This structure holds the source/destination transfer attribute configuration. */ + +struct s32k1xx_edma_xfrconfig_s +{ + uint32_t saddr; /* Source data address. */ + uint32_t daddr; /* Destination data address. */ + int16_t soff; /* Sign-extended offset for current source address. */ + int16_t doff; /* Sign-extended offset for current destination address. */ + uint16_t iter; /* Major loop iteration count. */ + uint8_t flags; /* See EDMA_CONFIG_* definitions */ + uint8_t ssize; /* Source data transfer size (see TCD_ATTR_SIZE_* definitions in rdware/. */ + uint8_t dsize; /* Destination data transfer size. */ + uint8_t ttype; /* Transfer type (see enum s32k1xx_edma_xfrtype_e). */ +#ifdef CONFIG_S32K1XX_EDMA_EMLIM + uint16_t nbytes; /* Bytes to transfer in a minor loop */ +#else + uint32_t nbytes; /* Bytes to transfer in a minor loop */ +#endif +#ifdef CONFIG_S32K1XX_EDMA_ELINK + DMACH_HANDLE linkch; /* Link channel (With EDMA_CONFIG_LINKTYPE_* flags) */ +#endif +}; + +/* The following is used for sampling DMA registers when CONFIG DEBUG_DMA is selected */ + +#ifdef CONFIG_DEBUG_DMA +struct s32k1xx_dmaregs_s +{ + uint8_t chan; /* Sampled channel */ + + /* eDMA Global Registers */ + + uint32_t cr; /* Control */ + uint32_t es; /* Error Status */ + uint32_t erq; /* Enable Request */ + uint32_t req; /* Interrupt Request */ + uint32_t err; /* Error */ + uint32_t hrs; /* Hardware Request Status */ + uint32_t ears; /* Enable Asynchronous Request in Stop */ + + /* eDMA Channel registers */ + + uint8_t dchpri; /* Channel priority */ + + /* eDMA TCD */ + + uint32_t saddr; /* TCD Source Address */ + uint16_t soff; /* TCD Signed Source Address Offset */ + uint16_t attr; /* TCD Transfer Attributes */ + uint32_t nbml; /* TCD Signed Minor Loop Offset / Byte Count */ + uint32_t slast; /* TCD Last Source Address Adjustment */ + uint32_t daddr; /* TCD Destination Address */ + uint16_t doff; /* TCD Signed Destination Address Offset */ + uint16_t citer; /* TCD Current Minor Loop Link, Major Loop Count */ + uint32_t dlastsga; /* TCD Last Destination Address Adjustment/Scatter Gather Address */ + uint16_t csr; /* TCD Control and Status */ + uint16_t biter; /* TCD Beginning Minor Loop Link, Major Loop Count */ + + /* DMAMUX registers */ + + uint32_t dmamux; /* Channel configuration */ +}; +#endif /* CONFIG_DEBUG_DMA */ + +/************************************************************************************ + * Inline Functions + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +/**************************************************************************** + * Name: s32k1xx_dmach_alloc + * + * Allocate a DMA channel. This function sets aside a DMA channel, + * initializes the DMAMUX for the channel, then gives the caller exclusive + * access to the DMA channel. + * + * Input Parameters: + * dmamux - DMAMUX configuration see DMAMUX channel configuration register + * bit-field definitions in hardware/s32k1xx_dmamux.h. Settings include: + * + * DMAMUX_CHCFG_SOURCE Chip-specific DMA source (required) + * DMAMUX_CHCFG_AON DMA Channel Always Enable (optional) + * DMAMUX_CHCFG_TRIG DMA Channel Trigger Enable (optional) + * DMAMUX_CHCFG_ENBL DMA Mux Channel Enable (required) + * + * A value of zero will disable the DMAMUX channel. + * dchpri - DCHPRI channel priority configuration. See DCHPRI channel + * configuration register bit-field definitions in + * hardware/s32k1xx_edma.h. Meaningful settings include: + * + * EDMA_DCHPRI_CHPRI Channel Arbitration Priority + * DCHPRI_DPA Disable Preempt Ability + * DCHPRI_ECP Enable Channel Preemption + * + * The power-on default, 0x05, is a reasonable choice. + * + * Returned Value: + * If a DMA channel is available, this function returns a non-NULL, void* + * DMA channel handle. NULL is returned on any failure. + * + ****************************************************************************/ + +DMACH_HANDLE s32k1xx_dmach_alloc(uint32_t dmamux, uint8_t dchpri); + +/************************************************************************************ + * Name: s32k1xx_dmach_free + * + * Description: + * Release a DMA channel. NOTE: The 'handle' used in this argument must NEVER be + * used again until s32k1xx_dmach_alloc() is called again to re-gain a valid handle. + * + * Returned Value: + * None + * + ************************************************************************************/ + +void s32k1xx_dmach_free(DMACH_HANDLE handle); + +/************************************************************************************ + * Name: s32k1xx_dmach_xfrsetup + * + * Description: + * This function adds the eDMA transfer to the DMA sequence. The request + * is setup according to the content of the transfer configuration + * structure. For "normal" DMA, s32k1xx_dmach_xfrsetup is called only once. + * Scatter/gather DMA is accomplished by calling this function repeatedly, + * once for each transfer in the sequence. Scatter/gather DMA processing + * is enabled automatically when the second transfer configuration is received. + * + * This function may be called multiple times to handle multiple, + * discontinuous transfers (scatter-gather) + * + * Input Parameters: + * handle - DMA channel handle created by s32k1xx_dmach_alloc() + * config - A DMA transfer configuration instance, populated by the + * The content of 'config' describes the transfer + * + * Returned Value + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + ************************************************************************************/ + +int s32k1xx_dmach_xfrsetup(DMACH_HANDLE *handle, + const struct s32k1xx_edma_xfrconfig_s *config); + +/************************************************************************************ + * Name: s32k1xx_dmach_start + * + * Description: + * Start the DMA transfer by enabling the channel DMA request. This function + * should be called after the final call to s32k1xx_dmasetup() in order to avoid + * race conditions. + * + * At the conclusion of each major DMA loop, a callback to the user-provided + * function is made: |For "normal" DMAs, this will correspond to the DMA DONE + * interrupt; for scatter gather DMAs, multiple interrupts will be generated + * with the final being the DONE interrupt. + * + * At the conclusion of the DMA, the DMA channel is reset, all TCDs are freed, and + * the callback function is called with the the success/fail result of the DMA. + * + * NOTE: On Rx DMAs (peripheral-to-memory or memory-to-memory), it is necessary + * to invalidate the destination memory. That is not done automatically by the + * DMA module. Invalidation of the destination memory regions is the + * responsibility of the caller. + * + * Input Parameters: + * handle - DMA channel handle created by s32k1xx_dmach_alloc() + * callback - The callback to be invoked when the DMA is completes or is aborted. + * arg - An argument that accompanies the callback + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + ************************************************************************************/ + +int s32k1xx_dmach_start(DMACH_HANDLE handle, edma_callback_t callback, void *arg); + +/************************************************************************************ + * Name: s32k1xx_dmach_stop + * + * Description: + * Cancel the DMA. After s32k1xx_dmach_stop() is called, the DMA channel is reset, + * all TCDs are freed, and s32k1xx_dmarx/txsetup() must be called before + * s32k1xx_dmach_start() can be called again + * + * Input Parameters: + * handle - DMA channel handle created by s32k1xx_dmach_alloc() + * + * Returned Value: + * None. + * + ************************************************************************************/ + +void s32k1xx_dmach_stop(DMACH_HANDLE handle); + +/************************************************************************************ + * Name: s32k1xx_dmach_getcount + * + * Description: + * This function checks the TCD (Task Control Descriptor) status for a + * specified eDMA channel and returns the the number of major loop counts + * that have not finished. + * + * NOTES: + * 1. This function can only be used to get unfinished major loop count of + * transfer without the next TCD, or it might be inaccuracy. + * 2. The unfinished/remaining transfer bytes cannot be obtained directly + * from registers while the channel is running. + * + * Because to calculate the remaining bytes, the initial NBYTES configured + * in DMA_TCDn_NBYTES_MLNO register is needed while the eDMA IP does not + * support getting it while a channel is active. In another words, the + * NBYTES value reading is always the actual (decrementing) NBYTES value + * the dma_engine is working with while a channel is running. + * Consequently, to get the remaining transfer bytes, a software-saved + * initial value of NBYTES (for example copied before enabling the channel) + * is needed. The formula to calculate it is shown below: + * + * RemainingBytes = RemainingMajorLoopCount * NBYTES(initially configured) + * + * Input Parameters: + * handle - DMA channel handle created by s32k1xx_dmach_alloc() + * + * Returned Value: + * Major loop count which has not been transferred yet for the current TCD. + * + ************************************************************************************/ + +unsigned int s32k1xx_dmach_getcount(DMACH_HANDLE *handle); + +/************************************************************************************ + * Name: s32k1xx_dmasample + * + * Description: + * Sample DMA register contents + * + ************************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA +void s32k1xx_dmasample(DMACH_HANDLE handle, struct s32k1xx_dmaregs_s *regs); +#else +# define s32k1xx_dmasample(handle,regs) +#endif + +/************************************************************************************ + * Name: s32k1xx_dmadump + * + * Description: + * Dump previously sampled DMA register contents + * + ************************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA +void s32k1xx_dmadump(const struct s32k1xx_dmaregs_s *regs, const char *msg); +#else +# define s32k1xx_dmadump(handle,regs,msg) +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_S32K1XX_S32K1XX_EDMAC_H */