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

#ifndef _LPC23XX_ETH
#define _LPC23XX_ETH

/*
*	DMA receive buffer descriptor
*/

typedef	struct {

	void		*data;				// Pointer to the data buffer
	unsigned	ctrl;				// Receiver control

} LPC_ETH_RXB;

/*
*	DMA receive status descriptor
*/

typedef	struct {

	unsigned	stat;					// Status flags
	unsigned	hash;					// Address hashes

} LPC_ETH_RXS;

/*
*	DMA transmit buffer descriptor
*/

typedef	struct {

	void		*data;					// Pointer to data buffer
	unsigned	ctrl;					// Transmitter control

} LPC_ETH_TXB;

/*
*	LPC2378 Ethernet controller registers
*	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/

struct s_lpc23xx_eth {

	unsigned	mac1;				// MAC config 1
	unsigned	mac2;				// MAC config 2
	unsigned	ipgt;				// Inter-packet gap, back-to-back
	unsigned	ipgr;				// Inter-packet gap, non back-to-back
	unsigned	clrt;				// Collision window and retry
	unsigned	maxf;				// Maximum frame size
	unsigned	supp;				// PHY support
	unsigned	test;				// Test
	unsigned	mcfg;				// RMII management config
	unsigned	mcmd;				// RMII command
	unsigned	madr;				// RMII address
	unsigned	mwtd;				// RMII write data
	unsigned	mrdd;				// RMII read data
	unsigned	mind;				// RMII indications
	unsigned	_1[2];
	unsigned	sa0;				// MAC address	bits 47-32
	unsigned	sa1;				// MAC address	bits 31-16
	unsigned	sa2;				// MAC address	bits 15- 0
	unsigned	_2[45];
	unsigned	cmd;				// Command
	unsigned	stat;				// Status
	LPC_ETH_RXB	*rxdesc;			// DMA receive descriptor base address
	LPC_ETH_RXS	*rxstat;			// DMA receive status base address
	unsigned	rxdescnum;			// Number of DMA receive descriptors
	unsigned	rxprodindex;		// DMA receive produce index
	unsigned	rxconsindex;		// DMA receive consume index
	LPC_ETH_TXB	*txdesc;			// DMA transmit descriptor base address
	unsigned	*txstat;			// DMA transmit status base address
	unsigned	txdescnum;			// Number of DMA transmit descriptors
	unsigned	txprodindex;		// DMA transmit produce index
	unsigned	txconsindex;		// DMA transmit consume index
	unsigned	_3[10];
	unsigned	tsv0;				// Transmit status vector 0
	unsigned	tsv1;				// Transmit status vector 1
	unsigned	rsv;				// Receive status vector 0
	unsigned	_4[3];
	unsigned	flowctrlcntr;		// Flow control counter
	unsigned	flowctrlstat;		// Flow control status
	unsigned	_5[34];
	unsigned	rxfilterctrl;		// Receive filter control
	unsigned	rxfilterwolstat;	// Receive wake-on-LAN status
	unsigned	rxfilterwolclr;		// Receive wake-on-LAN clear
	unsigned	_6;
	unsigned	hashfilterl;		// Hash filter least significant word
	unsigned	hashfilterh;		// Hash filter most significant word
	unsigned	_7[882];
	unsigned	intstat;			// Interrupt status
	unsigned	intenable;			// Interrupt enable
	unsigned	intclr;				// Interrupt clear
	unsigned	intset;				// Interrupt set
	unsigned	_8[2];
	unsigned	powerdown;			// Power down register
};

/****************************************************************************/
/*				Interrupt related definitions								*/
/****************************************************************************/

/*
*	Definitions for intstat, intenable, intset and intclr registers
*/

