/****************************************************************************/
/* Copyright 2010, © Bendor Research Pty. Ltd. All rights reserved.			*/
/* Permission is granted to use this software for any purpose whatsoever	*/
/* as long as this copyright notice is preserved. The code is provided		*/
/* "as is", with no explicit, implicit or implied warranty or guarantee		*/
/* of any kind and Bendor Research Pty. Ltd. can not be held liable for		*/
/* any loss or damages arising out of the use of this software.				*/
/****************************************************************************/
/*																			*/
/*	Include file describing the NXP LPC23xx DMA controller module			*/
/*	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~			*/
/*																			*/
/*	2010 Mar	ZK		Original											*/
/*	2010 May	ZK		Modified to match NXP's names						*/
/*																			*/
/****************************************************************************/

#ifndef _LPC23XX_DMA
#define _LPC23XX_DMA

/*
*	Linked-list DMA descriptor
*	~~~~~~~~~~~~~~~~~~~~~~~~~~
*/

struct dma_lli {

	void			*srcaddr;		// +00 Source address
	void			*dstaddr;		// +04 Destination address
	struct dma_lli	*lli;			// +08 Linked list item
	unsigned		ctrl;			// +0c Transfer control
};

/*
*	Channel control registers
*	~~~~~~~~~~~~~~~~~~~~~~~~~
*/

struct dma_chn {

	void			*srcaddr;		// +00 Channel source address
	void			*dstaddr;		// +04 Channel estination address
	struct dma_lli	*lli;			// +08 Linked list item
	unsigned		ctrl;			// +0c Channel control
	unsigned		conf;			// +10 Channel configuration
	unsigned		__[3];			//	   Makes it 0x20 long
};

/*
*	DMA engine registers
*	~~~~~~~~~~~~~~~~~~~~
*/

struct lpc23xx_dma {

	unsigned intstat;				// 000 Interrupt status
	unsigned inttcstat;				// 004 Terminal count interrupt status
	unsigned inttcclr;				// 008 Terminal count interrupt clear
	unsigned interrstat;			// 00c Error interrupt status
	unsigned interrclr;				// 010 Error interrupt clear
	unsigned rawinttcstat;			// 014 Raw terminal count IRQ status
	unsigned rawinterrstat;			// 018 Raw error IRQ status
	unsigned enabld_chns;			// 01c Enabled channels
	unsigned softbreq;				// 020 Software burst request
	unsigned softsreq;				// 024 Software single request
	unsigned softlbreq;				// 028 Software last burst request
	unsigned softlsreq;				// 02c Software last single request
	unsigned conf;					// 030 Configuration register
	unsigned sync;					// 034 Synchronisation register
	unsigned _[50];
	struct dma_chn chan[ 2 ];		// 100 DMA channels
};

/****************************************************************************/
/*					Global register related definitions						*/
/****************************************************************************/

/*
*	Definitions for the int_*, raw_int_* and enabld_chns registers
*/

#define	DMA_INT_CHAN0		0x01	// Channel 0
#define	DMA_INT_CHAN1		0x02	// Channel 1

/*
*	Definitions for the soft_* and sync registers
*
*	Note that not all bits exist in all registers. In particular:
*
*				SSP		MCI		I2S
*	soft_breq	 x		 x		 -
*	soft_sreq	 x		 x		 x
*	soft_lbreq	 -		 x		 -
*	soft_lsreq	 -		 x		 -
*	sync	 	 x		 x		 x
*/

#define	DMA_REQ_SSP0TX		0x01	// Software request for SSP 0 Tx
#define	DMA_REQ_SSP0RX		0x02	// Software request for SSP 0 Rx
#define	DMA_REQ_SSP1TX		0x04	// Software request for SSP 1 Tx
#define	DMA_REQ_SSP1RX		0x08	// Software request for SSP 1 Rx
#define	DMA_REQ_SDMMC		0x10	// Software request for MCI I/F
#define	DMA_REQ_I2S0		0x20	// Software request for I2S ch 0
#define	DMA_REQ_I2S1		0x40	// Software request for I2S ch 0

/*
*	Definitions for the config register
*/

#define	DMA_CONF_E			0x01	// DMA engine is enabled
#define	DMA_CONF_M			0x02	// Endianness (1:big 0:little)

/****************************************************************************/
/*				Per-channel register related definitions					*/
/****************************************************************************/

/*
*	Definitions for the 'ctrl' registers
*/

