/*
 * Ikanos Communications USB Device Controller driver
 *
 * Copyright (C) 2000-2002 Lineo
 *      by Stuart Lynne, Tom Rushworth, and Bruce Balden
 * Copyright (C) 2006 Ikanos Communications
 * Copyright (C) 2003 MontaVista Software (source@mvista.com)
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2.  This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

static const char ep0name[] = "ep0";

static const char *const ep_name[] = {
	ep0name,		/* everyone has ep0 */
	"ep1in-int",		/* interrupt IN */
	"ep2in-bulk",		/* bulk IN */
	"ep3out-bulk",		/* bulk OUT */
};

#define VOX160_UDC_NUM_EP (4)
#define VOX160_UDC_MAX_EP (7)

#define STALL_CLEARED (0)
#define STALL_EXIST    (1)

struct vox160udc_gen_regs {
	/* USB Device ID Register:offset 0x00 */
	u16 usb_id;
	u16 reserved1;
	/* Current USB Frame # Register:offset 0x04 */
	u16 usbd_frm;
	u16 reserved2;
#define USBD_FRM_MASK 0x07ff
	/* USB Frame Number Register:offset 0x08 */
	u16 usbd_frmt;
	u16 reserved3;
	/* Enable download into USB core resigster:offset 0x0c */
	u16 usbd_encfg_dl_cor;
#define USBD_EPBUF_RDY  0x4000	/* 1 - ready to accept byte */
#define USBD_EPBUF_CFG  0x8000	/* 1 - waiting for endpoint buffer data */
	u16 reserved4;
	/* USB Module Status Register:offset 0x10 */
	u16 usbd_stat;
#define USBD_STAT_SUSPENDED  0x0001	/* USB suspended */
#define USBD_STAT_RSTSIG     0x0002	/* USB reset signalling in progress */
#define USBD_STAT_SIP        0x0004	/* USB setup packet in progress */
#define USBD_STAT_PIP        0x0008	/* USB packet in progress */
#define USBD_STAT_EP         0x0070	/* Currently accessed endpoint */
#define USBD_STAT_AIF        0x0380	/* USB alternate interface number */
#define USBD_STAT_IF         0x0c00	/* USB interface number */
#define USBD_STAT_CFG        0x3000	/* USB configuration number */
#define USBD_STAT_TOKEN      0xc000	/* Last token received on USB */
	u16 reserved5;
	/* USB module control register:offset 0x14 */
	u16 usbd_ctrl;
#define USBD_CTRL_ENA        0x0001	/* 1 - USBD module enabled */
#define USBD_CTRL_UDCRST     0x0002	/* 1 - execute hard reset for USBD */
#define USBD_CTRL_EP0STALL   0x0100	/* 1 - assert a stall request */
#define USBD_CTRL_EP1STALL   0x0200	/* 1 - assert a stall request */
#define USBD_CTRL_EP2STALL   0x0400	/* 1 - assert a stall request */
#define USBD_CTRL_EP3STALL   0x0800	/* 1 - assert a stall request */
#define USBD_CTRL_EP4STALL   0x1000	/* 1 - assert a stall request */
#define USBD_CTRL_EP5STALL   0x2000	/* 1 - assert a stall request */
#define USBD_CTRL_EP6STALL   0x4000	/* 1 - assert a stall request */
#define USBD_CTRL_EP7STALL   0x8000	/* 1 - assert a stall request */
	u16 reserved6;
	/* Global Interrupt Register:offset 0x18 */
	u16 usbd_gintr;
#define USBD_GINTR_SOF        0x0001
#define USBD_GINTR_CFG        0x0002
#define USBD_GINTR_MSOF       0x0004
#define USBD_GINTR_RST        0x0008
#define USBD_GINTR_SUSP       0x0010
#define USBD_GINTR_RESUME     0x0020
#define USBD_GINTR_FRMMAT     0x0040
#define USBD_GINTR_DMAIRQ     0x0080
#define USBD_GINTR_EP0INT     0x0100
#define USBD_GINTR_EP1INT     0x0200
#define USBD_GINTR_EP2INT     0x0400
#define USBD_GINTR_EP3INT     0x0800
#define USBD_GINTR_EP4INT     0x1000
#define USBD_GINTR_EP5INT     0x2000
#define USBD_GINTR_EP6INT     0x4000
#define USBD_GINTR_EP7INT     0x8000
	u16 reserved7;
	/* Global Interrupt Mask Register:offset 0x1c */
	u16 usbd_gmask;
#define USBD_GMASK_SOFM       0x0001
#define USBD_GMASK_CFGM       0x0002
#define USBD_GMASK_MSOFM      0x0004
#define USBD_GMASK_RSTM       0x0008
#define USBD_GMASK_SUSPM      0x0010
#define USBD_GMASK_RESUMEM    0x0020
#define USBD_GMASK_FRMMATM    0x0040
#define USBD_GMASK_DMAIRQM    0x0080
#define USBD_GMASK_EP0MSK     0x0100
#define USBD_GMASK_EP1MSK     0x0200
#define USBD_GMASK_EP2MSK     0x0400
#define USBD_GMASK_EP3MSK     0x0800
#define USBD_GMASK_EP4MSK     0x1000
#define USBD_GMASK_EP5MSK     0x2000
#define USBD_GMASK_EP6MSK     0x4000
#define USBD_GMASK_EP7MSK     0x8000
	u16 reserved8;
} __attribute__ ((packed));