#define	ETH_INT_RX_OVERRUN		0x0001	// Receive overrun / descr. underrun
#define	ETH_INT_RX_ERROR		0x0002	// Receive error
#define	ETH_INT_RX_FINISHED		0x0004	// Receive done
#define	ETH_INT_RX_DONE			0x0008	// Transmit overrun / descr. underrun
#define	ETH_INT_TX_UNDERRUN		0x0010	// Transmit error
#define	ETH_INT_TX_ERROR		0x0020	// Transmit queue empty
#define	ETH_INT_TX_FINISHED		0x0040	// Transmit done (desc IRQ)
#define	ETH_INT_TX_DONE			0x0040	// Transmit done (desc IRQ)
#define	ETH_INT_SOFT			0x0100	// Software triggered interrupt
#define	ETH_INT_WAKEUP			0x0200	// Wake-up interrupt

/****************************************************************************/
/*				MAC related definitions										*/
/****************************************************************************/

/*
*	Definitions for the mac1 register
*/

#define	ETH_MAC1_RX_ENA			0x0001		// Receiver enable
#define	ETH_MAC1_RX_ALL			0x0002		// Receive all frames, inc. control
#define	ETH_MAC1_RX_FLOW		0x0004		// Enable receive flow control
#define	ETH_MAC1_TX_FLOW		0x0008		// Enable transmit flow control
#define	ETH_MAC1_LOOPBACK		0x0010		// Enable loopback mode
#define	ETH_MAC1_RESET_TX		0x0100		// Transmitter reset
#define	ETH_MAC1_RESET_MCSTX	0x0200		// Transmit side MAC reset
#define	ETH_MAC1_RESET_RX		0x0400		// Receiver reset
#define	ETH_MAC1_RESET_MCSRX	0x0800		// Receiver side MAC reset
#define	ETH_MAC1_SIM_RESET		0x4000		// Reset transmit RNG
#define	ETH_MAC1_SOFT_RESET		0x8000		// Soft reset

/*
*	Definitions for the mac2 register
*/

#define	ETH_MAC2_FULL_DUPLEX	0x0001		// Full duplex mode enabled
#define	ETH_MAC2_FLEN_CHECK		0x0002		// Perform frame length check
#define	ETH_MAC2_HUGE_FRAME_ENA	0x0004		// Enable huge frames
#define	ETH_MAC2_DELAYED_CRC	0x0008		// CRC ignores the first 8 bytes
#define	ETH_MAC2_CRC_ENA		0x0010		// Append CRC to frames
#define	ETH_MAC2_PAD_CRC_ENA	0x0020		// Enable short frame padding
#define	ETH_MAC2_VLAN_PAD_ENA	0x0040		// VLAN frame padding enable
#define	ETH_MAC2_AUTO_PAD_ENA	0x0080		// Enable padding for auto-detect
#define	ETH_MAC2_PURE_PRE_ENF	0x0100		// Pure preamble enforcement
#define	ETH_MAC2_LONG_PRE_ENF	0x0200		// Long preamble enforcement
#define	ETH_MAC2_NO_BACKOFF		0x1000		// No backoff on collision
#define	ETH_MAC2_BACKPRESSURE	0x2000		// No backoff during back pressure
#define	ETH_MAC2_EXCESS_DEFER	0x4000		// Enable excessive deferral

/*
*	Definitions for the ipgr register
*/

#define	ETH_IPGR_PART1(x)	 ((x)<<8)		// Set it to 12, as per IEEE std
#define	ETH_IPGR_PART2(x)	 (x)			// Set it to 18, as per IEEE std

/*
*	Definitions for the clrt register
*/

#define	ETH_CLRT_RETRANS_MAX(x)	(x)			// Should be 15 as per IEEE
#define	ETH_CLRT_COLL_WIND(x)	((x)<<8)	// Should be 55 as per IEEE

/*
*	Definitions for the supp register
*/

#define	ETH_SUPP_SPEED		0x100			// Opearting speed is 100Mbps

/****************************************************************************/
/*				RMII related definitions									*/
/****************************************************************************/

/*
*	Definitions for the mcfg register
*/

