/****************************************************************************/
/* 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 USB controller module			*/
/*	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~			*/
/*																			*/
/*	2010 Mar	ZK		Original
/*	2010 May	ZK		Modified to match NXP's names						*/
/*																			*/
/****************************************************************************/

#ifndef _LPC23XX_USB
#define _LPC23XX_USB

/*
*	USB DMA fragment descriptor structure
*	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*	Note that the 'size' field is only used in case of isochronous transfers.
*	In that case the 'stat' field shall be initialised to the AMLP() field
*	and not 0.
*	If the structure is only used for non-isochronous transfers, the 'size'
*	field does no not have to be physically present and any int[4] address
*	can be cast to (USB_DMA*).
*/

typedef struct {

	struct s_usb_dma	*next;	// Pointer to next descriptor			+00
	unsigned int		ctrl;	// Descriptor details					+04
	void				*addr;	// DMA buffer address					+08
	unsigned int		stat;	// Transfer status, init to 0 or ATLE	+0c
	unsigned int		*size;	// Pointer to transfer size in memory	+10

} USB_DMA;

/*
*	USB controller registers
*
*	NOTE:	The portsel register does *not* exist if you have OTG.
*			The clkctrl and clkst registers are shared with the OTG.
*/

struct lpc23xx_usb {

	unsigned	_0[68];
	unsigned	portsel;			// RW	Port select register 			110
	unsigned	_1[59];
	unsigned	devintst;			// R	Device interrupt status			200
	unsigned	devinten;			// RW	Device interrupt enable			204
	unsigned	devintclr;			// W	Device interrupt clear			208
	unsigned	devintset;			// W	Device interrupt set			20c
	unsigned	cmdcode;			// W	Serial I/F engine command code	210
	unsigned	cmddata;			// R	Serial I/F engine response data	214
	unsigned	rxdata;				// R	Receive data					218
	unsigned	txdata;				// W	Transmit data					21c
	unsigned	rxplen;				// R	Receive packet length			220
	unsigned	txplen;				// W	Transmit packet length			224
	unsigned	ctrl;				// RW	Device control					228
	unsigned	devintpri;			// W	Device interrupt priority		22c
	unsigned	epintst;			// R	Endpoint interrupt status		230
	unsigned	epinten;			// RW	Endpoint interrupt enable		234
	unsigned	epintclr;			// W	Endpoint interrupt clear		238
	unsigned	epintset;			// W	Endpoint interrupt set			23c
	unsigned	epintpri;			// W	Endpoint interrupt priority		240
	unsigned	reep;				// RW	Realise endpoint				244
	unsigned	epin;				// W	Endpoint select index			248
	unsigned	maxpsize;			// RW	Max packet length				24c
	unsigned	dmarst;				// R	DMA request status				250
	unsigned	dmarclr;			// W	DMA request clear				254
	unsigned	dmarset;			// W	DMA request set					258
	unsigned	_2[9];
	USB_DMA		*udcah;				// RW	Linked list head pointer		280
	unsigned	epdmast;			// R	Endpoint DMA status				284
	unsigned	epdmaen;			// W	Endpoint DMA enable				288
	unsigned	epdmadis;			// W	Endpoint DMA disable			28c
	unsigned	dmaintis;			// W	DMA interrupt status			290
	unsigned	dmainten;			// RW	DMA interrupt enable			294
	unsigned	_3[2];
	unsigned	eotintst;			// R	DMA end of transfer IRQ status	2a0
	unsigned	eotintclr;			// W	DMA end of transfer IRQ clear	2a4
	unsigned	eotintset;			// W	DMA end of transfer IRQ set		2a8
	unsigned	nddrintst;			// R	DMA descriptor req IRQ status	2ac
	unsigned	nddrintclr;			// W	DMA descriptor req IRQ clear	2b0
	unsigned	nddrintset;			// W	DMA descriptor req IRQ set		2b4
	unsigned	syserrintst;		// R	DMA error interrupt status		2b8
	unsigned	syserrintclr;		// W	DMA error interrupt clear		2bc
	unsigned	syserrintset;		// W	DMA error interrupt set			2c0
	unsigned	_4[844];
	unsigned	clkctrl;			// RW	Clock control					ff4
	unsigned	clkst;				// R	Clock status					ff8
};