struct vox160udc_dma_regs {
	/* DMA Master Channel Configuration Register */
	u16 usbd_dmacfg;
#define USBD_DMACFG_DMAEN      0x0001	/* 1 - DMA master channel enabled */
#define USBD_DMACFG_IOC        0x0004	/* 1 - interrupt concurrent with */
	/*     each DMA burst of 4 words */
#define USBD_DMACFG_DMABC      0x0080	/* 1 - clear DMA buffer */
#define USBD_DMACFG_IOE	       0x0100	/* 1 enable interrupt on error */
	u16 reserved1;
	/* DMA Master Channel Base Address Low Register */
	u16 usbd_dmabl;
	u16 reserved2;
	/* DMA Master Channel Base Address High Register */
	u16 usbd_dmabh;
	u16 reserved3;
	/* DMA Master Channel Count Register */
	u16 usbd_dmact;
	u16 reserved4;
	/* DMA Master Channel DMA Interrupt Register */
	u16 usbd_dmairq;
#define USBD_DMAIRQ_ERR		0x0001
#define USBD_DMAIRQ_COMP	0x0002
	u16 reserved5;
} __attribute__ ((packed));

struct vox160udc_ep_regs {
	u16 reg;
	u16 reserved;
} __attribute__ ((packed));

#ifndef USB_VENDOR_ID
#define USB_VENDOR_ID   0x1110	/* vendor ID for Analog Devices, Inc. */
#endif
#ifndef USB_PRODUCT_ID
#define USB_PRODUCT_ID  0x6489	/* product ID for AD6489 */
#endif

#define USBD_SOFT_RESET  (0)
#define USBD_HARD_RESET  (1)

#define VOX160_VBUS_GPIO_PIN_POLL_RATE (50)

/* DMA buffer is 2K bytes */

#define USBD_MEM_BASE           (0x19168000)	/* Base address USBD local mem */
#define USBD_DMA_BUFSIZE     	2048

/* The hardware has been set up for a total of 64 endpoints buffer,all of which 
 * must be allocated.
 */
#define NUM_EPBUF_BYTES 	(64 * 5)
#define MAX_EPBUF_WAIT  	(500)

#define PACKET_0   0
#define PACKET_8   8
#define PACKET_16 16
#define PACKET_32 32
#define PACKET_64 64

#define BUFFER_0       0
#define BUFFER_8       8
#define BUFFER_16      16
#define BUFFER_128   128
#define BUFFER_160   160
#define BUFFER_192   192
#define BUFFER_256   256
#define BUFFER_832   832
#define BUFFER_896   896
#define BUFFER_960   960
#define BUFFER_1600 1600

#define OFFSET_0       0
#define OFFSET_128   128
#define OFFSET_160   160
#define OFFSET_192   192
#define OFFSET_256   256
#define OFFSET_1088 1088
#define OFFSET_1152 1152
#define OFFSET_1792 1792

#define FRAMES_0    0
#define FRAMES_3    3

#define USBD_CONTROL_EP   (0)
#define USBD_INTERRUPT_EP (1)
#define USBD_BULK_IN_EP   (2)
#define USBD_BULK_OUT_EP  (3)