#define	ETH_MCFG_SCAN_INCR		0x0001	// RMII scan address is incremented
#define	ETH_MCFG_SUPR_PREA		0x0002	// RMII comms preamble suppressed
#define	ETH_MCFG_CLOCKSEL		0x001c	// RMII comms clock select mask
#define	ETH_MCFG_CLOCKSEL_4		0x0000	// RMII comms clock is HCLK / 4
#define	ETH_MCFG_CLOCKSEL_6		0x0008	// RMII comms clock is HCLK / 6
#define	ETH_MCFG_CLOCKSEL_8		0x000c	// RMII comms clock is HCLK / 8
#define	ETH_MCFG_CLOCKSEL_10	0x0010	// RMII comms clock is HCLK / 10
#define	ETH_MCFG_CLOCKSEL_14	0x0014	// RMII comms clock is HCLK / 14
#define	ETH_MCFG_CLOCKSEL_20	0x0018	// RMII comms clock is HCLK / 20
#define	ETH_MCFG_CLOCKSEL_28	0x001c	// RMII comms clock is HCLK / 28
#define	ETH_MCFG_RESET			0x8000	// Reset RMII

/*
*	Definitions for the mcmd register
*/

#define	ETH_MCMD_READ	0x01			// Execute a single RMII read cycle
#define	ETH_MCMD_SCAN	0x02			// Continuously scan (read) the RMII

/*
*	Definitions for the madr register
*	The macro encodes the PHY address and the
*	register address within the PHY.
*/

#define	ETH_MADR(phy,reg)	(((phy)<<8)|(reg))

/*
*	Definitions for the mind register
*/

#define	ETH_MIND_BUSY		0x01		// MII management is currently busy
#define	ETH_MIND_SCANNING	0x02		// Scan operation is in progress
#define	ETH_MIND_NOT_VALID	0x04		// Read is not finished yet
#define	ETH_MIND_LINK_FAIL	0x08		// MII link failure detected

/****************************************************************************/
/*			General	controller definitions									*/
/****************************************************************************/

/*
*	Definitions for the cmd register
*/

#define	ETH_CMD_RX_ENABLE		0x001	// Enable receiver
#define	ETH_CMD_TX_ENABLE		0x002	// Enable tranmitter
#define	ETH_CMD_REG_RESET		0x008	// Reset everything but the MAC
#define	ETH_CMD_TX_RESET		0x010	// Reset transmitter data path
#define	ETH_CMD_RX_RESET		0x020	// Reset receiver data path
#define	ETH_CMD_PASS_RUNT_FRAME	0x040	// Enable runt frames to pass through
#define	ETH_CMD_PASS_RX_FILTER	0x080	// Promiscuous mode
#define	ETH_CMD_TX_FLOW_CTRL	0x100	// Transmit flow control enable
#define	ETH_CMD_RMII			0x200	// RMII mode is selected (0:MII)
#define	ETH_CMD_FULL_DUPLEX		0x400	// Full duplex operation

/*
*	Definitions for the stat register
*/

#define	ETH_STAT_RX_STATUS		0x01	// Receiver is active
#define	ETH_STAT_TX_STATUS		0x02	// Transmitter is active

/*
*	Definitions for the tsv0 register
*/

#define	ETH_TSV0_CRC_ERROR		0x00000001	// SW/HW CRC difference error
#define	ETH_TSV0_LENGTH_ERROR	0x00000002	// Frame length / data size mismatch
#define	ETH_TSV0_LENGTH_RANGE	0x00000004	// Frame length was over 1500 bytes
#define	ETH_TSV0_DONE			0x00000008	// Transmission complete
#define	ETH_TSV0_MULTICAST		0x00000010	// Destination was a multicast
#define	ETH_TSV0_BROADCAST		0x00000020	// Destination was a broadcast
#define	ETH_TSV0_PACKET_DEFER	0x00000040	// There was deferral for the packet
#define	ETH_TSV0_EXCESS_DEFER	0x00000080	// Excessive deferral error
#define	ETH_TSV0_EXCESS_COLL	0x00000100	// Excessive collision error
#define	ETH_TSV0_LATE_COLL		0x00000200	// Late collision error
#define	ETH_TSV0_GIANT			0x00000400	// Frame size was over 64K
#define	ETH_TSV0_UNDERRUN		0x00000800	// Transmitter underrun
#define	ETH_TSV0_CTRL_FRAME		0x10000000	// The frame was a control frame
#define	ETH_TSV0_PAUSE			0x20000000	// The frame was a PAUSE frame
#define	ETH_TSV0_BACKPRESSURE	0x40000000	// Backpressure was applied
#define	ETH_TSV0_VLAN			0x80000000	// The frame was a VLAN frame
#define	ETH_TSV0_TOTAL_BYTES_M	0x0ffff000	// Total bytes mask
#define	ETH_TSV0_TOTAL_BYTES_S	12			// Total bytes shift