/*
*	Definitions for the portsel register
*/

#define	USB_PORTSEL_U1		0x00	// Pins are mapped to U1 port
#define	USB_PORTSEL_U2		0x03	// Pins are mapped to U2 port

/*
*	Definitions for the clkctrl and clkst  registers
*/

#define	USB_CLK_HOST		0x01	// OTG host clock
#define	USB_CLK_DEV			0x02	// USB subsytem clock
#define	USB_CLK_I2C			0x04	// OTG I2C clock
#define	USB_CLK_PORTSEL		0x08	// Port select register clock
#define USB_CLK_OTG			0x08	// OTG clock (same as portsel)
#define	USB_CLK_AHB			0x10	// AHB clock

/*
*	Definitions for

/*
*	Definitions for the devint??? registers
*	Note that the devintpri register has only two bits (the least significant
*	two). Only one of the bits in this register can be set to 1. That interrupt
*	will receive higher priority than the other.
*/

#define	USB_DEVINT_ERR_INT	0x200	// Error
#define	USB_DEVINT_EP_RLZED	0x100	// Endpoint realised
#define	USB_DEVINT_TXENDPKT	0x080	// End packet transmitted
#define	USB_DEVINT_RXENDPKT	0x040	// End packet received
#define	USB_DEVINT_CDFUL	0x020	// SIE response data register is full
#define	USB_DEVINT_CCEMPTY	0x010	// SIE command code register is empty
#define	USB_DEVINT_DEV_STAT	0x008	// Device state change
#define	USB_DEVINT_EP_SLOW	0x004	// Slow endpoint
#define	USB_DEVINT_EP_FAST	0x002	// Fast endpoint
#define	USB_DEVINT_FRAME	0x001	// USB frame

/*
*	Definitions for the epint??? registers
*	If a bit in the epintpri register is set, the corresponding interrupt
*	will generate a DEVINT_EP_FAST interrupt, otherwise DEVINT_EP_SLOW.
*/

#define	USB_EPINT_RX(n)		(1<<(n))	// Rx done, endpoint n
#define	USB_EPINT_TX(n)		(2<<(n))	// Tx done or NAK sent, endpoint n

/*
*	Definitions for the rxplen register
*/

#define	USB_RXPLEN_PKT_LNGTH	0x3ff	// Bytes in the endpoint's buffer
#define	USB_RXPLEN_DV			0x400	// Data in buffer is valid
#define	USB_RXPLEN_PKT_RDY		0x800	// Buffer is ready and length valid

/*
*	Definitions for the ctrl register
*/

#define	USB_CTLR_RD_EN			0x01	// Read mode is enabled
#define	USB_CTLR_WR_EN			0x02	// Write mode is enabled
#define	USB_CTLR_LOG_ENDPOINT_M 60		// Endpoint number mask
#define	USB_CTLR_LOG_ENDPOINT_S	2		// Endpoint number shift

/*
*	Definitions for the dmaintis and dmainten registers
*/

#define	USB_DMAINT_EOT			0x01	// End of transfer interrupt
#define	USB_DMAINT_NDDR			0x02	// New descriptor request interrupt
#define	USB_DMAINT_ERR			0x04	// Bus error during transfer interrupt

/****************************************************************************/
/*			Serial Interface Engine commands and parameters					*/
/****************************************************************************/

/*
*	Definitions for the cmdcode register
*/

#define	USB_CMDCODE_PHASE		0xff00	// Command phase mask
#define	USB_CMDCODE_PHASE_RD	0x0100 	// Read phase
#define	USB_CMDCODE_PHASE_WR	0x0200 	// Write phase
#define	USB_CMDCODE_PHASE_CMD	0x0500 	// Command phase
#define	USB_CMDCODE_WDATA(x)  ((x)<<15)	// Command or data word