#define EP_CONTROL_OUT_ATTRIBS ((0x00 << 2)|(0x00 << 4))
#define EP_INTERRUPT_ATTRIBS   ((0x02 << 2)|(0x01 << 4))

#define EP_BULK_IN_ATTRIBS     ((0x01 << 2)|(0x03 << 4))

#define EP_BULK_OUT_ATTRIBS    ((0x01 << 2)|(0x03 << 4))

/*-------------------------------------------------------------------------*/

/* DRIVER DATA STRUCTURES and UTILITIES */

struct vox160_ep {
	/* Public endpoint structure */
	struct usb_ep ep;

	/* Parent device */
	struct vox160_udc *dev;

	unsigned long irqs;

	/* Endpoint number */
	unsigned num:8;

	/* Whether this endpoint supports dma */
	unsigned dma:1;

	/* 1 if endpoint is INput (e.g. TX from UDC point of view) */

	unsigned is_in:1;
	/* 1 if endpoint is stopped */

	unsigned stopped:1;

	/* A chained list of vox160_request structures */
	struct list_head queue;

	/* Endpoint descriptor */
	const struct usb_endpoint_descriptor *desc;

	/* Maximum USB packet size for this end point */
	unsigned short max_packet_size;

	/* Maximum EPLEN */
	unsigned short max_buffer_len;
	/* Currently Programmed value in EPLEN */
	unsigned short current_max_buffer_len;

	/* Attributes to program into EPCFG */
	unsigned short cfg_attribs;

	/* Offset into DMA from DMA_BASE_ADDR */
	unsigned short dma_offset;

	/* Current Offset into DMA Memory */
	unsigned short cur_offset;

	/* ep interrupts list that we are interested in */
	unsigned short ep_intr_list;
};

struct vox160_request {
	/* The public request structure */
	struct usb_request req;
	/* The chained list to link requests belonging to one endpoint */
	struct list_head queue;
	unsigned mapped:1;
};

enum ep0state {
	EP0_DISCONNECT,		/* no host */
	EP0_IDLE,		/* between STATUS ack and SETUP report */
	EP0_IN, EP0_OUT,	/* data stage */
	EP0_STATUS,		/* status stage */
	EP0_OUT_STATUS,		/* status stage */
	EP0_IN_STATUS,		/* status stage */
	EP0_STALL,		/* data or status stages */
	EP0_SUSPEND,		/* usb suspend */
	EP0_WAIT_ZLP,		/* usb suspend */
	EP0_READY,		/* usb suspend */
	EP0_WAIT_HANDSHAKE,	/* usb suspend */
};

char *ep0statename[] = {
	"EP0_DISCONNECT",	/* no host */
	"EP0_IDLE",		/* between STATUS ack and SETUP report */
	"EP0_IN", "EP0_OUT",	/* data stage */
	"EP0_STATUS",		/* status stage */
	"EP0_OUT_STATUS",	/* status stage */
	"EP0_IN_STATUS",	/* status stage */
	"EP0_STALL",		/* data or status stages */
	"EP0_SUSPEND",		/* usb suspend */
	"EP0_WAIT_ZLP",		/* usb suspend */
	"EP0_READY",		/* usb suspend */
	"EP0_WAIT_HANDSHAKE",	/* usb suspend */
};

struct vox160_udc {
	/* Public gadget structure which represents a usb slave device */
	struct usb_gadget gadget;
	/* Spinlock for accessing the UDC */
	spinlock_t lock;

	/* All of UDC endpoints */
	struct vox160_ep ep[VOX160_UDC_NUM_EP];

	/* A pointer to bound gadget driver */
	struct usb_gadget_driver *driver;

	/* Current endpoint 0 state */
	enum ep0state ep0state;

	/* AD6489 USBD General Registers */
	struct vox160udc_gen_regs __iomem *gen_regs;
	/* DMA Registers */
	struct vox160udc_dma_regs __iomem *dma_regs;
	/* USB Endpoint(n) Interrupt Register (USBD_INTRn) */
	struct vox160udc_ep_regs __iomem *usbd_intr[VOX160_UDC_MAX_EP];
#define USBD_INTR_TC         0x0001
#define USBD_INTR_PC         0x0002
#define USBD_INTR_BCSTAT     0x0004
#define USBD_INTR_SETUP      0x0008
#define USBD_INTR_MSETUP     0x0010
#define USBD_INTR_MERR       0x0020