/*
*	Definitions for the tsv1 register
*/

#define	ETH_TSV1_TX_BYTE_COUNT_M 0x00ffff	// Total # in the frame	mask
#define	ETH_TSV1_TX_BYTE_COUNT_S 0			// Total # in the frame	shift
#define	ETH_TSV1_TX_COLL_COUNT_M 0xff0000	// Collision count mask
#define	ETH_TSV1_TX_COLL_COUNT_S 15			// Collision count shift

/*
*	Definitions for the rsv register
*/

#define	ETH_RSV_BYTE_COUNT_M	0x0000ffff	// Length of the received frame
#define	ETH_RSV_IGNORED			0x00010000	// Packet was dropped
#define	ETH_RSV_RXDV_EVENT		0x00020000	// Rx was too short for a packet
#define	ETH_RSV_CARR_EVENT		0x00040000	// A carrier event was seen
#define	ETH_RSV_RX_CODE_VIOL	0x00080000	// RMII data is not a valid Rx code
#define	ETH_RSV_CRC_ERROR		0x00100000	// Frame had CRC error
#define	ETH_RSV_LENGTH_CHECK	0x00200000	// Frame length doesn't mach
#define	ETH_RSV_LENGTH_RANGE	0x00400000	// Frame is larger than 1518 bytes
#define	ETH_RSV_RX_OK			0x00800000	// Reception finished with no error
#define	ETH_RSV_MULTICAST		0x01000000	// It is a multicast frame
#define	ETH_RSV_BROADCAST		0x02000000	// It is a broadcast frame
#define	ETH_RSV_DRIBBLE_NIBBLE	0x04000000	// There was dribble after frame
#define	ETH_RSV_CTRL_FRAME		0x08000000	// It is a control frame
#define	ETH_RSV_PAUSE			0x10000000	// It is a PASUE frame
#define	ETH_RSV_OPCODE			0x20000000	// Unsupported opcode
#define	ETH_RSV_VLAN			0x40000000	// It is a VLAN frame

/*
*	Definitions for the flowctrlcntr register
*/

#define	ETH_FLOWCTRLCNTR(mirror,pause) ((pause)<<16|(mirror))

/*
*	Definitions for the power register
*/

#define	ETH_POWER_DOWN_MAC_AHB	0x80000000	// Power down the AHB interface

/****************************************************************************/
/*				Receive address filtering related definitions				*/
/****************************************************************************/

/*
*	Definitions for rxfilerctrl register
*/

#define	ETH_RXFILTERCTRL_UCAST	0x0001	// Accept all unicast frames
#define	ETH_RXFILTERCTRL_BCAST	0x0002	// Accept all broadcast frames
#define	ETH_RXFILTERCTRL_MCAST	0x0004	// Accept all multicast frames
#define	ETH_RXFILTERCTRL_UHASH	0x0008	// Accept unicast hash match frames
#define	ETH_RXFILTERCTRL_MHASH	0x0010	// Accept multicast hash match frames
#define	ETH_RXFILTERCTRL_EXACT	0x0020	// Accept exact address match frames
#define	ETH_RXFILTERCTRL_MAGIC	0x0100	// Magic filter generates WoL interrupt
#define	ETH_RXFILTERCTRL_EXHSH	0x0200	// Exact & hash generates WoL interrupt

/*
*	Definitions for rxfilterwolstat and rxfilterwolclr registers
*/

