/*
 * @brief LPC18xx/43xx DMA driver
 *
 * @note
 * Copyright(C) NXP Semiconductors, 2012
 * All rights reserved.
 *
 * @par
 * Software that is described herein is for illustrative purposes only
 * which provides customers with programming information regarding the
 * LPC products.  This software is supplied "AS IS" without any warranties of
 * any kind, and NXP Semiconductors and its licensor disclaim any and
 * all warranties, express or implied, including all implied warranties of
 * merchantability, fitness for a particular purpose and non-infringement of
 * intellectual property rights. NXP Semiconductors assumes no responsibility
 * or liability for the use of the software, conveys no license or rights under any
 * patent, copyright, mask work right, or any other intellectual property rights in
 * or to any products. NXP Semiconductors reserves the right to make changes
 * in the software without notification. NXP Semiconductors also makes no
 * representation or warranty that such application will be suitable for the
 * specified use without further testing or modification.
 *
 * @par
 * Permission to use, copy, modify, and distribute this software and its
 * documentation is hereby granted, under NXP Semiconductors' and its
 * licensor's relevant copyrights in the software, without fee, provided that it
 * is used in conjunction with NXP Semiconductors microcontrollers.  This
 * copyright, permission, and disclaimer notice must appear in all copies of
 * this code.
 */

#ifndef __GPDMA_18XX_43XX_H_
#define __GPDMA_18XX_43XX_H_

