162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * USB Gadget driver for LPC32xx
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Authors:
662306a36Sopenharmony_ci *    Kevin Wells <kevin.wells@nxp.com>
762306a36Sopenharmony_ci *    Mike James
862306a36Sopenharmony_ci *    Roland Stigge <stigge@antcom.de>
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * Copyright (C) 2006 Philips Semiconductors
1162306a36Sopenharmony_ci * Copyright (C) 2009 NXP Semiconductors
1262306a36Sopenharmony_ci * Copyright (C) 2012 Roland Stigge
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci * Note: This driver is based on original work done by Mike James for
1562306a36Sopenharmony_ci *       the LPC3180.
1662306a36Sopenharmony_ci */
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include <linux/clk.h>
1962306a36Sopenharmony_ci#include <linux/delay.h>
2062306a36Sopenharmony_ci#include <linux/dma-mapping.h>
2162306a36Sopenharmony_ci#include <linux/dmapool.h>
2262306a36Sopenharmony_ci#include <linux/i2c.h>
2362306a36Sopenharmony_ci#include <linux/interrupt.h>
2462306a36Sopenharmony_ci#include <linux/module.h>
2562306a36Sopenharmony_ci#include <linux/of.h>
2662306a36Sopenharmony_ci#include <linux/platform_device.h>
2762306a36Sopenharmony_ci#include <linux/prefetch.h>
2862306a36Sopenharmony_ci#include <linux/proc_fs.h>
2962306a36Sopenharmony_ci#include <linux/slab.h>
3062306a36Sopenharmony_ci#include <linux/usb/ch9.h>
3162306a36Sopenharmony_ci#include <linux/usb/gadget.h>
3262306a36Sopenharmony_ci#include <linux/usb/isp1301.h>
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3562306a36Sopenharmony_ci#include <linux/debugfs.h>
3662306a36Sopenharmony_ci#include <linux/seq_file.h>
3762306a36Sopenharmony_ci#endif
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci/*
4062306a36Sopenharmony_ci * USB device configuration structure
4162306a36Sopenharmony_ci */
4262306a36Sopenharmony_citypedef void (*usc_chg_event)(int);
4362306a36Sopenharmony_cistruct lpc32xx_usbd_cfg {
4462306a36Sopenharmony_ci	int vbus_drv_pol;   /* 0=active low drive for VBUS via ISP1301 */
4562306a36Sopenharmony_ci	usc_chg_event conn_chgb; /* Connection change event (optional) */
4662306a36Sopenharmony_ci	usc_chg_event susp_chgb; /* Suspend/resume event (optional) */
4762306a36Sopenharmony_ci	usc_chg_event rmwk_chgb; /* Enable/disable remote wakeup */
4862306a36Sopenharmony_ci};
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci/*
5162306a36Sopenharmony_ci * controller driver data structures
5262306a36Sopenharmony_ci */
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci/* 16 endpoints (not to be confused with 32 hardware endpoints) */
5562306a36Sopenharmony_ci#define	NUM_ENDPOINTS	16
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci/*
5862306a36Sopenharmony_ci * IRQ indices make reading the code a little easier
5962306a36Sopenharmony_ci */
6062306a36Sopenharmony_ci#define IRQ_USB_LP	0
6162306a36Sopenharmony_ci#define IRQ_USB_HP	1
6262306a36Sopenharmony_ci#define IRQ_USB_DEVDMA	2
6362306a36Sopenharmony_ci#define IRQ_USB_ATX	3
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci#define EP_OUT 0 /* RX (from host) */
6662306a36Sopenharmony_ci#define EP_IN 1 /* TX (to host) */
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/* Returns the interrupt mask for the selected hardware endpoint */
6962306a36Sopenharmony_ci#define EP_MASK_SEL(ep, dir) (1 << (((ep) * 2) + dir))
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci#define EP_INT_TYPE 0
7262306a36Sopenharmony_ci#define EP_ISO_TYPE 1
7362306a36Sopenharmony_ci#define EP_BLK_TYPE 2
7462306a36Sopenharmony_ci#define EP_CTL_TYPE 3
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci/* EP0 states */
7762306a36Sopenharmony_ci#define WAIT_FOR_SETUP 0 /* Wait for setup packet */
7862306a36Sopenharmony_ci#define DATA_IN        1 /* Expect dev->host transfer */
7962306a36Sopenharmony_ci#define DATA_OUT       2 /* Expect host->dev transfer */
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci/* DD (DMA Descriptor) structure, requires word alignment, this is already
8262306a36Sopenharmony_ci * defined in the LPC32XX USB device header file, but this version is slightly
8362306a36Sopenharmony_ci * modified to tag some work data with each DMA descriptor. */
8462306a36Sopenharmony_cistruct lpc32xx_usbd_dd_gad {
8562306a36Sopenharmony_ci	u32 dd_next_phy;
8662306a36Sopenharmony_ci	u32 dd_setup;
8762306a36Sopenharmony_ci	u32 dd_buffer_addr;
8862306a36Sopenharmony_ci	u32 dd_status;
8962306a36Sopenharmony_ci	u32 dd_iso_ps_mem_addr;
9062306a36Sopenharmony_ci	u32 this_dma;
9162306a36Sopenharmony_ci	u32 iso_status[6]; /* 5 spare */
9262306a36Sopenharmony_ci	u32 dd_next_v;
9362306a36Sopenharmony_ci};
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci/*
9662306a36Sopenharmony_ci * Logical endpoint structure
9762306a36Sopenharmony_ci */
9862306a36Sopenharmony_cistruct lpc32xx_ep {
9962306a36Sopenharmony_ci	struct usb_ep		ep;
10062306a36Sopenharmony_ci	struct list_head	queue;
10162306a36Sopenharmony_ci	struct lpc32xx_udc	*udc;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	u32			hwep_num_base; /* Physical hardware EP */
10462306a36Sopenharmony_ci	u32			hwep_num; /* Maps to hardware endpoint */
10562306a36Sopenharmony_ci	u32			maxpacket;
10662306a36Sopenharmony_ci	u32			lep;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	bool			is_in;
10962306a36Sopenharmony_ci	bool			req_pending;
11062306a36Sopenharmony_ci	u32			eptype;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	u32                     totalints;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	bool			wedge;
11562306a36Sopenharmony_ci};
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cienum atx_type {
11862306a36Sopenharmony_ci	ISP1301,
11962306a36Sopenharmony_ci	STOTG04,
12062306a36Sopenharmony_ci};
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci/*
12362306a36Sopenharmony_ci * Common UDC structure
12462306a36Sopenharmony_ci */
12562306a36Sopenharmony_cistruct lpc32xx_udc {
12662306a36Sopenharmony_ci	struct usb_gadget	gadget;
12762306a36Sopenharmony_ci	struct usb_gadget_driver *driver;
12862306a36Sopenharmony_ci	struct platform_device	*pdev;
12962306a36Sopenharmony_ci	struct device		*dev;
13062306a36Sopenharmony_ci	spinlock_t		lock;
13162306a36Sopenharmony_ci	struct i2c_client	*isp1301_i2c_client;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	/* Board and device specific */
13462306a36Sopenharmony_ci	struct lpc32xx_usbd_cfg	*board;
13562306a36Sopenharmony_ci	void __iomem		*udp_baseaddr;
13662306a36Sopenharmony_ci	int			udp_irq[4];
13762306a36Sopenharmony_ci	struct clk		*usb_slv_clk;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	/* DMA support */
14062306a36Sopenharmony_ci	u32			*udca_v_base;
14162306a36Sopenharmony_ci	u32			udca_p_base;
14262306a36Sopenharmony_ci	struct dma_pool		*dd_cache;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	/* Common EP and control data */
14562306a36Sopenharmony_ci	u32			enabled_devints;
14662306a36Sopenharmony_ci	u32			enabled_hwepints;
14762306a36Sopenharmony_ci	u32			dev_status;
14862306a36Sopenharmony_ci	u32			realized_eps;
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	/* VBUS detection, pullup, and power flags */
15162306a36Sopenharmony_ci	u8			vbus;
15262306a36Sopenharmony_ci	u8			last_vbus;
15362306a36Sopenharmony_ci	int			pullup;
15462306a36Sopenharmony_ci	int			poweron;
15562306a36Sopenharmony_ci	enum atx_type		atx;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	/* Work queues related to I2C support */
15862306a36Sopenharmony_ci	struct work_struct	pullup_job;
15962306a36Sopenharmony_ci	struct work_struct	power_job;
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	/* USB device peripheral - various */
16262306a36Sopenharmony_ci	struct lpc32xx_ep	ep[NUM_ENDPOINTS];
16362306a36Sopenharmony_ci	bool			enabled;
16462306a36Sopenharmony_ci	bool			clocked;
16562306a36Sopenharmony_ci	bool			suspended;
16662306a36Sopenharmony_ci	int                     ep0state;
16762306a36Sopenharmony_ci	atomic_t                enabled_ep_cnt;
16862306a36Sopenharmony_ci	wait_queue_head_t       ep_disable_wait_queue;
16962306a36Sopenharmony_ci};
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci/*
17262306a36Sopenharmony_ci * Endpoint request
17362306a36Sopenharmony_ci */
17462306a36Sopenharmony_cistruct lpc32xx_request {
17562306a36Sopenharmony_ci	struct usb_request	req;
17662306a36Sopenharmony_ci	struct list_head	queue;
17762306a36Sopenharmony_ci	struct lpc32xx_usbd_dd_gad *dd_desc_ptr;
17862306a36Sopenharmony_ci	bool			mapped;
17962306a36Sopenharmony_ci	bool			send_zlp;
18062306a36Sopenharmony_ci};
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_cistatic inline struct lpc32xx_udc *to_udc(struct usb_gadget *g)
18362306a36Sopenharmony_ci{
18462306a36Sopenharmony_ci	return container_of(g, struct lpc32xx_udc, gadget);
18562306a36Sopenharmony_ci}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci#define ep_dbg(epp, fmt, arg...) \
18862306a36Sopenharmony_ci	dev_dbg(epp->udc->dev, "%s: " fmt, __func__, ## arg)
18962306a36Sopenharmony_ci#define ep_err(epp, fmt, arg...) \
19062306a36Sopenharmony_ci	dev_err(epp->udc->dev, "%s: " fmt, __func__, ## arg)
19162306a36Sopenharmony_ci#define ep_info(epp, fmt, arg...) \
19262306a36Sopenharmony_ci	dev_info(epp->udc->dev, "%s: " fmt, __func__, ## arg)
19362306a36Sopenharmony_ci#define ep_warn(epp, fmt, arg...) \
19462306a36Sopenharmony_ci	dev_warn(epp->udc->dev, "%s:" fmt, __func__, ## arg)
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci#define UDCA_BUFF_SIZE (128)
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci/**********************************************************************
19962306a36Sopenharmony_ci * USB device controller register offsets
20062306a36Sopenharmony_ci **********************************************************************/
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci#define USBD_DEVINTST(x)	((x) + 0x200)
20362306a36Sopenharmony_ci#define USBD_DEVINTEN(x)	((x) + 0x204)
20462306a36Sopenharmony_ci#define USBD_DEVINTCLR(x)	((x) + 0x208)
20562306a36Sopenharmony_ci#define USBD_DEVINTSET(x)	((x) + 0x20C)
20662306a36Sopenharmony_ci#define USBD_CMDCODE(x)		((x) + 0x210)
20762306a36Sopenharmony_ci#define USBD_CMDDATA(x)		((x) + 0x214)
20862306a36Sopenharmony_ci#define USBD_RXDATA(x)		((x) + 0x218)
20962306a36Sopenharmony_ci#define USBD_TXDATA(x)		((x) + 0x21C)
21062306a36Sopenharmony_ci#define USBD_RXPLEN(x)		((x) + 0x220)
21162306a36Sopenharmony_ci#define USBD_TXPLEN(x)		((x) + 0x224)
21262306a36Sopenharmony_ci#define USBD_CTRL(x)		((x) + 0x228)
21362306a36Sopenharmony_ci#define USBD_DEVINTPRI(x)	((x) + 0x22C)
21462306a36Sopenharmony_ci#define USBD_EPINTST(x)		((x) + 0x230)
21562306a36Sopenharmony_ci#define USBD_EPINTEN(x)		((x) + 0x234)
21662306a36Sopenharmony_ci#define USBD_EPINTCLR(x)	((x) + 0x238)
21762306a36Sopenharmony_ci#define USBD_EPINTSET(x)	((x) + 0x23C)
21862306a36Sopenharmony_ci#define USBD_EPINTPRI(x)	((x) + 0x240)
21962306a36Sopenharmony_ci#define USBD_REEP(x)		((x) + 0x244)
22062306a36Sopenharmony_ci#define USBD_EPIND(x)		((x) + 0x248)
22162306a36Sopenharmony_ci#define USBD_EPMAXPSIZE(x)	((x) + 0x24C)
22262306a36Sopenharmony_ci/* DMA support registers only below */
22362306a36Sopenharmony_ci/* Set, clear, or get enabled state of the DMA request status. If
22462306a36Sopenharmony_ci * enabled, an IN or OUT token will start a DMA transfer for the EP */
22562306a36Sopenharmony_ci#define USBD_DMARST(x)		((x) + 0x250)
22662306a36Sopenharmony_ci#define USBD_DMARCLR(x)		((x) + 0x254)
22762306a36Sopenharmony_ci#define USBD_DMARSET(x)		((x) + 0x258)
22862306a36Sopenharmony_ci/* DMA UDCA head pointer */
22962306a36Sopenharmony_ci#define USBD_UDCAH(x)		((x) + 0x280)
23062306a36Sopenharmony_ci/* EP DMA status, enable, and disable. This is used to specifically
23162306a36Sopenharmony_ci * enabled or disable DMA for a specific EP */
23262306a36Sopenharmony_ci#define USBD_EPDMAST(x)		((x) + 0x284)
23362306a36Sopenharmony_ci#define USBD_EPDMAEN(x)		((x) + 0x288)
23462306a36Sopenharmony_ci#define USBD_EPDMADIS(x)	((x) + 0x28C)
23562306a36Sopenharmony_ci/* DMA master interrupts enable and pending interrupts */
23662306a36Sopenharmony_ci#define USBD_DMAINTST(x)	((x) + 0x290)
23762306a36Sopenharmony_ci#define USBD_DMAINTEN(x)	((x) + 0x294)
23862306a36Sopenharmony_ci/* DMA end of transfer interrupt enable, disable, status */
23962306a36Sopenharmony_ci#define USBD_EOTINTST(x)	((x) + 0x2A0)
24062306a36Sopenharmony_ci#define USBD_EOTINTCLR(x)	((x) + 0x2A4)
24162306a36Sopenharmony_ci#define USBD_EOTINTSET(x)	((x) + 0x2A8)
24262306a36Sopenharmony_ci/* New DD request interrupt enable, disable, status */
24362306a36Sopenharmony_ci#define USBD_NDDRTINTST(x)	((x) + 0x2AC)
24462306a36Sopenharmony_ci#define USBD_NDDRTINTCLR(x)	((x) + 0x2B0)
24562306a36Sopenharmony_ci#define USBD_NDDRTINTSET(x)	((x) + 0x2B4)
24662306a36Sopenharmony_ci/* DMA error interrupt enable, disable, status */
24762306a36Sopenharmony_ci#define USBD_SYSERRTINTST(x)	((x) + 0x2B8)
24862306a36Sopenharmony_ci#define USBD_SYSERRTINTCLR(x)	((x) + 0x2BC)
24962306a36Sopenharmony_ci#define USBD_SYSERRTINTSET(x)	((x) + 0x2C0)
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci/**********************************************************************
25262306a36Sopenharmony_ci * USBD_DEVINTST/USBD_DEVINTEN/USBD_DEVINTCLR/USBD_DEVINTSET/
25362306a36Sopenharmony_ci * USBD_DEVINTPRI register definitions
25462306a36Sopenharmony_ci **********************************************************************/
25562306a36Sopenharmony_ci#define USBD_ERR_INT		(1 << 9)
25662306a36Sopenharmony_ci#define USBD_EP_RLZED		(1 << 8)
25762306a36Sopenharmony_ci#define USBD_TXENDPKT		(1 << 7)
25862306a36Sopenharmony_ci#define USBD_RXENDPKT		(1 << 6)
25962306a36Sopenharmony_ci#define USBD_CDFULL		(1 << 5)
26062306a36Sopenharmony_ci#define USBD_CCEMPTY		(1 << 4)
26162306a36Sopenharmony_ci#define USBD_DEV_STAT		(1 << 3)
26262306a36Sopenharmony_ci#define USBD_EP_SLOW		(1 << 2)
26362306a36Sopenharmony_ci#define USBD_EP_FAST		(1 << 1)
26462306a36Sopenharmony_ci#define USBD_FRAME		(1 << 0)
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci/**********************************************************************
26762306a36Sopenharmony_ci * USBD_EPINTST/USBD_EPINTEN/USBD_EPINTCLR/USBD_EPINTSET/
26862306a36Sopenharmony_ci * USBD_EPINTPRI register definitions
26962306a36Sopenharmony_ci **********************************************************************/
27062306a36Sopenharmony_ci/* End point selection macro (RX) */
27162306a36Sopenharmony_ci#define USBD_RX_EP_SEL(e)	(1 << ((e) << 1))
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci/* End point selection macro (TX) */
27462306a36Sopenharmony_ci#define USBD_TX_EP_SEL(e)	(1 << (((e) << 1) + 1))
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci/**********************************************************************
27762306a36Sopenharmony_ci * USBD_REEP/USBD_DMARST/USBD_DMARCLR/USBD_DMARSET/USBD_EPDMAST/
27862306a36Sopenharmony_ci * USBD_EPDMAEN/USBD_EPDMADIS/
27962306a36Sopenharmony_ci * USBD_NDDRTINTST/USBD_NDDRTINTCLR/USBD_NDDRTINTSET/
28062306a36Sopenharmony_ci * USBD_EOTINTST/USBD_EOTINTCLR/USBD_EOTINTSET/
28162306a36Sopenharmony_ci * USBD_SYSERRTINTST/USBD_SYSERRTINTCLR/USBD_SYSERRTINTSET
28262306a36Sopenharmony_ci * register definitions
28362306a36Sopenharmony_ci **********************************************************************/
28462306a36Sopenharmony_ci/* Endpoint selection macro */
28562306a36Sopenharmony_ci#define USBD_EP_SEL(e)		(1 << (e))
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci/**********************************************************************
28862306a36Sopenharmony_ci * SBD_DMAINTST/USBD_DMAINTEN
28962306a36Sopenharmony_ci **********************************************************************/
29062306a36Sopenharmony_ci#define USBD_SYS_ERR_INT	(1 << 2)
29162306a36Sopenharmony_ci#define USBD_NEW_DD_INT		(1 << 1)
29262306a36Sopenharmony_ci#define USBD_EOT_INT		(1 << 0)
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci/**********************************************************************
29562306a36Sopenharmony_ci * USBD_RXPLEN register definitions
29662306a36Sopenharmony_ci **********************************************************************/
29762306a36Sopenharmony_ci#define USBD_PKT_RDY		(1 << 11)
29862306a36Sopenharmony_ci#define USBD_DV			(1 << 10)
29962306a36Sopenharmony_ci#define USBD_PK_LEN_MASK	0x3FF
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci/**********************************************************************
30262306a36Sopenharmony_ci * USBD_CTRL register definitions
30362306a36Sopenharmony_ci **********************************************************************/
30462306a36Sopenharmony_ci#define USBD_LOG_ENDPOINT(e)	((e) << 2)
30562306a36Sopenharmony_ci#define USBD_WR_EN		(1 << 1)
30662306a36Sopenharmony_ci#define USBD_RD_EN		(1 << 0)
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci/**********************************************************************
30962306a36Sopenharmony_ci * USBD_CMDCODE register definitions
31062306a36Sopenharmony_ci **********************************************************************/
31162306a36Sopenharmony_ci#define USBD_CMD_CODE(c)	((c) << 16)
31262306a36Sopenharmony_ci#define USBD_CMD_PHASE(p)	((p) << 8)
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci/**********************************************************************
31562306a36Sopenharmony_ci * USBD_DMARST/USBD_DMARCLR/USBD_DMARSET register definitions
31662306a36Sopenharmony_ci **********************************************************************/
31762306a36Sopenharmony_ci#define USBD_DMAEP(e)		(1 << (e))
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci/* DD (DMA Descriptor) structure, requires word alignment */
32062306a36Sopenharmony_cistruct lpc32xx_usbd_dd {
32162306a36Sopenharmony_ci	u32 *dd_next;
32262306a36Sopenharmony_ci	u32 dd_setup;
32362306a36Sopenharmony_ci	u32 dd_buffer_addr;
32462306a36Sopenharmony_ci	u32 dd_status;
32562306a36Sopenharmony_ci	u32 dd_iso_ps_mem_addr;
32662306a36Sopenharmony_ci};
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci/* dd_setup bit defines */
32962306a36Sopenharmony_ci#define DD_SETUP_ATLE_DMA_MODE	0x01
33062306a36Sopenharmony_ci#define DD_SETUP_NEXT_DD_VALID	0x04
33162306a36Sopenharmony_ci#define DD_SETUP_ISO_EP		0x10
33262306a36Sopenharmony_ci#define DD_SETUP_PACKETLEN(n)	(((n) & 0x7FF) << 5)
33362306a36Sopenharmony_ci#define DD_SETUP_DMALENBYTES(n)	(((n) & 0xFFFF) << 16)
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci/* dd_status bit defines */
33662306a36Sopenharmony_ci#define DD_STATUS_DD_RETIRED	0x01
33762306a36Sopenharmony_ci#define DD_STATUS_STS_MASK	0x1E
33862306a36Sopenharmony_ci#define DD_STATUS_STS_NS	0x00 /* Not serviced */
33962306a36Sopenharmony_ci#define DD_STATUS_STS_BS	0x02 /* Being serviced */
34062306a36Sopenharmony_ci#define DD_STATUS_STS_NC	0x04 /* Normal completion */
34162306a36Sopenharmony_ci#define DD_STATUS_STS_DUR	0x06 /* Data underrun (short packet) */
34262306a36Sopenharmony_ci#define DD_STATUS_STS_DOR	0x08 /* Data overrun */
34362306a36Sopenharmony_ci#define DD_STATUS_STS_SE	0x12 /* System error */
34462306a36Sopenharmony_ci#define DD_STATUS_PKT_VAL	0x20 /* Packet valid */
34562306a36Sopenharmony_ci#define DD_STATUS_LSB_EX	0x40 /* LS byte extracted (ATLE) */
34662306a36Sopenharmony_ci#define DD_STATUS_MSB_EX	0x80 /* MS byte extracted (ATLE) */
34762306a36Sopenharmony_ci#define DD_STATUS_MLEN(n)	(((n) >> 8) & 0x3F)
34862306a36Sopenharmony_ci#define DD_STATUS_CURDMACNT(n)	(((n) >> 16) & 0xFFFF)
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci/*
35162306a36Sopenharmony_ci *
35262306a36Sopenharmony_ci * Protocol engine bits below
35362306a36Sopenharmony_ci *
35462306a36Sopenharmony_ci */
35562306a36Sopenharmony_ci/* Device Interrupt Bit Definitions */
35662306a36Sopenharmony_ci#define FRAME_INT		0x00000001
35762306a36Sopenharmony_ci#define EP_FAST_INT		0x00000002
35862306a36Sopenharmony_ci#define EP_SLOW_INT		0x00000004
35962306a36Sopenharmony_ci#define DEV_STAT_INT		0x00000008
36062306a36Sopenharmony_ci#define CCEMTY_INT		0x00000010
36162306a36Sopenharmony_ci#define CDFULL_INT		0x00000020
36262306a36Sopenharmony_ci#define RxENDPKT_INT		0x00000040
36362306a36Sopenharmony_ci#define TxENDPKT_INT		0x00000080
36462306a36Sopenharmony_ci#define EP_RLZED_INT		0x00000100
36562306a36Sopenharmony_ci#define ERR_INT			0x00000200
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci/* Rx & Tx Packet Length Definitions */
36862306a36Sopenharmony_ci#define PKT_LNGTH_MASK		0x000003FF
36962306a36Sopenharmony_ci#define PKT_DV			0x00000400
37062306a36Sopenharmony_ci#define PKT_RDY			0x00000800
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci/* USB Control Definitions */
37362306a36Sopenharmony_ci#define CTRL_RD_EN		0x00000001
37462306a36Sopenharmony_ci#define CTRL_WR_EN		0x00000002
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci/* Command Codes */
37762306a36Sopenharmony_ci#define CMD_SET_ADDR		0x00D00500
37862306a36Sopenharmony_ci#define CMD_CFG_DEV		0x00D80500
37962306a36Sopenharmony_ci#define CMD_SET_MODE		0x00F30500
38062306a36Sopenharmony_ci#define CMD_RD_FRAME		0x00F50500
38162306a36Sopenharmony_ci#define DAT_RD_FRAME		0x00F50200
38262306a36Sopenharmony_ci#define CMD_RD_TEST		0x00FD0500
38362306a36Sopenharmony_ci#define DAT_RD_TEST		0x00FD0200
38462306a36Sopenharmony_ci#define CMD_SET_DEV_STAT	0x00FE0500
38562306a36Sopenharmony_ci#define CMD_GET_DEV_STAT	0x00FE0500
38662306a36Sopenharmony_ci#define DAT_GET_DEV_STAT	0x00FE0200
38762306a36Sopenharmony_ci#define CMD_GET_ERR_CODE	0x00FF0500
38862306a36Sopenharmony_ci#define DAT_GET_ERR_CODE	0x00FF0200
38962306a36Sopenharmony_ci#define CMD_RD_ERR_STAT		0x00FB0500
39062306a36Sopenharmony_ci#define DAT_RD_ERR_STAT		0x00FB0200
39162306a36Sopenharmony_ci#define DAT_WR_BYTE(x)		(0x00000100 | ((x) << 16))
39262306a36Sopenharmony_ci#define CMD_SEL_EP(x)		(0x00000500 | ((x) << 16))
39362306a36Sopenharmony_ci#define DAT_SEL_EP(x)		(0x00000200 | ((x) << 16))
39462306a36Sopenharmony_ci#define CMD_SEL_EP_CLRI(x)	(0x00400500 | ((x) << 16))
39562306a36Sopenharmony_ci#define DAT_SEL_EP_CLRI(x)	(0x00400200 | ((x) << 16))
39662306a36Sopenharmony_ci#define CMD_SET_EP_STAT(x)	(0x00400500 | ((x) << 16))
39762306a36Sopenharmony_ci#define CMD_CLR_BUF		0x00F20500
39862306a36Sopenharmony_ci#define DAT_CLR_BUF		0x00F20200
39962306a36Sopenharmony_ci#define CMD_VALID_BUF		0x00FA0500
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci/* Device Address Register Definitions */
40262306a36Sopenharmony_ci#define DEV_ADDR_MASK		0x7F
40362306a36Sopenharmony_ci#define DEV_EN			0x80
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci/* Device Configure Register Definitions */
40662306a36Sopenharmony_ci#define CONF_DVICE		0x01
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci/* Device Mode Register Definitions */
40962306a36Sopenharmony_ci#define AP_CLK			0x01
41062306a36Sopenharmony_ci#define INAK_CI			0x02
41162306a36Sopenharmony_ci#define INAK_CO			0x04
41262306a36Sopenharmony_ci#define INAK_II			0x08
41362306a36Sopenharmony_ci#define INAK_IO			0x10
41462306a36Sopenharmony_ci#define INAK_BI			0x20
41562306a36Sopenharmony_ci#define INAK_BO			0x40
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci/* Device Status Register Definitions */
41862306a36Sopenharmony_ci#define DEV_CON			0x01
41962306a36Sopenharmony_ci#define DEV_CON_CH		0x02
42062306a36Sopenharmony_ci#define DEV_SUS			0x04
42162306a36Sopenharmony_ci#define DEV_SUS_CH		0x08
42262306a36Sopenharmony_ci#define DEV_RST			0x10
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci/* Error Code Register Definitions */
42562306a36Sopenharmony_ci#define ERR_EC_MASK		0x0F
42662306a36Sopenharmony_ci#define ERR_EA			0x10
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci/* Error Status Register Definitions */
42962306a36Sopenharmony_ci#define ERR_PID			0x01
43062306a36Sopenharmony_ci#define ERR_UEPKT		0x02
43162306a36Sopenharmony_ci#define ERR_DCRC		0x04
43262306a36Sopenharmony_ci#define ERR_TIMOUT		0x08
43362306a36Sopenharmony_ci#define ERR_EOP			0x10
43462306a36Sopenharmony_ci#define ERR_B_OVRN		0x20
43562306a36Sopenharmony_ci#define ERR_BTSTF		0x40
43662306a36Sopenharmony_ci#define ERR_TGL			0x80
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci/* Endpoint Select Register Definitions */
43962306a36Sopenharmony_ci#define EP_SEL_F		0x01
44062306a36Sopenharmony_ci#define EP_SEL_ST		0x02
44162306a36Sopenharmony_ci#define EP_SEL_STP		0x04
44262306a36Sopenharmony_ci#define EP_SEL_PO		0x08
44362306a36Sopenharmony_ci#define EP_SEL_EPN		0x10
44462306a36Sopenharmony_ci#define EP_SEL_B_1_FULL		0x20
44562306a36Sopenharmony_ci#define EP_SEL_B_2_FULL		0x40
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci/* Endpoint Status Register Definitions */
44862306a36Sopenharmony_ci#define EP_STAT_ST		0x01
44962306a36Sopenharmony_ci#define EP_STAT_DA		0x20
45062306a36Sopenharmony_ci#define EP_STAT_RF_MO		0x40
45162306a36Sopenharmony_ci#define EP_STAT_CND_ST		0x80
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci/* Clear Buffer Register Definitions */
45462306a36Sopenharmony_ci#define CLR_BUF_PO		0x01
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci/* DMA Interrupt Bit Definitions */
45762306a36Sopenharmony_ci#define EOT_INT			0x01
45862306a36Sopenharmony_ci#define NDD_REQ_INT		0x02
45962306a36Sopenharmony_ci#define SYS_ERR_INT		0x04
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci#define	DRIVER_VERSION	"1.03"
46262306a36Sopenharmony_cistatic const char driver_name[] = "lpc32xx_udc";
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci/*
46562306a36Sopenharmony_ci *
46662306a36Sopenharmony_ci * proc interface support
46762306a36Sopenharmony_ci *
46862306a36Sopenharmony_ci */
46962306a36Sopenharmony_ci#ifdef CONFIG_USB_GADGET_DEBUG_FILES
47062306a36Sopenharmony_cistatic char *epnames[] = {"INT", "ISO", "BULK", "CTRL"};
47162306a36Sopenharmony_cistatic const char debug_filename[] = "driver/udc";
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_cistatic void proc_ep_show(struct seq_file *s, struct lpc32xx_ep *ep)
47462306a36Sopenharmony_ci{
47562306a36Sopenharmony_ci	struct lpc32xx_request *req;
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	seq_printf(s, "\n");
47862306a36Sopenharmony_ci	seq_printf(s, "%12s, maxpacket %4d %3s",
47962306a36Sopenharmony_ci			ep->ep.name, ep->ep.maxpacket,
48062306a36Sopenharmony_ci			ep->is_in ? "in" : "out");
48162306a36Sopenharmony_ci	seq_printf(s, " type %4s", epnames[ep->eptype]);
48262306a36Sopenharmony_ci	seq_printf(s, " ints: %12d", ep->totalints);
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	if (list_empty(&ep->queue))
48562306a36Sopenharmony_ci		seq_printf(s, "\t(queue empty)\n");
48662306a36Sopenharmony_ci	else {
48762306a36Sopenharmony_ci		list_for_each_entry(req, &ep->queue, queue) {
48862306a36Sopenharmony_ci			u32 length = req->req.actual;
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci			seq_printf(s, "\treq %p len %d/%d buf %p\n",
49162306a36Sopenharmony_ci				   &req->req, length,
49262306a36Sopenharmony_ci				   req->req.length, req->req.buf);
49362306a36Sopenharmony_ci		}
49462306a36Sopenharmony_ci	}
49562306a36Sopenharmony_ci}
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_cistatic int udc_show(struct seq_file *s, void *unused)
49862306a36Sopenharmony_ci{
49962306a36Sopenharmony_ci	struct lpc32xx_udc *udc = s->private;
50062306a36Sopenharmony_ci	struct lpc32xx_ep *ep;
50162306a36Sopenharmony_ci	unsigned long flags;
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	seq_printf(s, "%s: version %s\n", driver_name, DRIVER_VERSION);
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	spin_lock_irqsave(&udc->lock, flags);
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	seq_printf(s, "vbus %s, pullup %s, %s powered%s, gadget %s\n\n",
50862306a36Sopenharmony_ci		   udc->vbus ? "present" : "off",
50962306a36Sopenharmony_ci		   udc->enabled ? (udc->vbus ? "active" : "enabled") :
51062306a36Sopenharmony_ci		   "disabled",
51162306a36Sopenharmony_ci		   udc->gadget.is_selfpowered ? "self" : "VBUS",
51262306a36Sopenharmony_ci		   udc->suspended ? ", suspended" : "",
51362306a36Sopenharmony_ci		   udc->driver ? udc->driver->driver.name : "(none)");
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	if (udc->enabled && udc->vbus) {
51662306a36Sopenharmony_ci		proc_ep_show(s, &udc->ep[0]);
51762306a36Sopenharmony_ci		list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list)
51862306a36Sopenharmony_ci			proc_ep_show(s, ep);
51962306a36Sopenharmony_ci	}
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	spin_unlock_irqrestore(&udc->lock, flags);
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	return 0;
52462306a36Sopenharmony_ci}
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(udc);
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_cistatic void create_debug_file(struct lpc32xx_udc *udc)
52962306a36Sopenharmony_ci{
53062306a36Sopenharmony_ci	debugfs_create_file(debug_filename, 0, NULL, udc, &udc_fops);
53162306a36Sopenharmony_ci}
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_cistatic void remove_debug_file(struct lpc32xx_udc *udc)
53462306a36Sopenharmony_ci{
53562306a36Sopenharmony_ci	debugfs_lookup_and_remove(debug_filename, NULL);
53662306a36Sopenharmony_ci}
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci#else
53962306a36Sopenharmony_cistatic inline void create_debug_file(struct lpc32xx_udc *udc) {}
54062306a36Sopenharmony_cistatic inline void remove_debug_file(struct lpc32xx_udc *udc) {}
54162306a36Sopenharmony_ci#endif
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci/* Primary initialization sequence for the ISP1301 transceiver */
54462306a36Sopenharmony_cistatic void isp1301_udc_configure(struct lpc32xx_udc *udc)
54562306a36Sopenharmony_ci{
54662306a36Sopenharmony_ci	u8 value;
54762306a36Sopenharmony_ci	s32 vendor, product;
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	vendor = i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x00);
55062306a36Sopenharmony_ci	product = i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x02);
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	if (vendor == 0x0483 && product == 0xa0c4)
55362306a36Sopenharmony_ci		udc->atx = STOTG04;
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	/* LPC32XX only supports DAT_SE0 USB mode */
55662306a36Sopenharmony_ci	/* This sequence is important */
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	/* Disable transparent UART mode first */
55962306a36Sopenharmony_ci	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
56062306a36Sopenharmony_ci		(ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR),
56162306a36Sopenharmony_ci		MC1_UART_EN);
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci	/* Set full speed and SE0 mode */
56462306a36Sopenharmony_ci	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
56562306a36Sopenharmony_ci		(ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR), ~0);
56662306a36Sopenharmony_ci	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
56762306a36Sopenharmony_ci		ISP1301_I2C_MODE_CONTROL_1, (MC1_SPEED_REG | MC1_DAT_SE0));
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	/*
57062306a36Sopenharmony_ci	 * The PSW_OE enable bit state is reversed in the ISP1301 User's Guide
57162306a36Sopenharmony_ci	 */
57262306a36Sopenharmony_ci	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
57362306a36Sopenharmony_ci		(ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR), ~0);
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	value = MC2_BI_DI;
57662306a36Sopenharmony_ci	if (udc->atx != STOTG04)
57762306a36Sopenharmony_ci		value |= MC2_SPD_SUSP_CTRL;
57862306a36Sopenharmony_ci	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
57962306a36Sopenharmony_ci		ISP1301_I2C_MODE_CONTROL_2, value);
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci	/* Driver VBUS_DRV high or low depending on board setup */
58262306a36Sopenharmony_ci	if (udc->board->vbus_drv_pol != 0)
58362306a36Sopenharmony_ci		i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
58462306a36Sopenharmony_ci			ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV);
58562306a36Sopenharmony_ci	else
58662306a36Sopenharmony_ci		i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
58762306a36Sopenharmony_ci			ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR,
58862306a36Sopenharmony_ci			OTG1_VBUS_DRV);
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	/* Bi-directional mode with suspend control
59162306a36Sopenharmony_ci	 * Enable both pulldowns for now - the pullup will be enable when VBUS
59262306a36Sopenharmony_ci	 * is detected */
59362306a36Sopenharmony_ci	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
59462306a36Sopenharmony_ci		(ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR), ~0);
59562306a36Sopenharmony_ci	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
59662306a36Sopenharmony_ci		ISP1301_I2C_OTG_CONTROL_1,
59762306a36Sopenharmony_ci		(0 | OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN));
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	/* Discharge VBUS (just in case) */
60062306a36Sopenharmony_ci	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
60162306a36Sopenharmony_ci		ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DISCHRG);
60262306a36Sopenharmony_ci	msleep(1);
60362306a36Sopenharmony_ci	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
60462306a36Sopenharmony_ci		(ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR),
60562306a36Sopenharmony_ci		OTG1_VBUS_DISCHRG);
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
60862306a36Sopenharmony_ci		ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
61162306a36Sopenharmony_ci		ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
61262306a36Sopenharmony_ci	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
61362306a36Sopenharmony_ci		ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci	dev_info(udc->dev, "ISP1301 Vendor ID  : 0x%04x\n", vendor);
61662306a36Sopenharmony_ci	dev_info(udc->dev, "ISP1301 Product ID : 0x%04x\n", product);
61762306a36Sopenharmony_ci	dev_info(udc->dev, "ISP1301 Version ID : 0x%04x\n",
61862306a36Sopenharmony_ci		 i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x14));
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci}
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci/* Enables or disables the USB device pullup via the ISP1301 transceiver */
62362306a36Sopenharmony_cistatic void isp1301_pullup_set(struct lpc32xx_udc *udc)
62462306a36Sopenharmony_ci{
62562306a36Sopenharmony_ci	if (udc->pullup)
62662306a36Sopenharmony_ci		/* Enable pullup for bus signalling */
62762306a36Sopenharmony_ci		i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
62862306a36Sopenharmony_ci			ISP1301_I2C_OTG_CONTROL_1, OTG1_DP_PULLUP);
62962306a36Sopenharmony_ci	else
63062306a36Sopenharmony_ci		/* Enable pullup for bus signalling */
63162306a36Sopenharmony_ci		i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
63262306a36Sopenharmony_ci			ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR,
63362306a36Sopenharmony_ci			OTG1_DP_PULLUP);
63462306a36Sopenharmony_ci}
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_cistatic void pullup_work(struct work_struct *work)
63762306a36Sopenharmony_ci{
63862306a36Sopenharmony_ci	struct lpc32xx_udc *udc =
63962306a36Sopenharmony_ci		container_of(work, struct lpc32xx_udc, pullup_job);
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci	isp1301_pullup_set(udc);
64262306a36Sopenharmony_ci}
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_cistatic void isp1301_pullup_enable(struct lpc32xx_udc *udc, int en_pullup,
64562306a36Sopenharmony_ci				  int block)
64662306a36Sopenharmony_ci{
64762306a36Sopenharmony_ci	if (en_pullup == udc->pullup)
64862306a36Sopenharmony_ci		return;
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	udc->pullup = en_pullup;
65162306a36Sopenharmony_ci	if (block)
65262306a36Sopenharmony_ci		isp1301_pullup_set(udc);
65362306a36Sopenharmony_ci	else
65462306a36Sopenharmony_ci		/* defer slow i2c pull up setting */
65562306a36Sopenharmony_ci		schedule_work(&udc->pullup_job);
65662306a36Sopenharmony_ci}
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci#ifdef CONFIG_PM
65962306a36Sopenharmony_ci/* Powers up or down the ISP1301 transceiver */
66062306a36Sopenharmony_cistatic void isp1301_set_powerstate(struct lpc32xx_udc *udc, int enable)
66162306a36Sopenharmony_ci{
66262306a36Sopenharmony_ci	/* There is no "global power down" register for stotg04 */
66362306a36Sopenharmony_ci	if (udc->atx == STOTG04)
66462306a36Sopenharmony_ci		return;
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	if (enable != 0)
66762306a36Sopenharmony_ci		/* Power up ISP1301 - this ISP1301 will automatically wakeup
66862306a36Sopenharmony_ci		   when VBUS is detected */
66962306a36Sopenharmony_ci		i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
67062306a36Sopenharmony_ci			ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR,
67162306a36Sopenharmony_ci			MC2_GLOBAL_PWR_DN);
67262306a36Sopenharmony_ci	else
67362306a36Sopenharmony_ci		/* Power down ISP1301 */
67462306a36Sopenharmony_ci		i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
67562306a36Sopenharmony_ci			ISP1301_I2C_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN);
67662306a36Sopenharmony_ci}
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_cistatic void power_work(struct work_struct *work)
67962306a36Sopenharmony_ci{
68062306a36Sopenharmony_ci	struct lpc32xx_udc *udc =
68162306a36Sopenharmony_ci		container_of(work, struct lpc32xx_udc, power_job);
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci	isp1301_set_powerstate(udc, udc->poweron);
68462306a36Sopenharmony_ci}
68562306a36Sopenharmony_ci#endif
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci/*
68862306a36Sopenharmony_ci *
68962306a36Sopenharmony_ci * USB protocol engine command/data read/write helper functions
69062306a36Sopenharmony_ci *
69162306a36Sopenharmony_ci */
69262306a36Sopenharmony_ci/* Issues a single command to the USB device state machine */
69362306a36Sopenharmony_cistatic void udc_protocol_cmd_w(struct lpc32xx_udc *udc, u32 cmd)
69462306a36Sopenharmony_ci{
69562306a36Sopenharmony_ci	u32 pass = 0;
69662306a36Sopenharmony_ci	int to;
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	/* EP may lock on CLRI if this read isn't done */
69962306a36Sopenharmony_ci	u32 tmp = readl(USBD_DEVINTST(udc->udp_baseaddr));
70062306a36Sopenharmony_ci	(void) tmp;
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci	while (pass == 0) {
70362306a36Sopenharmony_ci		writel(USBD_CCEMPTY, USBD_DEVINTCLR(udc->udp_baseaddr));
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_ci		/* Write command code */
70662306a36Sopenharmony_ci		writel(cmd, USBD_CMDCODE(udc->udp_baseaddr));
70762306a36Sopenharmony_ci		to = 10000;
70862306a36Sopenharmony_ci		while (((readl(USBD_DEVINTST(udc->udp_baseaddr)) &
70962306a36Sopenharmony_ci			 USBD_CCEMPTY) == 0) && (to > 0)) {
71062306a36Sopenharmony_ci			to--;
71162306a36Sopenharmony_ci		}
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci		if (to > 0)
71462306a36Sopenharmony_ci			pass = 1;
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci		cpu_relax();
71762306a36Sopenharmony_ci	}
71862306a36Sopenharmony_ci}
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci/* Issues 2 commands (or command and data) to the USB device state machine */
72162306a36Sopenharmony_cistatic inline void udc_protocol_cmd_data_w(struct lpc32xx_udc *udc, u32 cmd,
72262306a36Sopenharmony_ci					   u32 data)
72362306a36Sopenharmony_ci{
72462306a36Sopenharmony_ci	udc_protocol_cmd_w(udc, cmd);
72562306a36Sopenharmony_ci	udc_protocol_cmd_w(udc, data);
72662306a36Sopenharmony_ci}
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci/* Issues a single command to the USB device state machine and reads
72962306a36Sopenharmony_ci * response data */
73062306a36Sopenharmony_cistatic u32 udc_protocol_cmd_r(struct lpc32xx_udc *udc, u32 cmd)
73162306a36Sopenharmony_ci{
73262306a36Sopenharmony_ci	int to = 1000;
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci	/* Write a command and read data from the protocol engine */
73562306a36Sopenharmony_ci	writel((USBD_CDFULL | USBD_CCEMPTY),
73662306a36Sopenharmony_ci		     USBD_DEVINTCLR(udc->udp_baseaddr));
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	/* Write command code */
73962306a36Sopenharmony_ci	udc_protocol_cmd_w(udc, cmd);
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ci	while ((!(readl(USBD_DEVINTST(udc->udp_baseaddr)) & USBD_CDFULL))
74262306a36Sopenharmony_ci	       && (to > 0))
74362306a36Sopenharmony_ci		to--;
74462306a36Sopenharmony_ci	if (!to)
74562306a36Sopenharmony_ci		dev_dbg(udc->dev,
74662306a36Sopenharmony_ci			"Protocol engine didn't receive response (CDFULL)\n");
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci	return readl(USBD_CMDDATA(udc->udp_baseaddr));
74962306a36Sopenharmony_ci}
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci/*
75262306a36Sopenharmony_ci *
75362306a36Sopenharmony_ci * USB device interrupt mask support functions
75462306a36Sopenharmony_ci *
75562306a36Sopenharmony_ci */
75662306a36Sopenharmony_ci/* Enable one or more USB device interrupts */
75762306a36Sopenharmony_cistatic inline void uda_enable_devint(struct lpc32xx_udc *udc, u32 devmask)
75862306a36Sopenharmony_ci{
75962306a36Sopenharmony_ci	udc->enabled_devints |= devmask;
76062306a36Sopenharmony_ci	writel(udc->enabled_devints, USBD_DEVINTEN(udc->udp_baseaddr));
76162306a36Sopenharmony_ci}
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci/* Disable one or more USB device interrupts */
76462306a36Sopenharmony_cistatic inline void uda_disable_devint(struct lpc32xx_udc *udc, u32 mask)
76562306a36Sopenharmony_ci{
76662306a36Sopenharmony_ci	udc->enabled_devints &= ~mask;
76762306a36Sopenharmony_ci	writel(udc->enabled_devints, USBD_DEVINTEN(udc->udp_baseaddr));
76862306a36Sopenharmony_ci}
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_ci/* Clear one or more USB device interrupts */
77162306a36Sopenharmony_cistatic inline void uda_clear_devint(struct lpc32xx_udc *udc, u32 mask)
77262306a36Sopenharmony_ci{
77362306a36Sopenharmony_ci	writel(mask, USBD_DEVINTCLR(udc->udp_baseaddr));
77462306a36Sopenharmony_ci}
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci/*
77762306a36Sopenharmony_ci *
77862306a36Sopenharmony_ci * Endpoint interrupt disable/enable functions
77962306a36Sopenharmony_ci *
78062306a36Sopenharmony_ci */
78162306a36Sopenharmony_ci/* Enable one or more USB endpoint interrupts */
78262306a36Sopenharmony_cistatic void uda_enable_hwepint(struct lpc32xx_udc *udc, u32 hwep)
78362306a36Sopenharmony_ci{
78462306a36Sopenharmony_ci	udc->enabled_hwepints |= (1 << hwep);
78562306a36Sopenharmony_ci	writel(udc->enabled_hwepints, USBD_EPINTEN(udc->udp_baseaddr));
78662306a36Sopenharmony_ci}
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci/* Disable one or more USB endpoint interrupts */
78962306a36Sopenharmony_cistatic void uda_disable_hwepint(struct lpc32xx_udc *udc, u32 hwep)
79062306a36Sopenharmony_ci{
79162306a36Sopenharmony_ci	udc->enabled_hwepints &= ~(1 << hwep);
79262306a36Sopenharmony_ci	writel(udc->enabled_hwepints, USBD_EPINTEN(udc->udp_baseaddr));
79362306a36Sopenharmony_ci}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci/* Clear one or more USB endpoint interrupts */
79662306a36Sopenharmony_cistatic inline void uda_clear_hwepint(struct lpc32xx_udc *udc, u32 hwep)
79762306a36Sopenharmony_ci{
79862306a36Sopenharmony_ci	writel((1 << hwep), USBD_EPINTCLR(udc->udp_baseaddr));
79962306a36Sopenharmony_ci}
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci/* Enable DMA for the HW channel */
80262306a36Sopenharmony_cistatic inline void udc_ep_dma_enable(struct lpc32xx_udc *udc, u32 hwep)
80362306a36Sopenharmony_ci{
80462306a36Sopenharmony_ci	writel((1 << hwep), USBD_EPDMAEN(udc->udp_baseaddr));
80562306a36Sopenharmony_ci}
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci/* Disable DMA for the HW channel */
80862306a36Sopenharmony_cistatic inline void udc_ep_dma_disable(struct lpc32xx_udc *udc, u32 hwep)
80962306a36Sopenharmony_ci{
81062306a36Sopenharmony_ci	writel((1 << hwep), USBD_EPDMADIS(udc->udp_baseaddr));
81162306a36Sopenharmony_ci}
81262306a36Sopenharmony_ci
81362306a36Sopenharmony_ci/*
81462306a36Sopenharmony_ci *
81562306a36Sopenharmony_ci * Endpoint realize/unrealize functions
81662306a36Sopenharmony_ci *
81762306a36Sopenharmony_ci */
81862306a36Sopenharmony_ci/* Before an endpoint can be used, it needs to be realized
81962306a36Sopenharmony_ci * in the USB protocol engine - this realizes the endpoint.
82062306a36Sopenharmony_ci * The interrupt (FIFO or DMA) is not enabled with this function */
82162306a36Sopenharmony_cistatic void udc_realize_hwep(struct lpc32xx_udc *udc, u32 hwep,
82262306a36Sopenharmony_ci			     u32 maxpacket)
82362306a36Sopenharmony_ci{
82462306a36Sopenharmony_ci	int to = 1000;
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	writel(USBD_EP_RLZED, USBD_DEVINTCLR(udc->udp_baseaddr));
82762306a36Sopenharmony_ci	writel(hwep, USBD_EPIND(udc->udp_baseaddr));
82862306a36Sopenharmony_ci	udc->realized_eps |= (1 << hwep);
82962306a36Sopenharmony_ci	writel(udc->realized_eps, USBD_REEP(udc->udp_baseaddr));
83062306a36Sopenharmony_ci	writel(maxpacket, USBD_EPMAXPSIZE(udc->udp_baseaddr));
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	/* Wait until endpoint is realized in hardware */
83362306a36Sopenharmony_ci	while ((!(readl(USBD_DEVINTST(udc->udp_baseaddr)) &
83462306a36Sopenharmony_ci		  USBD_EP_RLZED)) && (to > 0))
83562306a36Sopenharmony_ci		to--;
83662306a36Sopenharmony_ci	if (!to)
83762306a36Sopenharmony_ci		dev_dbg(udc->dev, "EP not correctly realized in hardware\n");
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci	writel(USBD_EP_RLZED, USBD_DEVINTCLR(udc->udp_baseaddr));
84062306a36Sopenharmony_ci}
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_ci/* Unrealize an EP */
84362306a36Sopenharmony_cistatic void udc_unrealize_hwep(struct lpc32xx_udc *udc, u32 hwep)
84462306a36Sopenharmony_ci{
84562306a36Sopenharmony_ci	udc->realized_eps &= ~(1 << hwep);
84662306a36Sopenharmony_ci	writel(udc->realized_eps, USBD_REEP(udc->udp_baseaddr));
84762306a36Sopenharmony_ci}
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci/*
85062306a36Sopenharmony_ci *
85162306a36Sopenharmony_ci * Endpoint support functions
85262306a36Sopenharmony_ci *
85362306a36Sopenharmony_ci */
85462306a36Sopenharmony_ci/* Select and clear endpoint interrupt */
85562306a36Sopenharmony_cistatic u32 udc_selep_clrint(struct lpc32xx_udc *udc, u32 hwep)
85662306a36Sopenharmony_ci{
85762306a36Sopenharmony_ci	udc_protocol_cmd_w(udc, CMD_SEL_EP_CLRI(hwep));
85862306a36Sopenharmony_ci	return udc_protocol_cmd_r(udc, DAT_SEL_EP_CLRI(hwep));
85962306a36Sopenharmony_ci}
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci/* Disables the endpoint in the USB protocol engine */
86262306a36Sopenharmony_cistatic void udc_disable_hwep(struct lpc32xx_udc *udc, u32 hwep)
86362306a36Sopenharmony_ci{
86462306a36Sopenharmony_ci	udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(hwep),
86562306a36Sopenharmony_ci				DAT_WR_BYTE(EP_STAT_DA));
86662306a36Sopenharmony_ci}
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci/* Stalls the endpoint - endpoint will return STALL */
86962306a36Sopenharmony_cistatic void udc_stall_hwep(struct lpc32xx_udc *udc, u32 hwep)
87062306a36Sopenharmony_ci{
87162306a36Sopenharmony_ci	udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(hwep),
87262306a36Sopenharmony_ci				DAT_WR_BYTE(EP_STAT_ST));
87362306a36Sopenharmony_ci}
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci/* Clear stall or reset endpoint */
87662306a36Sopenharmony_cistatic void udc_clrstall_hwep(struct lpc32xx_udc *udc, u32 hwep)
87762306a36Sopenharmony_ci{
87862306a36Sopenharmony_ci	udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(hwep),
87962306a36Sopenharmony_ci				DAT_WR_BYTE(0));
88062306a36Sopenharmony_ci}
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci/* Select an endpoint for endpoint status, clear, validate */
88362306a36Sopenharmony_cistatic void udc_select_hwep(struct lpc32xx_udc *udc, u32 hwep)
88462306a36Sopenharmony_ci{
88562306a36Sopenharmony_ci	udc_protocol_cmd_w(udc, CMD_SEL_EP(hwep));
88662306a36Sopenharmony_ci}
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_ci/*
88962306a36Sopenharmony_ci *
89062306a36Sopenharmony_ci * Endpoint buffer management functions
89162306a36Sopenharmony_ci *
89262306a36Sopenharmony_ci */
89362306a36Sopenharmony_ci/* Clear the current endpoint's buffer */
89462306a36Sopenharmony_cistatic void udc_clr_buffer_hwep(struct lpc32xx_udc *udc, u32 hwep)
89562306a36Sopenharmony_ci{
89662306a36Sopenharmony_ci	udc_select_hwep(udc, hwep);
89762306a36Sopenharmony_ci	udc_protocol_cmd_w(udc, CMD_CLR_BUF);
89862306a36Sopenharmony_ci}
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci/* Validate the current endpoint's buffer */
90162306a36Sopenharmony_cistatic void udc_val_buffer_hwep(struct lpc32xx_udc *udc, u32 hwep)
90262306a36Sopenharmony_ci{
90362306a36Sopenharmony_ci	udc_select_hwep(udc, hwep);
90462306a36Sopenharmony_ci	udc_protocol_cmd_w(udc, CMD_VALID_BUF);
90562306a36Sopenharmony_ci}
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_cistatic inline u32 udc_clearep_getsts(struct lpc32xx_udc *udc, u32 hwep)
90862306a36Sopenharmony_ci{
90962306a36Sopenharmony_ci	/* Clear EP interrupt */
91062306a36Sopenharmony_ci	uda_clear_hwepint(udc, hwep);
91162306a36Sopenharmony_ci	return udc_selep_clrint(udc, hwep);
91262306a36Sopenharmony_ci}
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci/*
91562306a36Sopenharmony_ci *
91662306a36Sopenharmony_ci * USB EP DMA support
91762306a36Sopenharmony_ci *
91862306a36Sopenharmony_ci */
91962306a36Sopenharmony_ci/* Allocate a DMA Descriptor */
92062306a36Sopenharmony_cistatic struct lpc32xx_usbd_dd_gad *udc_dd_alloc(struct lpc32xx_udc *udc)
92162306a36Sopenharmony_ci{
92262306a36Sopenharmony_ci	dma_addr_t			dma;
92362306a36Sopenharmony_ci	struct lpc32xx_usbd_dd_gad	*dd;
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ci	dd = dma_pool_alloc(udc->dd_cache, GFP_ATOMIC | GFP_DMA, &dma);
92662306a36Sopenharmony_ci	if (dd)
92762306a36Sopenharmony_ci		dd->this_dma = dma;
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_ci	return dd;
93062306a36Sopenharmony_ci}
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci/* Free a DMA Descriptor */
93362306a36Sopenharmony_cistatic void udc_dd_free(struct lpc32xx_udc *udc, struct lpc32xx_usbd_dd_gad *dd)
93462306a36Sopenharmony_ci{
93562306a36Sopenharmony_ci	dma_pool_free(udc->dd_cache, dd, dd->this_dma);
93662306a36Sopenharmony_ci}
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci/*
93962306a36Sopenharmony_ci *
94062306a36Sopenharmony_ci * USB setup and shutdown functions
94162306a36Sopenharmony_ci *
94262306a36Sopenharmony_ci */
94362306a36Sopenharmony_ci/* Enables or disables most of the USB system clocks when low power mode is
94462306a36Sopenharmony_ci * needed. Clocks are typically started on a connection event, and disabled
94562306a36Sopenharmony_ci * when a cable is disconnected */
94662306a36Sopenharmony_cistatic void udc_clk_set(struct lpc32xx_udc *udc, int enable)
94762306a36Sopenharmony_ci{
94862306a36Sopenharmony_ci	if (enable != 0) {
94962306a36Sopenharmony_ci		if (udc->clocked)
95062306a36Sopenharmony_ci			return;
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci		udc->clocked = 1;
95362306a36Sopenharmony_ci		clk_prepare_enable(udc->usb_slv_clk);
95462306a36Sopenharmony_ci	} else {
95562306a36Sopenharmony_ci		if (!udc->clocked)
95662306a36Sopenharmony_ci			return;
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci		udc->clocked = 0;
95962306a36Sopenharmony_ci		clk_disable_unprepare(udc->usb_slv_clk);
96062306a36Sopenharmony_ci	}
96162306a36Sopenharmony_ci}
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_ci/* Set/reset USB device address */
96462306a36Sopenharmony_cistatic void udc_set_address(struct lpc32xx_udc *udc, u32 addr)
96562306a36Sopenharmony_ci{
96662306a36Sopenharmony_ci	/* Address will be latched at the end of the status phase, or
96762306a36Sopenharmony_ci	   latched immediately if function is called twice */
96862306a36Sopenharmony_ci	udc_protocol_cmd_data_w(udc, CMD_SET_ADDR,
96962306a36Sopenharmony_ci				DAT_WR_BYTE(DEV_EN | addr));
97062306a36Sopenharmony_ci}
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci/* Setup up a IN request for DMA transfer - this consists of determining the
97362306a36Sopenharmony_ci * list of DMA addresses for the transfer, allocating DMA Descriptors,
97462306a36Sopenharmony_ci * installing the DD into the UDCA, and then enabling the DMA for that EP */
97562306a36Sopenharmony_cistatic int udc_ep_in_req_dma(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
97662306a36Sopenharmony_ci{
97762306a36Sopenharmony_ci	struct lpc32xx_request *req;
97862306a36Sopenharmony_ci	u32 hwep = ep->hwep_num;
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ci	ep->req_pending = 1;
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci	/* There will always be a request waiting here */
98362306a36Sopenharmony_ci	req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci	/* Place the DD Descriptor into the UDCA */
98662306a36Sopenharmony_ci	udc->udca_v_base[hwep] = req->dd_desc_ptr->this_dma;
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci	/* Enable DMA and interrupt for the HW EP */
98962306a36Sopenharmony_ci	udc_ep_dma_enable(udc, hwep);
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci	/* Clear ZLP if last packet is not of MAXP size */
99262306a36Sopenharmony_ci	if (req->req.length % ep->ep.maxpacket)
99362306a36Sopenharmony_ci		req->send_zlp = 0;
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ci	return 0;
99662306a36Sopenharmony_ci}
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci/* Setup up a OUT request for DMA transfer - this consists of determining the
99962306a36Sopenharmony_ci * list of DMA addresses for the transfer, allocating DMA Descriptors,
100062306a36Sopenharmony_ci * installing the DD into the UDCA, and then enabling the DMA for that EP */
100162306a36Sopenharmony_cistatic int udc_ep_out_req_dma(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
100262306a36Sopenharmony_ci{
100362306a36Sopenharmony_ci	struct lpc32xx_request *req;
100462306a36Sopenharmony_ci	u32 hwep = ep->hwep_num;
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_ci	ep->req_pending = 1;
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci	/* There will always be a request waiting here */
100962306a36Sopenharmony_ci	req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci	/* Place the DD Descriptor into the UDCA */
101262306a36Sopenharmony_ci	udc->udca_v_base[hwep] = req->dd_desc_ptr->this_dma;
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci	/* Enable DMA and interrupt for the HW EP */
101562306a36Sopenharmony_ci	udc_ep_dma_enable(udc, hwep);
101662306a36Sopenharmony_ci	return 0;
101762306a36Sopenharmony_ci}
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_cistatic void udc_disable(struct lpc32xx_udc *udc)
102062306a36Sopenharmony_ci{
102162306a36Sopenharmony_ci	u32 i;
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_ci	/* Disable device */
102462306a36Sopenharmony_ci	udc_protocol_cmd_data_w(udc, CMD_CFG_DEV, DAT_WR_BYTE(0));
102562306a36Sopenharmony_ci	udc_protocol_cmd_data_w(udc, CMD_SET_DEV_STAT, DAT_WR_BYTE(0));
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci	/* Disable all device interrupts (including EP0) */
102862306a36Sopenharmony_ci	uda_disable_devint(udc, 0x3FF);
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_ci	/* Disable and reset all endpoint interrupts */
103162306a36Sopenharmony_ci	for (i = 0; i < 32; i++) {
103262306a36Sopenharmony_ci		uda_disable_hwepint(udc, i);
103362306a36Sopenharmony_ci		uda_clear_hwepint(udc, i);
103462306a36Sopenharmony_ci		udc_disable_hwep(udc, i);
103562306a36Sopenharmony_ci		udc_unrealize_hwep(udc, i);
103662306a36Sopenharmony_ci		udc->udca_v_base[i] = 0;
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci		/* Disable and clear all interrupts and DMA */
103962306a36Sopenharmony_ci		udc_ep_dma_disable(udc, i);
104062306a36Sopenharmony_ci		writel((1 << i), USBD_EOTINTCLR(udc->udp_baseaddr));
104162306a36Sopenharmony_ci		writel((1 << i), USBD_NDDRTINTCLR(udc->udp_baseaddr));
104262306a36Sopenharmony_ci		writel((1 << i), USBD_SYSERRTINTCLR(udc->udp_baseaddr));
104362306a36Sopenharmony_ci		writel((1 << i), USBD_DMARCLR(udc->udp_baseaddr));
104462306a36Sopenharmony_ci	}
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_ci	/* Disable DMA interrupts */
104762306a36Sopenharmony_ci	writel(0, USBD_DMAINTEN(udc->udp_baseaddr));
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_ci	writel(0, USBD_UDCAH(udc->udp_baseaddr));
105062306a36Sopenharmony_ci}
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_cistatic void udc_enable(struct lpc32xx_udc *udc)
105362306a36Sopenharmony_ci{
105462306a36Sopenharmony_ci	u32 i;
105562306a36Sopenharmony_ci	struct lpc32xx_ep *ep = &udc->ep[0];
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_ci	/* Start with known state */
105862306a36Sopenharmony_ci	udc_disable(udc);
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci	/* Enable device */
106162306a36Sopenharmony_ci	udc_protocol_cmd_data_w(udc, CMD_SET_DEV_STAT, DAT_WR_BYTE(DEV_CON));
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci	/* EP interrupts on high priority, FRAME interrupt on low priority */
106462306a36Sopenharmony_ci	writel(USBD_EP_FAST, USBD_DEVINTPRI(udc->udp_baseaddr));
106562306a36Sopenharmony_ci	writel(0xFFFF, USBD_EPINTPRI(udc->udp_baseaddr));
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ci	/* Clear any pending device interrupts */
106862306a36Sopenharmony_ci	writel(0x3FF, USBD_DEVINTCLR(udc->udp_baseaddr));
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci	/* Setup UDCA - not yet used (DMA) */
107162306a36Sopenharmony_ci	writel(udc->udca_p_base, USBD_UDCAH(udc->udp_baseaddr));
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci	/* Only enable EP0 in and out for now, EP0 only works in FIFO mode */
107462306a36Sopenharmony_ci	for (i = 0; i <= 1; i++) {
107562306a36Sopenharmony_ci		udc_realize_hwep(udc, i, ep->ep.maxpacket);
107662306a36Sopenharmony_ci		uda_enable_hwepint(udc, i);
107762306a36Sopenharmony_ci		udc_select_hwep(udc, i);
107862306a36Sopenharmony_ci		udc_clrstall_hwep(udc, i);
107962306a36Sopenharmony_ci		udc_clr_buffer_hwep(udc, i);
108062306a36Sopenharmony_ci	}
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ci	/* Device interrupt setup */
108362306a36Sopenharmony_ci	uda_clear_devint(udc, (USBD_ERR_INT | USBD_DEV_STAT | USBD_EP_SLOW |
108462306a36Sopenharmony_ci			       USBD_EP_FAST));
108562306a36Sopenharmony_ci	uda_enable_devint(udc, (USBD_ERR_INT | USBD_DEV_STAT | USBD_EP_SLOW |
108662306a36Sopenharmony_ci				USBD_EP_FAST));
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	/* Set device address to 0 - called twice to force a latch in the USB
108962306a36Sopenharmony_ci	   engine without the need of a setup packet status closure */
109062306a36Sopenharmony_ci	udc_set_address(udc, 0);
109162306a36Sopenharmony_ci	udc_set_address(udc, 0);
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	/* Enable master DMA interrupts */
109462306a36Sopenharmony_ci	writel((USBD_SYS_ERR_INT | USBD_EOT_INT),
109562306a36Sopenharmony_ci		     USBD_DMAINTEN(udc->udp_baseaddr));
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci	udc->dev_status = 0;
109862306a36Sopenharmony_ci}
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci/*
110162306a36Sopenharmony_ci *
110262306a36Sopenharmony_ci * USB device board specific events handled via callbacks
110362306a36Sopenharmony_ci *
110462306a36Sopenharmony_ci */
110562306a36Sopenharmony_ci/* Connection change event - notify board function of change */
110662306a36Sopenharmony_cistatic void uda_power_event(struct lpc32xx_udc *udc, u32 conn)
110762306a36Sopenharmony_ci{
110862306a36Sopenharmony_ci	/* Just notify of a connection change event (optional) */
110962306a36Sopenharmony_ci	if (udc->board->conn_chgb != NULL)
111062306a36Sopenharmony_ci		udc->board->conn_chgb(conn);
111162306a36Sopenharmony_ci}
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci/* Suspend/resume event - notify board function of change */
111462306a36Sopenharmony_cistatic void uda_resm_susp_event(struct lpc32xx_udc *udc, u32 conn)
111562306a36Sopenharmony_ci{
111662306a36Sopenharmony_ci	/* Just notify of a Suspend/resume change event (optional) */
111762306a36Sopenharmony_ci	if (udc->board->susp_chgb != NULL)
111862306a36Sopenharmony_ci		udc->board->susp_chgb(conn);
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci	if (conn)
112162306a36Sopenharmony_ci		udc->suspended = 0;
112262306a36Sopenharmony_ci	else
112362306a36Sopenharmony_ci		udc->suspended = 1;
112462306a36Sopenharmony_ci}
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_ci/* Remote wakeup enable/disable - notify board function of change */
112762306a36Sopenharmony_cistatic void uda_remwkp_cgh(struct lpc32xx_udc *udc)
112862306a36Sopenharmony_ci{
112962306a36Sopenharmony_ci	if (udc->board->rmwk_chgb != NULL)
113062306a36Sopenharmony_ci		udc->board->rmwk_chgb(udc->dev_status &
113162306a36Sopenharmony_ci				      (1 << USB_DEVICE_REMOTE_WAKEUP));
113262306a36Sopenharmony_ci}
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci/* Reads data from FIFO, adjusts for alignment and data size */
113562306a36Sopenharmony_cistatic void udc_pop_fifo(struct lpc32xx_udc *udc, u8 *data, u32 bytes)
113662306a36Sopenharmony_ci{
113762306a36Sopenharmony_ci	int n, i, bl;
113862306a36Sopenharmony_ci	u16 *p16;
113962306a36Sopenharmony_ci	u32 *p32, tmp, cbytes;
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci	/* Use optimal data transfer method based on source address and size */
114262306a36Sopenharmony_ci	switch (((uintptr_t) data) & 0x3) {
114362306a36Sopenharmony_ci	case 0: /* 32-bit aligned */
114462306a36Sopenharmony_ci		p32 = (u32 *) data;
114562306a36Sopenharmony_ci		cbytes = (bytes & ~0x3);
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_ci		/* Copy 32-bit aligned data first */
114862306a36Sopenharmony_ci		for (n = 0; n < cbytes; n += 4)
114962306a36Sopenharmony_ci			*p32++ = readl(USBD_RXDATA(udc->udp_baseaddr));
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci		/* Handle any remaining bytes */
115262306a36Sopenharmony_ci		bl = bytes - cbytes;
115362306a36Sopenharmony_ci		if (bl) {
115462306a36Sopenharmony_ci			tmp = readl(USBD_RXDATA(udc->udp_baseaddr));
115562306a36Sopenharmony_ci			for (n = 0; n < bl; n++)
115662306a36Sopenharmony_ci				data[cbytes + n] = ((tmp >> (n * 8)) & 0xFF);
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci		}
115962306a36Sopenharmony_ci		break;
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_ci	case 1: /* 8-bit aligned */
116262306a36Sopenharmony_ci	case 3:
116362306a36Sopenharmony_ci		/* Each byte has to be handled independently */
116462306a36Sopenharmony_ci		for (n = 0; n < bytes; n += 4) {
116562306a36Sopenharmony_ci			tmp = readl(USBD_RXDATA(udc->udp_baseaddr));
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci			bl = bytes - n;
116862306a36Sopenharmony_ci			if (bl > 4)
116962306a36Sopenharmony_ci				bl = 4;
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_ci			for (i = 0; i < bl; i++)
117262306a36Sopenharmony_ci				data[n + i] = (u8) ((tmp >> (i * 8)) & 0xFF);
117362306a36Sopenharmony_ci		}
117462306a36Sopenharmony_ci		break;
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_ci	case 2: /* 16-bit aligned */
117762306a36Sopenharmony_ci		p16 = (u16 *) data;
117862306a36Sopenharmony_ci		cbytes = (bytes & ~0x3);
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci		/* Copy 32-bit sized objects first with 16-bit alignment */
118162306a36Sopenharmony_ci		for (n = 0; n < cbytes; n += 4) {
118262306a36Sopenharmony_ci			tmp = readl(USBD_RXDATA(udc->udp_baseaddr));
118362306a36Sopenharmony_ci			*p16++ = (u16)(tmp & 0xFFFF);
118462306a36Sopenharmony_ci			*p16++ = (u16)((tmp >> 16) & 0xFFFF);
118562306a36Sopenharmony_ci		}
118662306a36Sopenharmony_ci
118762306a36Sopenharmony_ci		/* Handle any remaining bytes */
118862306a36Sopenharmony_ci		bl = bytes - cbytes;
118962306a36Sopenharmony_ci		if (bl) {
119062306a36Sopenharmony_ci			tmp = readl(USBD_RXDATA(udc->udp_baseaddr));
119162306a36Sopenharmony_ci			for (n = 0; n < bl; n++)
119262306a36Sopenharmony_ci				data[cbytes + n] = ((tmp >> (n * 8)) & 0xFF);
119362306a36Sopenharmony_ci		}
119462306a36Sopenharmony_ci		break;
119562306a36Sopenharmony_ci	}
119662306a36Sopenharmony_ci}
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci/* Read data from the FIFO for an endpoint. This function is for endpoints (such
119962306a36Sopenharmony_ci * as EP0) that don't use DMA. This function should only be called if a packet
120062306a36Sopenharmony_ci * is known to be ready to read for the endpoint. Note that the endpoint must
120162306a36Sopenharmony_ci * be selected in the protocol engine prior to this call. */
120262306a36Sopenharmony_cistatic u32 udc_read_hwep(struct lpc32xx_udc *udc, u32 hwep, u32 *data,
120362306a36Sopenharmony_ci			 u32 bytes)
120462306a36Sopenharmony_ci{
120562306a36Sopenharmony_ci	u32 tmpv;
120662306a36Sopenharmony_ci	int to = 1000;
120762306a36Sopenharmony_ci	u32 tmp, hwrep = ((hwep & 0x1E) << 1) | CTRL_RD_EN;
120862306a36Sopenharmony_ci
120962306a36Sopenharmony_ci	/* Setup read of endpoint */
121062306a36Sopenharmony_ci	writel(hwrep, USBD_CTRL(udc->udp_baseaddr));
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci	/* Wait until packet is ready */
121362306a36Sopenharmony_ci	while ((((tmpv = readl(USBD_RXPLEN(udc->udp_baseaddr))) &
121462306a36Sopenharmony_ci		 PKT_RDY) == 0)	&& (to > 0))
121562306a36Sopenharmony_ci		to--;
121662306a36Sopenharmony_ci	if (!to)
121762306a36Sopenharmony_ci		dev_dbg(udc->dev, "No packet ready on FIFO EP read\n");
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_ci	/* Mask out count */
122062306a36Sopenharmony_ci	tmp = tmpv & PKT_LNGTH_MASK;
122162306a36Sopenharmony_ci	if (bytes < tmp)
122262306a36Sopenharmony_ci		tmp = bytes;
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci	if ((tmp > 0) && (data != NULL))
122562306a36Sopenharmony_ci		udc_pop_fifo(udc, (u8 *) data, tmp);
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	writel(((hwep & 0x1E) << 1), USBD_CTRL(udc->udp_baseaddr));
122862306a36Sopenharmony_ci
122962306a36Sopenharmony_ci	/* Clear the buffer */
123062306a36Sopenharmony_ci	udc_clr_buffer_hwep(udc, hwep);
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_ci	return tmp;
123362306a36Sopenharmony_ci}
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci/* Stuffs data into the FIFO, adjusts for alignment and data size */
123662306a36Sopenharmony_cistatic void udc_stuff_fifo(struct lpc32xx_udc *udc, u8 *data, u32 bytes)
123762306a36Sopenharmony_ci{
123862306a36Sopenharmony_ci	int n, i, bl;
123962306a36Sopenharmony_ci	u16 *p16;
124062306a36Sopenharmony_ci	u32 *p32, tmp, cbytes;
124162306a36Sopenharmony_ci
124262306a36Sopenharmony_ci	/* Use optimal data transfer method based on source address and size */
124362306a36Sopenharmony_ci	switch (((uintptr_t) data) & 0x3) {
124462306a36Sopenharmony_ci	case 0: /* 32-bit aligned */
124562306a36Sopenharmony_ci		p32 = (u32 *) data;
124662306a36Sopenharmony_ci		cbytes = (bytes & ~0x3);
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci		/* Copy 32-bit aligned data first */
124962306a36Sopenharmony_ci		for (n = 0; n < cbytes; n += 4)
125062306a36Sopenharmony_ci			writel(*p32++, USBD_TXDATA(udc->udp_baseaddr));
125162306a36Sopenharmony_ci
125262306a36Sopenharmony_ci		/* Handle any remaining bytes */
125362306a36Sopenharmony_ci		bl = bytes - cbytes;
125462306a36Sopenharmony_ci		if (bl) {
125562306a36Sopenharmony_ci			tmp = 0;
125662306a36Sopenharmony_ci			for (n = 0; n < bl; n++)
125762306a36Sopenharmony_ci				tmp |= data[cbytes + n] << (n * 8);
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci			writel(tmp, USBD_TXDATA(udc->udp_baseaddr));
126062306a36Sopenharmony_ci		}
126162306a36Sopenharmony_ci		break;
126262306a36Sopenharmony_ci
126362306a36Sopenharmony_ci	case 1: /* 8-bit aligned */
126462306a36Sopenharmony_ci	case 3:
126562306a36Sopenharmony_ci		/* Each byte has to be handled independently */
126662306a36Sopenharmony_ci		for (n = 0; n < bytes; n += 4) {
126762306a36Sopenharmony_ci			bl = bytes - n;
126862306a36Sopenharmony_ci			if (bl > 4)
126962306a36Sopenharmony_ci				bl = 4;
127062306a36Sopenharmony_ci
127162306a36Sopenharmony_ci			tmp = 0;
127262306a36Sopenharmony_ci			for (i = 0; i < bl; i++)
127362306a36Sopenharmony_ci				tmp |= data[n + i] << (i * 8);
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_ci			writel(tmp, USBD_TXDATA(udc->udp_baseaddr));
127662306a36Sopenharmony_ci		}
127762306a36Sopenharmony_ci		break;
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_ci	case 2: /* 16-bit aligned */
128062306a36Sopenharmony_ci		p16 = (u16 *) data;
128162306a36Sopenharmony_ci		cbytes = (bytes & ~0x3);
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci		/* Copy 32-bit aligned data first */
128462306a36Sopenharmony_ci		for (n = 0; n < cbytes; n += 4) {
128562306a36Sopenharmony_ci			tmp = *p16++ & 0xFFFF;
128662306a36Sopenharmony_ci			tmp |= (*p16++ & 0xFFFF) << 16;
128762306a36Sopenharmony_ci			writel(tmp, USBD_TXDATA(udc->udp_baseaddr));
128862306a36Sopenharmony_ci		}
128962306a36Sopenharmony_ci
129062306a36Sopenharmony_ci		/* Handle any remaining bytes */
129162306a36Sopenharmony_ci		bl = bytes - cbytes;
129262306a36Sopenharmony_ci		if (bl) {
129362306a36Sopenharmony_ci			tmp = 0;
129462306a36Sopenharmony_ci			for (n = 0; n < bl; n++)
129562306a36Sopenharmony_ci				tmp |= data[cbytes + n] << (n * 8);
129662306a36Sopenharmony_ci
129762306a36Sopenharmony_ci			writel(tmp, USBD_TXDATA(udc->udp_baseaddr));
129862306a36Sopenharmony_ci		}
129962306a36Sopenharmony_ci		break;
130062306a36Sopenharmony_ci	}
130162306a36Sopenharmony_ci}
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_ci/* Write data to the FIFO for an endpoint. This function is for endpoints (such
130462306a36Sopenharmony_ci * as EP0) that don't use DMA. Note that the endpoint must be selected in the
130562306a36Sopenharmony_ci * protocol engine prior to this call. */
130662306a36Sopenharmony_cistatic void udc_write_hwep(struct lpc32xx_udc *udc, u32 hwep, u32 *data,
130762306a36Sopenharmony_ci			   u32 bytes)
130862306a36Sopenharmony_ci{
130962306a36Sopenharmony_ci	u32 hwwep = ((hwep & 0x1E) << 1) | CTRL_WR_EN;
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_ci	if ((bytes > 0) && (data == NULL))
131262306a36Sopenharmony_ci		return;
131362306a36Sopenharmony_ci
131462306a36Sopenharmony_ci	/* Setup write of endpoint */
131562306a36Sopenharmony_ci	writel(hwwep, USBD_CTRL(udc->udp_baseaddr));
131662306a36Sopenharmony_ci
131762306a36Sopenharmony_ci	writel(bytes, USBD_TXPLEN(udc->udp_baseaddr));
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_ci	/* Need at least 1 byte to trigger TX */
132062306a36Sopenharmony_ci	if (bytes == 0)
132162306a36Sopenharmony_ci		writel(0, USBD_TXDATA(udc->udp_baseaddr));
132262306a36Sopenharmony_ci	else
132362306a36Sopenharmony_ci		udc_stuff_fifo(udc, (u8 *) data, bytes);
132462306a36Sopenharmony_ci
132562306a36Sopenharmony_ci	writel(((hwep & 0x1E) << 1), USBD_CTRL(udc->udp_baseaddr));
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci	udc_val_buffer_hwep(udc, hwep);
132862306a36Sopenharmony_ci}
132962306a36Sopenharmony_ci
133062306a36Sopenharmony_ci/* USB device reset - resets USB to a default state with just EP0
133162306a36Sopenharmony_ci   enabled */
133262306a36Sopenharmony_cistatic void uda_usb_reset(struct lpc32xx_udc *udc)
133362306a36Sopenharmony_ci{
133462306a36Sopenharmony_ci	u32 i = 0;
133562306a36Sopenharmony_ci	/* Re-init device controller and EP0 */
133662306a36Sopenharmony_ci	udc_enable(udc);
133762306a36Sopenharmony_ci	udc->gadget.speed = USB_SPEED_FULL;
133862306a36Sopenharmony_ci
133962306a36Sopenharmony_ci	for (i = 1; i < NUM_ENDPOINTS; i++) {
134062306a36Sopenharmony_ci		struct lpc32xx_ep *ep = &udc->ep[i];
134162306a36Sopenharmony_ci		ep->req_pending = 0;
134262306a36Sopenharmony_ci	}
134362306a36Sopenharmony_ci}
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci/* Send a ZLP on EP0 */
134662306a36Sopenharmony_cistatic void udc_ep0_send_zlp(struct lpc32xx_udc *udc)
134762306a36Sopenharmony_ci{
134862306a36Sopenharmony_ci	udc_write_hwep(udc, EP_IN, NULL, 0);
134962306a36Sopenharmony_ci}
135062306a36Sopenharmony_ci
135162306a36Sopenharmony_ci/* Get current frame number */
135262306a36Sopenharmony_cistatic u16 udc_get_current_frame(struct lpc32xx_udc *udc)
135362306a36Sopenharmony_ci{
135462306a36Sopenharmony_ci	u16 flo, fhi;
135562306a36Sopenharmony_ci
135662306a36Sopenharmony_ci	udc_protocol_cmd_w(udc, CMD_RD_FRAME);
135762306a36Sopenharmony_ci	flo = (u16) udc_protocol_cmd_r(udc, DAT_RD_FRAME);
135862306a36Sopenharmony_ci	fhi = (u16) udc_protocol_cmd_r(udc, DAT_RD_FRAME);
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ci	return (fhi << 8) | flo;
136162306a36Sopenharmony_ci}
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci/* Set the device as configured - enables all endpoints */
136462306a36Sopenharmony_cistatic inline void udc_set_device_configured(struct lpc32xx_udc *udc)
136562306a36Sopenharmony_ci{
136662306a36Sopenharmony_ci	udc_protocol_cmd_data_w(udc, CMD_CFG_DEV, DAT_WR_BYTE(CONF_DVICE));
136762306a36Sopenharmony_ci}
136862306a36Sopenharmony_ci
136962306a36Sopenharmony_ci/* Set the device as unconfigured - disables all endpoints */
137062306a36Sopenharmony_cistatic inline void udc_set_device_unconfigured(struct lpc32xx_udc *udc)
137162306a36Sopenharmony_ci{
137262306a36Sopenharmony_ci	udc_protocol_cmd_data_w(udc, CMD_CFG_DEV, DAT_WR_BYTE(0));
137362306a36Sopenharmony_ci}
137462306a36Sopenharmony_ci
137562306a36Sopenharmony_ci/* reinit == restore initial software state */
137662306a36Sopenharmony_cistatic void udc_reinit(struct lpc32xx_udc *udc)
137762306a36Sopenharmony_ci{
137862306a36Sopenharmony_ci	u32 i;
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_ci	INIT_LIST_HEAD(&udc->gadget.ep_list);
138162306a36Sopenharmony_ci	INIT_LIST_HEAD(&udc->gadget.ep0->ep_list);
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci	for (i = 0; i < NUM_ENDPOINTS; i++) {
138462306a36Sopenharmony_ci		struct lpc32xx_ep *ep = &udc->ep[i];
138562306a36Sopenharmony_ci
138662306a36Sopenharmony_ci		if (i != 0)
138762306a36Sopenharmony_ci			list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
138862306a36Sopenharmony_ci		usb_ep_set_maxpacket_limit(&ep->ep, ep->maxpacket);
138962306a36Sopenharmony_ci		INIT_LIST_HEAD(&ep->queue);
139062306a36Sopenharmony_ci		ep->req_pending = 0;
139162306a36Sopenharmony_ci	}
139262306a36Sopenharmony_ci
139362306a36Sopenharmony_ci	udc->ep0state = WAIT_FOR_SETUP;
139462306a36Sopenharmony_ci}
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci/* Must be called with lock */
139762306a36Sopenharmony_cistatic void done(struct lpc32xx_ep *ep, struct lpc32xx_request *req, int status)
139862306a36Sopenharmony_ci{
139962306a36Sopenharmony_ci	struct lpc32xx_udc *udc = ep->udc;
140062306a36Sopenharmony_ci
140162306a36Sopenharmony_ci	list_del_init(&req->queue);
140262306a36Sopenharmony_ci	if (req->req.status == -EINPROGRESS)
140362306a36Sopenharmony_ci		req->req.status = status;
140462306a36Sopenharmony_ci	else
140562306a36Sopenharmony_ci		status = req->req.status;
140662306a36Sopenharmony_ci
140762306a36Sopenharmony_ci	if (ep->lep) {
140862306a36Sopenharmony_ci		usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
140962306a36Sopenharmony_ci
141062306a36Sopenharmony_ci		/* Free DDs */
141162306a36Sopenharmony_ci		udc_dd_free(udc, req->dd_desc_ptr);
141262306a36Sopenharmony_ci	}
141362306a36Sopenharmony_ci
141462306a36Sopenharmony_ci	if (status && status != -ESHUTDOWN)
141562306a36Sopenharmony_ci		ep_dbg(ep, "%s done %p, status %d\n", ep->ep.name, req, status);
141662306a36Sopenharmony_ci
141762306a36Sopenharmony_ci	ep->req_pending = 0;
141862306a36Sopenharmony_ci	spin_unlock(&udc->lock);
141962306a36Sopenharmony_ci	usb_gadget_giveback_request(&ep->ep, &req->req);
142062306a36Sopenharmony_ci	spin_lock(&udc->lock);
142162306a36Sopenharmony_ci}
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_ci/* Must be called with lock */
142462306a36Sopenharmony_cistatic void nuke(struct lpc32xx_ep *ep, int status)
142562306a36Sopenharmony_ci{
142662306a36Sopenharmony_ci	struct lpc32xx_request *req;
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_ci	while (!list_empty(&ep->queue)) {
142962306a36Sopenharmony_ci		req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
143062306a36Sopenharmony_ci		done(ep, req, status);
143162306a36Sopenharmony_ci	}
143262306a36Sopenharmony_ci
143362306a36Sopenharmony_ci	if (status == -ESHUTDOWN) {
143462306a36Sopenharmony_ci		uda_disable_hwepint(ep->udc, ep->hwep_num);
143562306a36Sopenharmony_ci		udc_disable_hwep(ep->udc, ep->hwep_num);
143662306a36Sopenharmony_ci	}
143762306a36Sopenharmony_ci}
143862306a36Sopenharmony_ci
143962306a36Sopenharmony_ci/* IN endpoint 0 transfer */
144062306a36Sopenharmony_cistatic int udc_ep0_in_req(struct lpc32xx_udc *udc)
144162306a36Sopenharmony_ci{
144262306a36Sopenharmony_ci	struct lpc32xx_request *req;
144362306a36Sopenharmony_ci	struct lpc32xx_ep *ep0 = &udc->ep[0];
144462306a36Sopenharmony_ci	u32 tsend, ts = 0;
144562306a36Sopenharmony_ci
144662306a36Sopenharmony_ci	if (list_empty(&ep0->queue))
144762306a36Sopenharmony_ci		/* Nothing to send */
144862306a36Sopenharmony_ci		return 0;
144962306a36Sopenharmony_ci	else
145062306a36Sopenharmony_ci		req = list_entry(ep0->queue.next, struct lpc32xx_request,
145162306a36Sopenharmony_ci				 queue);
145262306a36Sopenharmony_ci
145362306a36Sopenharmony_ci	tsend = ts = req->req.length - req->req.actual;
145462306a36Sopenharmony_ci	if (ts == 0) {
145562306a36Sopenharmony_ci		/* Send a ZLP */
145662306a36Sopenharmony_ci		udc_ep0_send_zlp(udc);
145762306a36Sopenharmony_ci		done(ep0, req, 0);
145862306a36Sopenharmony_ci		return 1;
145962306a36Sopenharmony_ci	} else if (ts > ep0->ep.maxpacket)
146062306a36Sopenharmony_ci		ts = ep0->ep.maxpacket; /* Just send what we can */
146162306a36Sopenharmony_ci
146262306a36Sopenharmony_ci	/* Write data to the EP0 FIFO and start transfer */
146362306a36Sopenharmony_ci	udc_write_hwep(udc, EP_IN, (req->req.buf + req->req.actual), ts);
146462306a36Sopenharmony_ci
146562306a36Sopenharmony_ci	/* Increment data pointer */
146662306a36Sopenharmony_ci	req->req.actual += ts;
146762306a36Sopenharmony_ci
146862306a36Sopenharmony_ci	if (tsend >= ep0->ep.maxpacket)
146962306a36Sopenharmony_ci		return 0; /* Stay in data transfer state */
147062306a36Sopenharmony_ci
147162306a36Sopenharmony_ci	/* Transfer request is complete */
147262306a36Sopenharmony_ci	udc->ep0state = WAIT_FOR_SETUP;
147362306a36Sopenharmony_ci	done(ep0, req, 0);
147462306a36Sopenharmony_ci	return 1;
147562306a36Sopenharmony_ci}
147662306a36Sopenharmony_ci
147762306a36Sopenharmony_ci/* OUT endpoint 0 transfer */
147862306a36Sopenharmony_cistatic int udc_ep0_out_req(struct lpc32xx_udc *udc)
147962306a36Sopenharmony_ci{
148062306a36Sopenharmony_ci	struct lpc32xx_request *req;
148162306a36Sopenharmony_ci	struct lpc32xx_ep *ep0 = &udc->ep[0];
148262306a36Sopenharmony_ci	u32 tr, bufferspace;
148362306a36Sopenharmony_ci
148462306a36Sopenharmony_ci	if (list_empty(&ep0->queue))
148562306a36Sopenharmony_ci		return 0;
148662306a36Sopenharmony_ci	else
148762306a36Sopenharmony_ci		req = list_entry(ep0->queue.next, struct lpc32xx_request,
148862306a36Sopenharmony_ci				 queue);
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_ci	if (req) {
149162306a36Sopenharmony_ci		if (req->req.length == 0) {
149262306a36Sopenharmony_ci			/* Just dequeue request */
149362306a36Sopenharmony_ci			done(ep0, req, 0);
149462306a36Sopenharmony_ci			udc->ep0state = WAIT_FOR_SETUP;
149562306a36Sopenharmony_ci			return 1;
149662306a36Sopenharmony_ci		}
149762306a36Sopenharmony_ci
149862306a36Sopenharmony_ci		/* Get data from FIFO */
149962306a36Sopenharmony_ci		bufferspace = req->req.length - req->req.actual;
150062306a36Sopenharmony_ci		if (bufferspace > ep0->ep.maxpacket)
150162306a36Sopenharmony_ci			bufferspace = ep0->ep.maxpacket;
150262306a36Sopenharmony_ci
150362306a36Sopenharmony_ci		/* Copy data to buffer */
150462306a36Sopenharmony_ci		prefetchw(req->req.buf + req->req.actual);
150562306a36Sopenharmony_ci		tr = udc_read_hwep(udc, EP_OUT, req->req.buf + req->req.actual,
150662306a36Sopenharmony_ci				   bufferspace);
150762306a36Sopenharmony_ci		req->req.actual += bufferspace;
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_ci		if (tr < ep0->ep.maxpacket) {
151062306a36Sopenharmony_ci			/* This is the last packet */
151162306a36Sopenharmony_ci			done(ep0, req, 0);
151262306a36Sopenharmony_ci			udc->ep0state = WAIT_FOR_SETUP;
151362306a36Sopenharmony_ci			return 1;
151462306a36Sopenharmony_ci		}
151562306a36Sopenharmony_ci	}
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_ci	return 0;
151862306a36Sopenharmony_ci}
151962306a36Sopenharmony_ci
152062306a36Sopenharmony_ci/* Must be called with lock */
152162306a36Sopenharmony_cistatic void stop_activity(struct lpc32xx_udc *udc)
152262306a36Sopenharmony_ci{
152362306a36Sopenharmony_ci	struct usb_gadget_driver *driver = udc->driver;
152462306a36Sopenharmony_ci	int i;
152562306a36Sopenharmony_ci
152662306a36Sopenharmony_ci	if (udc->gadget.speed == USB_SPEED_UNKNOWN)
152762306a36Sopenharmony_ci		driver = NULL;
152862306a36Sopenharmony_ci
152962306a36Sopenharmony_ci	udc->gadget.speed = USB_SPEED_UNKNOWN;
153062306a36Sopenharmony_ci	udc->suspended = 0;
153162306a36Sopenharmony_ci
153262306a36Sopenharmony_ci	for (i = 0; i < NUM_ENDPOINTS; i++) {
153362306a36Sopenharmony_ci		struct lpc32xx_ep *ep = &udc->ep[i];
153462306a36Sopenharmony_ci		nuke(ep, -ESHUTDOWN);
153562306a36Sopenharmony_ci	}
153662306a36Sopenharmony_ci	if (driver) {
153762306a36Sopenharmony_ci		spin_unlock(&udc->lock);
153862306a36Sopenharmony_ci		driver->disconnect(&udc->gadget);
153962306a36Sopenharmony_ci		spin_lock(&udc->lock);
154062306a36Sopenharmony_ci	}
154162306a36Sopenharmony_ci
154262306a36Sopenharmony_ci	isp1301_pullup_enable(udc, 0, 0);
154362306a36Sopenharmony_ci	udc_disable(udc);
154462306a36Sopenharmony_ci	udc_reinit(udc);
154562306a36Sopenharmony_ci}
154662306a36Sopenharmony_ci
154762306a36Sopenharmony_ci/*
154862306a36Sopenharmony_ci * Activate or kill host pullup
154962306a36Sopenharmony_ci * Can be called with or without lock
155062306a36Sopenharmony_ci */
155162306a36Sopenharmony_cistatic void pullup(struct lpc32xx_udc *udc, int is_on)
155262306a36Sopenharmony_ci{
155362306a36Sopenharmony_ci	if (!udc->clocked)
155462306a36Sopenharmony_ci		return;
155562306a36Sopenharmony_ci
155662306a36Sopenharmony_ci	if (!udc->enabled || !udc->vbus)
155762306a36Sopenharmony_ci		is_on = 0;
155862306a36Sopenharmony_ci
155962306a36Sopenharmony_ci	if (is_on != udc->pullup)
156062306a36Sopenharmony_ci		isp1301_pullup_enable(udc, is_on, 0);
156162306a36Sopenharmony_ci}
156262306a36Sopenharmony_ci
156362306a36Sopenharmony_ci/* Must be called without lock */
156462306a36Sopenharmony_cistatic int lpc32xx_ep_disable(struct usb_ep *_ep)
156562306a36Sopenharmony_ci{
156662306a36Sopenharmony_ci	struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep);
156762306a36Sopenharmony_ci	struct lpc32xx_udc *udc = ep->udc;
156862306a36Sopenharmony_ci	unsigned long	flags;
156962306a36Sopenharmony_ci
157062306a36Sopenharmony_ci	if ((ep->hwep_num_base == 0) || (ep->hwep_num == 0))
157162306a36Sopenharmony_ci		return -EINVAL;
157262306a36Sopenharmony_ci	spin_lock_irqsave(&udc->lock, flags);
157362306a36Sopenharmony_ci
157462306a36Sopenharmony_ci	nuke(ep, -ESHUTDOWN);
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci	/* Clear all DMA statuses for this EP */
157762306a36Sopenharmony_ci	udc_ep_dma_disable(udc, ep->hwep_num);
157862306a36Sopenharmony_ci	writel(1 << ep->hwep_num, USBD_EOTINTCLR(udc->udp_baseaddr));
157962306a36Sopenharmony_ci	writel(1 << ep->hwep_num, USBD_NDDRTINTCLR(udc->udp_baseaddr));
158062306a36Sopenharmony_ci	writel(1 << ep->hwep_num, USBD_SYSERRTINTCLR(udc->udp_baseaddr));
158162306a36Sopenharmony_ci	writel(1 << ep->hwep_num, USBD_DMARCLR(udc->udp_baseaddr));
158262306a36Sopenharmony_ci
158362306a36Sopenharmony_ci	/* Remove the DD pointer in the UDCA */
158462306a36Sopenharmony_ci	udc->udca_v_base[ep->hwep_num] = 0;
158562306a36Sopenharmony_ci
158662306a36Sopenharmony_ci	/* Disable and reset endpoint and interrupt */
158762306a36Sopenharmony_ci	uda_clear_hwepint(udc, ep->hwep_num);
158862306a36Sopenharmony_ci	udc_unrealize_hwep(udc, ep->hwep_num);
158962306a36Sopenharmony_ci
159062306a36Sopenharmony_ci	ep->hwep_num = 0;
159162306a36Sopenharmony_ci
159262306a36Sopenharmony_ci	spin_unlock_irqrestore(&udc->lock, flags);
159362306a36Sopenharmony_ci
159462306a36Sopenharmony_ci	atomic_dec(&udc->enabled_ep_cnt);
159562306a36Sopenharmony_ci	wake_up(&udc->ep_disable_wait_queue);
159662306a36Sopenharmony_ci
159762306a36Sopenharmony_ci	return 0;
159862306a36Sopenharmony_ci}
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_ci/* Must be called without lock */
160162306a36Sopenharmony_cistatic int lpc32xx_ep_enable(struct usb_ep *_ep,
160262306a36Sopenharmony_ci			     const struct usb_endpoint_descriptor *desc)
160362306a36Sopenharmony_ci{
160462306a36Sopenharmony_ci	struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep);
160562306a36Sopenharmony_ci	struct lpc32xx_udc *udc;
160662306a36Sopenharmony_ci	u16 maxpacket;
160762306a36Sopenharmony_ci	u32 tmp;
160862306a36Sopenharmony_ci	unsigned long flags;
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci	/* Verify EP data */
161162306a36Sopenharmony_ci	if ((!_ep) || (!ep) || (!desc) ||
161262306a36Sopenharmony_ci	    (desc->bDescriptorType != USB_DT_ENDPOINT))
161362306a36Sopenharmony_ci		return -EINVAL;
161462306a36Sopenharmony_ci
161562306a36Sopenharmony_ci	udc = ep->udc;
161662306a36Sopenharmony_ci	maxpacket = usb_endpoint_maxp(desc);
161762306a36Sopenharmony_ci	if ((maxpacket == 0) || (maxpacket > ep->maxpacket)) {
161862306a36Sopenharmony_ci		dev_dbg(udc->dev, "bad ep descriptor's packet size\n");
161962306a36Sopenharmony_ci		return -EINVAL;
162062306a36Sopenharmony_ci	}
162162306a36Sopenharmony_ci
162262306a36Sopenharmony_ci	/* Don't touch EP0 */
162362306a36Sopenharmony_ci	if (ep->hwep_num_base == 0) {
162462306a36Sopenharmony_ci		dev_dbg(udc->dev, "Can't re-enable EP0!!!\n");
162562306a36Sopenharmony_ci		return -EINVAL;
162662306a36Sopenharmony_ci	}
162762306a36Sopenharmony_ci
162862306a36Sopenharmony_ci	/* Is driver ready? */
162962306a36Sopenharmony_ci	if ((!udc->driver) || (udc->gadget.speed == USB_SPEED_UNKNOWN)) {
163062306a36Sopenharmony_ci		dev_dbg(udc->dev, "bogus device state\n");
163162306a36Sopenharmony_ci		return -ESHUTDOWN;
163262306a36Sopenharmony_ci	}
163362306a36Sopenharmony_ci
163462306a36Sopenharmony_ci	tmp = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
163562306a36Sopenharmony_ci	switch (tmp) {
163662306a36Sopenharmony_ci	case USB_ENDPOINT_XFER_CONTROL:
163762306a36Sopenharmony_ci		return -EINVAL;
163862306a36Sopenharmony_ci
163962306a36Sopenharmony_ci	case USB_ENDPOINT_XFER_INT:
164062306a36Sopenharmony_ci		if (maxpacket > ep->maxpacket) {
164162306a36Sopenharmony_ci			dev_dbg(udc->dev,
164262306a36Sopenharmony_ci				"Bad INT endpoint maxpacket %d\n", maxpacket);
164362306a36Sopenharmony_ci			return -EINVAL;
164462306a36Sopenharmony_ci		}
164562306a36Sopenharmony_ci		break;
164662306a36Sopenharmony_ci
164762306a36Sopenharmony_ci	case USB_ENDPOINT_XFER_BULK:
164862306a36Sopenharmony_ci		switch (maxpacket) {
164962306a36Sopenharmony_ci		case 8:
165062306a36Sopenharmony_ci		case 16:
165162306a36Sopenharmony_ci		case 32:
165262306a36Sopenharmony_ci		case 64:
165362306a36Sopenharmony_ci			break;
165462306a36Sopenharmony_ci
165562306a36Sopenharmony_ci		default:
165662306a36Sopenharmony_ci			dev_dbg(udc->dev,
165762306a36Sopenharmony_ci				"Bad BULK endpoint maxpacket %d\n", maxpacket);
165862306a36Sopenharmony_ci			return -EINVAL;
165962306a36Sopenharmony_ci		}
166062306a36Sopenharmony_ci		break;
166162306a36Sopenharmony_ci
166262306a36Sopenharmony_ci	case USB_ENDPOINT_XFER_ISOC:
166362306a36Sopenharmony_ci		break;
166462306a36Sopenharmony_ci	}
166562306a36Sopenharmony_ci	spin_lock_irqsave(&udc->lock, flags);
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_ci	/* Initialize endpoint to match the selected descriptor */
166862306a36Sopenharmony_ci	ep->is_in = (desc->bEndpointAddress & USB_DIR_IN) != 0;
166962306a36Sopenharmony_ci	ep->ep.maxpacket = maxpacket;
167062306a36Sopenharmony_ci
167162306a36Sopenharmony_ci	/* Map hardware endpoint from base and direction */
167262306a36Sopenharmony_ci	if (ep->is_in)
167362306a36Sopenharmony_ci		/* IN endpoints are offset 1 from the OUT endpoint */
167462306a36Sopenharmony_ci		ep->hwep_num = ep->hwep_num_base + EP_IN;
167562306a36Sopenharmony_ci	else
167662306a36Sopenharmony_ci		ep->hwep_num = ep->hwep_num_base;
167762306a36Sopenharmony_ci
167862306a36Sopenharmony_ci	ep_dbg(ep, "EP enabled: %s, HW:%d, MP:%d IN:%d\n", ep->ep.name,
167962306a36Sopenharmony_ci	       ep->hwep_num, maxpacket, (ep->is_in == 1));
168062306a36Sopenharmony_ci
168162306a36Sopenharmony_ci	/* Realize the endpoint, interrupt is enabled later when
168262306a36Sopenharmony_ci	 * buffers are queued, IN EPs will NAK until buffers are ready */
168362306a36Sopenharmony_ci	udc_realize_hwep(udc, ep->hwep_num, ep->ep.maxpacket);
168462306a36Sopenharmony_ci	udc_clr_buffer_hwep(udc, ep->hwep_num);
168562306a36Sopenharmony_ci	uda_disable_hwepint(udc, ep->hwep_num);
168662306a36Sopenharmony_ci	udc_clrstall_hwep(udc, ep->hwep_num);
168762306a36Sopenharmony_ci
168862306a36Sopenharmony_ci	/* Clear all DMA statuses for this EP */
168962306a36Sopenharmony_ci	udc_ep_dma_disable(udc, ep->hwep_num);
169062306a36Sopenharmony_ci	writel(1 << ep->hwep_num, USBD_EOTINTCLR(udc->udp_baseaddr));
169162306a36Sopenharmony_ci	writel(1 << ep->hwep_num, USBD_NDDRTINTCLR(udc->udp_baseaddr));
169262306a36Sopenharmony_ci	writel(1 << ep->hwep_num, USBD_SYSERRTINTCLR(udc->udp_baseaddr));
169362306a36Sopenharmony_ci	writel(1 << ep->hwep_num, USBD_DMARCLR(udc->udp_baseaddr));
169462306a36Sopenharmony_ci
169562306a36Sopenharmony_ci	spin_unlock_irqrestore(&udc->lock, flags);
169662306a36Sopenharmony_ci
169762306a36Sopenharmony_ci	atomic_inc(&udc->enabled_ep_cnt);
169862306a36Sopenharmony_ci	return 0;
169962306a36Sopenharmony_ci}
170062306a36Sopenharmony_ci
170162306a36Sopenharmony_ci/*
170262306a36Sopenharmony_ci * Allocate a USB request list
170362306a36Sopenharmony_ci * Can be called with or without lock
170462306a36Sopenharmony_ci */
170562306a36Sopenharmony_cistatic struct usb_request *lpc32xx_ep_alloc_request(struct usb_ep *_ep,
170662306a36Sopenharmony_ci						    gfp_t gfp_flags)
170762306a36Sopenharmony_ci{
170862306a36Sopenharmony_ci	struct lpc32xx_request *req;
170962306a36Sopenharmony_ci
171062306a36Sopenharmony_ci	req = kzalloc(sizeof(struct lpc32xx_request), gfp_flags);
171162306a36Sopenharmony_ci	if (!req)
171262306a36Sopenharmony_ci		return NULL;
171362306a36Sopenharmony_ci
171462306a36Sopenharmony_ci	INIT_LIST_HEAD(&req->queue);
171562306a36Sopenharmony_ci	return &req->req;
171662306a36Sopenharmony_ci}
171762306a36Sopenharmony_ci
171862306a36Sopenharmony_ci/*
171962306a36Sopenharmony_ci * De-allocate a USB request list
172062306a36Sopenharmony_ci * Can be called with or without lock
172162306a36Sopenharmony_ci */
172262306a36Sopenharmony_cistatic void lpc32xx_ep_free_request(struct usb_ep *_ep,
172362306a36Sopenharmony_ci				    struct usb_request *_req)
172462306a36Sopenharmony_ci{
172562306a36Sopenharmony_ci	struct lpc32xx_request *req;
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci	req = container_of(_req, struct lpc32xx_request, req);
172862306a36Sopenharmony_ci	BUG_ON(!list_empty(&req->queue));
172962306a36Sopenharmony_ci	kfree(req);
173062306a36Sopenharmony_ci}
173162306a36Sopenharmony_ci
173262306a36Sopenharmony_ci/* Must be called without lock */
173362306a36Sopenharmony_cistatic int lpc32xx_ep_queue(struct usb_ep *_ep,
173462306a36Sopenharmony_ci			    struct usb_request *_req, gfp_t gfp_flags)
173562306a36Sopenharmony_ci{
173662306a36Sopenharmony_ci	struct lpc32xx_request *req;
173762306a36Sopenharmony_ci	struct lpc32xx_ep *ep;
173862306a36Sopenharmony_ci	struct lpc32xx_udc *udc;
173962306a36Sopenharmony_ci	unsigned long flags;
174062306a36Sopenharmony_ci	int status = 0;
174162306a36Sopenharmony_ci
174262306a36Sopenharmony_ci	req = container_of(_req, struct lpc32xx_request, req);
174362306a36Sopenharmony_ci	ep = container_of(_ep, struct lpc32xx_ep, ep);
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_ci	if (!_ep || !_req || !_req->complete || !_req->buf ||
174662306a36Sopenharmony_ci	    !list_empty(&req->queue))
174762306a36Sopenharmony_ci		return -EINVAL;
174862306a36Sopenharmony_ci
174962306a36Sopenharmony_ci	udc = ep->udc;
175062306a36Sopenharmony_ci
175162306a36Sopenharmony_ci	if (udc->gadget.speed == USB_SPEED_UNKNOWN)
175262306a36Sopenharmony_ci		return -EPIPE;
175362306a36Sopenharmony_ci
175462306a36Sopenharmony_ci	if (ep->lep) {
175562306a36Sopenharmony_ci		struct lpc32xx_usbd_dd_gad *dd;
175662306a36Sopenharmony_ci
175762306a36Sopenharmony_ci		status = usb_gadget_map_request(&udc->gadget, _req, ep->is_in);
175862306a36Sopenharmony_ci		if (status)
175962306a36Sopenharmony_ci			return status;
176062306a36Sopenharmony_ci
176162306a36Sopenharmony_ci		/* For the request, build a list of DDs */
176262306a36Sopenharmony_ci		dd = udc_dd_alloc(udc);
176362306a36Sopenharmony_ci		if (!dd) {
176462306a36Sopenharmony_ci			/* Error allocating DD */
176562306a36Sopenharmony_ci			return -ENOMEM;
176662306a36Sopenharmony_ci		}
176762306a36Sopenharmony_ci		req->dd_desc_ptr = dd;
176862306a36Sopenharmony_ci
176962306a36Sopenharmony_ci		/* Setup the DMA descriptor */
177062306a36Sopenharmony_ci		dd->dd_next_phy = dd->dd_next_v = 0;
177162306a36Sopenharmony_ci		dd->dd_buffer_addr = req->req.dma;
177262306a36Sopenharmony_ci		dd->dd_status = 0;
177362306a36Sopenharmony_ci
177462306a36Sopenharmony_ci		/* Special handling for ISO EPs */
177562306a36Sopenharmony_ci		if (ep->eptype == EP_ISO_TYPE) {
177662306a36Sopenharmony_ci			dd->dd_setup = DD_SETUP_ISO_EP |
177762306a36Sopenharmony_ci				DD_SETUP_PACKETLEN(0) |
177862306a36Sopenharmony_ci				DD_SETUP_DMALENBYTES(1);
177962306a36Sopenharmony_ci			dd->dd_iso_ps_mem_addr = dd->this_dma + 24;
178062306a36Sopenharmony_ci			if (ep->is_in)
178162306a36Sopenharmony_ci				dd->iso_status[0] = req->req.length;
178262306a36Sopenharmony_ci			else
178362306a36Sopenharmony_ci				dd->iso_status[0] = 0;
178462306a36Sopenharmony_ci		} else
178562306a36Sopenharmony_ci			dd->dd_setup = DD_SETUP_PACKETLEN(ep->ep.maxpacket) |
178662306a36Sopenharmony_ci				DD_SETUP_DMALENBYTES(req->req.length);
178762306a36Sopenharmony_ci	}
178862306a36Sopenharmony_ci
178962306a36Sopenharmony_ci	ep_dbg(ep, "%s queue req %p len %d buf %p (in=%d) z=%d\n", _ep->name,
179062306a36Sopenharmony_ci	       _req, _req->length, _req->buf, ep->is_in, _req->zero);
179162306a36Sopenharmony_ci
179262306a36Sopenharmony_ci	spin_lock_irqsave(&udc->lock, flags);
179362306a36Sopenharmony_ci
179462306a36Sopenharmony_ci	_req->status = -EINPROGRESS;
179562306a36Sopenharmony_ci	_req->actual = 0;
179662306a36Sopenharmony_ci	req->send_zlp = _req->zero;
179762306a36Sopenharmony_ci
179862306a36Sopenharmony_ci	/* Kickstart empty queues */
179962306a36Sopenharmony_ci	if (list_empty(&ep->queue)) {
180062306a36Sopenharmony_ci		list_add_tail(&req->queue, &ep->queue);
180162306a36Sopenharmony_ci
180262306a36Sopenharmony_ci		if (ep->hwep_num_base == 0) {
180362306a36Sopenharmony_ci			/* Handle expected data direction */
180462306a36Sopenharmony_ci			if (ep->is_in) {
180562306a36Sopenharmony_ci				/* IN packet to host */
180662306a36Sopenharmony_ci				udc->ep0state = DATA_IN;
180762306a36Sopenharmony_ci				status = udc_ep0_in_req(udc);
180862306a36Sopenharmony_ci			} else {
180962306a36Sopenharmony_ci				/* OUT packet from host */
181062306a36Sopenharmony_ci				udc->ep0state = DATA_OUT;
181162306a36Sopenharmony_ci				status = udc_ep0_out_req(udc);
181262306a36Sopenharmony_ci			}
181362306a36Sopenharmony_ci		} else if (ep->is_in) {
181462306a36Sopenharmony_ci			/* IN packet to host and kick off transfer */
181562306a36Sopenharmony_ci			if (!ep->req_pending)
181662306a36Sopenharmony_ci				udc_ep_in_req_dma(udc, ep);
181762306a36Sopenharmony_ci		} else
181862306a36Sopenharmony_ci			/* OUT packet from host and kick off list */
181962306a36Sopenharmony_ci			if (!ep->req_pending)
182062306a36Sopenharmony_ci				udc_ep_out_req_dma(udc, ep);
182162306a36Sopenharmony_ci	} else
182262306a36Sopenharmony_ci		list_add_tail(&req->queue, &ep->queue);
182362306a36Sopenharmony_ci
182462306a36Sopenharmony_ci	spin_unlock_irqrestore(&udc->lock, flags);
182562306a36Sopenharmony_ci
182662306a36Sopenharmony_ci	return (status < 0) ? status : 0;
182762306a36Sopenharmony_ci}
182862306a36Sopenharmony_ci
182962306a36Sopenharmony_ci/* Must be called without lock */
183062306a36Sopenharmony_cistatic int lpc32xx_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
183162306a36Sopenharmony_ci{
183262306a36Sopenharmony_ci	struct lpc32xx_ep *ep;
183362306a36Sopenharmony_ci	struct lpc32xx_request *req = NULL, *iter;
183462306a36Sopenharmony_ci	unsigned long flags;
183562306a36Sopenharmony_ci
183662306a36Sopenharmony_ci	ep = container_of(_ep, struct lpc32xx_ep, ep);
183762306a36Sopenharmony_ci	if (!_ep || ep->hwep_num_base == 0)
183862306a36Sopenharmony_ci		return -EINVAL;
183962306a36Sopenharmony_ci
184062306a36Sopenharmony_ci	spin_lock_irqsave(&ep->udc->lock, flags);
184162306a36Sopenharmony_ci
184262306a36Sopenharmony_ci	/* make sure it's actually queued on this endpoint */
184362306a36Sopenharmony_ci	list_for_each_entry(iter, &ep->queue, queue) {
184462306a36Sopenharmony_ci		if (&iter->req != _req)
184562306a36Sopenharmony_ci			continue;
184662306a36Sopenharmony_ci		req = iter;
184762306a36Sopenharmony_ci		break;
184862306a36Sopenharmony_ci	}
184962306a36Sopenharmony_ci	if (!req) {
185062306a36Sopenharmony_ci		spin_unlock_irqrestore(&ep->udc->lock, flags);
185162306a36Sopenharmony_ci		return -EINVAL;
185262306a36Sopenharmony_ci	}
185362306a36Sopenharmony_ci
185462306a36Sopenharmony_ci	done(ep, req, -ECONNRESET);
185562306a36Sopenharmony_ci
185662306a36Sopenharmony_ci	spin_unlock_irqrestore(&ep->udc->lock, flags);
185762306a36Sopenharmony_ci
185862306a36Sopenharmony_ci	return 0;
185962306a36Sopenharmony_ci}
186062306a36Sopenharmony_ci
186162306a36Sopenharmony_ci/* Must be called without lock */
186262306a36Sopenharmony_cistatic int lpc32xx_ep_set_halt(struct usb_ep *_ep, int value)
186362306a36Sopenharmony_ci{
186462306a36Sopenharmony_ci	struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep);
186562306a36Sopenharmony_ci	struct lpc32xx_udc *udc;
186662306a36Sopenharmony_ci	unsigned long flags;
186762306a36Sopenharmony_ci
186862306a36Sopenharmony_ci	if ((!ep) || (ep->hwep_num <= 1))
186962306a36Sopenharmony_ci		return -EINVAL;
187062306a36Sopenharmony_ci
187162306a36Sopenharmony_ci	/* Don't halt an IN EP */
187262306a36Sopenharmony_ci	if (ep->is_in)
187362306a36Sopenharmony_ci		return -EAGAIN;
187462306a36Sopenharmony_ci
187562306a36Sopenharmony_ci	udc = ep->udc;
187662306a36Sopenharmony_ci	spin_lock_irqsave(&udc->lock, flags);
187762306a36Sopenharmony_ci
187862306a36Sopenharmony_ci	if (value == 1) {
187962306a36Sopenharmony_ci		/* stall */
188062306a36Sopenharmony_ci		udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(ep->hwep_num),
188162306a36Sopenharmony_ci					DAT_WR_BYTE(EP_STAT_ST));
188262306a36Sopenharmony_ci	} else {
188362306a36Sopenharmony_ci		/* End stall */
188462306a36Sopenharmony_ci		ep->wedge = 0;
188562306a36Sopenharmony_ci		udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(ep->hwep_num),
188662306a36Sopenharmony_ci					DAT_WR_BYTE(0));
188762306a36Sopenharmony_ci	}
188862306a36Sopenharmony_ci
188962306a36Sopenharmony_ci	spin_unlock_irqrestore(&udc->lock, flags);
189062306a36Sopenharmony_ci
189162306a36Sopenharmony_ci	return 0;
189262306a36Sopenharmony_ci}
189362306a36Sopenharmony_ci
189462306a36Sopenharmony_ci/* set the halt feature and ignores clear requests */
189562306a36Sopenharmony_cistatic int lpc32xx_ep_set_wedge(struct usb_ep *_ep)
189662306a36Sopenharmony_ci{
189762306a36Sopenharmony_ci	struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep);
189862306a36Sopenharmony_ci
189962306a36Sopenharmony_ci	if (!_ep || !ep->udc)
190062306a36Sopenharmony_ci		return -EINVAL;
190162306a36Sopenharmony_ci
190262306a36Sopenharmony_ci	ep->wedge = 1;
190362306a36Sopenharmony_ci
190462306a36Sopenharmony_ci	return usb_ep_set_halt(_ep);
190562306a36Sopenharmony_ci}
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_cistatic const struct usb_ep_ops lpc32xx_ep_ops = {
190862306a36Sopenharmony_ci	.enable		= lpc32xx_ep_enable,
190962306a36Sopenharmony_ci	.disable	= lpc32xx_ep_disable,
191062306a36Sopenharmony_ci	.alloc_request	= lpc32xx_ep_alloc_request,
191162306a36Sopenharmony_ci	.free_request	= lpc32xx_ep_free_request,
191262306a36Sopenharmony_ci	.queue		= lpc32xx_ep_queue,
191362306a36Sopenharmony_ci	.dequeue	= lpc32xx_ep_dequeue,
191462306a36Sopenharmony_ci	.set_halt	= lpc32xx_ep_set_halt,
191562306a36Sopenharmony_ci	.set_wedge	= lpc32xx_ep_set_wedge,
191662306a36Sopenharmony_ci};
191762306a36Sopenharmony_ci
191862306a36Sopenharmony_ci/* Send a ZLP on a non-0 IN EP */
191962306a36Sopenharmony_cistatic void udc_send_in_zlp(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
192062306a36Sopenharmony_ci{
192162306a36Sopenharmony_ci	/* Clear EP status */
192262306a36Sopenharmony_ci	udc_clearep_getsts(udc, ep->hwep_num);
192362306a36Sopenharmony_ci
192462306a36Sopenharmony_ci	/* Send ZLP via FIFO mechanism */
192562306a36Sopenharmony_ci	udc_write_hwep(udc, ep->hwep_num, NULL, 0);
192662306a36Sopenharmony_ci}
192762306a36Sopenharmony_ci
192862306a36Sopenharmony_ci/*
192962306a36Sopenharmony_ci * Handle EP completion for ZLP
193062306a36Sopenharmony_ci * This function will only be called when a delayed ZLP needs to be sent out
193162306a36Sopenharmony_ci * after a DMA transfer has filled both buffers.
193262306a36Sopenharmony_ci */
193362306a36Sopenharmony_cistatic void udc_handle_eps(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
193462306a36Sopenharmony_ci{
193562306a36Sopenharmony_ci	u32 epstatus;
193662306a36Sopenharmony_ci	struct lpc32xx_request *req;
193762306a36Sopenharmony_ci
193862306a36Sopenharmony_ci	if (ep->hwep_num <= 0)
193962306a36Sopenharmony_ci		return;
194062306a36Sopenharmony_ci
194162306a36Sopenharmony_ci	uda_clear_hwepint(udc, ep->hwep_num);
194262306a36Sopenharmony_ci
194362306a36Sopenharmony_ci	/* If this interrupt isn't enabled, return now */
194462306a36Sopenharmony_ci	if (!(udc->enabled_hwepints & (1 << ep->hwep_num)))
194562306a36Sopenharmony_ci		return;
194662306a36Sopenharmony_ci
194762306a36Sopenharmony_ci	/* Get endpoint status */
194862306a36Sopenharmony_ci	epstatus = udc_clearep_getsts(udc, ep->hwep_num);
194962306a36Sopenharmony_ci
195062306a36Sopenharmony_ci	/*
195162306a36Sopenharmony_ci	 * This should never happen, but protect against writing to the
195262306a36Sopenharmony_ci	 * buffer when full.
195362306a36Sopenharmony_ci	 */
195462306a36Sopenharmony_ci	if (epstatus & EP_SEL_F)
195562306a36Sopenharmony_ci		return;
195662306a36Sopenharmony_ci
195762306a36Sopenharmony_ci	if (ep->is_in) {
195862306a36Sopenharmony_ci		udc_send_in_zlp(udc, ep);
195962306a36Sopenharmony_ci		uda_disable_hwepint(udc, ep->hwep_num);
196062306a36Sopenharmony_ci	} else
196162306a36Sopenharmony_ci		return;
196262306a36Sopenharmony_ci
196362306a36Sopenharmony_ci	/* If there isn't a request waiting, something went wrong */
196462306a36Sopenharmony_ci	req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
196562306a36Sopenharmony_ci	if (req) {
196662306a36Sopenharmony_ci		done(ep, req, 0);
196762306a36Sopenharmony_ci
196862306a36Sopenharmony_ci		/* Start another request if ready */
196962306a36Sopenharmony_ci		if (!list_empty(&ep->queue)) {
197062306a36Sopenharmony_ci			if (ep->is_in)
197162306a36Sopenharmony_ci				udc_ep_in_req_dma(udc, ep);
197262306a36Sopenharmony_ci			else
197362306a36Sopenharmony_ci				udc_ep_out_req_dma(udc, ep);
197462306a36Sopenharmony_ci		} else
197562306a36Sopenharmony_ci			ep->req_pending = 0;
197662306a36Sopenharmony_ci	}
197762306a36Sopenharmony_ci}
197862306a36Sopenharmony_ci
197962306a36Sopenharmony_ci
198062306a36Sopenharmony_ci/* DMA end of transfer completion */
198162306a36Sopenharmony_cistatic void udc_handle_dma_ep(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
198262306a36Sopenharmony_ci{
198362306a36Sopenharmony_ci	u32 status;
198462306a36Sopenharmony_ci	struct lpc32xx_request *req;
198562306a36Sopenharmony_ci	struct lpc32xx_usbd_dd_gad *dd;
198662306a36Sopenharmony_ci
198762306a36Sopenharmony_ci#ifdef CONFIG_USB_GADGET_DEBUG_FILES
198862306a36Sopenharmony_ci	ep->totalints++;
198962306a36Sopenharmony_ci#endif
199062306a36Sopenharmony_ci
199162306a36Sopenharmony_ci	req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
199262306a36Sopenharmony_ci	if (!req) {
199362306a36Sopenharmony_ci		ep_err(ep, "DMA interrupt on no req!\n");
199462306a36Sopenharmony_ci		return;
199562306a36Sopenharmony_ci	}
199662306a36Sopenharmony_ci	dd = req->dd_desc_ptr;
199762306a36Sopenharmony_ci
199862306a36Sopenharmony_ci	/* DMA descriptor should always be retired for this call */
199962306a36Sopenharmony_ci	if (!(dd->dd_status & DD_STATUS_DD_RETIRED))
200062306a36Sopenharmony_ci		ep_warn(ep, "DMA descriptor did not retire\n");
200162306a36Sopenharmony_ci
200262306a36Sopenharmony_ci	/* Disable DMA */
200362306a36Sopenharmony_ci	udc_ep_dma_disable(udc, ep->hwep_num);
200462306a36Sopenharmony_ci	writel((1 << ep->hwep_num), USBD_EOTINTCLR(udc->udp_baseaddr));
200562306a36Sopenharmony_ci	writel((1 << ep->hwep_num), USBD_NDDRTINTCLR(udc->udp_baseaddr));
200662306a36Sopenharmony_ci
200762306a36Sopenharmony_ci	/* System error? */
200862306a36Sopenharmony_ci	if (readl(USBD_SYSERRTINTST(udc->udp_baseaddr)) &
200962306a36Sopenharmony_ci	    (1 << ep->hwep_num)) {
201062306a36Sopenharmony_ci		writel((1 << ep->hwep_num),
201162306a36Sopenharmony_ci			     USBD_SYSERRTINTCLR(udc->udp_baseaddr));
201262306a36Sopenharmony_ci		ep_err(ep, "AHB critical error!\n");
201362306a36Sopenharmony_ci		ep->req_pending = 0;
201462306a36Sopenharmony_ci
201562306a36Sopenharmony_ci		/* The error could have occurred on a packet of a multipacket
201662306a36Sopenharmony_ci		 * transfer, so recovering the transfer is not possible. Close
201762306a36Sopenharmony_ci		 * the request with an error */
201862306a36Sopenharmony_ci		done(ep, req, -ECONNABORTED);
201962306a36Sopenharmony_ci		return;
202062306a36Sopenharmony_ci	}
202162306a36Sopenharmony_ci
202262306a36Sopenharmony_ci	/* Handle the current DD's status */
202362306a36Sopenharmony_ci	status = dd->dd_status;
202462306a36Sopenharmony_ci	switch (status & DD_STATUS_STS_MASK) {
202562306a36Sopenharmony_ci	case DD_STATUS_STS_NS:
202662306a36Sopenharmony_ci		/* DD not serviced? This shouldn't happen! */
202762306a36Sopenharmony_ci		ep->req_pending = 0;
202862306a36Sopenharmony_ci		ep_err(ep, "DMA critical EP error: DD not serviced (0x%x)!\n",
202962306a36Sopenharmony_ci		       status);
203062306a36Sopenharmony_ci
203162306a36Sopenharmony_ci		done(ep, req, -ECONNABORTED);
203262306a36Sopenharmony_ci		return;
203362306a36Sopenharmony_ci
203462306a36Sopenharmony_ci	case DD_STATUS_STS_BS:
203562306a36Sopenharmony_ci		/* Interrupt only fires on EOT - This shouldn't happen! */
203662306a36Sopenharmony_ci		ep->req_pending = 0;
203762306a36Sopenharmony_ci		ep_err(ep, "DMA critical EP error: EOT prior to service completion (0x%x)!\n",
203862306a36Sopenharmony_ci		       status);
203962306a36Sopenharmony_ci		done(ep, req, -ECONNABORTED);
204062306a36Sopenharmony_ci		return;
204162306a36Sopenharmony_ci
204262306a36Sopenharmony_ci	case DD_STATUS_STS_NC:
204362306a36Sopenharmony_ci	case DD_STATUS_STS_DUR:
204462306a36Sopenharmony_ci		/* Really just a short packet, not an underrun */
204562306a36Sopenharmony_ci		/* This is a good status and what we expect */
204662306a36Sopenharmony_ci		break;
204762306a36Sopenharmony_ci
204862306a36Sopenharmony_ci	default:
204962306a36Sopenharmony_ci		/* Data overrun, system error, or unknown */
205062306a36Sopenharmony_ci		ep->req_pending = 0;
205162306a36Sopenharmony_ci		ep_err(ep, "DMA critical EP error: System error (0x%x)!\n",
205262306a36Sopenharmony_ci		       status);
205362306a36Sopenharmony_ci		done(ep, req, -ECONNABORTED);
205462306a36Sopenharmony_ci		return;
205562306a36Sopenharmony_ci	}
205662306a36Sopenharmony_ci
205762306a36Sopenharmony_ci	/* ISO endpoints are handled differently */
205862306a36Sopenharmony_ci	if (ep->eptype == EP_ISO_TYPE) {
205962306a36Sopenharmony_ci		if (ep->is_in)
206062306a36Sopenharmony_ci			req->req.actual = req->req.length;
206162306a36Sopenharmony_ci		else
206262306a36Sopenharmony_ci			req->req.actual = dd->iso_status[0] & 0xFFFF;
206362306a36Sopenharmony_ci	} else
206462306a36Sopenharmony_ci		req->req.actual += DD_STATUS_CURDMACNT(status);
206562306a36Sopenharmony_ci
206662306a36Sopenharmony_ci	/* Send a ZLP if necessary. This will be done for non-int
206762306a36Sopenharmony_ci	 * packets which have a size that is a divisor of MAXP */
206862306a36Sopenharmony_ci	if (req->send_zlp) {
206962306a36Sopenharmony_ci		/*
207062306a36Sopenharmony_ci		 * If at least 1 buffer is available, send the ZLP now.
207162306a36Sopenharmony_ci		 * Otherwise, the ZLP send needs to be deferred until a
207262306a36Sopenharmony_ci		 * buffer is available.
207362306a36Sopenharmony_ci		 */
207462306a36Sopenharmony_ci		if (udc_clearep_getsts(udc, ep->hwep_num) & EP_SEL_F) {
207562306a36Sopenharmony_ci			udc_clearep_getsts(udc, ep->hwep_num);
207662306a36Sopenharmony_ci			uda_enable_hwepint(udc, ep->hwep_num);
207762306a36Sopenharmony_ci			udc_clearep_getsts(udc, ep->hwep_num);
207862306a36Sopenharmony_ci
207962306a36Sopenharmony_ci			/* Let the EP interrupt handle the ZLP */
208062306a36Sopenharmony_ci			return;
208162306a36Sopenharmony_ci		} else
208262306a36Sopenharmony_ci			udc_send_in_zlp(udc, ep);
208362306a36Sopenharmony_ci	}
208462306a36Sopenharmony_ci
208562306a36Sopenharmony_ci	/* Transfer request is complete */
208662306a36Sopenharmony_ci	done(ep, req, 0);
208762306a36Sopenharmony_ci
208862306a36Sopenharmony_ci	/* Start another request if ready */
208962306a36Sopenharmony_ci	udc_clearep_getsts(udc, ep->hwep_num);
209062306a36Sopenharmony_ci	if (!list_empty((&ep->queue))) {
209162306a36Sopenharmony_ci		if (ep->is_in)
209262306a36Sopenharmony_ci			udc_ep_in_req_dma(udc, ep);
209362306a36Sopenharmony_ci		else
209462306a36Sopenharmony_ci			udc_ep_out_req_dma(udc, ep);
209562306a36Sopenharmony_ci	} else
209662306a36Sopenharmony_ci		ep->req_pending = 0;
209762306a36Sopenharmony_ci
209862306a36Sopenharmony_ci}
209962306a36Sopenharmony_ci
210062306a36Sopenharmony_ci/*
210162306a36Sopenharmony_ci *
210262306a36Sopenharmony_ci * Endpoint 0 functions
210362306a36Sopenharmony_ci *
210462306a36Sopenharmony_ci */
210562306a36Sopenharmony_cistatic void udc_handle_dev(struct lpc32xx_udc *udc)
210662306a36Sopenharmony_ci{
210762306a36Sopenharmony_ci	u32 tmp;
210862306a36Sopenharmony_ci
210962306a36Sopenharmony_ci	udc_protocol_cmd_w(udc, CMD_GET_DEV_STAT);
211062306a36Sopenharmony_ci	tmp = udc_protocol_cmd_r(udc, DAT_GET_DEV_STAT);
211162306a36Sopenharmony_ci
211262306a36Sopenharmony_ci	if (tmp & DEV_RST)
211362306a36Sopenharmony_ci		uda_usb_reset(udc);
211462306a36Sopenharmony_ci	else if (tmp & DEV_CON_CH)
211562306a36Sopenharmony_ci		uda_power_event(udc, (tmp & DEV_CON));
211662306a36Sopenharmony_ci	else if (tmp & DEV_SUS_CH) {
211762306a36Sopenharmony_ci		if (tmp & DEV_SUS) {
211862306a36Sopenharmony_ci			if (udc->vbus == 0)
211962306a36Sopenharmony_ci				stop_activity(udc);
212062306a36Sopenharmony_ci			else if ((udc->gadget.speed != USB_SPEED_UNKNOWN) &&
212162306a36Sopenharmony_ci				 udc->driver) {
212262306a36Sopenharmony_ci				/* Power down transceiver */
212362306a36Sopenharmony_ci				udc->poweron = 0;
212462306a36Sopenharmony_ci				schedule_work(&udc->pullup_job);
212562306a36Sopenharmony_ci				uda_resm_susp_event(udc, 1);
212662306a36Sopenharmony_ci			}
212762306a36Sopenharmony_ci		} else if ((udc->gadget.speed != USB_SPEED_UNKNOWN) &&
212862306a36Sopenharmony_ci			   udc->driver && udc->vbus) {
212962306a36Sopenharmony_ci			uda_resm_susp_event(udc, 0);
213062306a36Sopenharmony_ci			/* Power up transceiver */
213162306a36Sopenharmony_ci			udc->poweron = 1;
213262306a36Sopenharmony_ci			schedule_work(&udc->pullup_job);
213362306a36Sopenharmony_ci		}
213462306a36Sopenharmony_ci	}
213562306a36Sopenharmony_ci}
213662306a36Sopenharmony_ci
213762306a36Sopenharmony_cistatic int udc_get_status(struct lpc32xx_udc *udc, u16 reqtype, u16 wIndex)
213862306a36Sopenharmony_ci{
213962306a36Sopenharmony_ci	struct lpc32xx_ep *ep;
214062306a36Sopenharmony_ci	u32 ep0buff = 0, tmp;
214162306a36Sopenharmony_ci
214262306a36Sopenharmony_ci	switch (reqtype & USB_RECIP_MASK) {
214362306a36Sopenharmony_ci	case USB_RECIP_INTERFACE:
214462306a36Sopenharmony_ci		break; /* Not supported */
214562306a36Sopenharmony_ci
214662306a36Sopenharmony_ci	case USB_RECIP_DEVICE:
214762306a36Sopenharmony_ci		ep0buff = udc->gadget.is_selfpowered;
214862306a36Sopenharmony_ci		if (udc->dev_status & (1 << USB_DEVICE_REMOTE_WAKEUP))
214962306a36Sopenharmony_ci			ep0buff |= (1 << USB_DEVICE_REMOTE_WAKEUP);
215062306a36Sopenharmony_ci		break;
215162306a36Sopenharmony_ci
215262306a36Sopenharmony_ci	case USB_RECIP_ENDPOINT:
215362306a36Sopenharmony_ci		tmp = wIndex & USB_ENDPOINT_NUMBER_MASK;
215462306a36Sopenharmony_ci		ep = &udc->ep[tmp];
215562306a36Sopenharmony_ci		if ((tmp == 0) || (tmp >= NUM_ENDPOINTS))
215662306a36Sopenharmony_ci			return -EOPNOTSUPP;
215762306a36Sopenharmony_ci
215862306a36Sopenharmony_ci		if (wIndex & USB_DIR_IN) {
215962306a36Sopenharmony_ci			if (!ep->is_in)
216062306a36Sopenharmony_ci				return -EOPNOTSUPP; /* Something's wrong */
216162306a36Sopenharmony_ci		} else if (ep->is_in)
216262306a36Sopenharmony_ci			return -EOPNOTSUPP; /* Not an IN endpoint */
216362306a36Sopenharmony_ci
216462306a36Sopenharmony_ci		/* Get status of the endpoint */
216562306a36Sopenharmony_ci		udc_protocol_cmd_w(udc, CMD_SEL_EP(ep->hwep_num));
216662306a36Sopenharmony_ci		tmp = udc_protocol_cmd_r(udc, DAT_SEL_EP(ep->hwep_num));
216762306a36Sopenharmony_ci
216862306a36Sopenharmony_ci		if (tmp & EP_SEL_ST)
216962306a36Sopenharmony_ci			ep0buff = (1 << USB_ENDPOINT_HALT);
217062306a36Sopenharmony_ci		else
217162306a36Sopenharmony_ci			ep0buff = 0;
217262306a36Sopenharmony_ci		break;
217362306a36Sopenharmony_ci
217462306a36Sopenharmony_ci	default:
217562306a36Sopenharmony_ci		break;
217662306a36Sopenharmony_ci	}
217762306a36Sopenharmony_ci
217862306a36Sopenharmony_ci	/* Return data */
217962306a36Sopenharmony_ci	udc_write_hwep(udc, EP_IN, &ep0buff, 2);
218062306a36Sopenharmony_ci
218162306a36Sopenharmony_ci	return 0;
218262306a36Sopenharmony_ci}
218362306a36Sopenharmony_ci
218462306a36Sopenharmony_cistatic void udc_handle_ep0_setup(struct lpc32xx_udc *udc)
218562306a36Sopenharmony_ci{
218662306a36Sopenharmony_ci	struct lpc32xx_ep *ep, *ep0 = &udc->ep[0];
218762306a36Sopenharmony_ci	struct usb_ctrlrequest ctrlpkt;
218862306a36Sopenharmony_ci	int i, bytes;
218962306a36Sopenharmony_ci	u16 wIndex, wValue, reqtype, req, tmp;
219062306a36Sopenharmony_ci
219162306a36Sopenharmony_ci	/* Nuke previous transfers */
219262306a36Sopenharmony_ci	nuke(ep0, -EPROTO);
219362306a36Sopenharmony_ci
219462306a36Sopenharmony_ci	/* Get setup packet */
219562306a36Sopenharmony_ci	bytes = udc_read_hwep(udc, EP_OUT, (u32 *) &ctrlpkt, 8);
219662306a36Sopenharmony_ci	if (bytes != 8) {
219762306a36Sopenharmony_ci		ep_warn(ep0, "Incorrectly sized setup packet (s/b 8, is %d)!\n",
219862306a36Sopenharmony_ci			bytes);
219962306a36Sopenharmony_ci		return;
220062306a36Sopenharmony_ci	}
220162306a36Sopenharmony_ci
220262306a36Sopenharmony_ci	/* Native endianness */
220362306a36Sopenharmony_ci	wIndex = le16_to_cpu(ctrlpkt.wIndex);
220462306a36Sopenharmony_ci	wValue = le16_to_cpu(ctrlpkt.wValue);
220562306a36Sopenharmony_ci	reqtype = le16_to_cpu(ctrlpkt.bRequestType);
220662306a36Sopenharmony_ci
220762306a36Sopenharmony_ci	/* Set direction of EP0 */
220862306a36Sopenharmony_ci	if (likely(reqtype & USB_DIR_IN))
220962306a36Sopenharmony_ci		ep0->is_in = 1;
221062306a36Sopenharmony_ci	else
221162306a36Sopenharmony_ci		ep0->is_in = 0;
221262306a36Sopenharmony_ci
221362306a36Sopenharmony_ci	/* Handle SETUP packet */
221462306a36Sopenharmony_ci	req = le16_to_cpu(ctrlpkt.bRequest);
221562306a36Sopenharmony_ci	switch (req) {
221662306a36Sopenharmony_ci	case USB_REQ_CLEAR_FEATURE:
221762306a36Sopenharmony_ci	case USB_REQ_SET_FEATURE:
221862306a36Sopenharmony_ci		switch (reqtype) {
221962306a36Sopenharmony_ci		case (USB_TYPE_STANDARD | USB_RECIP_DEVICE):
222062306a36Sopenharmony_ci			if (wValue != USB_DEVICE_REMOTE_WAKEUP)
222162306a36Sopenharmony_ci				goto stall; /* Nothing else handled */
222262306a36Sopenharmony_ci
222362306a36Sopenharmony_ci			/* Tell board about event */
222462306a36Sopenharmony_ci			if (req == USB_REQ_CLEAR_FEATURE)
222562306a36Sopenharmony_ci				udc->dev_status &=
222662306a36Sopenharmony_ci					~(1 << USB_DEVICE_REMOTE_WAKEUP);
222762306a36Sopenharmony_ci			else
222862306a36Sopenharmony_ci				udc->dev_status |=
222962306a36Sopenharmony_ci					(1 << USB_DEVICE_REMOTE_WAKEUP);
223062306a36Sopenharmony_ci			uda_remwkp_cgh(udc);
223162306a36Sopenharmony_ci			goto zlp_send;
223262306a36Sopenharmony_ci
223362306a36Sopenharmony_ci		case (USB_TYPE_STANDARD | USB_RECIP_ENDPOINT):
223462306a36Sopenharmony_ci			tmp = wIndex & USB_ENDPOINT_NUMBER_MASK;
223562306a36Sopenharmony_ci			if ((wValue != USB_ENDPOINT_HALT) ||
223662306a36Sopenharmony_ci			    (tmp >= NUM_ENDPOINTS))
223762306a36Sopenharmony_ci				break;
223862306a36Sopenharmony_ci
223962306a36Sopenharmony_ci			/* Find hardware endpoint from logical endpoint */
224062306a36Sopenharmony_ci			ep = &udc->ep[tmp];
224162306a36Sopenharmony_ci			tmp = ep->hwep_num;
224262306a36Sopenharmony_ci			if (tmp == 0)
224362306a36Sopenharmony_ci				break;
224462306a36Sopenharmony_ci
224562306a36Sopenharmony_ci			if (req == USB_REQ_SET_FEATURE)
224662306a36Sopenharmony_ci				udc_stall_hwep(udc, tmp);
224762306a36Sopenharmony_ci			else if (!ep->wedge)
224862306a36Sopenharmony_ci				udc_clrstall_hwep(udc, tmp);
224962306a36Sopenharmony_ci
225062306a36Sopenharmony_ci			goto zlp_send;
225162306a36Sopenharmony_ci
225262306a36Sopenharmony_ci		default:
225362306a36Sopenharmony_ci			break;
225462306a36Sopenharmony_ci		}
225562306a36Sopenharmony_ci		break;
225662306a36Sopenharmony_ci
225762306a36Sopenharmony_ci	case USB_REQ_SET_ADDRESS:
225862306a36Sopenharmony_ci		if (reqtype == (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) {
225962306a36Sopenharmony_ci			udc_set_address(udc, wValue);
226062306a36Sopenharmony_ci			goto zlp_send;
226162306a36Sopenharmony_ci		}
226262306a36Sopenharmony_ci		break;
226362306a36Sopenharmony_ci
226462306a36Sopenharmony_ci	case USB_REQ_GET_STATUS:
226562306a36Sopenharmony_ci		udc_get_status(udc, reqtype, wIndex);
226662306a36Sopenharmony_ci		return;
226762306a36Sopenharmony_ci
226862306a36Sopenharmony_ci	default:
226962306a36Sopenharmony_ci		break; /* Let GadgetFS handle the descriptor instead */
227062306a36Sopenharmony_ci	}
227162306a36Sopenharmony_ci
227262306a36Sopenharmony_ci	if (likely(udc->driver)) {
227362306a36Sopenharmony_ci		/* device-2-host (IN) or no data setup command, process
227462306a36Sopenharmony_ci		 * immediately */
227562306a36Sopenharmony_ci		spin_unlock(&udc->lock);
227662306a36Sopenharmony_ci		i = udc->driver->setup(&udc->gadget, &ctrlpkt);
227762306a36Sopenharmony_ci
227862306a36Sopenharmony_ci		spin_lock(&udc->lock);
227962306a36Sopenharmony_ci		if (req == USB_REQ_SET_CONFIGURATION) {
228062306a36Sopenharmony_ci			/* Configuration is set after endpoints are realized */
228162306a36Sopenharmony_ci			if (wValue) {
228262306a36Sopenharmony_ci				/* Set configuration */
228362306a36Sopenharmony_ci				udc_set_device_configured(udc);
228462306a36Sopenharmony_ci
228562306a36Sopenharmony_ci				udc_protocol_cmd_data_w(udc, CMD_SET_MODE,
228662306a36Sopenharmony_ci							DAT_WR_BYTE(AP_CLK |
228762306a36Sopenharmony_ci							INAK_BI | INAK_II));
228862306a36Sopenharmony_ci			} else {
228962306a36Sopenharmony_ci				/* Clear configuration */
229062306a36Sopenharmony_ci				udc_set_device_unconfigured(udc);
229162306a36Sopenharmony_ci
229262306a36Sopenharmony_ci				/* Disable NAK interrupts */
229362306a36Sopenharmony_ci				udc_protocol_cmd_data_w(udc, CMD_SET_MODE,
229462306a36Sopenharmony_ci							DAT_WR_BYTE(AP_CLK));
229562306a36Sopenharmony_ci			}
229662306a36Sopenharmony_ci		}
229762306a36Sopenharmony_ci
229862306a36Sopenharmony_ci		if (i < 0) {
229962306a36Sopenharmony_ci			/* setup processing failed, force stall */
230062306a36Sopenharmony_ci			dev_dbg(udc->dev,
230162306a36Sopenharmony_ci				"req %02x.%02x protocol STALL; stat %d\n",
230262306a36Sopenharmony_ci				reqtype, req, i);
230362306a36Sopenharmony_ci			udc->ep0state = WAIT_FOR_SETUP;
230462306a36Sopenharmony_ci			goto stall;
230562306a36Sopenharmony_ci		}
230662306a36Sopenharmony_ci	}
230762306a36Sopenharmony_ci
230862306a36Sopenharmony_ci	if (!ep0->is_in)
230962306a36Sopenharmony_ci		udc_ep0_send_zlp(udc); /* ZLP IN packet on data phase */
231062306a36Sopenharmony_ci
231162306a36Sopenharmony_ci	return;
231262306a36Sopenharmony_ci
231362306a36Sopenharmony_cistall:
231462306a36Sopenharmony_ci	udc_stall_hwep(udc, EP_IN);
231562306a36Sopenharmony_ci	return;
231662306a36Sopenharmony_ci
231762306a36Sopenharmony_cizlp_send:
231862306a36Sopenharmony_ci	udc_ep0_send_zlp(udc);
231962306a36Sopenharmony_ci	return;
232062306a36Sopenharmony_ci}
232162306a36Sopenharmony_ci
232262306a36Sopenharmony_ci/* IN endpoint 0 transfer */
232362306a36Sopenharmony_cistatic void udc_handle_ep0_in(struct lpc32xx_udc *udc)
232462306a36Sopenharmony_ci{
232562306a36Sopenharmony_ci	struct lpc32xx_ep *ep0 = &udc->ep[0];
232662306a36Sopenharmony_ci	u32 epstatus;
232762306a36Sopenharmony_ci
232862306a36Sopenharmony_ci	/* Clear EP interrupt */
232962306a36Sopenharmony_ci	epstatus = udc_clearep_getsts(udc, EP_IN);
233062306a36Sopenharmony_ci
233162306a36Sopenharmony_ci#ifdef CONFIG_USB_GADGET_DEBUG_FILES
233262306a36Sopenharmony_ci	ep0->totalints++;
233362306a36Sopenharmony_ci#endif
233462306a36Sopenharmony_ci
233562306a36Sopenharmony_ci	/* Stalled? Clear stall and reset buffers */
233662306a36Sopenharmony_ci	if (epstatus & EP_SEL_ST) {
233762306a36Sopenharmony_ci		udc_clrstall_hwep(udc, EP_IN);
233862306a36Sopenharmony_ci		nuke(ep0, -ECONNABORTED);
233962306a36Sopenharmony_ci		udc->ep0state = WAIT_FOR_SETUP;
234062306a36Sopenharmony_ci		return;
234162306a36Sopenharmony_ci	}
234262306a36Sopenharmony_ci
234362306a36Sopenharmony_ci	/* Is a buffer available? */
234462306a36Sopenharmony_ci	if (!(epstatus & EP_SEL_F)) {
234562306a36Sopenharmony_ci		/* Handle based on current state */
234662306a36Sopenharmony_ci		if (udc->ep0state == DATA_IN)
234762306a36Sopenharmony_ci			udc_ep0_in_req(udc);
234862306a36Sopenharmony_ci		else {
234962306a36Sopenharmony_ci			/* Unknown state for EP0 oe end of DATA IN phase */
235062306a36Sopenharmony_ci			nuke(ep0, -ECONNABORTED);
235162306a36Sopenharmony_ci			udc->ep0state = WAIT_FOR_SETUP;
235262306a36Sopenharmony_ci		}
235362306a36Sopenharmony_ci	}
235462306a36Sopenharmony_ci}
235562306a36Sopenharmony_ci
235662306a36Sopenharmony_ci/* OUT endpoint 0 transfer */
235762306a36Sopenharmony_cistatic void udc_handle_ep0_out(struct lpc32xx_udc *udc)
235862306a36Sopenharmony_ci{
235962306a36Sopenharmony_ci	struct lpc32xx_ep *ep0 = &udc->ep[0];
236062306a36Sopenharmony_ci	u32 epstatus;
236162306a36Sopenharmony_ci
236262306a36Sopenharmony_ci	/* Clear EP interrupt */
236362306a36Sopenharmony_ci	epstatus = udc_clearep_getsts(udc, EP_OUT);
236462306a36Sopenharmony_ci
236562306a36Sopenharmony_ci
236662306a36Sopenharmony_ci#ifdef CONFIG_USB_GADGET_DEBUG_FILES
236762306a36Sopenharmony_ci	ep0->totalints++;
236862306a36Sopenharmony_ci#endif
236962306a36Sopenharmony_ci
237062306a36Sopenharmony_ci	/* Stalled? */
237162306a36Sopenharmony_ci	if (epstatus & EP_SEL_ST) {
237262306a36Sopenharmony_ci		udc_clrstall_hwep(udc, EP_OUT);
237362306a36Sopenharmony_ci		nuke(ep0, -ECONNABORTED);
237462306a36Sopenharmony_ci		udc->ep0state = WAIT_FOR_SETUP;
237562306a36Sopenharmony_ci		return;
237662306a36Sopenharmony_ci	}
237762306a36Sopenharmony_ci
237862306a36Sopenharmony_ci	/* A NAK may occur if a packet couldn't be received yet */
237962306a36Sopenharmony_ci	if (epstatus & EP_SEL_EPN)
238062306a36Sopenharmony_ci		return;
238162306a36Sopenharmony_ci	/* Setup packet incoming? */
238262306a36Sopenharmony_ci	if (epstatus & EP_SEL_STP) {
238362306a36Sopenharmony_ci		nuke(ep0, 0);
238462306a36Sopenharmony_ci		udc->ep0state = WAIT_FOR_SETUP;
238562306a36Sopenharmony_ci	}
238662306a36Sopenharmony_ci
238762306a36Sopenharmony_ci	/* Data available? */
238862306a36Sopenharmony_ci	if (epstatus & EP_SEL_F)
238962306a36Sopenharmony_ci		/* Handle based on current state */
239062306a36Sopenharmony_ci		switch (udc->ep0state) {
239162306a36Sopenharmony_ci		case WAIT_FOR_SETUP:
239262306a36Sopenharmony_ci			udc_handle_ep0_setup(udc);
239362306a36Sopenharmony_ci			break;
239462306a36Sopenharmony_ci
239562306a36Sopenharmony_ci		case DATA_OUT:
239662306a36Sopenharmony_ci			udc_ep0_out_req(udc);
239762306a36Sopenharmony_ci			break;
239862306a36Sopenharmony_ci
239962306a36Sopenharmony_ci		default:
240062306a36Sopenharmony_ci			/* Unknown state for EP0 */
240162306a36Sopenharmony_ci			nuke(ep0, -ECONNABORTED);
240262306a36Sopenharmony_ci			udc->ep0state = WAIT_FOR_SETUP;
240362306a36Sopenharmony_ci		}
240462306a36Sopenharmony_ci}
240562306a36Sopenharmony_ci
240662306a36Sopenharmony_ci/* Must be called without lock */
240762306a36Sopenharmony_cistatic int lpc32xx_get_frame(struct usb_gadget *gadget)
240862306a36Sopenharmony_ci{
240962306a36Sopenharmony_ci	int frame;
241062306a36Sopenharmony_ci	unsigned long flags;
241162306a36Sopenharmony_ci	struct lpc32xx_udc *udc = to_udc(gadget);
241262306a36Sopenharmony_ci
241362306a36Sopenharmony_ci	if (!udc->clocked)
241462306a36Sopenharmony_ci		return -EINVAL;
241562306a36Sopenharmony_ci
241662306a36Sopenharmony_ci	spin_lock_irqsave(&udc->lock, flags);
241762306a36Sopenharmony_ci
241862306a36Sopenharmony_ci	frame = (int) udc_get_current_frame(udc);
241962306a36Sopenharmony_ci
242062306a36Sopenharmony_ci	spin_unlock_irqrestore(&udc->lock, flags);
242162306a36Sopenharmony_ci
242262306a36Sopenharmony_ci	return frame;
242362306a36Sopenharmony_ci}
242462306a36Sopenharmony_ci
242562306a36Sopenharmony_cistatic int lpc32xx_wakeup(struct usb_gadget *gadget)
242662306a36Sopenharmony_ci{
242762306a36Sopenharmony_ci	return -ENOTSUPP;
242862306a36Sopenharmony_ci}
242962306a36Sopenharmony_ci
243062306a36Sopenharmony_cistatic int lpc32xx_set_selfpowered(struct usb_gadget *gadget, int is_on)
243162306a36Sopenharmony_ci{
243262306a36Sopenharmony_ci	gadget->is_selfpowered = (is_on != 0);
243362306a36Sopenharmony_ci
243462306a36Sopenharmony_ci	return 0;
243562306a36Sopenharmony_ci}
243662306a36Sopenharmony_ci
243762306a36Sopenharmony_ci/*
243862306a36Sopenharmony_ci * vbus is here!  turn everything on that's ready
243962306a36Sopenharmony_ci * Must be called without lock
244062306a36Sopenharmony_ci */
244162306a36Sopenharmony_cistatic int lpc32xx_vbus_session(struct usb_gadget *gadget, int is_active)
244262306a36Sopenharmony_ci{
244362306a36Sopenharmony_ci	unsigned long flags;
244462306a36Sopenharmony_ci	struct lpc32xx_udc *udc = to_udc(gadget);
244562306a36Sopenharmony_ci
244662306a36Sopenharmony_ci	spin_lock_irqsave(&udc->lock, flags);
244762306a36Sopenharmony_ci
244862306a36Sopenharmony_ci	/* Doesn't need lock */
244962306a36Sopenharmony_ci	if (udc->driver) {
245062306a36Sopenharmony_ci		udc_clk_set(udc, 1);
245162306a36Sopenharmony_ci		udc_enable(udc);
245262306a36Sopenharmony_ci		pullup(udc, is_active);
245362306a36Sopenharmony_ci	} else {
245462306a36Sopenharmony_ci		stop_activity(udc);
245562306a36Sopenharmony_ci		pullup(udc, 0);
245662306a36Sopenharmony_ci
245762306a36Sopenharmony_ci		spin_unlock_irqrestore(&udc->lock, flags);
245862306a36Sopenharmony_ci		/*
245962306a36Sopenharmony_ci		 *  Wait for all the endpoints to disable,
246062306a36Sopenharmony_ci		 *  before disabling clocks. Don't wait if
246162306a36Sopenharmony_ci		 *  endpoints are not enabled.
246262306a36Sopenharmony_ci		 */
246362306a36Sopenharmony_ci		if (atomic_read(&udc->enabled_ep_cnt))
246462306a36Sopenharmony_ci			wait_event_interruptible(udc->ep_disable_wait_queue,
246562306a36Sopenharmony_ci				 (atomic_read(&udc->enabled_ep_cnt) == 0));
246662306a36Sopenharmony_ci
246762306a36Sopenharmony_ci		spin_lock_irqsave(&udc->lock, flags);
246862306a36Sopenharmony_ci
246962306a36Sopenharmony_ci		udc_clk_set(udc, 0);
247062306a36Sopenharmony_ci	}
247162306a36Sopenharmony_ci
247262306a36Sopenharmony_ci	spin_unlock_irqrestore(&udc->lock, flags);
247362306a36Sopenharmony_ci
247462306a36Sopenharmony_ci	return 0;
247562306a36Sopenharmony_ci}
247662306a36Sopenharmony_ci
247762306a36Sopenharmony_ci/* Can be called with or without lock */
247862306a36Sopenharmony_cistatic int lpc32xx_pullup(struct usb_gadget *gadget, int is_on)
247962306a36Sopenharmony_ci{
248062306a36Sopenharmony_ci	struct lpc32xx_udc *udc = to_udc(gadget);
248162306a36Sopenharmony_ci
248262306a36Sopenharmony_ci	/* Doesn't need lock */
248362306a36Sopenharmony_ci	pullup(udc, is_on);
248462306a36Sopenharmony_ci
248562306a36Sopenharmony_ci	return 0;
248662306a36Sopenharmony_ci}
248762306a36Sopenharmony_ci
248862306a36Sopenharmony_cistatic int lpc32xx_start(struct usb_gadget *, struct usb_gadget_driver *);
248962306a36Sopenharmony_cistatic int lpc32xx_stop(struct usb_gadget *);
249062306a36Sopenharmony_ci
249162306a36Sopenharmony_cistatic const struct usb_gadget_ops lpc32xx_udc_ops = {
249262306a36Sopenharmony_ci	.get_frame		= lpc32xx_get_frame,
249362306a36Sopenharmony_ci	.wakeup			= lpc32xx_wakeup,
249462306a36Sopenharmony_ci	.set_selfpowered	= lpc32xx_set_selfpowered,
249562306a36Sopenharmony_ci	.vbus_session		= lpc32xx_vbus_session,
249662306a36Sopenharmony_ci	.pullup			= lpc32xx_pullup,
249762306a36Sopenharmony_ci	.udc_start		= lpc32xx_start,
249862306a36Sopenharmony_ci	.udc_stop		= lpc32xx_stop,
249962306a36Sopenharmony_ci};
250062306a36Sopenharmony_ci
250162306a36Sopenharmony_cistatic void nop_release(struct device *dev)
250262306a36Sopenharmony_ci{
250362306a36Sopenharmony_ci	/* nothing to free */
250462306a36Sopenharmony_ci}
250562306a36Sopenharmony_ci
250662306a36Sopenharmony_cistatic const struct lpc32xx_udc controller_template = {
250762306a36Sopenharmony_ci	.gadget = {
250862306a36Sopenharmony_ci		.ops	= &lpc32xx_udc_ops,
250962306a36Sopenharmony_ci		.name	= driver_name,
251062306a36Sopenharmony_ci		.dev	= {
251162306a36Sopenharmony_ci			.init_name = "gadget",
251262306a36Sopenharmony_ci			.release = nop_release,
251362306a36Sopenharmony_ci		}
251462306a36Sopenharmony_ci	},
251562306a36Sopenharmony_ci	.ep[0] = {
251662306a36Sopenharmony_ci		.ep = {
251762306a36Sopenharmony_ci			.name	= "ep0",
251862306a36Sopenharmony_ci			.ops	= &lpc32xx_ep_ops,
251962306a36Sopenharmony_ci			.caps	= USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL,
252062306a36Sopenharmony_ci					USB_EP_CAPS_DIR_ALL),
252162306a36Sopenharmony_ci		},
252262306a36Sopenharmony_ci		.maxpacket	= 64,
252362306a36Sopenharmony_ci		.hwep_num_base	= 0,
252462306a36Sopenharmony_ci		.hwep_num	= 0, /* Can be 0 or 1, has special handling */
252562306a36Sopenharmony_ci		.lep		= 0,
252662306a36Sopenharmony_ci		.eptype		= EP_CTL_TYPE,
252762306a36Sopenharmony_ci	},
252862306a36Sopenharmony_ci	.ep[1] = {
252962306a36Sopenharmony_ci		.ep = {
253062306a36Sopenharmony_ci			.name	= "ep1-int",
253162306a36Sopenharmony_ci			.ops	= &lpc32xx_ep_ops,
253262306a36Sopenharmony_ci			.caps	= USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
253362306a36Sopenharmony_ci					USB_EP_CAPS_DIR_ALL),
253462306a36Sopenharmony_ci		},
253562306a36Sopenharmony_ci		.maxpacket	= 64,
253662306a36Sopenharmony_ci		.hwep_num_base	= 2,
253762306a36Sopenharmony_ci		.hwep_num	= 0, /* 2 or 3, will be set later */
253862306a36Sopenharmony_ci		.lep		= 1,
253962306a36Sopenharmony_ci		.eptype		= EP_INT_TYPE,
254062306a36Sopenharmony_ci	},
254162306a36Sopenharmony_ci	.ep[2] = {
254262306a36Sopenharmony_ci		.ep = {
254362306a36Sopenharmony_ci			.name	= "ep2-bulk",
254462306a36Sopenharmony_ci			.ops	= &lpc32xx_ep_ops,
254562306a36Sopenharmony_ci			.caps	= USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
254662306a36Sopenharmony_ci					USB_EP_CAPS_DIR_ALL),
254762306a36Sopenharmony_ci		},
254862306a36Sopenharmony_ci		.maxpacket	= 64,
254962306a36Sopenharmony_ci		.hwep_num_base	= 4,
255062306a36Sopenharmony_ci		.hwep_num	= 0, /* 4 or 5, will be set later */
255162306a36Sopenharmony_ci		.lep		= 2,
255262306a36Sopenharmony_ci		.eptype		= EP_BLK_TYPE,
255362306a36Sopenharmony_ci	},
255462306a36Sopenharmony_ci	.ep[3] = {
255562306a36Sopenharmony_ci		.ep = {
255662306a36Sopenharmony_ci			.name	= "ep3-iso",
255762306a36Sopenharmony_ci			.ops	= &lpc32xx_ep_ops,
255862306a36Sopenharmony_ci			.caps	= USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
255962306a36Sopenharmony_ci					USB_EP_CAPS_DIR_ALL),
256062306a36Sopenharmony_ci		},
256162306a36Sopenharmony_ci		.maxpacket	= 1023,
256262306a36Sopenharmony_ci		.hwep_num_base	= 6,
256362306a36Sopenharmony_ci		.hwep_num	= 0, /* 6 or 7, will be set later */
256462306a36Sopenharmony_ci		.lep		= 3,
256562306a36Sopenharmony_ci		.eptype		= EP_ISO_TYPE,
256662306a36Sopenharmony_ci	},
256762306a36Sopenharmony_ci	.ep[4] = {
256862306a36Sopenharmony_ci		.ep = {
256962306a36Sopenharmony_ci			.name	= "ep4-int",
257062306a36Sopenharmony_ci			.ops	= &lpc32xx_ep_ops,
257162306a36Sopenharmony_ci			.caps	= USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
257262306a36Sopenharmony_ci					USB_EP_CAPS_DIR_ALL),
257362306a36Sopenharmony_ci		},
257462306a36Sopenharmony_ci		.maxpacket	= 64,
257562306a36Sopenharmony_ci		.hwep_num_base	= 8,
257662306a36Sopenharmony_ci		.hwep_num	= 0, /* 8 or 9, will be set later */
257762306a36Sopenharmony_ci		.lep		= 4,
257862306a36Sopenharmony_ci		.eptype		= EP_INT_TYPE,
257962306a36Sopenharmony_ci	},
258062306a36Sopenharmony_ci	.ep[5] = {
258162306a36Sopenharmony_ci		.ep = {
258262306a36Sopenharmony_ci			.name	= "ep5-bulk",
258362306a36Sopenharmony_ci			.ops	= &lpc32xx_ep_ops,
258462306a36Sopenharmony_ci			.caps	= USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
258562306a36Sopenharmony_ci					USB_EP_CAPS_DIR_ALL),
258662306a36Sopenharmony_ci		},
258762306a36Sopenharmony_ci		.maxpacket	= 64,
258862306a36Sopenharmony_ci		.hwep_num_base	= 10,
258962306a36Sopenharmony_ci		.hwep_num	= 0, /* 10 or 11, will be set later */
259062306a36Sopenharmony_ci		.lep		= 5,
259162306a36Sopenharmony_ci		.eptype		= EP_BLK_TYPE,
259262306a36Sopenharmony_ci	},
259362306a36Sopenharmony_ci	.ep[6] = {
259462306a36Sopenharmony_ci		.ep = {
259562306a36Sopenharmony_ci			.name	= "ep6-iso",
259662306a36Sopenharmony_ci			.ops	= &lpc32xx_ep_ops,
259762306a36Sopenharmony_ci			.caps	= USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
259862306a36Sopenharmony_ci					USB_EP_CAPS_DIR_ALL),
259962306a36Sopenharmony_ci		},
260062306a36Sopenharmony_ci		.maxpacket	= 1023,
260162306a36Sopenharmony_ci		.hwep_num_base	= 12,
260262306a36Sopenharmony_ci		.hwep_num	= 0, /* 12 or 13, will be set later */
260362306a36Sopenharmony_ci		.lep		= 6,
260462306a36Sopenharmony_ci		.eptype		= EP_ISO_TYPE,
260562306a36Sopenharmony_ci	},
260662306a36Sopenharmony_ci	.ep[7] = {
260762306a36Sopenharmony_ci		.ep = {
260862306a36Sopenharmony_ci			.name	= "ep7-int",
260962306a36Sopenharmony_ci			.ops	= &lpc32xx_ep_ops,
261062306a36Sopenharmony_ci			.caps	= USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
261162306a36Sopenharmony_ci					USB_EP_CAPS_DIR_ALL),
261262306a36Sopenharmony_ci		},
261362306a36Sopenharmony_ci		.maxpacket	= 64,
261462306a36Sopenharmony_ci		.hwep_num_base	= 14,
261562306a36Sopenharmony_ci		.hwep_num	= 0,
261662306a36Sopenharmony_ci		.lep		= 7,
261762306a36Sopenharmony_ci		.eptype		= EP_INT_TYPE,
261862306a36Sopenharmony_ci	},
261962306a36Sopenharmony_ci	.ep[8] = {
262062306a36Sopenharmony_ci		.ep = {
262162306a36Sopenharmony_ci			.name	= "ep8-bulk",
262262306a36Sopenharmony_ci			.ops	= &lpc32xx_ep_ops,
262362306a36Sopenharmony_ci			.caps	= USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
262462306a36Sopenharmony_ci					USB_EP_CAPS_DIR_ALL),
262562306a36Sopenharmony_ci		},
262662306a36Sopenharmony_ci		.maxpacket	= 64,
262762306a36Sopenharmony_ci		.hwep_num_base	= 16,
262862306a36Sopenharmony_ci		.hwep_num	= 0,
262962306a36Sopenharmony_ci		.lep		= 8,
263062306a36Sopenharmony_ci		.eptype		= EP_BLK_TYPE,
263162306a36Sopenharmony_ci	},
263262306a36Sopenharmony_ci	.ep[9] = {
263362306a36Sopenharmony_ci		.ep = {
263462306a36Sopenharmony_ci			.name	= "ep9-iso",
263562306a36Sopenharmony_ci			.ops	= &lpc32xx_ep_ops,
263662306a36Sopenharmony_ci			.caps	= USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
263762306a36Sopenharmony_ci					USB_EP_CAPS_DIR_ALL),
263862306a36Sopenharmony_ci		},
263962306a36Sopenharmony_ci		.maxpacket	= 1023,
264062306a36Sopenharmony_ci		.hwep_num_base	= 18,
264162306a36Sopenharmony_ci		.hwep_num	= 0,
264262306a36Sopenharmony_ci		.lep		= 9,
264362306a36Sopenharmony_ci		.eptype		= EP_ISO_TYPE,
264462306a36Sopenharmony_ci	},
264562306a36Sopenharmony_ci	.ep[10] = {
264662306a36Sopenharmony_ci		.ep = {
264762306a36Sopenharmony_ci			.name	= "ep10-int",
264862306a36Sopenharmony_ci			.ops	= &lpc32xx_ep_ops,
264962306a36Sopenharmony_ci			.caps	= USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
265062306a36Sopenharmony_ci					USB_EP_CAPS_DIR_ALL),
265162306a36Sopenharmony_ci		},
265262306a36Sopenharmony_ci		.maxpacket	= 64,
265362306a36Sopenharmony_ci		.hwep_num_base	= 20,
265462306a36Sopenharmony_ci		.hwep_num	= 0,
265562306a36Sopenharmony_ci		.lep		= 10,
265662306a36Sopenharmony_ci		.eptype		= EP_INT_TYPE,
265762306a36Sopenharmony_ci	},
265862306a36Sopenharmony_ci	.ep[11] = {
265962306a36Sopenharmony_ci		.ep = {
266062306a36Sopenharmony_ci			.name	= "ep11-bulk",
266162306a36Sopenharmony_ci			.ops	= &lpc32xx_ep_ops,
266262306a36Sopenharmony_ci			.caps	= USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
266362306a36Sopenharmony_ci					USB_EP_CAPS_DIR_ALL),
266462306a36Sopenharmony_ci		},
266562306a36Sopenharmony_ci		.maxpacket	= 64,
266662306a36Sopenharmony_ci		.hwep_num_base	= 22,
266762306a36Sopenharmony_ci		.hwep_num	= 0,
266862306a36Sopenharmony_ci		.lep		= 11,
266962306a36Sopenharmony_ci		.eptype		= EP_BLK_TYPE,
267062306a36Sopenharmony_ci	},
267162306a36Sopenharmony_ci	.ep[12] = {
267262306a36Sopenharmony_ci		.ep = {
267362306a36Sopenharmony_ci			.name	= "ep12-iso",
267462306a36Sopenharmony_ci			.ops	= &lpc32xx_ep_ops,
267562306a36Sopenharmony_ci			.caps	= USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
267662306a36Sopenharmony_ci					USB_EP_CAPS_DIR_ALL),
267762306a36Sopenharmony_ci		},
267862306a36Sopenharmony_ci		.maxpacket	= 1023,
267962306a36Sopenharmony_ci		.hwep_num_base	= 24,
268062306a36Sopenharmony_ci		.hwep_num	= 0,
268162306a36Sopenharmony_ci		.lep		= 12,
268262306a36Sopenharmony_ci		.eptype		= EP_ISO_TYPE,
268362306a36Sopenharmony_ci	},
268462306a36Sopenharmony_ci	.ep[13] = {
268562306a36Sopenharmony_ci		.ep = {
268662306a36Sopenharmony_ci			.name	= "ep13-int",
268762306a36Sopenharmony_ci			.ops	= &lpc32xx_ep_ops,
268862306a36Sopenharmony_ci			.caps	= USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
268962306a36Sopenharmony_ci					USB_EP_CAPS_DIR_ALL),
269062306a36Sopenharmony_ci		},
269162306a36Sopenharmony_ci		.maxpacket	= 64,
269262306a36Sopenharmony_ci		.hwep_num_base	= 26,
269362306a36Sopenharmony_ci		.hwep_num	= 0,
269462306a36Sopenharmony_ci		.lep		= 13,
269562306a36Sopenharmony_ci		.eptype		= EP_INT_TYPE,
269662306a36Sopenharmony_ci	},
269762306a36Sopenharmony_ci	.ep[14] = {
269862306a36Sopenharmony_ci		.ep = {
269962306a36Sopenharmony_ci			.name	= "ep14-bulk",
270062306a36Sopenharmony_ci			.ops	= &lpc32xx_ep_ops,
270162306a36Sopenharmony_ci			.caps	= USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
270262306a36Sopenharmony_ci					USB_EP_CAPS_DIR_ALL),
270362306a36Sopenharmony_ci		},
270462306a36Sopenharmony_ci		.maxpacket	= 64,
270562306a36Sopenharmony_ci		.hwep_num_base	= 28,
270662306a36Sopenharmony_ci		.hwep_num	= 0,
270762306a36Sopenharmony_ci		.lep		= 14,
270862306a36Sopenharmony_ci		.eptype		= EP_BLK_TYPE,
270962306a36Sopenharmony_ci	},
271062306a36Sopenharmony_ci	.ep[15] = {
271162306a36Sopenharmony_ci		.ep = {
271262306a36Sopenharmony_ci			.name	= "ep15-bulk",
271362306a36Sopenharmony_ci			.ops	= &lpc32xx_ep_ops,
271462306a36Sopenharmony_ci			.caps	= USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
271562306a36Sopenharmony_ci					USB_EP_CAPS_DIR_ALL),
271662306a36Sopenharmony_ci		},
271762306a36Sopenharmony_ci		.maxpacket	= 1023,
271862306a36Sopenharmony_ci		.hwep_num_base	= 30,
271962306a36Sopenharmony_ci		.hwep_num	= 0,
272062306a36Sopenharmony_ci		.lep		= 15,
272162306a36Sopenharmony_ci		.eptype		= EP_BLK_TYPE,
272262306a36Sopenharmony_ci	},
272362306a36Sopenharmony_ci};
272462306a36Sopenharmony_ci
272562306a36Sopenharmony_ci/* ISO and status interrupts */
272662306a36Sopenharmony_cistatic irqreturn_t lpc32xx_usb_lp_irq(int irq, void *_udc)
272762306a36Sopenharmony_ci{
272862306a36Sopenharmony_ci	u32 tmp, devstat;
272962306a36Sopenharmony_ci	struct lpc32xx_udc *udc = _udc;
273062306a36Sopenharmony_ci
273162306a36Sopenharmony_ci	spin_lock(&udc->lock);
273262306a36Sopenharmony_ci
273362306a36Sopenharmony_ci	/* Read the device status register */
273462306a36Sopenharmony_ci	devstat = readl(USBD_DEVINTST(udc->udp_baseaddr));
273562306a36Sopenharmony_ci
273662306a36Sopenharmony_ci	devstat &= ~USBD_EP_FAST;
273762306a36Sopenharmony_ci	writel(devstat, USBD_DEVINTCLR(udc->udp_baseaddr));
273862306a36Sopenharmony_ci	devstat = devstat & udc->enabled_devints;
273962306a36Sopenharmony_ci
274062306a36Sopenharmony_ci	/* Device specific handling needed? */
274162306a36Sopenharmony_ci	if (devstat & USBD_DEV_STAT)
274262306a36Sopenharmony_ci		udc_handle_dev(udc);
274362306a36Sopenharmony_ci
274462306a36Sopenharmony_ci	/* Start of frame? (devstat & FRAME_INT):
274562306a36Sopenharmony_ci	 * The frame interrupt isn't really needed for ISO support,
274662306a36Sopenharmony_ci	 * as the driver will queue the necessary packets */
274762306a36Sopenharmony_ci
274862306a36Sopenharmony_ci	/* Error? */
274962306a36Sopenharmony_ci	if (devstat & ERR_INT) {
275062306a36Sopenharmony_ci		/* All types of errors, from cable removal during transfer to
275162306a36Sopenharmony_ci		 * misc protocol and bit errors. These are mostly for just info,
275262306a36Sopenharmony_ci		 * as the USB hardware will work around these. If these errors
275362306a36Sopenharmony_ci		 * happen alot, something is wrong. */
275462306a36Sopenharmony_ci		udc_protocol_cmd_w(udc, CMD_RD_ERR_STAT);
275562306a36Sopenharmony_ci		tmp = udc_protocol_cmd_r(udc, DAT_RD_ERR_STAT);
275662306a36Sopenharmony_ci		dev_dbg(udc->dev, "Device error (0x%x)!\n", tmp);
275762306a36Sopenharmony_ci	}
275862306a36Sopenharmony_ci
275962306a36Sopenharmony_ci	spin_unlock(&udc->lock);
276062306a36Sopenharmony_ci
276162306a36Sopenharmony_ci	return IRQ_HANDLED;
276262306a36Sopenharmony_ci}
276362306a36Sopenharmony_ci
276462306a36Sopenharmony_ci/* EP interrupts */
276562306a36Sopenharmony_cistatic irqreturn_t lpc32xx_usb_hp_irq(int irq, void *_udc)
276662306a36Sopenharmony_ci{
276762306a36Sopenharmony_ci	u32 tmp;
276862306a36Sopenharmony_ci	struct lpc32xx_udc *udc = _udc;
276962306a36Sopenharmony_ci
277062306a36Sopenharmony_ci	spin_lock(&udc->lock);
277162306a36Sopenharmony_ci
277262306a36Sopenharmony_ci	/* Read the device status register */
277362306a36Sopenharmony_ci	writel(USBD_EP_FAST, USBD_DEVINTCLR(udc->udp_baseaddr));
277462306a36Sopenharmony_ci
277562306a36Sopenharmony_ci	/* Endpoints */
277662306a36Sopenharmony_ci	tmp = readl(USBD_EPINTST(udc->udp_baseaddr));
277762306a36Sopenharmony_ci
277862306a36Sopenharmony_ci	/* Special handling for EP0 */
277962306a36Sopenharmony_ci	if (tmp & (EP_MASK_SEL(0, EP_OUT) | EP_MASK_SEL(0, EP_IN))) {
278062306a36Sopenharmony_ci		/* Handle EP0 IN */
278162306a36Sopenharmony_ci		if (tmp & (EP_MASK_SEL(0, EP_IN)))
278262306a36Sopenharmony_ci			udc_handle_ep0_in(udc);
278362306a36Sopenharmony_ci
278462306a36Sopenharmony_ci		/* Handle EP0 OUT */
278562306a36Sopenharmony_ci		if (tmp & (EP_MASK_SEL(0, EP_OUT)))
278662306a36Sopenharmony_ci			udc_handle_ep0_out(udc);
278762306a36Sopenharmony_ci	}
278862306a36Sopenharmony_ci
278962306a36Sopenharmony_ci	/* All other EPs */
279062306a36Sopenharmony_ci	if (tmp & ~(EP_MASK_SEL(0, EP_OUT) | EP_MASK_SEL(0, EP_IN))) {
279162306a36Sopenharmony_ci		int i;
279262306a36Sopenharmony_ci
279362306a36Sopenharmony_ci		/* Handle other EP interrupts */
279462306a36Sopenharmony_ci		for (i = 1; i < NUM_ENDPOINTS; i++) {
279562306a36Sopenharmony_ci			if (tmp & (1 << udc->ep[i].hwep_num))
279662306a36Sopenharmony_ci				udc_handle_eps(udc, &udc->ep[i]);
279762306a36Sopenharmony_ci		}
279862306a36Sopenharmony_ci	}
279962306a36Sopenharmony_ci
280062306a36Sopenharmony_ci	spin_unlock(&udc->lock);
280162306a36Sopenharmony_ci
280262306a36Sopenharmony_ci	return IRQ_HANDLED;
280362306a36Sopenharmony_ci}
280462306a36Sopenharmony_ci
280562306a36Sopenharmony_cistatic irqreturn_t lpc32xx_usb_devdma_irq(int irq, void *_udc)
280662306a36Sopenharmony_ci{
280762306a36Sopenharmony_ci	struct lpc32xx_udc *udc = _udc;
280862306a36Sopenharmony_ci
280962306a36Sopenharmony_ci	int i;
281062306a36Sopenharmony_ci	u32 tmp;
281162306a36Sopenharmony_ci
281262306a36Sopenharmony_ci	spin_lock(&udc->lock);
281362306a36Sopenharmony_ci
281462306a36Sopenharmony_ci	/* Handle EP DMA EOT interrupts */
281562306a36Sopenharmony_ci	tmp = readl(USBD_EOTINTST(udc->udp_baseaddr)) |
281662306a36Sopenharmony_ci		(readl(USBD_EPDMAST(udc->udp_baseaddr)) &
281762306a36Sopenharmony_ci		 readl(USBD_NDDRTINTST(udc->udp_baseaddr))) |
281862306a36Sopenharmony_ci		readl(USBD_SYSERRTINTST(udc->udp_baseaddr));
281962306a36Sopenharmony_ci	for (i = 1; i < NUM_ENDPOINTS; i++) {
282062306a36Sopenharmony_ci		if (tmp & (1 << udc->ep[i].hwep_num))
282162306a36Sopenharmony_ci			udc_handle_dma_ep(udc, &udc->ep[i]);
282262306a36Sopenharmony_ci	}
282362306a36Sopenharmony_ci
282462306a36Sopenharmony_ci	spin_unlock(&udc->lock);
282562306a36Sopenharmony_ci
282662306a36Sopenharmony_ci	return IRQ_HANDLED;
282762306a36Sopenharmony_ci}
282862306a36Sopenharmony_ci
282962306a36Sopenharmony_ci/*
283062306a36Sopenharmony_ci *
283162306a36Sopenharmony_ci * VBUS detection, pullup handler, and Gadget cable state notification
283262306a36Sopenharmony_ci *
283362306a36Sopenharmony_ci */
283462306a36Sopenharmony_cistatic void vbus_work(struct lpc32xx_udc *udc)
283562306a36Sopenharmony_ci{
283662306a36Sopenharmony_ci	u8 value;
283762306a36Sopenharmony_ci
283862306a36Sopenharmony_ci	if (udc->enabled != 0) {
283962306a36Sopenharmony_ci		/* Discharge VBUS real quick */
284062306a36Sopenharmony_ci		i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
284162306a36Sopenharmony_ci			ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DISCHRG);
284262306a36Sopenharmony_ci
284362306a36Sopenharmony_ci		/* Give VBUS some time (100mS) to discharge */
284462306a36Sopenharmony_ci		msleep(100);
284562306a36Sopenharmony_ci
284662306a36Sopenharmony_ci		/* Disable VBUS discharge resistor */
284762306a36Sopenharmony_ci		i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
284862306a36Sopenharmony_ci			ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR,
284962306a36Sopenharmony_ci			OTG1_VBUS_DISCHRG);
285062306a36Sopenharmony_ci
285162306a36Sopenharmony_ci		/* Clear interrupt */
285262306a36Sopenharmony_ci		i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
285362306a36Sopenharmony_ci			ISP1301_I2C_INTERRUPT_LATCH |
285462306a36Sopenharmony_ci			ISP1301_I2C_REG_CLEAR_ADDR, ~0);
285562306a36Sopenharmony_ci
285662306a36Sopenharmony_ci		/* Get the VBUS status from the transceiver */
285762306a36Sopenharmony_ci		value = i2c_smbus_read_byte_data(udc->isp1301_i2c_client,
285862306a36Sopenharmony_ci						 ISP1301_I2C_INTERRUPT_SOURCE);
285962306a36Sopenharmony_ci
286062306a36Sopenharmony_ci		/* VBUS on or off? */
286162306a36Sopenharmony_ci		if (value & INT_SESS_VLD)
286262306a36Sopenharmony_ci			udc->vbus = 1;
286362306a36Sopenharmony_ci		else
286462306a36Sopenharmony_ci			udc->vbus = 0;
286562306a36Sopenharmony_ci
286662306a36Sopenharmony_ci		/* VBUS changed? */
286762306a36Sopenharmony_ci		if (udc->last_vbus != udc->vbus) {
286862306a36Sopenharmony_ci			udc->last_vbus = udc->vbus;
286962306a36Sopenharmony_ci			lpc32xx_vbus_session(&udc->gadget, udc->vbus);
287062306a36Sopenharmony_ci		}
287162306a36Sopenharmony_ci	}
287262306a36Sopenharmony_ci}
287362306a36Sopenharmony_ci
287462306a36Sopenharmony_cistatic irqreturn_t lpc32xx_usb_vbus_irq(int irq, void *_udc)
287562306a36Sopenharmony_ci{
287662306a36Sopenharmony_ci	struct lpc32xx_udc *udc = _udc;
287762306a36Sopenharmony_ci
287862306a36Sopenharmony_ci	vbus_work(udc);
287962306a36Sopenharmony_ci
288062306a36Sopenharmony_ci	return IRQ_HANDLED;
288162306a36Sopenharmony_ci}
288262306a36Sopenharmony_ci
288362306a36Sopenharmony_cistatic int lpc32xx_start(struct usb_gadget *gadget,
288462306a36Sopenharmony_ci			 struct usb_gadget_driver *driver)
288562306a36Sopenharmony_ci{
288662306a36Sopenharmony_ci	struct lpc32xx_udc *udc = to_udc(gadget);
288762306a36Sopenharmony_ci
288862306a36Sopenharmony_ci	if (!driver || driver->max_speed < USB_SPEED_FULL || !driver->setup) {
288962306a36Sopenharmony_ci		dev_err(udc->dev, "bad parameter.\n");
289062306a36Sopenharmony_ci		return -EINVAL;
289162306a36Sopenharmony_ci	}
289262306a36Sopenharmony_ci
289362306a36Sopenharmony_ci	if (udc->driver) {
289462306a36Sopenharmony_ci		dev_err(udc->dev, "UDC already has a gadget driver\n");
289562306a36Sopenharmony_ci		return -EBUSY;
289662306a36Sopenharmony_ci	}
289762306a36Sopenharmony_ci
289862306a36Sopenharmony_ci	udc->driver = driver;
289962306a36Sopenharmony_ci	udc->gadget.dev.of_node = udc->dev->of_node;
290062306a36Sopenharmony_ci	udc->enabled = 1;
290162306a36Sopenharmony_ci	udc->gadget.is_selfpowered = 1;
290262306a36Sopenharmony_ci	udc->vbus = 0;
290362306a36Sopenharmony_ci
290462306a36Sopenharmony_ci	/* Force VBUS process once to check for cable insertion */
290562306a36Sopenharmony_ci	udc->last_vbus = udc->vbus = 0;
290662306a36Sopenharmony_ci	vbus_work(udc);
290762306a36Sopenharmony_ci
290862306a36Sopenharmony_ci	/* enable interrupts */
290962306a36Sopenharmony_ci	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
291062306a36Sopenharmony_ci		ISP1301_I2C_INTERRUPT_FALLING, INT_SESS_VLD | INT_VBUS_VLD);
291162306a36Sopenharmony_ci	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
291262306a36Sopenharmony_ci		ISP1301_I2C_INTERRUPT_RISING, INT_SESS_VLD | INT_VBUS_VLD);
291362306a36Sopenharmony_ci
291462306a36Sopenharmony_ci	return 0;
291562306a36Sopenharmony_ci}
291662306a36Sopenharmony_ci
291762306a36Sopenharmony_cistatic int lpc32xx_stop(struct usb_gadget *gadget)
291862306a36Sopenharmony_ci{
291962306a36Sopenharmony_ci	struct lpc32xx_udc *udc = to_udc(gadget);
292062306a36Sopenharmony_ci
292162306a36Sopenharmony_ci	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
292262306a36Sopenharmony_ci		ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
292362306a36Sopenharmony_ci	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
292462306a36Sopenharmony_ci		ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
292562306a36Sopenharmony_ci
292662306a36Sopenharmony_ci	if (udc->clocked) {
292762306a36Sopenharmony_ci		spin_lock(&udc->lock);
292862306a36Sopenharmony_ci		stop_activity(udc);
292962306a36Sopenharmony_ci		spin_unlock(&udc->lock);
293062306a36Sopenharmony_ci
293162306a36Sopenharmony_ci		/*
293262306a36Sopenharmony_ci		 *  Wait for all the endpoints to disable,
293362306a36Sopenharmony_ci		 *  before disabling clocks. Don't wait if
293462306a36Sopenharmony_ci		 *  endpoints are not enabled.
293562306a36Sopenharmony_ci		 */
293662306a36Sopenharmony_ci		if (atomic_read(&udc->enabled_ep_cnt))
293762306a36Sopenharmony_ci			wait_event_interruptible(udc->ep_disable_wait_queue,
293862306a36Sopenharmony_ci				(atomic_read(&udc->enabled_ep_cnt) == 0));
293962306a36Sopenharmony_ci
294062306a36Sopenharmony_ci		spin_lock(&udc->lock);
294162306a36Sopenharmony_ci		udc_clk_set(udc, 0);
294262306a36Sopenharmony_ci		spin_unlock(&udc->lock);
294362306a36Sopenharmony_ci	}
294462306a36Sopenharmony_ci
294562306a36Sopenharmony_ci	udc->enabled = 0;
294662306a36Sopenharmony_ci	udc->driver = NULL;
294762306a36Sopenharmony_ci
294862306a36Sopenharmony_ci	return 0;
294962306a36Sopenharmony_ci}
295062306a36Sopenharmony_ci
295162306a36Sopenharmony_cistatic void lpc32xx_udc_shutdown(struct platform_device *dev)
295262306a36Sopenharmony_ci{
295362306a36Sopenharmony_ci	/* Force disconnect on reboot */
295462306a36Sopenharmony_ci	struct lpc32xx_udc *udc = platform_get_drvdata(dev);
295562306a36Sopenharmony_ci
295662306a36Sopenharmony_ci	pullup(udc, 0);
295762306a36Sopenharmony_ci}
295862306a36Sopenharmony_ci
295962306a36Sopenharmony_ci/*
296062306a36Sopenharmony_ci * Callbacks to be overridden by options passed via OF (TODO)
296162306a36Sopenharmony_ci */
296262306a36Sopenharmony_ci
296362306a36Sopenharmony_cistatic void lpc32xx_usbd_conn_chg(int conn)
296462306a36Sopenharmony_ci{
296562306a36Sopenharmony_ci	/* Do nothing, it might be nice to enable an LED
296662306a36Sopenharmony_ci	 * based on conn state being !0 */
296762306a36Sopenharmony_ci}
296862306a36Sopenharmony_ci
296962306a36Sopenharmony_cistatic void lpc32xx_usbd_susp_chg(int susp)
297062306a36Sopenharmony_ci{
297162306a36Sopenharmony_ci	/* Device suspend if susp != 0 */
297262306a36Sopenharmony_ci}
297362306a36Sopenharmony_ci
297462306a36Sopenharmony_cistatic void lpc32xx_rmwkup_chg(int remote_wakup_enable)
297562306a36Sopenharmony_ci{
297662306a36Sopenharmony_ci	/* Enable or disable USB remote wakeup */
297762306a36Sopenharmony_ci}
297862306a36Sopenharmony_ci
297962306a36Sopenharmony_cistatic struct lpc32xx_usbd_cfg lpc32xx_usbddata = {
298062306a36Sopenharmony_ci	.vbus_drv_pol = 0,
298162306a36Sopenharmony_ci	.conn_chgb = &lpc32xx_usbd_conn_chg,
298262306a36Sopenharmony_ci	.susp_chgb = &lpc32xx_usbd_susp_chg,
298362306a36Sopenharmony_ci	.rmwk_chgb = &lpc32xx_rmwkup_chg,
298462306a36Sopenharmony_ci};
298562306a36Sopenharmony_ci
298662306a36Sopenharmony_ci
298762306a36Sopenharmony_cistatic u64 lpc32xx_usbd_dmamask = ~(u32) 0x7F;
298862306a36Sopenharmony_ci
298962306a36Sopenharmony_cistatic int lpc32xx_udc_probe(struct platform_device *pdev)
299062306a36Sopenharmony_ci{
299162306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
299262306a36Sopenharmony_ci	struct lpc32xx_udc *udc;
299362306a36Sopenharmony_ci	int retval, i;
299462306a36Sopenharmony_ci	dma_addr_t dma_handle;
299562306a36Sopenharmony_ci	struct device_node *isp1301_node;
299662306a36Sopenharmony_ci
299762306a36Sopenharmony_ci	udc = devm_kmemdup(dev, &controller_template, sizeof(*udc), GFP_KERNEL);
299862306a36Sopenharmony_ci	if (!udc)
299962306a36Sopenharmony_ci		return -ENOMEM;
300062306a36Sopenharmony_ci
300162306a36Sopenharmony_ci	for (i = 0; i <= 15; i++)
300262306a36Sopenharmony_ci		udc->ep[i].udc = udc;
300362306a36Sopenharmony_ci	udc->gadget.ep0 = &udc->ep[0].ep;
300462306a36Sopenharmony_ci
300562306a36Sopenharmony_ci	/* init software state */
300662306a36Sopenharmony_ci	udc->gadget.dev.parent = dev;
300762306a36Sopenharmony_ci	udc->pdev = pdev;
300862306a36Sopenharmony_ci	udc->dev = &pdev->dev;
300962306a36Sopenharmony_ci	udc->enabled = 0;
301062306a36Sopenharmony_ci
301162306a36Sopenharmony_ci	if (pdev->dev.of_node) {
301262306a36Sopenharmony_ci		isp1301_node = of_parse_phandle(pdev->dev.of_node,
301362306a36Sopenharmony_ci						"transceiver", 0);
301462306a36Sopenharmony_ci	} else {
301562306a36Sopenharmony_ci		isp1301_node = NULL;
301662306a36Sopenharmony_ci	}
301762306a36Sopenharmony_ci
301862306a36Sopenharmony_ci	udc->isp1301_i2c_client = isp1301_get_client(isp1301_node);
301962306a36Sopenharmony_ci	of_node_put(isp1301_node);
302062306a36Sopenharmony_ci	if (!udc->isp1301_i2c_client) {
302162306a36Sopenharmony_ci		return -EPROBE_DEFER;
302262306a36Sopenharmony_ci	}
302362306a36Sopenharmony_ci
302462306a36Sopenharmony_ci	dev_info(udc->dev, "ISP1301 I2C device at address 0x%x\n",
302562306a36Sopenharmony_ci		 udc->isp1301_i2c_client->addr);
302662306a36Sopenharmony_ci
302762306a36Sopenharmony_ci	pdev->dev.dma_mask = &lpc32xx_usbd_dmamask;
302862306a36Sopenharmony_ci	retval = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
302962306a36Sopenharmony_ci	if (retval)
303062306a36Sopenharmony_ci		return retval;
303162306a36Sopenharmony_ci
303262306a36Sopenharmony_ci	udc->board = &lpc32xx_usbddata;
303362306a36Sopenharmony_ci
303462306a36Sopenharmony_ci	/*
303562306a36Sopenharmony_ci	 * Resources are mapped as follows:
303662306a36Sopenharmony_ci	 *  IORESOURCE_MEM, base address and size of USB space
303762306a36Sopenharmony_ci	 *  IORESOURCE_IRQ, USB device low priority interrupt number
303862306a36Sopenharmony_ci	 *  IORESOURCE_IRQ, USB device high priority interrupt number
303962306a36Sopenharmony_ci	 *  IORESOURCE_IRQ, USB device interrupt number
304062306a36Sopenharmony_ci	 *  IORESOURCE_IRQ, USB transceiver interrupt number
304162306a36Sopenharmony_ci	 */
304262306a36Sopenharmony_ci
304362306a36Sopenharmony_ci	spin_lock_init(&udc->lock);
304462306a36Sopenharmony_ci
304562306a36Sopenharmony_ci	/* Get IRQs */
304662306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
304762306a36Sopenharmony_ci		udc->udp_irq[i] = platform_get_irq(pdev, i);
304862306a36Sopenharmony_ci		if (udc->udp_irq[i] < 0)
304962306a36Sopenharmony_ci			return udc->udp_irq[i];
305062306a36Sopenharmony_ci	}
305162306a36Sopenharmony_ci
305262306a36Sopenharmony_ci	udc->udp_baseaddr = devm_platform_ioremap_resource(pdev, 0);
305362306a36Sopenharmony_ci	if (IS_ERR(udc->udp_baseaddr)) {
305462306a36Sopenharmony_ci		dev_err(udc->dev, "IO map failure\n");
305562306a36Sopenharmony_ci		return PTR_ERR(udc->udp_baseaddr);
305662306a36Sopenharmony_ci	}
305762306a36Sopenharmony_ci
305862306a36Sopenharmony_ci	/* Get USB device clock */
305962306a36Sopenharmony_ci	udc->usb_slv_clk = devm_clk_get(&pdev->dev, NULL);
306062306a36Sopenharmony_ci	if (IS_ERR(udc->usb_slv_clk)) {
306162306a36Sopenharmony_ci		dev_err(udc->dev, "failed to acquire USB device clock\n");
306262306a36Sopenharmony_ci		return PTR_ERR(udc->usb_slv_clk);
306362306a36Sopenharmony_ci	}
306462306a36Sopenharmony_ci
306562306a36Sopenharmony_ci	/* Enable USB device clock */
306662306a36Sopenharmony_ci	retval = clk_prepare_enable(udc->usb_slv_clk);
306762306a36Sopenharmony_ci	if (retval < 0) {
306862306a36Sopenharmony_ci		dev_err(udc->dev, "failed to start USB device clock\n");
306962306a36Sopenharmony_ci		return retval;
307062306a36Sopenharmony_ci	}
307162306a36Sopenharmony_ci
307262306a36Sopenharmony_ci	/* Setup deferred workqueue data */
307362306a36Sopenharmony_ci	udc->poweron = udc->pullup = 0;
307462306a36Sopenharmony_ci	INIT_WORK(&udc->pullup_job, pullup_work);
307562306a36Sopenharmony_ci#ifdef CONFIG_PM
307662306a36Sopenharmony_ci	INIT_WORK(&udc->power_job, power_work);
307762306a36Sopenharmony_ci#endif
307862306a36Sopenharmony_ci
307962306a36Sopenharmony_ci	/* All clocks are now on */
308062306a36Sopenharmony_ci	udc->clocked = 1;
308162306a36Sopenharmony_ci
308262306a36Sopenharmony_ci	isp1301_udc_configure(udc);
308362306a36Sopenharmony_ci	/* Allocate memory for the UDCA */
308462306a36Sopenharmony_ci	udc->udca_v_base = dma_alloc_coherent(&pdev->dev, UDCA_BUFF_SIZE,
308562306a36Sopenharmony_ci					      &dma_handle,
308662306a36Sopenharmony_ci					      (GFP_KERNEL | GFP_DMA));
308762306a36Sopenharmony_ci	if (!udc->udca_v_base) {
308862306a36Sopenharmony_ci		dev_err(udc->dev, "error getting UDCA region\n");
308962306a36Sopenharmony_ci		retval = -ENOMEM;
309062306a36Sopenharmony_ci		goto i2c_fail;
309162306a36Sopenharmony_ci	}
309262306a36Sopenharmony_ci	udc->udca_p_base = dma_handle;
309362306a36Sopenharmony_ci	dev_dbg(udc->dev, "DMA buffer(0x%x bytes), P:0x%08x, V:0x%p\n",
309462306a36Sopenharmony_ci		UDCA_BUFF_SIZE, udc->udca_p_base, udc->udca_v_base);
309562306a36Sopenharmony_ci
309662306a36Sopenharmony_ci	/* Setup the DD DMA memory pool */
309762306a36Sopenharmony_ci	udc->dd_cache = dma_pool_create("udc_dd", udc->dev,
309862306a36Sopenharmony_ci					sizeof(struct lpc32xx_usbd_dd_gad),
309962306a36Sopenharmony_ci					sizeof(u32), 0);
310062306a36Sopenharmony_ci	if (!udc->dd_cache) {
310162306a36Sopenharmony_ci		dev_err(udc->dev, "error getting DD DMA region\n");
310262306a36Sopenharmony_ci		retval = -ENOMEM;
310362306a36Sopenharmony_ci		goto dma_alloc_fail;
310462306a36Sopenharmony_ci	}
310562306a36Sopenharmony_ci
310662306a36Sopenharmony_ci	/* Clear USB peripheral and initialize gadget endpoints */
310762306a36Sopenharmony_ci	udc_disable(udc);
310862306a36Sopenharmony_ci	udc_reinit(udc);
310962306a36Sopenharmony_ci
311062306a36Sopenharmony_ci	/* Request IRQs - low and high priority USB device IRQs are routed to
311162306a36Sopenharmony_ci	 * the same handler, while the DMA interrupt is routed elsewhere */
311262306a36Sopenharmony_ci	retval = devm_request_irq(dev, udc->udp_irq[IRQ_USB_LP],
311362306a36Sopenharmony_ci				  lpc32xx_usb_lp_irq, 0, "udc_lp", udc);
311462306a36Sopenharmony_ci	if (retval < 0) {
311562306a36Sopenharmony_ci		dev_err(udc->dev, "LP request irq %d failed\n",
311662306a36Sopenharmony_ci			udc->udp_irq[IRQ_USB_LP]);
311762306a36Sopenharmony_ci		goto irq_req_fail;
311862306a36Sopenharmony_ci	}
311962306a36Sopenharmony_ci	retval = devm_request_irq(dev, udc->udp_irq[IRQ_USB_HP],
312062306a36Sopenharmony_ci				  lpc32xx_usb_hp_irq, 0, "udc_hp", udc);
312162306a36Sopenharmony_ci	if (retval < 0) {
312262306a36Sopenharmony_ci		dev_err(udc->dev, "HP request irq %d failed\n",
312362306a36Sopenharmony_ci			udc->udp_irq[IRQ_USB_HP]);
312462306a36Sopenharmony_ci		goto irq_req_fail;
312562306a36Sopenharmony_ci	}
312662306a36Sopenharmony_ci
312762306a36Sopenharmony_ci	retval = devm_request_irq(dev, udc->udp_irq[IRQ_USB_DEVDMA],
312862306a36Sopenharmony_ci				  lpc32xx_usb_devdma_irq, 0, "udc_dma", udc);
312962306a36Sopenharmony_ci	if (retval < 0) {
313062306a36Sopenharmony_ci		dev_err(udc->dev, "DEV request irq %d failed\n",
313162306a36Sopenharmony_ci			udc->udp_irq[IRQ_USB_DEVDMA]);
313262306a36Sopenharmony_ci		goto irq_req_fail;
313362306a36Sopenharmony_ci	}
313462306a36Sopenharmony_ci
313562306a36Sopenharmony_ci	/* The transceiver interrupt is used for VBUS detection and will
313662306a36Sopenharmony_ci	   kick off the VBUS handler function */
313762306a36Sopenharmony_ci	retval = devm_request_threaded_irq(dev, udc->udp_irq[IRQ_USB_ATX], NULL,
313862306a36Sopenharmony_ci					   lpc32xx_usb_vbus_irq, IRQF_ONESHOT,
313962306a36Sopenharmony_ci					   "udc_otg", udc);
314062306a36Sopenharmony_ci	if (retval < 0) {
314162306a36Sopenharmony_ci		dev_err(udc->dev, "VBUS request irq %d failed\n",
314262306a36Sopenharmony_ci			udc->udp_irq[IRQ_USB_ATX]);
314362306a36Sopenharmony_ci		goto irq_req_fail;
314462306a36Sopenharmony_ci	}
314562306a36Sopenharmony_ci
314662306a36Sopenharmony_ci	/* Initialize wait queue */
314762306a36Sopenharmony_ci	init_waitqueue_head(&udc->ep_disable_wait_queue);
314862306a36Sopenharmony_ci	atomic_set(&udc->enabled_ep_cnt, 0);
314962306a36Sopenharmony_ci
315062306a36Sopenharmony_ci	retval = usb_add_gadget_udc(dev, &udc->gadget);
315162306a36Sopenharmony_ci	if (retval < 0)
315262306a36Sopenharmony_ci		goto add_gadget_fail;
315362306a36Sopenharmony_ci
315462306a36Sopenharmony_ci	dev_set_drvdata(dev, udc);
315562306a36Sopenharmony_ci	device_init_wakeup(dev, 1);
315662306a36Sopenharmony_ci	create_debug_file(udc);
315762306a36Sopenharmony_ci
315862306a36Sopenharmony_ci	/* Disable clocks for now */
315962306a36Sopenharmony_ci	udc_clk_set(udc, 0);
316062306a36Sopenharmony_ci
316162306a36Sopenharmony_ci	dev_info(udc->dev, "%s version %s\n", driver_name, DRIVER_VERSION);
316262306a36Sopenharmony_ci	return 0;
316362306a36Sopenharmony_ci
316462306a36Sopenharmony_ciadd_gadget_fail:
316562306a36Sopenharmony_ciirq_req_fail:
316662306a36Sopenharmony_ci	dma_pool_destroy(udc->dd_cache);
316762306a36Sopenharmony_cidma_alloc_fail:
316862306a36Sopenharmony_ci	dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
316962306a36Sopenharmony_ci			  udc->udca_v_base, udc->udca_p_base);
317062306a36Sopenharmony_cii2c_fail:
317162306a36Sopenharmony_ci	clk_disable_unprepare(udc->usb_slv_clk);
317262306a36Sopenharmony_ci	dev_err(udc->dev, "%s probe failed, %d\n", driver_name, retval);
317362306a36Sopenharmony_ci
317462306a36Sopenharmony_ci	return retval;
317562306a36Sopenharmony_ci}
317662306a36Sopenharmony_ci
317762306a36Sopenharmony_cistatic int lpc32xx_udc_remove(struct platform_device *pdev)
317862306a36Sopenharmony_ci{
317962306a36Sopenharmony_ci	struct lpc32xx_udc *udc = platform_get_drvdata(pdev);
318062306a36Sopenharmony_ci
318162306a36Sopenharmony_ci	usb_del_gadget_udc(&udc->gadget);
318262306a36Sopenharmony_ci	if (udc->driver)
318362306a36Sopenharmony_ci		return -EBUSY;
318462306a36Sopenharmony_ci
318562306a36Sopenharmony_ci	udc_clk_set(udc, 1);
318662306a36Sopenharmony_ci	udc_disable(udc);
318762306a36Sopenharmony_ci	pullup(udc, 0);
318862306a36Sopenharmony_ci
318962306a36Sopenharmony_ci	device_init_wakeup(&pdev->dev, 0);
319062306a36Sopenharmony_ci	remove_debug_file(udc);
319162306a36Sopenharmony_ci
319262306a36Sopenharmony_ci	dma_pool_destroy(udc->dd_cache);
319362306a36Sopenharmony_ci	dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
319462306a36Sopenharmony_ci			  udc->udca_v_base, udc->udca_p_base);
319562306a36Sopenharmony_ci
319662306a36Sopenharmony_ci	clk_disable_unprepare(udc->usb_slv_clk);
319762306a36Sopenharmony_ci
319862306a36Sopenharmony_ci	return 0;
319962306a36Sopenharmony_ci}
320062306a36Sopenharmony_ci
320162306a36Sopenharmony_ci#ifdef CONFIG_PM
320262306a36Sopenharmony_cistatic int lpc32xx_udc_suspend(struct platform_device *pdev, pm_message_t mesg)
320362306a36Sopenharmony_ci{
320462306a36Sopenharmony_ci	struct lpc32xx_udc *udc = platform_get_drvdata(pdev);
320562306a36Sopenharmony_ci
320662306a36Sopenharmony_ci	if (udc->clocked) {
320762306a36Sopenharmony_ci		/* Power down ISP */
320862306a36Sopenharmony_ci		udc->poweron = 0;
320962306a36Sopenharmony_ci		isp1301_set_powerstate(udc, 0);
321062306a36Sopenharmony_ci
321162306a36Sopenharmony_ci		/* Disable clocking */
321262306a36Sopenharmony_ci		udc_clk_set(udc, 0);
321362306a36Sopenharmony_ci
321462306a36Sopenharmony_ci		/* Keep clock flag on, so we know to re-enable clocks
321562306a36Sopenharmony_ci		   on resume */
321662306a36Sopenharmony_ci		udc->clocked = 1;
321762306a36Sopenharmony_ci
321862306a36Sopenharmony_ci		/* Kill global USB clock */
321962306a36Sopenharmony_ci		clk_disable_unprepare(udc->usb_slv_clk);
322062306a36Sopenharmony_ci	}
322162306a36Sopenharmony_ci
322262306a36Sopenharmony_ci	return 0;
322362306a36Sopenharmony_ci}
322462306a36Sopenharmony_ci
322562306a36Sopenharmony_cistatic int lpc32xx_udc_resume(struct platform_device *pdev)
322662306a36Sopenharmony_ci{
322762306a36Sopenharmony_ci	struct lpc32xx_udc *udc = platform_get_drvdata(pdev);
322862306a36Sopenharmony_ci
322962306a36Sopenharmony_ci	if (udc->clocked) {
323062306a36Sopenharmony_ci		/* Enable global USB clock */
323162306a36Sopenharmony_ci		clk_prepare_enable(udc->usb_slv_clk);
323262306a36Sopenharmony_ci
323362306a36Sopenharmony_ci		/* Enable clocking */
323462306a36Sopenharmony_ci		udc_clk_set(udc, 1);
323562306a36Sopenharmony_ci
323662306a36Sopenharmony_ci		/* ISP back to normal power mode */
323762306a36Sopenharmony_ci		udc->poweron = 1;
323862306a36Sopenharmony_ci		isp1301_set_powerstate(udc, 1);
323962306a36Sopenharmony_ci	}
324062306a36Sopenharmony_ci
324162306a36Sopenharmony_ci	return 0;
324262306a36Sopenharmony_ci}
324362306a36Sopenharmony_ci#else
324462306a36Sopenharmony_ci#define	lpc32xx_udc_suspend	NULL
324562306a36Sopenharmony_ci#define	lpc32xx_udc_resume	NULL
324662306a36Sopenharmony_ci#endif
324762306a36Sopenharmony_ci
324862306a36Sopenharmony_ci#ifdef CONFIG_OF
324962306a36Sopenharmony_cistatic const struct of_device_id lpc32xx_udc_of_match[] = {
325062306a36Sopenharmony_ci	{ .compatible = "nxp,lpc3220-udc", },
325162306a36Sopenharmony_ci	{ },
325262306a36Sopenharmony_ci};
325362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, lpc32xx_udc_of_match);
325462306a36Sopenharmony_ci#endif
325562306a36Sopenharmony_ci
325662306a36Sopenharmony_cistatic struct platform_driver lpc32xx_udc_driver = {
325762306a36Sopenharmony_ci	.remove		= lpc32xx_udc_remove,
325862306a36Sopenharmony_ci	.shutdown	= lpc32xx_udc_shutdown,
325962306a36Sopenharmony_ci	.suspend	= lpc32xx_udc_suspend,
326062306a36Sopenharmony_ci	.resume		= lpc32xx_udc_resume,
326162306a36Sopenharmony_ci	.driver		= {
326262306a36Sopenharmony_ci		.name	= driver_name,
326362306a36Sopenharmony_ci		.of_match_table = of_match_ptr(lpc32xx_udc_of_match),
326462306a36Sopenharmony_ci	},
326562306a36Sopenharmony_ci};
326662306a36Sopenharmony_ci
326762306a36Sopenharmony_cimodule_platform_driver_probe(lpc32xx_udc_driver, lpc32xx_udc_probe);
326862306a36Sopenharmony_ci
326962306a36Sopenharmony_ciMODULE_DESCRIPTION("LPC32XX udc driver");
327062306a36Sopenharmony_ciMODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");
327162306a36Sopenharmony_ciMODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
327262306a36Sopenharmony_ciMODULE_LICENSE("GPL");
327362306a36Sopenharmony_ciMODULE_ALIAS("platform:lpc32xx_udc");
3274