#define	ETH_RXFILTERWOL_UCAST	0x0001	// Wake-up on all unicast frames
#define	ETH_RXFILTERWOL_BCAST	0x0002	// Wake-up on all broadcast frames
#define	ETH_RXFILTERWOL_MCAST	0x0004	// Wake-up on all multicast frames
#define	ETH_RXFILTERWOL_UHASH	0x0008	// Wake-up on unicast hash match
#define	ETH_RXFILTERWOL_MHASH	0x0010	// Wake-up on multicast hash match
#define	ETH_RXFILTERWOL_EXACT	0x0020	// Wake-up on exact address match
#define	ETH_RXFILTERWOL_EXHSH	0x0080	// Wake-up on exact or any hash
#define	ETH_RXFILTERWOL_MAGIC	0x0100	// Wake-up on magic filter

/****************************************************************************/
/*				DMA related definitions										*/
/****************************************************************************/

/*
*	Definitions for the ctrl field of the ETH_RXD DMA control descriptor
*/

#define	ETH_RXB_SIZE(x)	((x)-1)		// Size of the buffer-1, max 2047
#define	ETH_RXB_IREQ	0x80000000	// Request for interrupt when finished

/*
*	Definitions for the stat field of the ETH_RXS DMA status descriptor
*/

#define	ETH_RXS_SIZEM	0x000007ff	// Received data length mask
#define	ETH_RXS_CTRLF	0x00040000	// Indicates a flow control frame
#define	ETH_RXS_VLANF	0x00080000	// Indicates a VLAN tagged frame
#define	ETH_RXS_FILTF	0x00100000	// Indicates filter mismatch with frame
#define	ETH_RXS_MCAST	0x00200000	// Indicates a multicast frame
#define	ETH_RXS_BCAST	0x00400000	// Indicates a broadcast frame
#define	ETH_RXS_ERCRC	0x00800000	// Frame CRC error
#define	ETH_RXS_ERSYM	0x01000000	// Bit error reported by PHY
#define	ETH_RXS_ERLEN	0x02000000	// Size field does not match pkt size
#define	ETH_RXS_ERRNG	0x04000000	// Frame size exceeds max pkt size
#define	ETH_RXS_ERALN	0x08000000	// Aligment error
#define	ETH_RXS_EROVR	0x10000000	// Receiver overrun error
#define	ETH_RXS_ERDES	0x20000000	// Receiver ran out of descriptors
#define	ETH_RXS_FLAST	0x40000000	// Last descriptor for the frame
#define	ETH_RXS_ERROR	0x80000000	// ALN | RNG | LEN | SYM | CRC | OVR

/*
*	Definitions for the ctrl field of the ETH_TXB DMA status descriptor
*/

#define	ETH_TXB_SIZE(x)		(x)		// Sizeo buffer-1, max 2047
#define	ETH_TXB_FDES	0x04000000	// Flags from MAC(0) or descriptor(1)
#define	ETH_TXB_HUGE	0x08000000	// Allow frames larger than mac_mfs
#define	ETH_TXB_PADS	0x10000000	// Pad short frames to 64 bytes
#define	ETH_TXB_ACRC	0x20000000	// Append CRC
#define	ETH_TXB_LAST	0x40000000	// Last descriptor of the frame
#define	ETH_TXB_IERQ	0x80000000	// Request for interrupt when finished

/*
*	Definitions for the DMA transmit status word
*/

#define	ETH_TXS_COLCT(x) (((x)>>21)&15)	// Collision count
#define	ETH_TXS_DEFER	0x02000000	// Packet incurred deferral
#define	ETH_TXS_EXDEF	0x04000000	// Excessive deferral error
#define	ETH_TXS_EXCOL	0x08000000	// Excessive collision error
#define	ETH_TXS_LTCOL	0x10000000	// Late collision error
#define	ETH_TXS_UNDER	0x20000000	// Transmit underrun
#define	ETH_TXS_NODES	0x40000000	// Transmitter ran out of descriptors
#define	ETH_TXS_ERROR	0x80000000	// Transmission error

/*
*	Ethernet instance
*/

static volatile struct lpc23xx_eth * const lpc_eth = (void *) 0xffe00000;

#endif