#ifdef __cplusplus
extern "C" {
#endif

/** @defgroup GPDMA_18XX_43XX CHIP: LPC18xx/43xx General Purpose DMA driver
 * @ingroup CHIP_18XX_43XX_Drivers
 * @{
 */

/**
 * @brief Number of channels on GPDMA
 */
#define GPDMA_NUMBER_CHANNELS 8

/**
 * @brief GPDMA request connections
 */
#define GPDMA_CONN_MEMORY           ((0UL))			/**< MEMORY             */
#define GPDMA_CONN_MAT0_0           ((1UL))			/**< MAT0.0             */
#define GPDMA_CONN_UART0_Tx         ((2UL))			/**< UART0 Tx           */
#define GPDMA_CONN_MAT0_1           ((3UL))			/**< MAT0.1             */
#define GPDMA_CONN_UART0_Rx         ((4UL))			/**< UART0 Rx           */
#define GPDMA_CONN_MAT1_0           ((5UL))			/**< MAT1.0             */
#define GPDMA_CONN_UART1_Tx         ((6UL))			/**< UART1 Tx           */
#define GPDMA_CONN_MAT1_1           ((7UL))			/**< MAT1.1             */
#define GPDMA_CONN_UART1_Rx         ((8UL))			/**< UART1 Rx           */
#define GPDMA_CONN_MAT2_0           ((9UL))			/**< MAT2.0             */
#define GPDMA_CONN_UART2_Tx         ((10UL))		/**< UART2 Tx           */
#define GPDMA_CONN_MAT2_1           ((11UL))		/**< MAT2.1             */
#define GPDMA_CONN_UART2_Rx         ((12UL))		/**< UART2 Rx           */
#define GPDMA_CONN_MAT3_0           ((13UL))		/**< MAT3.0             */
#define GPDMA_CONN_UART3_Tx         ((14UL))		/**< UART3 Tx           */
#define GPDMA_CONN_SCT_0            ((15UL))		/**< SCT timer channel 0*/
#define GPDMA_CONN_MAT3_1           ((16UL))		/**< MAT3.1             */
#define GPDMA_CONN_UART3_Rx         ((17UL))		/**< UART3 Rx           */
#define GPDMA_CONN_SCT_1            ((18UL))		/**< SCT timer channel 1*/
#define GPDMA_CONN_SSP0_Rx          ((19UL))		/**< SSP0 Rx            */
#define GPDMA_CONN_I2S_Tx_Channel_0 ((20UL))		/**< I2S channel 0      */
#define GPDMA_CONN_SSP0_Tx          ((21UL))		/**< SSP0 Tx            */
#define GPDMA_CONN_I2S_Rx_Channel_1 ((22UL))		/**< I2S channel 1      */
#define GPDMA_CONN_SSP1_Rx          ((23UL))		/**< SSP1 Rx            */
#define GPDMA_CONN_SSP1_Tx          ((24UL))		/**< SSP1 Tx            */
#define GPDMA_CONN_ADC_0            ((25UL))		/**< ADC 0              */
#define GPDMA_CONN_ADC_1            ((26UL))		/**< ADC 1              */
#define GPDMA_CONN_DAC              ((27UL))		/**< DAC                */
#define GPDMA_CONN_I2S_Tx_Channel_1 ((28UL))		/**< I2S channel 0      */
#define GPDMA_CONN_I2S_Rx_Channel_0 ((29UL))		/**< I2S channel 0      */

/**
 * @brief GPDMA Burst size in Source and Destination definitions
 */
#define GPDMA_BSIZE_1   ((0UL))	/*!< Burst size = 1 */
#define GPDMA_BSIZE_4   ((1UL))	/*!< Burst size = 4 */
#define GPDMA_BSIZE_8   ((2UL))	/*!< Burst size = 8 */
#define GPDMA_BSIZE_16  ((3UL))	/*!< Burst size = 16 */
#define GPDMA_BSIZE_32  ((4UL))	/*!< Burst size = 32 */
#define GPDMA_BSIZE_64  ((5UL))	/*!< Burst size = 64 */
#define GPDMA_BSIZE_128 ((6UL))	/*!< Burst size = 128 */
#define GPDMA_BSIZE_256 ((7UL))	/*!< Burst size = 256 */

/**
 * @brief Width in Source transfer width and Destination transfer width definitions
 */
#define GPDMA_WIDTH_BYTE        ((0UL))	/*!< Width = 1 byte */
#define GPDMA_WIDTH_HALFWORD    ((1UL))	/*!< Width = 2 bytes */
#define GPDMA_WIDTH_WORD        ((2UL))	/*!< Width = 4 bytes */

/**
 * @brief Flow control definitions
 */
#define DMA_CONTROLLER 0		/*!< Flow control is DMA controller*/
#define SRC_PER_CONTROLLER 1	/*!< Flow control is Source peripheral controller*/
#define DST_PER_CONTROLLER 2	/*!< Flow control is Destination peripheral controller*/

/**
 * @brief DMA channel handle structure
 */
typedef struct {
	FunctionalState ChannelStatus;	/*!< DMA channel status */
} DMA_ChannelHandle_t;

/**
 * @brief Transfer Descriptor structure typedef
 */
typedef struct DMA_TransferDescriptor {
	uint32_t src;	/*!< Source address */
	uint32_t dst;	/*!< Destination address */
	uint32_t lli;	/*!< Pointer to next descriptor structure */
	uint32_t ctrl;	/*!< Control word that has transfer size, type etc. */
} DMA_TransferDescriptor_t;

/**
 * @brief	Read the status from different registers according to the type
 * @param	pGPDMA	: The base of GPDMA on the chip
 * @param	type	: Status mode, should be:
 *						- GPDMA_STAT_INT		: GPDMA Interrupt Status
 *						- GPDMA_STAT_INTTC		: GPDMA Interrupt Terminal Count Request Status
 *						- GPDMA_STAT_INTERR		: GPDMA Interrupt Error Status
 *						- GPDMA_STAT_RAWINTTC	: GPDMA Raw Interrupt Terminal Count Status
 *						- GPDMA_STAT_RAWINTERR	: GPDMA Raw Error Interrupt Status
 *						- GPDMA_STAT_ENABLED_CH	: GPDMA Enabled Channel Status
 * @param	channel	: The GPDMA channel : 0 - 7
 * @return	SET is interrupt is pending or RESET if not pending
 */
STATIC INLINE IntStatus Chip_GPDMA_IntGetStatus(LPC_GPDMA_T *pGPDMA, IP_GPDMA_STATUS_T type, uint8_t channel)
{
	return IP_GPDMA_IntGetStatus(pGPDMA, type, channel);
}

/**
 * @brief	Clear the Interrupt Flag from different registers according to the type
 * @param	pGPDMA	: The base of GPDMA on the chip
 * @param	type	: Flag mode, should be:
 *						- GPDMA_STATCLR_INTTC	: GPDMA Interrupt Terminal Count Request
 *						- GPDMA_STATCLR_INTERR	: GPDMA Interrupt Error
 * @param	channel	: The GPDMA channel : 0 - 7
 * @return	Nothing
 */
STATIC INLINE void Chip_GPDMA_ClearIntPending(LPC_GPDMA_T *pGPDMA, IP_GPDMA_STATECLEAR_T type, uint8_t channel)
{
	IP_GPDMA_ClearIntPending(pGPDMA, type, channel);
}

/**
 * @brief	Enable or Disable the GPDMA Channel
 * @param	pGPDMA		: The base of GPDMA on the chip
 * @param	channelNum	: The GPDMA channel : 0 - 7
 * @param	NewState	: ENABLE to enable GPDMA or DISABLE to disable GPDMA
 * @return	Nothing
 */
STATIC INLINE void Chip_GPDMA_ChannelCmd(LPC_GPDMA_T *pGPDMA, uint8_t channelNum, FunctionalState NewState)
{
	IP_GPDMA_ChannelCmd(pGPDMA, channelNum, NewState);
}

/**
 * @brief	Initialize the GPDMA
 * @param	pGPDMA	: The base of GPDMA on the chip
 * @return	Nothing
 */
void Chip_GPDMA_Init(LPC_GPDMA_T *pGPDMA);

/**
 * @brief	Shutdown the GPDMA
 * @param	pGPDMA	: The base of GPDMA on the chip
 * @return	Nothing
 */
void Chip_GPDMA_DeInit(LPC_GPDMA_T *pGPDMA);

/**
 * @brief	Stop a stream DMA transfer
 * @param	pGPDMA		: The base of GPDMA on the chip
 * @param	ChannelNum	: Channel Number to be closed
 * @return	Nothing
 */
void Chip_DMA_Stop(LPC_GPDMA_T *pGPDMA, uint8_t ChannelNum);

/**
 * @brief	The GPDMA stream interrupt status checking
 * @param	pGPDMA		: The base of GPDMA on the chip
 * @param	ChannelNum	: Channel Number to be checked on interruption
 * @return	Status:
 *              - SUCCESS	: DMA transfer success
 *              - ERROR		: DMA transfer failed
 */
Status Chip_DMA_Interrupt(LPC_GPDMA_T *pGPDMA, uint8_t ChannelNum);

/**
 * @brief	Get a free GPDMA channel for one DMA connection
 * @param	pGPDMA					: The base of GPDMA on the chip
 * @param	PeripheralConnection_ID	: Some chip fix each peripheral DMA connection on a specified channel ( have not used in 18xx/43xx )
 * @return	The channel number which is selected
 */
uint8_t Chip_DMA_GetFreeChannel(LPC_GPDMA_T *pGPDMA, uint32_t PeripheralConnection_ID);

/**
 * @brief	Do a DMA transfer M2M, M2P,P2M or P2P
 * @param	pGPDMA		: The base of GPDMA on the chip
 * @param	ChannelNum	: Channel used for transfer
 * @param	src			: Address of Memory or PeripheralConnection_ID which is the source
 * @param	dst			: Address of Memory or PeripheralConnection_ID which is the destination
 * @param	TransferType: Select the transfer controller and the type of transfer. Should be:
 *                               - GPDMA_TRANSFERTYPE_M2M_CONTROLLER_DMA
 *                               - GPDMA_TRANSFERTYPE_M2P_CONTROLLER_DMA
 *                               - GPDMA_TRANSFERTYPE_P2M_CONTROLLER_DMA
 *                               - GPDMA_TRANSFERTYPE_P2P_CONTROLLER_DMA
 *                               - GPDMA_TRANSFERTYPE_P2P_CONTROLLER_DestPERIPHERAL
 *                               - GPDMA_TRANSFERTYPE_M2P_CONTROLLER_PERIPHERAL
 *                               - GPDMA_TRANSFERTYPE_P2M_CONTROLLER_PERIPHERAL
 *                               - GPDMA_TRANSFERTYPE_P2P_CONTROLLER_SrcPERIPHERAL
 * @param	Size		: The number of DMA transfers
 * @return	ERROR on error, SUCCESS on success
 */
Status Chip_DMA_Transfer(LPC_GPDMA_T *pGPDMA,
						 uint8_t ChannelNum,
						 uint32_t src,
						 uint32_t dst,
						 IP_GPDMA_FLOW_CONTROL_T TransferType,
						 uint32_t Size);

/**
 * @brief	Do a DMA transfer using linked list of descriptors
 * @param	pGPDMA			: The base of GPDMA on the chip
 * @param	ChannelNum		: Channel used for transfer *must be obtained using Chip_DMA_GetFreeChannel()*
 * @param	DMADescriptor	: First node in the linked list of descriptors
 * @param	TransferType	: Select the transfer controller and the type of transfer. (See, #IP_GPDMA_FLOW_CONTROL_T)
 * @return	ERROR on error, SUCCESS on success
 */
Status Chip_DMA_SGTransfer(LPC_GPDMA_T *pGPDMA,
						   uint8_t ChannelNum,
						   const DMA_TransferDescriptor_t *DMADescriptor,
						   IP_GPDMA_FLOW_CONTROL_T TransferType);

/**
 * @brief	Prepare a single DMA descriptor
 * @param	pGPDMA			: The base of GPDMA on the chip
 * @param	DMADescriptor	: DMA Descriptor to be initialized
 * @param	src				: Address of Memory or one of @link #GPDMA_CONN_MEMORY
 *                              PeripheralConnection_ID @endlink, which is the source
 * @param	dst				: Address of Memory or one of @link #GPDMA_CONN_MEMORY
 *                              PeripheralConnection_ID @endlink, which is the destination
 * @param	Size			: The number of DMA transfers
 * @param	TransferType	: Select the transfer controller and the type of transfer. (See, #IP_GPDMA_FLOW_CONTROL_T)
 * @param	NextDescriptor	: Pointer to next descriptor (0 if no more descriptors available)
 * @return	ERROR on error, SUCCESS on success
 */
Status Chip_DMA_PrepareDescriptor(LPC_GPDMA_T *pGPDMA,
								  DMA_TransferDescriptor_t *DMADescriptor,
								  uint32_t src,
								  uint32_t dst,
								  uint32_t Size,
								  IP_GPDMA_FLOW_CONTROL_T TransferType,
								  const DMA_TransferDescriptor_t *NextDescriptor);

/**
 * @brief	Initialize channel configuration strucutre
 * @param	pGPDMA	: The base of GPDMA on the chip
 * @param	GPDMACfg		: Pointer to configuration structure to be initialized
 * @param	ChannelNum		: Channel used for transfer *must be obtained using Chip_DMA_GetFreeChannel()*
 * @param	src				: Address of Memory or one of @link #GPDMA_CONN_MEMORY
 *                              PeripheralConnection_ID @endlink, which is the source
 * @param	dst				: Address of Memory or one of @link #GPDMA_CONN_MEMORY
 *                              PeripheralConnection_ID @endlink, which is the destination
 * @param	Size			: The number of DMA transfers
 * @param	TransferType	: Select the transfer controller and the type of transfer. (See, #IP_GPDMA_FLOW_CONTROL_T)
 * @return	ERROR on error, SUCCESS on success
 */
int Chip_DMA_InitChannelCfg(LPC_GPDMA_T *pGPDMA,
							GPDMA_Channel_CFG_T *GPDMACfg,
							uint8_t  ChannelNum,
							uint32_t src,
							uint32_t dst,
							uint32_t Size,
							IP_GPDMA_FLOW_CONTROL_T TransferType);

/**
 * @}
 */

#ifdef __cplusplus
}
#endif

#endif /* __GPDMA_18XX_43XX_H_ */