	/* USB Endpoint(n) Mask Register (USBD_MASKn) */
	struct vox160udc_ep_regs __iomem *usbd_mask[VOX160_UDC_MAX_EP];
#define USBD_MASK_TC         0x0001
#define USBD_MASK_PC         0x0002
#define USBD_MASK_BCSTAT     0x0004
#define USBD_MASK_SETUP      0x0008
#define USBD_MASK_MSETUP     0x0010
#define USBD_MASK_MERR       0x0020
#define USBD_EP_MASK_ALL     0x003f

	/* USB Endpoint(n) Control Register (USBD_EPCFGn) */
	struct vox160udc_ep_regs __iomem *usbd_epcfg[VOX160_UDC_MAX_EP];
#define USBD_EPCFG_ARM        0x0001	/* 1 - arm endpoint */
#define USBD_EPCFG_DIR_OUT    0x0000	/* transfer direction out */
#define USBD_EPCFG_DIR_IN     0x0002	/* transfer direction in */
#define USBD_EPCFG_MAX_8      0x0000
#define USBD_EPCFG_MAX_16     (0x01 << 4)
#define USBD_EPCFG_MAX_32     (0x02 << 4)
#define USBD_EPCFG_MAX_64     (0x03 << 4)

	/* USB Endpoint(n) Address Offset Register (USBD_EPADRn) */
	struct vox160udc_ep_regs __iomem *usbd_epadr[VOX160_UDC_MAX_EP];
	/* USB Endpoint(n) Buffer Length Register (USBD_EPLENn) */
	struct vox160udc_ep_regs __iomem *usbd_eplen[VOX160_UDC_MAX_EP];

	/* VOx160 USBD GPIO registers */
	void __iomem *gpio_dir_reg;
	void __iomem *gpio_flag_set;
	void __iomem *gpio_flag_clear;

	/* USBD dma base address */
	void __iomem *dma_base_address;

	/* The following is used for device cleanup */

	/* Number of IRQs requested so far */
	unsigned got_irq:2;
	/* 1 if the UDC is enabled */
	unsigned enabled:1;
	unsigned vbus:1;
	/* 1 if device has been registered with the kernel */
	unsigned registered:1;
	unsigned fake_config:1;

	/* statistics... */
	unsigned long irqs;	/* total interrupt rcvd */
	unsigned long sof_irqs;	/* No of SOF interrupt rcvd */
	unsigned long cfg_irqs;	/* No of SOF interrupt rcvd */
	unsigned long msof_irqs;	/* No of MSOF interrupt rcvd */
	unsigned long rst_irqs;	/* No of RST interrupt rcvd */
	unsigned long susp_irqs;	/* No of SUSP interrupt rcvd */
	unsigned long resume_irqs;	/* No of RESUME interrupt rcvd */
	unsigned long frmmat_irqs;	/* No of FRMMAT interrupt rcvd */
	unsigned long dma_irqs;	/* No of DMA interrupt rcvd */
	unsigned long ep0_irqs;	/* No of EP0 interrupt rcvd */
	unsigned long ep1_irqs;	/* No of EP1 interrupt rcvd */
	unsigned long ep2_irqs;	/* No of EP2 interrupt rcvd */
	unsigned long ep3_irqs;	/* No of EP3 interrupt rcvd */
	unsigned long frame_number;	/* No of EP3 interrupt rcvd */
};

/*-------------------------------------------------------------------------*/
#define xprintk(dev,level,fmt,args...) \
	printk(level "%s:" fmt,dev->gadget.name , ## args)

#ifdef DEBUG
#define DBG(dev,fmt,args...) \
	xprintk(dev , KERN_CRIT , fmt , ## args)
#else
#define DBG(dev,fmt,args...) \
	do { } while (0)
#endif				/* DEBUG */

#ifdef VERBOSE
#define VDBG DBG
#else
#define VDBG(dev,fmt,args...) \
	do { } while (0)
#endif				/* VERBOSE */

#define ERROR(dev,fmt,args...) \
	xprintk(dev , KERN_ERR , fmt , ## args)
#define WARN(dev,fmt,args...) \
	xprintk(dev , KERN_WARNING , fmt , ## args)
#define INFO(dev,fmt,args...) \
	xprintk(dev , KERN_INFO , fmt , ## args)
