#ifndef __UBOOT_MB9BFXXX_UDC_H
#define __UBOOT_MB9BFXXX_UDC_H

#undef MB9BFXXX_DEBUG

#ifdef MB9BFXXX_DEBUG
	#define PDEBUG(level, fmt, args...) \
		if (debug >= (level)) serial_printf("[%s:%d] " fmt, \
		__PRETTY_FUNCTION__, __LINE__ , ## args)
#else
	#define PDEBUG(level, fmt, args...) do {} while(0)
#endif

#define UECLK_USBEN0	0x40036030
#define UECLK_USBEN1	0x40036034

#define USB_HCNT	(CONFIG_FM3_UDC + 0x0000)
#define USB_HIRQ	(CONFIG_FM3_UDC + 0x0004)
#define USB_HERR	(CONFIG_FM3_UDC + 0x0005)
#define USB_HSTATE	(CONFIG_FM3_UDC + 0x0008)
#define USB_HCOMP	(CONFIG_FM3_UDC + 0x0009)
#define USB_HRTIMER	(CONFIG_FM3_UDC + 0x000c)
#define USB_HRTIMER2	(CONFIG_FM3_UDC + 0x0010)
#define USB_HADDR	(CONFIG_FM3_UDC + 0x0011)
#define USB_HEOF	(CONFIG_FM3_UDC + 0x0014)
#define USB_HFRAME	(CONFIG_FM3_UDC + 0x0018)
#define USB_HTOKEN	(CONFIG_FM3_UDC + 0x001c)
#define USB_UDCC	(CONFIG_FM3_UDC + 0x0020)
#define USB_EP0C	(CONFIG_FM3_UDC + 0x0024)
#define USB_EP1C	(CONFIG_FM3_UDC + 0x0028)
#define USB_EP2C	(CONFIG_FM3_UDC + 0x002c)
#define USB_EP3C	(CONFIG_FM3_UDC + 0x0030)
#define USB_EP4C	(CONFIG_FM3_UDC + 0x0034)
#define USB_EP5C	(CONFIG_FM3_UDC + 0x0038)
#define USB_TMSP	(CONFIG_FM3_UDC + 0x003c)
#define USB_UDCS	(CONFIG_FM3_UDC + 0x0040)
#define USB_UDCIE	(CONFIG_FM3_UDC + 0x0041)
#define USB_EP0IS	(CONFIG_FM3_UDC + 0x0044)
#define USB_EP0OS	(CONFIG_FM3_UDC + 0x0048)
#define USB_EP1S	(CONFIG_FM3_UDC + 0x004c)
#define USB_EP2S	(CONFIG_FM3_UDC + 0x0050)
#define USB_EP3S	(CONFIG_FM3_UDC + 0x0054)
#define USB_EP4S	(CONFIG_FM3_UDC + 0x0058)
#define USB_EP5S	(CONFIG_FM3_UDC + 0x005c)
#define USB_EP0DTL	(CONFIG_FM3_UDC + 0x0060)
#define USB_EP0DTH	(CONFIG_FM3_UDC + 0x0061)
#define USB_EP1DTL	(CONFIG_FM3_UDC + 0x0064)
#define USB_EP1DTH	(CONFIG_FM3_UDC + 0x0065)
#define USB_EP2DTL	(CONFIG_FM3_UDC + 0x0068)
#define USB_EP2DTH	(CONFIG_FM3_UDC + 0x0069)
#define USB_EP3DTL	(CONFIG_FM3_UDC + 0x006c)
#define USB_EP3DTH	(CONFIG_FM3_UDC + 0x006d)
#define USB_EP4DTL	(CONFIG_FM3_UDC + 0x0070)
#define USB_EP4DTH	(CONFIG_FM3_UDC + 0x0071)
#define USB_EP5DTL	(CONFIG_FM3_UDC + 0x0074)
#define USB_EP5DTH	(CONFIG_FM3_UDC + 0x0075)

#define USB_UDCS_SUSP	(1 << 5)
#define USB_UDCS_SOF	(1 << 4)
#define USB_UDCS_BRST	(1 << 3)
#define USB_UDCS_WKUP	(1 << 2)
#define USB_UDCS_SETP	(1 << 1)
#define USB_UDCS_CONF	(1 << 0)

#define USB_UDCC_RST	(1 << 7)
#define USB_UDCC_RESUM	(1 << 6)
#define USB_UDCC_HCONX	(1 << 5)
#define USB_UDCC_USTP	(1 << 4)
#define USB_UDCC_STALCLREN	(1 << 3)
#define USB_UDCC_RFBK	(1 << 1)
#define USB_UDCC_PWC	(1 << 0)

#define USB_EPC_EPEN	(1 << 15)
#define USB_EPC_TYPE	(1 << 13)
#define USB_EPC_DIR	(1 << 12)
#define USB_EPC_DMAE	(1 << 11)
#define USB_EPC_NULE	(1 << 10)
#define USB_EPC_STAL	(1 << 9)

#define MAX_EP_SIZE	64
#define MAX_EP1_SIZE	256

struct mb9bfxxx_ep {
	struct usb_ep                           ep;
	struct mb9bfxxx_udc			*dev;
	int					acct_req_lengths[4];
	int					acct_req_dir[4];//direction
	unsigned long				queue_reqs;//how many times has mb9bfxxx_queue been called
	unsigned long				queue_active;//how many current requests
	unsigned long				packets;//counter of raw packets
	unsigned				num:4,
						numActual:4,
						fifoNum:2,
						is_in:1,
						stage:2,//for ep0, 0 = unused, 1 = got setup, 2 = done transfer/ready to send/receive ZLP
						toggle:1,
						nuking:1,//are we killing on off this endpoint//only used for ep0 to help with stages
						enable:1,
						configure:1;
	/* analogous to a host-side qh */
	struct list_head			queue;
	const struct usb_endpoint_descriptor	*desc;
	unsigned short				maxlenmask;

	unsigned long				control;
	unsigned long				fifo;
	unsigned long				status;
};

struct mb9bfxxx_request {
	struct usb_request		req;
	struct list_head		queue;
	int				complete;//this is added for tx requests
						//if set the entire request has been written to the fifo, just waiting for confirmation
};

struct mb9bfxxx_udc {
	struct usb_gadget		gadget;
	struct mb9bfxxx_ep		ep[6];
	struct usb_gadget_driver	*driver;
};

#endif	/* __UBOOT_MB9BFXXX_UDC_H */