/*
*	SIE command codes
*	The comment contains if this command is a read transaction,
*	a write transaction or none. The number(s) in parens indicate(s)
*	the number of data byte(s) during the data phase.
*/

#define	USB_SET_ADDRESS			0xd0		// Wr(1) Set device address
#define	USB_CONFIGURE_DEVICE	0xd8		// Wr(1) Set device configuration
#define	USB_SET_MODE			0xf3		// Wr Set device mode
#define	USB_SET_DEVICE_STAT		0xfe		// Wr(1) Set device status
#define	USB_GET_DEVICE_STAT		0xfe		// Rd(1) Get device status
#define	USB_READ_FRAME_NUMBER	0xf5		// Rd(1/2) Get current frame number
#define	USB_READ_TEST_REGISTER	0xfd		// Rd(2) Get test register
#define	USB_READ_ERROR_STAT		0xfb		// Rd(1) Get error status
#define	USB_GET_ERROR_CODE		0xff		// Rd(1) Get error code
#define	USB_CLR_BUFFER			0xf2		// Rd(0/1) Clr buffer of sel'd endpt
#define	USB_VALIDATE_BUFFER		0xfa		// -- Validate buffer of sel'd endpt
#define	USB_SELECT_ENDPOINT(n)	 (n)		// Rd(0/1) Select endpoint n
#define	USB_CLR_INTERRUPT(n)     ((n)|0x40)	// Rd(1) Select endpoint n, clr IRQ
#define	USB_SET_ENDPOINT_STAT(n) ((n)|0x40)	// Wr(1) Set endpoint n status

/*
*	Definitions for the SET_ADDRESS command
*/

#define	USB_DEV_ADDR(x)		(x)		// Device address (0-127)
#define USB_DEV_EN			0x80	// Enable the device

/*
*	Definitions for the CONFIGURE_DEVICE command
*/

#define	USB_CONF_DEVICE		0x01	// Configuration is complete

/*
*	Definitions for the SET_MODE command
*/

#define	USB_AP_CLK			0x01	// Clock is needed even in suspend
#define	USB_INAK_CI			0x02	// Interrupt on NAK on control in endp
#define	USB_INAK_CO			0x04	// Interrupt on NAK on control out endp
#define	USB_INAK_II			0x08	// Interrupt on NAK on intrpt in endp
#define	USB_INAK_IO			0x10	// Interrupt on NAK on intrpt out endp
#define	USB_INAK_BI			0x20	// Interrupt on NAK on bulk in endp
#define	USB_INAK_BO			0x40	// Interrupt on NAK on bulk out endp

/*
*	Definitions for the SET_DEVICE_STATUS and GET_DEVICE_STATUS commands
*/

#define	USB_CON				0x01	// Connect pin (soft connect) state
#define	USB_CON_CH			0x02	// Change in connect pin status
#define	USB_SUS				0x04	// Device is suspended
#define	USB_SUS_CH			0x08	// Change in suspend
#define	USB_RST				0x10	// Bus reset was received

/*
*	Definitions for the GET_ERROR_CODE command
*/

#define	USB_EA				0x10	// Error is active
#define	USB_EC				0x0f	// Mask of actual error type
#define	USB_EC_NONE			0		// No error
#define	USB_EC_PID_ENCODING	1		// PID encoding error
#define	USB_EC_UNKNOWN_PID	2		// Unknown PID
#define	USB_EC_UNEXPECTED	3		// Unexpected packet
#define	USB_EC_TOKEN_CRC	4		// Token CRC error
#define	USB_EC_DATA_CRC		5		// Data CRC error
#define	USB_EC_TIMEOUT		6		// Timeout
#define	USB_EC_BABLE		7		// Babble
#define	USB_EC_EOP			8		// Error in end of packet
#define	USB_EC_NAK			9		// Sent or received NAK
#define	USB_EC_STALL		10		// Sent a stall
#define	USB_EC_OVERRUN		11		// Buffer overrun
#define	USB_EC_EMPTY		12		// Sent an empty isochronous packet
#define	USB_EC_BITSTUFF		13		// Bitstuff error
#define	USB_EC_SYNC			14		// SYNC error
#define	USB_EC_WRONG_TOGGLE	15		// Wrong toggle bit, data ignored