#define DMA_CTRL_XFER_SIZE(n) (n)		// Transfer size if DMA controls it
#define DMA_CTRL_SB_SIZE(n)	((n)<<12)	// Source burst size
#define DMA_CTRL_DB_SIZE(n)	((n)<<15)	// Destination burst size
#define DMA_CTRL_SWIDTH(n)	((n)<<18)	// Source transfer width
#define DMA_CTRL_DWIDTH(n)	((n)<<21)	// Destination transfer width
#define DMA_CTRL_SI			0x04000000	// Source address increment
#define DMA_CTRL_DI			0x08000000	// Destination address increment
#define DMA_CTRL_PROT		0x70000000	// Execute in priviliged mode
#define DMA_CTRL_PROT_USER	0x00000000	// Execute in user mode
#define DMA_CTRL_PROT_PRIV	0x10000000	// Execute in user mode
#define DMA_CTRL_PROT_BUFF	0x20000000	// Accesses are bufferable
#define DMA_CTRL_PROT_CACHE	0x40000000	// Accesses are cacheable
#define	DMA_CTRL_I			0x80000000	// Interrupt on terminal count enabled

/*
*	Values for the SB_SIZE and DB_SIZE fields
*/

#define	DMA_SIZE_1			0			// Burts size is 1
#define	DMA_SIZE_4			1			// Burts size is 4
#define	DMA_SIZE_8			2			// Burts size is 8
#define	DMA_SIZE_16			3			// Burts size is 16
#define	DMA_SIZE_32			4			// Burts size is 32
#define	DMA_SIZE_64			5			// Burts size is 64
#define	DMA_SIZE_128		6			// Burts size is 128
#define	DMA_SIZE_256		7			// Burts size is 256

/*
*	Values for the SWIDTH and DWIDTH fields
*/

#define	DMA_WIDTH_BYTE		0			// Port width is  8 bits
#define	DMA_WIDTH_HALF		1			// Port width is 16 bits
#define	DMA_WIDTH_WORD		2			// Port width is 32 bits

/*
*	Definitions for the per-channel conf registers
*/

// The CONF_E bit is already define, to the same value, for the DMA_CONF
// global register.
// #define	DMA_CONF_E				0x000001	// Channel enabled

#define	DMA_CONF_SRC_PER(x)		((x)<<1)	// Source peripheral
#define	DMA_CONF_DST_PER(x)		((x)<<6)	// Destination peripheral
#define	DMA_CONF_FLOW_CTRL(x)	((x)<<11)	// Transfer type
#define	DMA_CONF_IE				0x004000	// Enable interrupt on errors
#define	DMA_CONF_ITC			0x008000	// Enable interrupt in term. cnt.
#define	DMA_CONF_L				0x010000	// Enable locked transfers
#define	DMA_CONF_A				0x020000	// Active
#define	DMA_CONF_H				0x040000	// Halt

/*
*	Definitions for the SRC_PER and DST_PER fields
*/

#define	DMA_PER_SSP0TX			0		// SSP 0 Tx
#define	DMA_PER_SSP0RX			1		// SSP 0 Rx
#define	DMA_PER_SSP1TX			2		// SSP 1 Tx
#define	DMA_PER_SSP1RX			3		// SSP 1 Rx
#define	DMA_PER_SDMMC			4		// MCI
#define	DMA_PER_I2S0			5		// I2S ch 0
#define	DMA_PER_I2S1			6		// I2S ch 1

/*
*	Definitions for the FLOW_CTRL filed
*/

#define	DMA_FLOW_MEM_MEM_DMA	0		// Memory to memory, flow by DMA
#define	DMA_FLOW_MEM_PER_DMA	1		// Memory to periph, flow by DMA
#define	DMA_FLOW_PER_MEM_DMA	2		// Periph to memory, flow by DMA
#define	DMA_FLOW_PER_PER_DMA	3		// Periph to periph, flow by DMA
#define	DMA_FLOW_PER_PER_DST	4		// Periph to periph, flow by dest
#define	DMA_FLOW_MEM_PER_DST	5		// Memory to periph, flow by dest
#define	DMA_FLOW_PER_MEM_SRC	6		// Periph to memory, flow by source
#define	DMA_FLOW_PER_PER_SRC	7		// Periph to periph, flow by source

/*
*	DMA instance
*/

static volatile struct lpc23xx_dma * const lpc_dma = (void *) 0xffe04000;

#endif