/*
*	Definitions for the READ_ERROR_STAT command
*/

#define	USB_PID_ERR			0x01	// PID error (encoding, unknown or CRC)
#define	USB_UNPKT			0x02	// Unexpected packet
#define	USB_DCRC			0x04	// Data CRC error
#define	USB_TIMEOUT			0x08	// Timeout
#define	USB_EOP				0x10	// Error in end of packet
#define	USB_B_OVRN			0x20	// Buffer overrun
#define	USB_BTSTF			0x40	// Bitstuff error
#define	USB_TGL_ERR			0x80	// Wrong toggle bit, data ignored

/*
*	Definitions for the SELECT_ENDPOINT and CLR_INTERRUPT commands
*/

#define	USB_FE				0x01	// Full/empty
#define USB_ST				0x02	// Stalled endpoint indicator
#define USB_STP				0x04	// Setup
#define USB_PO				0x08	// Packet over-written
#define USB_EPN				0x10	// EP NAK-ed
#define USB_B_1_FULL		0x20	// Buffer 1 is full
#define USB_B_2_FULL		0x40	// Buffer 2 is full

/*
*	Definitions for the SET_ENDPOINT_STAT command
*/

#define USB_STEP			0x01	// Stall endpoint
#define USB_DA				0x20	// Disable endpoint
#define USB_RF_MO			0x40	// Rate feedback mode
#define USB_CND_ST			0x80	// Conditional stall

/*
*	Definitions for the CLEAR_BUFFER command
*/

#define USB_EP0_PO			0x01	// Packet overwritten (EP0 only)

/****************************************************************************/
/*					USB DMA descriptor relate definitions					*/
/****************************************************************************/

/*
*	The control word's definitions
*/

#define	USB_DMA_CTRL_NORM	0x00000000	// Normal mode
#define	USB_DMA_CTRL_ATLE	0x00000001	// Auto tranfer length mode
#define	USB_DMA_CTRL_NDDV	0x00000004	// Next DMA descriptor is valid
#define	USB_DMA_CTRL_ISOC	0x00000010	// This is an isochronous enpoint
#define	USB_DMA_CTRL_MAXP(n) ((n)<<5)	// Max packet size (up to 2KB)
#define	USB_DMA_CTRL_BLEN(n) ((n)<<15)	// Buffer length (up to 32KB)

/*
*	Status word's definitions
*	Note that the bits in the status are only set by the HW, it is the
*	responsibility of the SW to clear them before passing the descriptor
*	to the HW. All bits should be initialised to 0, except the message
*	length position in ATLE mode (which in that case can be set to any
*	value between 0 and 63).
*/

#define	USB_DMA_STAT_RETI	0x00000001	// Descriptor is retired
#define	USB_DMA_STAT_SMASK	0x0000001e	// Transfer status mask
#define	USB_DMA_STAT_SWAIT	0x00000000	// Descriptor is not serviced
#define	USB_DMA_STAT_SBUSY	0x00000002	// Descriptor is being serviced
#define	USB_DMA_STAT_SDONE	0x00000004	// Transfer completed normally
#define	USB_DMA_STAT_SSHRT	0x00000006	// Transfer complete, short packet
#define	USB_DMA_STAT_SDOVR	0x00000010	// Aborted, data overrun
#define	USB_DMA_STAT_SBUSE	0x00000012	// Bus error during transfer
#define	USB_DMA_STAT_PVAL	0x00000020	// Packet is valid
#define	USB_DMA_STAT_LSOK	0x00000040	// ATLE low byte extracted
#define	USB_DMA_STAT_MSOK	0x00000080	// ATLE high byte extracted
#define	USB_DMA_STAT_AMPL(n) ((n)<<8)	// ATLE message length position <64
#define	USB_DMA_STAT_GPDC(x) (((x)>>16)&0xffff)	// Get present DMA count

/*
*	OTG instance
*/

static volatile struct lpc23xx_otg * const lpc_usb = (void *) 0xffe0c000;

#endif

