xref: /rk3399_rockchip-uboot/drivers/usb/gadget/atmel_usba_udc.c (revision 1a4f6af8bfd44c8ae6e87a81ff125eed47042cc5)
19e40493fSBo Shen /*
29e40493fSBo Shen  * Driver for the Atmel USBA high speed USB device controller
39e40493fSBo Shen  * [Original from Linux kernel: drivers/usb/gadget/atmel_usba_udc.c]
49e40493fSBo Shen  *
59e40493fSBo Shen  * Copyright (C) 2005-2013 Atmel Corporation
69e40493fSBo Shen  *			   Bo Shen <voice.shen@atmel.com>
79e40493fSBo Shen  *
89e40493fSBo Shen  * SPDX-License-Identifier:     GPL-2.0+
99e40493fSBo Shen  */
109e40493fSBo Shen 
119e40493fSBo Shen #include <common.h>
121221ce45SMasahiro Yamada #include <linux/errno.h>
139e40493fSBo Shen #include <asm/gpio.h>
149e40493fSBo Shen #include <asm/hardware.h>
159e40493fSBo Shen #include <linux/list.h>
169e40493fSBo Shen #include <linux/usb/ch9.h>
179e40493fSBo Shen #include <linux/usb/gadget.h>
189e40493fSBo Shen #include <linux/usb/atmel_usba_udc.h>
199e40493fSBo Shen #include <malloc.h>
209e40493fSBo Shen 
219e40493fSBo Shen #include "atmel_usba_udc.h"
229e40493fSBo Shen 
vbus_is_present(struct usba_udc * udc)239e40493fSBo Shen static int vbus_is_present(struct usba_udc *udc)
249e40493fSBo Shen {
259e40493fSBo Shen 	/* No Vbus detection: Assume always present */
269e40493fSBo Shen 	return 1;
279e40493fSBo Shen }
289e40493fSBo Shen 
next_fifo_transaction(struct usba_ep * ep,struct usba_request * req)299e40493fSBo Shen static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req)
309e40493fSBo Shen {
319e40493fSBo Shen 	unsigned int transaction_len;
329e40493fSBo Shen 
339e40493fSBo Shen 	transaction_len = req->req.length - req->req.actual;
349e40493fSBo Shen 	req->last_transaction = 1;
359e40493fSBo Shen 	if (transaction_len > ep->ep.maxpacket) {
369e40493fSBo Shen 		transaction_len = ep->ep.maxpacket;
379e40493fSBo Shen 		req->last_transaction = 0;
389e40493fSBo Shen 	} else if (transaction_len == ep->ep.maxpacket && req->req.zero) {
399e40493fSBo Shen 			req->last_transaction = 0;
409e40493fSBo Shen 	}
419e40493fSBo Shen 
429e40493fSBo Shen 	DBG(DBG_QUEUE, "%s: submit_transaction, req %p (length %d)%s\n",
439e40493fSBo Shen 	    ep->ep.name, req, transaction_len,
449e40493fSBo Shen 	    req->last_transaction ? ", done" : "");
459e40493fSBo Shen 
469e40493fSBo Shen 	memcpy(ep->fifo, req->req.buf + req->req.actual, transaction_len);
479e40493fSBo Shen 	usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
489e40493fSBo Shen 	req->req.actual += transaction_len;
499e40493fSBo Shen }
509e40493fSBo Shen 
submit_request(struct usba_ep * ep,struct usba_request * req)519e40493fSBo Shen static void submit_request(struct usba_ep *ep, struct usba_request *req)
529e40493fSBo Shen {
539e40493fSBo Shen 	DBG(DBG_QUEUE, "%s: submit_request: req %p (length %d), dma: %d\n",
549e40493fSBo Shen 	    ep->ep.name, req, req->req.length, req->using_dma);
559e40493fSBo Shen 
569e40493fSBo Shen 	req->req.actual = 0;
579e40493fSBo Shen 	req->submitted = 1;
589e40493fSBo Shen 
599e40493fSBo Shen 	next_fifo_transaction(ep, req);
609e40493fSBo Shen 	if (req->last_transaction) {
619e40493fSBo Shen 		usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY);
629e40493fSBo Shen 		usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
639e40493fSBo Shen 	} else {
649e40493fSBo Shen 		usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
659e40493fSBo Shen 		usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY);
669e40493fSBo Shen 	}
679e40493fSBo Shen }
689e40493fSBo Shen 
submit_next_request(struct usba_ep * ep)699e40493fSBo Shen static void submit_next_request(struct usba_ep *ep)
709e40493fSBo Shen {
719e40493fSBo Shen 	struct usba_request *req;
729e40493fSBo Shen 
739e40493fSBo Shen 	if (list_empty(&ep->queue)) {
749e40493fSBo Shen 		usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY | USBA_RX_BK_RDY);
759e40493fSBo Shen 		return;
769e40493fSBo Shen 	}
779e40493fSBo Shen 
789e40493fSBo Shen 	req = list_entry(ep->queue.next, struct usba_request, queue);
799e40493fSBo Shen 	if (!req->submitted)
809e40493fSBo Shen 		submit_request(ep, req);
819e40493fSBo Shen }
829e40493fSBo Shen 
send_status(struct usba_udc * udc,struct usba_ep * ep)839e40493fSBo Shen static void send_status(struct usba_udc *udc, struct usba_ep *ep)
849e40493fSBo Shen {
859e40493fSBo Shen 	ep->state = STATUS_STAGE_IN;
869e40493fSBo Shen 	usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
879e40493fSBo Shen 	usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
889e40493fSBo Shen }
899e40493fSBo Shen 
receive_data(struct usba_ep * ep)909e40493fSBo Shen static void receive_data(struct usba_ep *ep)
919e40493fSBo Shen {
929e40493fSBo Shen 	struct usba_udc *udc = ep->udc;
939e40493fSBo Shen 	struct usba_request *req;
949e40493fSBo Shen 	unsigned long status;
959e40493fSBo Shen 	unsigned int bytecount, nr_busy;
969e40493fSBo Shen 	int is_complete = 0;
979e40493fSBo Shen 
989e40493fSBo Shen 	status = usba_ep_readl(ep, STA);
999e40493fSBo Shen 	nr_busy = USBA_BFEXT(BUSY_BANKS, status);
1009e40493fSBo Shen 
1019e40493fSBo Shen 	DBG(DBG_QUEUE, "receive data: nr_busy=%u\n", nr_busy);
1029e40493fSBo Shen 
1039e40493fSBo Shen 	while (nr_busy > 0) {
1049e40493fSBo Shen 		if (list_empty(&ep->queue)) {
1059e40493fSBo Shen 			usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
1069e40493fSBo Shen 			break;
1079e40493fSBo Shen 		}
1089e40493fSBo Shen 		req = list_entry(ep->queue.next,
1099e40493fSBo Shen 				 struct usba_request, queue);
1109e40493fSBo Shen 
1119e40493fSBo Shen 		bytecount = USBA_BFEXT(BYTE_COUNT, status);
1129e40493fSBo Shen 
1139e40493fSBo Shen 		if (status & USBA_SHORT_PACKET)
1149e40493fSBo Shen 			is_complete = 1;
1159e40493fSBo Shen 		if (req->req.actual + bytecount >= req->req.length) {
1169e40493fSBo Shen 			is_complete = 1;
1179e40493fSBo Shen 			bytecount = req->req.length - req->req.actual;
1189e40493fSBo Shen 		}
1199e40493fSBo Shen 
1209e40493fSBo Shen 		memcpy(req->req.buf + req->req.actual, ep->fifo, bytecount);
1219e40493fSBo Shen 		req->req.actual += bytecount;
1229e40493fSBo Shen 
1239e40493fSBo Shen 		usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
1249e40493fSBo Shen 
1259e40493fSBo Shen 		if (is_complete) {
1269e40493fSBo Shen 			DBG(DBG_QUEUE, "%s: request done\n", ep->ep.name);
1279e40493fSBo Shen 			req->req.status = 0;
1289e40493fSBo Shen 			list_del_init(&req->queue);
1299e40493fSBo Shen 			usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
1309e40493fSBo Shen 			spin_lock(&udc->lock);
1319e40493fSBo Shen 			req->req.complete(&ep->ep, &req->req);
1329e40493fSBo Shen 			spin_unlock(&udc->lock);
1339e40493fSBo Shen 		}
1349e40493fSBo Shen 
1359e40493fSBo Shen 		status = usba_ep_readl(ep, STA);
1369e40493fSBo Shen 		nr_busy = USBA_BFEXT(BUSY_BANKS, status);
1379e40493fSBo Shen 
1389e40493fSBo Shen 		if (is_complete && ep_is_control(ep)) {
1399e40493fSBo Shen 			send_status(udc, ep);
1409e40493fSBo Shen 			break;
1419e40493fSBo Shen 		}
1429e40493fSBo Shen 	}
1439e40493fSBo Shen }
1449e40493fSBo Shen 
1459e40493fSBo Shen static void
request_complete(struct usba_ep * ep,struct usba_request * req,int status)1469e40493fSBo Shen request_complete(struct usba_ep *ep, struct usba_request *req, int status)
1479e40493fSBo Shen {
1489e40493fSBo Shen 	if (req->req.status == -EINPROGRESS)
1499e40493fSBo Shen 		req->req.status = status;
1509e40493fSBo Shen 
1519e40493fSBo Shen 	DBG(DBG_GADGET | DBG_REQ, "%s: req %p complete: status %d, actual %u\n",
1529e40493fSBo Shen 	    ep->ep.name, req, req->req.status, req->req.actual);
1539e40493fSBo Shen 
1549e40493fSBo Shen 	req->req.complete(&ep->ep, &req->req);
1559e40493fSBo Shen }
1569e40493fSBo Shen 
1579e40493fSBo Shen static void
request_complete_list(struct usba_ep * ep,struct list_head * list,int status)1589e40493fSBo Shen request_complete_list(struct usba_ep *ep, struct list_head *list, int status)
1599e40493fSBo Shen {
1609e40493fSBo Shen 	struct usba_request *req, *tmp_req;
1619e40493fSBo Shen 
1629e40493fSBo Shen 	list_for_each_entry_safe(req, tmp_req, list, queue) {
1639e40493fSBo Shen 		list_del_init(&req->queue);
1649e40493fSBo Shen 		request_complete(ep, req, status);
1659e40493fSBo Shen 	}
1669e40493fSBo Shen }
1679e40493fSBo Shen 
1689e40493fSBo Shen static int
usba_ep_enable(struct usb_ep * _ep,const struct usb_endpoint_descriptor * desc)1699e40493fSBo Shen usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
1709e40493fSBo Shen {
1719e40493fSBo Shen 	struct usba_ep *ep = to_usba_ep(_ep);
1729e40493fSBo Shen 	struct usba_udc *udc = ep->udc;
173f9abd4b4SBo Shen 	unsigned long flags = 0, ept_cfg, maxpacket;
1749e40493fSBo Shen 	unsigned int nr_trans;
1759e40493fSBo Shen 
1769e40493fSBo Shen 	DBG(DBG_GADGET, "%s: ep_enable: desc=%p\n", ep->ep.name, desc);
1779e40493fSBo Shen 
1789e40493fSBo Shen 	maxpacket = usb_endpoint_maxp(desc) & 0x7ff;
1799e40493fSBo Shen 
1809e40493fSBo Shen 	if (((desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)
1819e40493fSBo Shen 	      != ep->index) ||
1829e40493fSBo Shen 	      ep->index == 0 ||
1839e40493fSBo Shen 	      desc->bDescriptorType != USB_DT_ENDPOINT ||
1849e40493fSBo Shen 	      maxpacket == 0 ||
1859e40493fSBo Shen 	      maxpacket > ep->fifo_size) {
1869e40493fSBo Shen 		DBG(DBG_ERR, "ep_enable: Invalid argument");
1879e40493fSBo Shen 		return -EINVAL;
1889e40493fSBo Shen 	}
1899e40493fSBo Shen 
1909e40493fSBo Shen 	ep->is_isoc = 0;
1919e40493fSBo Shen 	ep->is_in = 0;
1929e40493fSBo Shen 
1939e40493fSBo Shen 	if (maxpacket <= 8)
1949e40493fSBo Shen 		ept_cfg = USBA_BF(EPT_SIZE, USBA_EPT_SIZE_8);
1959e40493fSBo Shen 	else
1969e40493fSBo Shen 		/* LSB is bit 1, not 0 */
1979e40493fSBo Shen 		ept_cfg = USBA_BF(EPT_SIZE, fls(maxpacket - 1) - 3);
1989e40493fSBo Shen 
1999e40493fSBo Shen 	DBG(DBG_HW, "%s: EPT_SIZE = %lu (maxpacket = %lu)\n",
2009e40493fSBo Shen 	    ep->ep.name, ept_cfg, maxpacket);
2019e40493fSBo Shen 
2029e40493fSBo Shen 	if (usb_endpoint_dir_in(desc)) {
2039e40493fSBo Shen 		ep->is_in = 1;
2049e40493fSBo Shen 		ept_cfg |= USBA_EPT_DIR_IN;
2059e40493fSBo Shen 	}
2069e40493fSBo Shen 
2079e40493fSBo Shen 	switch (usb_endpoint_type(desc)) {
2089e40493fSBo Shen 	case USB_ENDPOINT_XFER_CONTROL:
2099e40493fSBo Shen 		ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL);
2109e40493fSBo Shen 		ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE);
2119e40493fSBo Shen 		break;
2129e40493fSBo Shen 	case USB_ENDPOINT_XFER_ISOC:
2139e40493fSBo Shen 		if (!ep->can_isoc) {
2149e40493fSBo Shen 			DBG(DBG_ERR, "ep_enable: %s is not isoc capable\n",
2159e40493fSBo Shen 			    ep->ep.name);
2169e40493fSBo Shen 			return -EINVAL;
2179e40493fSBo Shen 		}
2189e40493fSBo Shen 
2199e40493fSBo Shen 		/*
2209e40493fSBo Shen 		 * Bits 11:12 specify number of _additional_
2219e40493fSBo Shen 		 * transactions per microframe.
2229e40493fSBo Shen 		 */
2239e40493fSBo Shen 		nr_trans = ((usb_endpoint_maxp(desc) >> 11) & 3) + 1;
2249e40493fSBo Shen 		if (nr_trans > 3)
2259e40493fSBo Shen 			return -EINVAL;
2269e40493fSBo Shen 
2279e40493fSBo Shen 		ep->is_isoc = 1;
2289e40493fSBo Shen 		ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_ISO);
2299e40493fSBo Shen 
2309e40493fSBo Shen 		/*
2319e40493fSBo Shen 		 * Do triple-buffering on high-bandwidth iso endpoints.
2329e40493fSBo Shen 		 */
2339e40493fSBo Shen 		if (nr_trans > 1 && ep->nr_banks == 3)
2349e40493fSBo Shen 			ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_TRIPLE);
2359e40493fSBo Shen 		else
2369e40493fSBo Shen 			ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE);
2379e40493fSBo Shen 		ept_cfg |= USBA_BF(NB_TRANS, nr_trans);
2389e40493fSBo Shen 		break;
2399e40493fSBo Shen 	case USB_ENDPOINT_XFER_BULK:
2409e40493fSBo Shen 		ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK);
2419e40493fSBo Shen 		ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE);
2429e40493fSBo Shen 		break;
2439e40493fSBo Shen 	case USB_ENDPOINT_XFER_INT:
2449e40493fSBo Shen 		ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_INT);
2459e40493fSBo Shen 		ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE);
2469e40493fSBo Shen 		break;
2479e40493fSBo Shen 	}
2489e40493fSBo Shen 
2499e40493fSBo Shen 	spin_lock_irqsave(&ep->udc->lock, flags);
2509e40493fSBo Shen 
2519e40493fSBo Shen 	ep->desc = desc;
2529e40493fSBo Shen 	ep->ep.maxpacket = maxpacket;
2539e40493fSBo Shen 
2549e40493fSBo Shen 	usba_ep_writel(ep, CFG, ept_cfg);
2559e40493fSBo Shen 	usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE);
2569e40493fSBo Shen 
2579e40493fSBo Shen 	usba_writel(udc, INT_ENB,
2589e40493fSBo Shen 		    (usba_readl(udc, INT_ENB)
2599e40493fSBo Shen 		     | USBA_BF(EPT_INT, 1 << ep->index)));
2609e40493fSBo Shen 
2619e40493fSBo Shen 	spin_unlock_irqrestore(&udc->lock, flags);
2629e40493fSBo Shen 
2639e40493fSBo Shen 	DBG(DBG_HW, "EPT_CFG%d after init: %#08lx\n", ep->index,
2649e40493fSBo Shen 	    (unsigned long)usba_ep_readl(ep, CFG));
2659e40493fSBo Shen 	DBG(DBG_HW, "INT_ENB after init: %#08lx\n",
2669e40493fSBo Shen 	    (unsigned long)usba_readl(udc, INT_ENB));
2679e40493fSBo Shen 
2689e40493fSBo Shen 	return 0;
2699e40493fSBo Shen }
2709e40493fSBo Shen 
usba_ep_disable(struct usb_ep * _ep)2719e40493fSBo Shen static int usba_ep_disable(struct usb_ep *_ep)
2729e40493fSBo Shen {
2739e40493fSBo Shen 	struct usba_ep *ep = to_usba_ep(_ep);
2749e40493fSBo Shen 	struct usba_udc *udc = ep->udc;
2759e40493fSBo Shen 	LIST_HEAD(req_list);
276f9abd4b4SBo Shen 	unsigned long flags = 0;
2779e40493fSBo Shen 
2789e40493fSBo Shen 	DBG(DBG_GADGET, "ep_disable: %s\n", ep->ep.name);
2799e40493fSBo Shen 
2809e40493fSBo Shen 	spin_lock_irqsave(&udc->lock, flags);
2819e40493fSBo Shen 
2829e40493fSBo Shen 	if (!ep->desc) {
2839e40493fSBo Shen 		spin_unlock_irqrestore(&udc->lock, flags);
2849e40493fSBo Shen 		/* REVISIT because this driver disables endpoints in
2859e40493fSBo Shen 		 * reset_all_endpoints() before calling disconnect(),
2869e40493fSBo Shen 		 * most gadget drivers would trigger this non-error ...
2879e40493fSBo Shen 		 */
2889e40493fSBo Shen 		if (udc->gadget.speed != USB_SPEED_UNKNOWN)
2899e40493fSBo Shen 			DBG(DBG_ERR, "ep_disable: %s not enabled\n",
2909e40493fSBo Shen 			    ep->ep.name);
2919e40493fSBo Shen 		return -EINVAL;
2929e40493fSBo Shen 	}
2939e40493fSBo Shen 	ep->desc = NULL;
2949e40493fSBo Shen 
2959e40493fSBo Shen 	list_splice_init(&ep->queue, &req_list);
2969e40493fSBo Shen 	usba_ep_writel(ep, CFG, 0);
2979e40493fSBo Shen 	usba_ep_writel(ep, CTL_DIS, USBA_EPT_ENABLE);
2989e40493fSBo Shen 	usba_writel(udc, INT_ENB,
2999e40493fSBo Shen 		    usba_readl(udc, INT_ENB) &
3009e40493fSBo Shen 		    ~USBA_BF(EPT_INT, 1 << ep->index));
3019e40493fSBo Shen 
3029e40493fSBo Shen 	request_complete_list(ep, &req_list, -ESHUTDOWN);
3039e40493fSBo Shen 
3049e40493fSBo Shen 	spin_unlock_irqrestore(&udc->lock, flags);
3059e40493fSBo Shen 
3069e40493fSBo Shen 	return 0;
3079e40493fSBo Shen }
3089e40493fSBo Shen 
3099e40493fSBo Shen static struct usb_request *
usba_ep_alloc_request(struct usb_ep * _ep,gfp_t gfp_flags)3109e40493fSBo Shen usba_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
3119e40493fSBo Shen {
3129e40493fSBo Shen 	struct usba_request *req;
3139e40493fSBo Shen 
3149e40493fSBo Shen 	DBG(DBG_GADGET, "ep_alloc_request: %p, 0x%x\n", _ep, gfp_flags);
3159e40493fSBo Shen 
316369d3c43SStephen Warren 	req = calloc(1, sizeof(struct usba_request));
3179e40493fSBo Shen 	if (!req)
3189e40493fSBo Shen 		return NULL;
3199e40493fSBo Shen 
3209e40493fSBo Shen 	INIT_LIST_HEAD(&req->queue);
3219e40493fSBo Shen 
3229e40493fSBo Shen 	return &req->req;
3239e40493fSBo Shen }
3249e40493fSBo Shen 
3259e40493fSBo Shen static void
usba_ep_free_request(struct usb_ep * _ep,struct usb_request * _req)3269e40493fSBo Shen usba_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
3279e40493fSBo Shen {
3289e40493fSBo Shen 	struct usba_request *req = to_usba_req(_req);
3299e40493fSBo Shen 
3309e40493fSBo Shen 	DBG(DBG_GADGET, "ep_free_request: %p, %p\n", _ep, _req);
3319e40493fSBo Shen 
3329e40493fSBo Shen 	free(req);
3339e40493fSBo Shen }
3349e40493fSBo Shen 
3359e40493fSBo Shen static int
usba_ep_queue(struct usb_ep * _ep,struct usb_request * _req,gfp_t gfp_flags)3369e40493fSBo Shen usba_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
3379e40493fSBo Shen {
3389e40493fSBo Shen 	struct usba_request *req = to_usba_req(_req);
3399e40493fSBo Shen 	struct usba_ep *ep = to_usba_ep(_ep);
3409e40493fSBo Shen 	struct usba_udc *udc = ep->udc;
341f9abd4b4SBo Shen 	unsigned long flags = 0;
3429e40493fSBo Shen 	int ret;
3439e40493fSBo Shen 
3449e40493fSBo Shen 	DBG(DBG_GADGET | DBG_QUEUE | DBG_REQ, "%s: queue req %p, len %u\n",
3459e40493fSBo Shen 	    ep->ep.name, req, _req->length);
3469e40493fSBo Shen 
3479e40493fSBo Shen 	if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN ||
3489e40493fSBo Shen 	    !ep->desc)
3499e40493fSBo Shen 		return -ESHUTDOWN;
3509e40493fSBo Shen 
3519e40493fSBo Shen 	req->submitted = 0;
3529e40493fSBo Shen 	req->using_dma = 0;
3539e40493fSBo Shen 	req->last_transaction = 0;
3549e40493fSBo Shen 
3559e40493fSBo Shen 	_req->status = -EINPROGRESS;
3569e40493fSBo Shen 	_req->actual = 0;
3579e40493fSBo Shen 
3589e40493fSBo Shen 	/* May have received a reset since last time we checked */
3599e40493fSBo Shen 	ret = -ESHUTDOWN;
3609e40493fSBo Shen 	spin_lock_irqsave(&udc->lock, flags);
3619e40493fSBo Shen 	if (ep->desc) {
3629e40493fSBo Shen 		list_add_tail(&req->queue, &ep->queue);
3639e40493fSBo Shen 
3649e40493fSBo Shen 		if ((!ep_is_control(ep) && ep->is_in) ||
3659e40493fSBo Shen 		    (ep_is_control(ep) && (ep->state == DATA_STAGE_IN ||
3669e40493fSBo Shen 		    ep->state == STATUS_STAGE_IN)))
3679e40493fSBo Shen 			usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY);
3689e40493fSBo Shen 		else
3699e40493fSBo Shen 			usba_ep_writel(ep, CTL_ENB, USBA_RX_BK_RDY);
3709e40493fSBo Shen 
3719e40493fSBo Shen 		ret = 0;
3729e40493fSBo Shen 	}
3739e40493fSBo Shen 	spin_unlock_irqrestore(&udc->lock, flags);
3749e40493fSBo Shen 
3759e40493fSBo Shen 	return ret;
3769e40493fSBo Shen }
3779e40493fSBo Shen 
usba_ep_dequeue(struct usb_ep * _ep,struct usb_request * _req)3789e40493fSBo Shen static int usba_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
3799e40493fSBo Shen {
3809e40493fSBo Shen 	struct usba_ep *ep = to_usba_ep(_ep);
3819e40493fSBo Shen 	struct usba_request *req = to_usba_req(_req);
3829e40493fSBo Shen 
3839e40493fSBo Shen 	DBG(DBG_GADGET | DBG_QUEUE, "ep_dequeue: %s, req %p\n",
3849e40493fSBo Shen 	    ep->ep.name, req);
3859e40493fSBo Shen 
3869e40493fSBo Shen 	/*
3879e40493fSBo Shen 	 * Errors should stop the queue from advancing until the
3889e40493fSBo Shen 	 * completion function returns.
3899e40493fSBo Shen 	 */
3909e40493fSBo Shen 	list_del_init(&req->queue);
3919e40493fSBo Shen 
3929e40493fSBo Shen 	request_complete(ep, req, -ECONNRESET);
3939e40493fSBo Shen 
3949e40493fSBo Shen 	/* Process the next request if any */
3959e40493fSBo Shen 	submit_next_request(ep);
3969e40493fSBo Shen 
3979e40493fSBo Shen 	return 0;
3989e40493fSBo Shen }
3999e40493fSBo Shen 
usba_ep_set_halt(struct usb_ep * _ep,int value)4009e40493fSBo Shen static int usba_ep_set_halt(struct usb_ep *_ep, int value)
4019e40493fSBo Shen {
4029e40493fSBo Shen 	struct usba_ep *ep = to_usba_ep(_ep);
403f9abd4b4SBo Shen 	unsigned long flags = 0;
4049e40493fSBo Shen 	int ret = 0;
4059e40493fSBo Shen 
4069e40493fSBo Shen 	DBG(DBG_GADGET, "endpoint %s: %s HALT\n", ep->ep.name,
4079e40493fSBo Shen 	    value ? "set" : "clear");
4089e40493fSBo Shen 
4099e40493fSBo Shen 	if (!ep->desc) {
4109e40493fSBo Shen 		DBG(DBG_ERR, "Attempted to halt uninitialized ep %s\n",
4119e40493fSBo Shen 		    ep->ep.name);
4129e40493fSBo Shen 		return -ENODEV;
4139e40493fSBo Shen 	}
4149e40493fSBo Shen 
4159e40493fSBo Shen 	if (ep->is_isoc) {
4169e40493fSBo Shen 		DBG(DBG_ERR, "Attempted to halt isochronous ep %s\n",
4179e40493fSBo Shen 		    ep->ep.name);
4189e40493fSBo Shen 		return -ENOTTY;
4199e40493fSBo Shen 	}
4209e40493fSBo Shen 
4219e40493fSBo Shen 	spin_lock_irqsave(&udc->lock, flags);
4229e40493fSBo Shen 
4239e40493fSBo Shen 	/*
4249e40493fSBo Shen 	 * We can't halt IN endpoints while there are still data to be
4259e40493fSBo Shen 	 * transferred
4269e40493fSBo Shen 	 */
4279e40493fSBo Shen 	if (!list_empty(&ep->queue) ||
4289e40493fSBo Shen 	    ((value && ep->is_in && (usba_ep_readl(ep, STA) &
4299e40493fSBo Shen 	    USBA_BF(BUSY_BANKS, -1L))))) {
4309e40493fSBo Shen 		ret = -EAGAIN;
4319e40493fSBo Shen 	} else {
4329e40493fSBo Shen 		if (value)
4339e40493fSBo Shen 			usba_ep_writel(ep, SET_STA, USBA_FORCE_STALL);
4349e40493fSBo Shen 		else
4359e40493fSBo Shen 			usba_ep_writel(ep, CLR_STA,
4369e40493fSBo Shen 				       USBA_FORCE_STALL | USBA_TOGGLE_CLR);
4379e40493fSBo Shen 		usba_ep_readl(ep, STA);
4389e40493fSBo Shen 	}
4399e40493fSBo Shen 
4409e40493fSBo Shen 	spin_unlock_irqrestore(&udc->lock, flags);
4419e40493fSBo Shen 
4429e40493fSBo Shen 	return ret;
4439e40493fSBo Shen }
4449e40493fSBo Shen 
usba_ep_fifo_status(struct usb_ep * _ep)4459e40493fSBo Shen static int usba_ep_fifo_status(struct usb_ep *_ep)
4469e40493fSBo Shen {
4479e40493fSBo Shen 	struct usba_ep *ep = to_usba_ep(_ep);
4489e40493fSBo Shen 
4499e40493fSBo Shen 	return USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA));
4509e40493fSBo Shen }
4519e40493fSBo Shen 
usba_ep_fifo_flush(struct usb_ep * _ep)4529e40493fSBo Shen static void usba_ep_fifo_flush(struct usb_ep *_ep)
4539e40493fSBo Shen {
4549e40493fSBo Shen 	struct usba_ep *ep = to_usba_ep(_ep);
4559e40493fSBo Shen 	struct usba_udc *udc = ep->udc;
4569e40493fSBo Shen 
4579e40493fSBo Shen 	usba_writel(udc, EPT_RST, 1 << ep->index);
4589e40493fSBo Shen }
4599e40493fSBo Shen 
4609e40493fSBo Shen static const struct usb_ep_ops usba_ep_ops = {
4619e40493fSBo Shen 	.enable		= usba_ep_enable,
4629e40493fSBo Shen 	.disable	= usba_ep_disable,
4639e40493fSBo Shen 	.alloc_request	= usba_ep_alloc_request,
4649e40493fSBo Shen 	.free_request	= usba_ep_free_request,
4659e40493fSBo Shen 	.queue		= usba_ep_queue,
4669e40493fSBo Shen 	.dequeue	= usba_ep_dequeue,
4679e40493fSBo Shen 	.set_halt	= usba_ep_set_halt,
4689e40493fSBo Shen 	.fifo_status	= usba_ep_fifo_status,
4699e40493fSBo Shen 	.fifo_flush	= usba_ep_fifo_flush,
4709e40493fSBo Shen };
4719e40493fSBo Shen 
usba_udc_get_frame(struct usb_gadget * gadget)4729e40493fSBo Shen static int usba_udc_get_frame(struct usb_gadget *gadget)
4739e40493fSBo Shen {
4749e40493fSBo Shen 	struct usba_udc *udc = to_usba_udc(gadget);
4759e40493fSBo Shen 
4769e40493fSBo Shen 	return USBA_BFEXT(FRAME_NUMBER, usba_readl(udc, FNUM));
4779e40493fSBo Shen }
4789e40493fSBo Shen 
usba_udc_wakeup(struct usb_gadget * gadget)4799e40493fSBo Shen static int usba_udc_wakeup(struct usb_gadget *gadget)
4809e40493fSBo Shen {
4819e40493fSBo Shen 	struct usba_udc *udc = to_usba_udc(gadget);
482f9abd4b4SBo Shen 	unsigned long flags = 0;
4839e40493fSBo Shen 	u32 ctrl;
4849e40493fSBo Shen 	int ret = -EINVAL;
4859e40493fSBo Shen 
4869e40493fSBo Shen 	spin_lock_irqsave(&udc->lock, flags);
4879e40493fSBo Shen 	if (udc->devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
4889e40493fSBo Shen 		ctrl = usba_readl(udc, CTRL);
4899e40493fSBo Shen 		usba_writel(udc, CTRL, ctrl | USBA_REMOTE_WAKE_UP);
4909e40493fSBo Shen 		ret = 0;
4919e40493fSBo Shen 	}
4929e40493fSBo Shen 	spin_unlock_irqrestore(&udc->lock, flags);
4939e40493fSBo Shen 
4949e40493fSBo Shen 	return ret;
4959e40493fSBo Shen }
4969e40493fSBo Shen 
4979e40493fSBo Shen static int
usba_udc_set_selfpowered(struct usb_gadget * gadget,int is_selfpowered)4989e40493fSBo Shen usba_udc_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered)
4999e40493fSBo Shen {
5009e40493fSBo Shen 	struct usba_udc *udc = to_usba_udc(gadget);
501f9abd4b4SBo Shen 	unsigned long flags = 0;
5029e40493fSBo Shen 
5039e40493fSBo Shen 	spin_lock_irqsave(&udc->lock, flags);
5049e40493fSBo Shen 	if (is_selfpowered)
5059e40493fSBo Shen 		udc->devstatus |= 1 << USB_DEVICE_SELF_POWERED;
5069e40493fSBo Shen 	else
5079e40493fSBo Shen 		udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);
5089e40493fSBo Shen 	spin_unlock_irqrestore(&udc->lock, flags);
5099e40493fSBo Shen 
5109e40493fSBo Shen 	return 0;
5119e40493fSBo Shen }
5129e40493fSBo Shen 
5139e40493fSBo Shen static const struct usb_gadget_ops usba_udc_ops = {
5149e40493fSBo Shen 	.get_frame		= usba_udc_get_frame,
5159e40493fSBo Shen 	.wakeup			= usba_udc_wakeup,
5169e40493fSBo Shen 	.set_selfpowered	= usba_udc_set_selfpowered,
5179e40493fSBo Shen };
5189e40493fSBo Shen 
5199e40493fSBo Shen static struct usb_endpoint_descriptor usba_ep0_desc = {
5209e40493fSBo Shen 	.bLength = USB_DT_ENDPOINT_SIZE,
5219e40493fSBo Shen 	.bDescriptorType = USB_DT_ENDPOINT,
5229e40493fSBo Shen 	.bEndpointAddress = 0,
5239e40493fSBo Shen 	.bmAttributes = USB_ENDPOINT_XFER_CONTROL,
5249e40493fSBo Shen 	.wMaxPacketSize = cpu_to_le16(64),
5259e40493fSBo Shen 	/* FIXME: I have no idea what to put here */
5269e40493fSBo Shen 	.bInterval = 1,
5279e40493fSBo Shen };
5289e40493fSBo Shen 
5299e40493fSBo Shen /*
5309e40493fSBo Shen  * Called with interrupts disabled and udc->lock held.
5319e40493fSBo Shen  */
reset_all_endpoints(struct usba_udc * udc)5329e40493fSBo Shen static void reset_all_endpoints(struct usba_udc *udc)
5339e40493fSBo Shen {
5349e40493fSBo Shen 	struct usba_ep *ep;
5359e40493fSBo Shen 	struct usba_request *req, *tmp_req;
5369e40493fSBo Shen 
5379e40493fSBo Shen 	usba_writel(udc, EPT_RST, ~0UL);
5389e40493fSBo Shen 
5399e40493fSBo Shen 	ep = to_usba_ep(udc->gadget.ep0);
5409e40493fSBo Shen 	list_for_each_entry_safe(req, tmp_req, &ep->queue, queue) {
5419e40493fSBo Shen 		list_del_init(&req->queue);
5429e40493fSBo Shen 		request_complete(ep, req, -ECONNRESET);
5439e40493fSBo Shen 	}
5449e40493fSBo Shen 
5459e40493fSBo Shen 	/* NOTE:  normally, the next call to the gadget driver is in
5469e40493fSBo Shen 	 * charge of disabling endpoints... usually disconnect().
5479e40493fSBo Shen 	 * The exception would be entering a high speed test mode.
5489e40493fSBo Shen 	 *
5499e40493fSBo Shen 	 * FIXME remove this code ... and retest thoroughly.
5509e40493fSBo Shen 	 */
5519e40493fSBo Shen 	list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
5529e40493fSBo Shen 		if (ep->desc) {
5539e40493fSBo Shen 			spin_unlock(&udc->lock);
5549e40493fSBo Shen 			usba_ep_disable(&ep->ep);
5559e40493fSBo Shen 			spin_lock(&udc->lock);
5569e40493fSBo Shen 		}
5579e40493fSBo Shen 	}
5589e40493fSBo Shen }
5599e40493fSBo Shen 
get_ep_by_addr(struct usba_udc * udc,u16 wIndex)5609e40493fSBo Shen static struct usba_ep *get_ep_by_addr(struct usba_udc *udc, u16 wIndex)
5619e40493fSBo Shen {
5629e40493fSBo Shen 	struct usba_ep *ep;
5639e40493fSBo Shen 
5649e40493fSBo Shen 	if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
5659e40493fSBo Shen 		return to_usba_ep(udc->gadget.ep0);
5669e40493fSBo Shen 
5679e40493fSBo Shen 	list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
5689e40493fSBo Shen 		u8 bEndpointAddress;
5699e40493fSBo Shen 
5709e40493fSBo Shen 		if (!ep->desc)
5719e40493fSBo Shen 			continue;
5729e40493fSBo Shen 		bEndpointAddress = ep->desc->bEndpointAddress;
5739e40493fSBo Shen 		if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
5749e40493fSBo Shen 			continue;
5759e40493fSBo Shen 		if ((bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)
5769e40493fSBo Shen 				== (wIndex & USB_ENDPOINT_NUMBER_MASK))
5779e40493fSBo Shen 			return ep;
5789e40493fSBo Shen 	}
5799e40493fSBo Shen 
5809e40493fSBo Shen 	return NULL;
5819e40493fSBo Shen }
5829e40493fSBo Shen 
5839e40493fSBo Shen /* Called with interrupts disabled and udc->lock held */
set_protocol_stall(struct usba_udc * udc,struct usba_ep * ep)5849e40493fSBo Shen static inline void set_protocol_stall(struct usba_udc *udc, struct usba_ep *ep)
5859e40493fSBo Shen {
5869e40493fSBo Shen 	usba_ep_writel(ep, SET_STA, USBA_FORCE_STALL);
5879e40493fSBo Shen 	ep->state = WAIT_FOR_SETUP;
5889e40493fSBo Shen }
5899e40493fSBo Shen 
is_stalled(struct usba_udc * udc,struct usba_ep * ep)5909e40493fSBo Shen static inline int is_stalled(struct usba_udc *udc, struct usba_ep *ep)
5919e40493fSBo Shen {
5929e40493fSBo Shen 	if (usba_ep_readl(ep, STA) & USBA_FORCE_STALL)
5939e40493fSBo Shen 		return 1;
5949e40493fSBo Shen 	return 0;
5959e40493fSBo Shen }
5969e40493fSBo Shen 
set_address(struct usba_udc * udc,unsigned int addr)5979e40493fSBo Shen static inline void set_address(struct usba_udc *udc, unsigned int addr)
5989e40493fSBo Shen {
5999e40493fSBo Shen 	u32 regval;
6009e40493fSBo Shen 
6019e40493fSBo Shen 	DBG(DBG_BUS, "setting address %u...\n", addr);
6029e40493fSBo Shen 	regval = usba_readl(udc, CTRL);
6039e40493fSBo Shen 	regval = USBA_BFINS(DEV_ADDR, addr, regval);
6049e40493fSBo Shen 	usba_writel(udc, CTRL, regval);
6059e40493fSBo Shen }
6069e40493fSBo Shen 
do_test_mode(struct usba_udc * udc)6079e40493fSBo Shen static int do_test_mode(struct usba_udc *udc)
6089e40493fSBo Shen {
6099e40493fSBo Shen 	static const char test_packet_buffer[] = {
6109e40493fSBo Shen 		/* JKJKJKJK * 9 */
6119e40493fSBo Shen 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6129e40493fSBo Shen 		/* JJKKJJKK * 8 */
6139e40493fSBo Shen 		0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
6149e40493fSBo Shen 		/* JJKKJJKK * 8 */
6159e40493fSBo Shen 		0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
6169e40493fSBo Shen 		/* JJJJJJJKKKKKKK * 8 */
6179e40493fSBo Shen 		0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
6189e40493fSBo Shen 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
6199e40493fSBo Shen 		/* JJJJJJJK * 8 */
6209e40493fSBo Shen 		0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD,
6219e40493fSBo Shen 		/* {JKKKKKKK * 10}, JK */
6229e40493fSBo Shen 		0xFC, 0x7E, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0x7E
6239e40493fSBo Shen 	};
6249e40493fSBo Shen 	struct usba_ep *ep;
6259e40493fSBo Shen 	int test_mode;
6269e40493fSBo Shen 
6279e40493fSBo Shen 	test_mode = udc->test_mode;
6289e40493fSBo Shen 
6299e40493fSBo Shen 	/* Start from a clean slate */
6309e40493fSBo Shen 	reset_all_endpoints(udc);
6319e40493fSBo Shen 
6329e40493fSBo Shen 	switch (test_mode) {
6339e40493fSBo Shen 	case 0x0100:
6349e40493fSBo Shen 		/* Test_J */
6359e40493fSBo Shen 		usba_writel(udc, TST, USBA_TST_J_MODE);
6369e40493fSBo Shen 		DBG(DBG_ALL, "Entering Test_J mode...\n");
6379e40493fSBo Shen 		break;
6389e40493fSBo Shen 	case 0x0200:
6399e40493fSBo Shen 		/* Test_K */
6409e40493fSBo Shen 		usba_writel(udc, TST, USBA_TST_K_MODE);
6419e40493fSBo Shen 		DBG(DBG_ALL, "Entering Test_K mode...\n");
6429e40493fSBo Shen 		break;
6439e40493fSBo Shen 	case 0x0300:
6449e40493fSBo Shen 		/*
6459e40493fSBo Shen 		 * Test_SE0_NAK: Force high-speed mode and set up ep0
6469e40493fSBo Shen 		 * for Bulk IN transfers
6479e40493fSBo Shen 		 */
6489e40493fSBo Shen 		ep = &udc->usba_ep[0];
6499e40493fSBo Shen 		usba_writel(udc, TST,
6509e40493fSBo Shen 			    USBA_BF(SPEED_CFG, USBA_SPEED_CFG_FORCE_HIGH));
6519e40493fSBo Shen 		usba_ep_writel(ep, CFG,
6529e40493fSBo Shen 			       USBA_BF(EPT_SIZE, USBA_EPT_SIZE_64)
6539e40493fSBo Shen 			       | USBA_EPT_DIR_IN
6549e40493fSBo Shen 			       | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK)
6559e40493fSBo Shen 			       | USBA_BF(BK_NUMBER, 1));
6569e40493fSBo Shen 		if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) {
6579e40493fSBo Shen 			set_protocol_stall(udc, ep);
6589e40493fSBo Shen 			DBG(DBG_ALL, "Test_SE0_NAK: ep0 not mapped\n");
6599e40493fSBo Shen 		} else {
6609e40493fSBo Shen 			usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE);
6619e40493fSBo Shen 			DBG(DBG_ALL, "Entering Test_SE0_NAK mode...\n");
6629e40493fSBo Shen 		}
6639e40493fSBo Shen 		break;
6649e40493fSBo Shen 	case 0x0400:
6659e40493fSBo Shen 		/* Test_Packet */
6669e40493fSBo Shen 		ep = &udc->usba_ep[0];
6679e40493fSBo Shen 		usba_ep_writel(ep, CFG,
6689e40493fSBo Shen 			       USBA_BF(EPT_SIZE, USBA_EPT_SIZE_64)
6699e40493fSBo Shen 			       | USBA_EPT_DIR_IN
6709e40493fSBo Shen 			       | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK)
6719e40493fSBo Shen 			       | USBA_BF(BK_NUMBER, 1));
6729e40493fSBo Shen 		if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) {
6739e40493fSBo Shen 			set_protocol_stall(udc, ep);
6749e40493fSBo Shen 			DBG(DBG_ALL, "Test_Packet: ep0 not mapped\n");
6759e40493fSBo Shen 		} else {
6769e40493fSBo Shen 			usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE);
6779e40493fSBo Shen 			usba_writel(udc, TST, USBA_TST_PKT_MODE);
6789e40493fSBo Shen 			memcpy(ep->fifo, test_packet_buffer,
6799e40493fSBo Shen 			       sizeof(test_packet_buffer));
6809e40493fSBo Shen 			usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
6819e40493fSBo Shen 			DBG(DBG_ALL, "Entering Test_Packet mode...\n");
6829e40493fSBo Shen 		}
6839e40493fSBo Shen 		break;
6849e40493fSBo Shen 	default:
6859e40493fSBo Shen 		DBG(DBG_ERR, "Invalid test mode: 0x%04x\n", test_mode);
6869e40493fSBo Shen 		return -EINVAL;
6879e40493fSBo Shen 	}
6889e40493fSBo Shen 
6899e40493fSBo Shen 	return 0;
6909e40493fSBo Shen }
6919e40493fSBo Shen 
6929e40493fSBo Shen /* Avoid overly long expressions */
feature_is_dev_remote_wakeup(struct usb_ctrlrequest * crq)6939e40493fSBo Shen static inline bool feature_is_dev_remote_wakeup(struct usb_ctrlrequest *crq)
6949e40493fSBo Shen {
6959e40493fSBo Shen 	if (crq->wValue == cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP))
6969e40493fSBo Shen 		return true;
6979e40493fSBo Shen 	return false;
6989e40493fSBo Shen }
6999e40493fSBo Shen 
feature_is_dev_test_mode(struct usb_ctrlrequest * crq)7009e40493fSBo Shen static inline bool feature_is_dev_test_mode(struct usb_ctrlrequest *crq)
7019e40493fSBo Shen {
7029e40493fSBo Shen 	if (crq->wValue == cpu_to_le16(USB_DEVICE_TEST_MODE))
7039e40493fSBo Shen 		return true;
7049e40493fSBo Shen 	return false;
7059e40493fSBo Shen }
7069e40493fSBo Shen 
feature_is_ep_halt(struct usb_ctrlrequest * crq)7079e40493fSBo Shen static inline bool feature_is_ep_halt(struct usb_ctrlrequest *crq)
7089e40493fSBo Shen {
7099e40493fSBo Shen 	if (crq->wValue == cpu_to_le16(USB_ENDPOINT_HALT))
7109e40493fSBo Shen 		return true;
7119e40493fSBo Shen 	return false;
7129e40493fSBo Shen }
7139e40493fSBo Shen 
handle_ep0_setup(struct usba_udc * udc,struct usba_ep * ep,struct usb_ctrlrequest * crq)7149e40493fSBo Shen static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep,
7159e40493fSBo Shen 		struct usb_ctrlrequest *crq)
7169e40493fSBo Shen {
7179e40493fSBo Shen 	int retval = 0;
7189e40493fSBo Shen 
7199e40493fSBo Shen 	switch (crq->bRequest) {
7209e40493fSBo Shen 	case USB_REQ_GET_STATUS: {
7219e40493fSBo Shen 		u16 status;
7229e40493fSBo Shen 
7239e40493fSBo Shen 		if (crq->bRequestType == (USB_DIR_IN | USB_RECIP_DEVICE)) {
7249e40493fSBo Shen 			status = cpu_to_le16(udc->devstatus);
7259e40493fSBo Shen 		} else if (crq->bRequestType
7269e40493fSBo Shen 				== (USB_DIR_IN | USB_RECIP_INTERFACE)) {
7279e40493fSBo Shen 			status = cpu_to_le16(0);
7289e40493fSBo Shen 		} else if (crq->bRequestType
7299e40493fSBo Shen 				== (USB_DIR_IN | USB_RECIP_ENDPOINT)) {
7309e40493fSBo Shen 			struct usba_ep *target;
7319e40493fSBo Shen 
7329e40493fSBo Shen 			target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
7339e40493fSBo Shen 			if (!target)
7349e40493fSBo Shen 				goto stall;
7359e40493fSBo Shen 
7369e40493fSBo Shen 			status = 0;
7379e40493fSBo Shen 			if (is_stalled(udc, target))
7389e40493fSBo Shen 				status |= cpu_to_le16(1);
7399e40493fSBo Shen 		} else {
7409e40493fSBo Shen 			goto delegate;
7419e40493fSBo Shen 		}
7429e40493fSBo Shen 
7439e40493fSBo Shen 		/* Write directly to the FIFO. No queueing is done. */
7449e40493fSBo Shen 		if (crq->wLength != cpu_to_le16(sizeof(status)))
7459e40493fSBo Shen 			goto stall;
7469e40493fSBo Shen 		ep->state = DATA_STAGE_IN;
7479e40493fSBo Shen 		__raw_writew(status, ep->fifo);
7489e40493fSBo Shen 		usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
7499e40493fSBo Shen 		break;
7509e40493fSBo Shen 	}
7519e40493fSBo Shen 
7529e40493fSBo Shen 	case USB_REQ_CLEAR_FEATURE: {
7539e40493fSBo Shen 		if (crq->bRequestType == USB_RECIP_DEVICE) {
7549e40493fSBo Shen 			if (feature_is_dev_remote_wakeup(crq))
7559e40493fSBo Shen 				udc->devstatus
7569e40493fSBo Shen 					&= ~(1 << USB_DEVICE_REMOTE_WAKEUP);
7579e40493fSBo Shen 			else
7589e40493fSBo Shen 				/* Can't CLEAR_FEATURE TEST_MODE */
7599e40493fSBo Shen 				goto stall;
7609e40493fSBo Shen 		} else if (crq->bRequestType == USB_RECIP_ENDPOINT) {
7619e40493fSBo Shen 			struct usba_ep *target;
7629e40493fSBo Shen 
7639e40493fSBo Shen 			if (crq->wLength != cpu_to_le16(0) ||
7649e40493fSBo Shen 			    !feature_is_ep_halt(crq))
7659e40493fSBo Shen 				goto stall;
7669e40493fSBo Shen 			target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
7679e40493fSBo Shen 			if (!target)
7689e40493fSBo Shen 				goto stall;
7699e40493fSBo Shen 
7709e40493fSBo Shen 			usba_ep_writel(target, CLR_STA, USBA_FORCE_STALL);
7719e40493fSBo Shen 			if (target->index != 0)
7729e40493fSBo Shen 				usba_ep_writel(target, CLR_STA,
7739e40493fSBo Shen 					       USBA_TOGGLE_CLR);
7749e40493fSBo Shen 		} else {
7759e40493fSBo Shen 			goto delegate;
7769e40493fSBo Shen 		}
7779e40493fSBo Shen 
7789e40493fSBo Shen 		send_status(udc, ep);
7799e40493fSBo Shen 		break;
7809e40493fSBo Shen 	}
7819e40493fSBo Shen 
7829e40493fSBo Shen 	case USB_REQ_SET_FEATURE: {
7839e40493fSBo Shen 		if (crq->bRequestType == USB_RECIP_DEVICE) {
7849e40493fSBo Shen 			if (feature_is_dev_test_mode(crq)) {
7859e40493fSBo Shen 				send_status(udc, ep);
7869e40493fSBo Shen 				ep->state = STATUS_STAGE_TEST;
7879e40493fSBo Shen 				udc->test_mode = le16_to_cpu(crq->wIndex);
7889e40493fSBo Shen 				return 0;
7899e40493fSBo Shen 			} else if (feature_is_dev_remote_wakeup(crq)) {
7909e40493fSBo Shen 				udc->devstatus |= 1 << USB_DEVICE_REMOTE_WAKEUP;
7919e40493fSBo Shen 			} else {
7929e40493fSBo Shen 				goto stall;
7939e40493fSBo Shen 			}
7949e40493fSBo Shen 		} else if (crq->bRequestType == USB_RECIP_ENDPOINT) {
7959e40493fSBo Shen 			struct usba_ep *target;
7969e40493fSBo Shen 
7979e40493fSBo Shen 			if (crq->wLength != cpu_to_le16(0) ||
7989e40493fSBo Shen 			    !feature_is_ep_halt(crq))
7999e40493fSBo Shen 				goto stall;
8009e40493fSBo Shen 
8019e40493fSBo Shen 			target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
8029e40493fSBo Shen 			if (!target)
8039e40493fSBo Shen 				goto stall;
8049e40493fSBo Shen 
8059e40493fSBo Shen 			usba_ep_writel(target, SET_STA, USBA_FORCE_STALL);
8069e40493fSBo Shen 		} else {
8079e40493fSBo Shen 			goto delegate;
8089e40493fSBo Shen 		}
8099e40493fSBo Shen 
8109e40493fSBo Shen 		send_status(udc, ep);
8119e40493fSBo Shen 		break;
8129e40493fSBo Shen 	}
8139e40493fSBo Shen 
8149e40493fSBo Shen 	case USB_REQ_SET_ADDRESS:
8159e40493fSBo Shen 		if (crq->bRequestType != (USB_DIR_OUT | USB_RECIP_DEVICE))
8169e40493fSBo Shen 			goto delegate;
8179e40493fSBo Shen 
8189e40493fSBo Shen 		set_address(udc, le16_to_cpu(crq->wValue));
8199e40493fSBo Shen 		send_status(udc, ep);
8209e40493fSBo Shen 		ep->state = STATUS_STAGE_ADDR;
8219e40493fSBo Shen 		break;
8229e40493fSBo Shen 
8239e40493fSBo Shen 	default:
8249e40493fSBo Shen delegate:
8259e40493fSBo Shen 		spin_unlock(&udc->lock);
8269e40493fSBo Shen 		retval = udc->driver->setup(&udc->gadget, crq);
8279e40493fSBo Shen 		spin_lock(&udc->lock);
8289e40493fSBo Shen 	}
8299e40493fSBo Shen 
8309e40493fSBo Shen 	return retval;
8319e40493fSBo Shen 
8329e40493fSBo Shen stall:
8339e40493fSBo Shen 	DBG(DBG_ALL, "%s: Invalid setup request: %02x.%02x v%04x i%04x l%d\n",
8349e40493fSBo Shen 	    ep->ep.name, crq->bRequestType, crq->bRequest,
8359e40493fSBo Shen 	    le16_to_cpu(crq->wValue), le16_to_cpu(crq->wIndex),
8369e40493fSBo Shen 	    le16_to_cpu(crq->wLength));
8379e40493fSBo Shen 	set_protocol_stall(udc, ep);
8389e40493fSBo Shen 
8399e40493fSBo Shen 	return -1;
8409e40493fSBo Shen }
8419e40493fSBo Shen 
usba_control_irq(struct usba_udc * udc,struct usba_ep * ep)8429e40493fSBo Shen static void usba_control_irq(struct usba_udc *udc, struct usba_ep *ep)
8439e40493fSBo Shen {
8449e40493fSBo Shen 	struct usba_request *req;
8459e40493fSBo Shen 	u32 epstatus;
8469e40493fSBo Shen 	u32 epctrl;
8479e40493fSBo Shen 
8489e40493fSBo Shen restart:
8499e40493fSBo Shen 	epstatus = usba_ep_readl(ep, STA);
8509e40493fSBo Shen 	epctrl = usba_ep_readl(ep, CTL);
8519e40493fSBo Shen 
8529e40493fSBo Shen 	DBG(DBG_INT, "%s [%d]: s/%08x c/%08x\n",
8539e40493fSBo Shen 	    ep->ep.name, ep->state, epstatus, epctrl);
8549e40493fSBo Shen 
8559e40493fSBo Shen 	req = NULL;
8569e40493fSBo Shen 	if (!list_empty(&ep->queue))
8579e40493fSBo Shen 		req = list_entry(ep->queue.next,
8589e40493fSBo Shen 				 struct usba_request, queue);
8599e40493fSBo Shen 
8609e40493fSBo Shen 	if ((epctrl & USBA_TX_PK_RDY) && !(epstatus & USBA_TX_PK_RDY)) {
8619e40493fSBo Shen 		if (req->submitted)
8629e40493fSBo Shen 			next_fifo_transaction(ep, req);
8639e40493fSBo Shen 		else
8649e40493fSBo Shen 			submit_request(ep, req);
8659e40493fSBo Shen 
8669e40493fSBo Shen 		if (req->last_transaction) {
8679e40493fSBo Shen 			usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY);
8689e40493fSBo Shen 			usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
8699e40493fSBo Shen 		}
8709e40493fSBo Shen 		goto restart;
8719e40493fSBo Shen 	}
8729e40493fSBo Shen 	if ((epstatus & epctrl) & USBA_TX_COMPLETE) {
8739e40493fSBo Shen 		usba_ep_writel(ep, CLR_STA, USBA_TX_COMPLETE);
8749e40493fSBo Shen 
8759e40493fSBo Shen 		switch (ep->state) {
8769e40493fSBo Shen 		case DATA_STAGE_IN:
8779e40493fSBo Shen 			usba_ep_writel(ep, CTL_ENB, USBA_RX_BK_RDY);
8789e40493fSBo Shen 			usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
8799e40493fSBo Shen 			ep->state = STATUS_STAGE_OUT;
8809e40493fSBo Shen 			break;
8819e40493fSBo Shen 		case STATUS_STAGE_ADDR:
8829e40493fSBo Shen 			/* Activate our new address */
8839e40493fSBo Shen 			usba_writel(udc, CTRL, (usba_readl(udc, CTRL)
8849e40493fSBo Shen 						| USBA_FADDR_EN));
8859e40493fSBo Shen 			usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
8869e40493fSBo Shen 			ep->state = WAIT_FOR_SETUP;
8879e40493fSBo Shen 			break;
8889e40493fSBo Shen 		case STATUS_STAGE_IN:
8899e40493fSBo Shen 			if (req) {
8909e40493fSBo Shen 				list_del_init(&req->queue);
8919e40493fSBo Shen 				request_complete(ep, req, 0);
8929e40493fSBo Shen 				submit_next_request(ep);
8939e40493fSBo Shen 			}
8949e40493fSBo Shen 			usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
8959e40493fSBo Shen 			ep->state = WAIT_FOR_SETUP;
8969e40493fSBo Shen 			break;
8979e40493fSBo Shen 		case STATUS_STAGE_TEST:
8989e40493fSBo Shen 			usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
8999e40493fSBo Shen 			ep->state = WAIT_FOR_SETUP;
9009e40493fSBo Shen 			if (do_test_mode(udc))
9019e40493fSBo Shen 				set_protocol_stall(udc, ep);
9029e40493fSBo Shen 			break;
9039e40493fSBo Shen 		default:
9049e40493fSBo Shen 			DBG(DBG_ALL, "%s: TXCOMP: Invalid endpoint state %d\n",
9059e40493fSBo Shen 			    ep->ep.name, ep->state);
9069e40493fSBo Shen 			set_protocol_stall(udc, ep);
9079e40493fSBo Shen 			break;
9089e40493fSBo Shen 		}
9099e40493fSBo Shen 
9109e40493fSBo Shen 		goto restart;
9119e40493fSBo Shen 	}
9129e40493fSBo Shen 	if ((epstatus & epctrl) & USBA_RX_BK_RDY) {
9139e40493fSBo Shen 		switch (ep->state) {
9149e40493fSBo Shen 		case STATUS_STAGE_OUT:
9159e40493fSBo Shen 			usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
9169e40493fSBo Shen 			usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
9179e40493fSBo Shen 
9189e40493fSBo Shen 			if (req) {
9199e40493fSBo Shen 				list_del_init(&req->queue);
9209e40493fSBo Shen 				request_complete(ep, req, 0);
9219e40493fSBo Shen 			}
9229e40493fSBo Shen 			ep->state = WAIT_FOR_SETUP;
9239e40493fSBo Shen 			break;
9249e40493fSBo Shen 
9259e40493fSBo Shen 		case DATA_STAGE_OUT:
9269e40493fSBo Shen 			receive_data(ep);
9279e40493fSBo Shen 			break;
9289e40493fSBo Shen 
9299e40493fSBo Shen 		default:
9309e40493fSBo Shen 			usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
9319e40493fSBo Shen 			usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
9329e40493fSBo Shen 			DBG(DBG_ALL, "%s: RXRDY: Invalid endpoint state %d\n",
9339e40493fSBo Shen 			    ep->ep.name, ep->state);
9349e40493fSBo Shen 			set_protocol_stall(udc, ep);
9359e40493fSBo Shen 			break;
9369e40493fSBo Shen 		}
9379e40493fSBo Shen 
9389e40493fSBo Shen 		goto restart;
9399e40493fSBo Shen 	}
9409e40493fSBo Shen 	if (epstatus & USBA_RX_SETUP) {
9419e40493fSBo Shen 		union {
9429e40493fSBo Shen 			struct usb_ctrlrequest crq;
9439e40493fSBo Shen 			unsigned long data[2];
9449e40493fSBo Shen 		} crq;
9459e40493fSBo Shen 		unsigned int pkt_len;
9469e40493fSBo Shen 		int ret;
9479e40493fSBo Shen 
9489e40493fSBo Shen 		if (ep->state != WAIT_FOR_SETUP) {
9499e40493fSBo Shen 			/*
9509e40493fSBo Shen 			 * Didn't expect a SETUP packet at this
9519e40493fSBo Shen 			 * point. Clean up any pending requests (which
9529e40493fSBo Shen 			 * may be successful).
9539e40493fSBo Shen 			 */
9549e40493fSBo Shen 			int status = -EPROTO;
9559e40493fSBo Shen 
9569e40493fSBo Shen 			/*
9579e40493fSBo Shen 			 * RXRDY and TXCOMP are dropped when SETUP
9589e40493fSBo Shen 			 * packets arrive.  Just pretend we received
9599e40493fSBo Shen 			 * the status packet.
9609e40493fSBo Shen 			 */
9619e40493fSBo Shen 			if (ep->state == STATUS_STAGE_OUT ||
9629e40493fSBo Shen 			    ep->state == STATUS_STAGE_IN) {
9639e40493fSBo Shen 				usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
9649e40493fSBo Shen 				status = 0;
9659e40493fSBo Shen 			}
9669e40493fSBo Shen 
9679e40493fSBo Shen 			if (req) {
9689e40493fSBo Shen 				list_del_init(&req->queue);
9699e40493fSBo Shen 				request_complete(ep, req, status);
9709e40493fSBo Shen 			}
9719e40493fSBo Shen 		}
9729e40493fSBo Shen 
9739e40493fSBo Shen 		pkt_len = USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA));
9749e40493fSBo Shen 		DBG(DBG_HW, "Packet length: %u\n", pkt_len);
9759e40493fSBo Shen 		if (pkt_len != sizeof(crq)) {
9769e40493fSBo Shen 			DBG(DBG_ALL, "udc: Invalid length %u (expected %zu)\n",
9779e40493fSBo Shen 			    pkt_len, sizeof(crq));
9789e40493fSBo Shen 			set_protocol_stall(udc, ep);
9799e40493fSBo Shen 			return;
9809e40493fSBo Shen 		}
9819e40493fSBo Shen 
9829e40493fSBo Shen 		DBG(DBG_FIFO, "Copying ctrl request from 0x%p:\n", ep->fifo);
9839e40493fSBo Shen 		memcpy(crq.data, ep->fifo, sizeof(crq));
9849e40493fSBo Shen 
9859e40493fSBo Shen 		/* Free up one bank in the FIFO so that we can
9869e40493fSBo Shen 		 * generate or receive a reply right away. */
9879e40493fSBo Shen 		usba_ep_writel(ep, CLR_STA, USBA_RX_SETUP);
9889e40493fSBo Shen 
9899e40493fSBo Shen 		if (crq.crq.bRequestType & USB_DIR_IN) {
9909e40493fSBo Shen 			/*
9919e40493fSBo Shen 			 * The USB 2.0 spec states that "if wLength is
9929e40493fSBo Shen 			 * zero, there is no data transfer phase."
9939e40493fSBo Shen 			 * However, testusb #14 seems to actually
9949e40493fSBo Shen 			 * expect a data phase even if wLength = 0...
9959e40493fSBo Shen 			 */
9969e40493fSBo Shen 			ep->state = DATA_STAGE_IN;
9979e40493fSBo Shen 		} else {
9989e40493fSBo Shen 			if (crq.crq.wLength != cpu_to_le16(0))
9999e40493fSBo Shen 				ep->state = DATA_STAGE_OUT;
10009e40493fSBo Shen 			else
10019e40493fSBo Shen 				ep->state = STATUS_STAGE_IN;
10029e40493fSBo Shen 		}
10039e40493fSBo Shen 
10049e40493fSBo Shen 		ret = -1;
10059e40493fSBo Shen 		if (ep->index == 0) {
10069e40493fSBo Shen 			ret = handle_ep0_setup(udc, ep, &crq.crq);
10079e40493fSBo Shen 		} else {
10089e40493fSBo Shen 			spin_unlock(&udc->lock);
10099e40493fSBo Shen 			ret = udc->driver->setup(&udc->gadget, &crq.crq);
10109e40493fSBo Shen 			spin_lock(&udc->lock);
10119e40493fSBo Shen 		}
10129e40493fSBo Shen 
10139e40493fSBo Shen 		DBG(DBG_BUS, "req %02x.%02x, length %d, state %d, ret %d\n",
10149e40493fSBo Shen 		    crq.crq.bRequestType, crq.crq.bRequest,
10159e40493fSBo Shen 		    le16_to_cpu(crq.crq.wLength), ep->state, ret);
10169e40493fSBo Shen 
10179e40493fSBo Shen 		if (ret < 0) {
10189e40493fSBo Shen 			/* Let the host know that we failed */
10199e40493fSBo Shen 			set_protocol_stall(udc, ep);
10209e40493fSBo Shen 		}
10219e40493fSBo Shen 	}
10229e40493fSBo Shen }
10239e40493fSBo Shen 
usba_ep_irq(struct usba_udc * udc,struct usba_ep * ep)10249e40493fSBo Shen static void usba_ep_irq(struct usba_udc *udc, struct usba_ep *ep)
10259e40493fSBo Shen {
10269e40493fSBo Shen 	struct usba_request *req;
10279e40493fSBo Shen 	u32 epstatus;
10289e40493fSBo Shen 	u32 epctrl;
10299e40493fSBo Shen 
10309e40493fSBo Shen 	epstatus = usba_ep_readl(ep, STA);
10319e40493fSBo Shen 	epctrl = usba_ep_readl(ep, CTL);
10329e40493fSBo Shen 
10339e40493fSBo Shen 	DBG(DBG_INT, "%s: interrupt, status: 0x%08x\n", ep->ep.name, epstatus);
10349e40493fSBo Shen 
10359e40493fSBo Shen 	while ((epctrl & USBA_TX_PK_RDY) && !(epstatus & USBA_TX_PK_RDY)) {
10369e40493fSBo Shen 		DBG(DBG_BUS, "%s: TX PK ready\n", ep->ep.name);
10379e40493fSBo Shen 
10389e40493fSBo Shen 		if (list_empty(&ep->queue)) {
10399e40493fSBo Shen 			DBG(DBG_INT, "ep_irq: queue empty\n");
10409e40493fSBo Shen 			usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY);
10419e40493fSBo Shen 			return;
10429e40493fSBo Shen 		}
10439e40493fSBo Shen 
10449e40493fSBo Shen 		req = list_entry(ep->queue.next, struct usba_request, queue);
10459e40493fSBo Shen 
10469e40493fSBo Shen 		if (req->submitted)
10479e40493fSBo Shen 			next_fifo_transaction(ep, req);
10489e40493fSBo Shen 		else
10499e40493fSBo Shen 			submit_request(ep, req);
10509e40493fSBo Shen 
10519e40493fSBo Shen 		if (req->last_transaction) {
10529e40493fSBo Shen 			list_del_init(&req->queue);
10539e40493fSBo Shen 			submit_next_request(ep);
10549e40493fSBo Shen 			request_complete(ep, req, 0);
10559e40493fSBo Shen 		}
10569e40493fSBo Shen 
10579e40493fSBo Shen 		epstatus = usba_ep_readl(ep, STA);
10589e40493fSBo Shen 		epctrl = usba_ep_readl(ep, CTL);
10599e40493fSBo Shen 	}
10609e40493fSBo Shen 
10619e40493fSBo Shen 	if ((epstatus & epctrl) & USBA_RX_BK_RDY) {
10629e40493fSBo Shen 		DBG(DBG_BUS, "%s: RX data ready\n", ep->ep.name);
10639e40493fSBo Shen 		receive_data(ep);
10649e40493fSBo Shen 	}
10659e40493fSBo Shen }
10669e40493fSBo Shen 
usba_udc_irq(struct usba_udc * udc)10679e40493fSBo Shen static int usba_udc_irq(struct usba_udc *udc)
10689e40493fSBo Shen {
10699e40493fSBo Shen 	u32 status, ep_status;
10709e40493fSBo Shen 
10719e40493fSBo Shen 	spin_lock(&udc->lock);
10729e40493fSBo Shen 
10739e40493fSBo Shen 	status = usba_readl(udc, INT_STA);
10749e40493fSBo Shen 	DBG(DBG_INT, "irq, status=%#08x\n", status);
10759e40493fSBo Shen 
10769e40493fSBo Shen 	if (status & USBA_DET_SUSPEND) {
10779e40493fSBo Shen 		usba_writel(udc, INT_CLR, USBA_DET_SUSPEND);
10789e40493fSBo Shen 		DBG(DBG_BUS, "Suspend detected\n");
10799e40493fSBo Shen 		if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
10809e40493fSBo Shen 		    udc->driver && udc->driver->suspend) {
10819e40493fSBo Shen 			spin_unlock(&udc->lock);
10829e40493fSBo Shen 			udc->driver->suspend(&udc->gadget);
10839e40493fSBo Shen 			spin_lock(&udc->lock);
10849e40493fSBo Shen 		}
10859e40493fSBo Shen 	}
10869e40493fSBo Shen 
10879e40493fSBo Shen 	if (status & USBA_WAKE_UP) {
10889e40493fSBo Shen 		usba_writel(udc, INT_CLR, USBA_WAKE_UP);
10899e40493fSBo Shen 		DBG(DBG_BUS, "Wake Up CPU detected\n");
10909e40493fSBo Shen 	}
10919e40493fSBo Shen 
10929e40493fSBo Shen 	if (status & USBA_END_OF_RESUME) {
10939e40493fSBo Shen 		usba_writel(udc, INT_CLR, USBA_END_OF_RESUME);
10949e40493fSBo Shen 		DBG(DBG_BUS, "Resume detected\n");
10959e40493fSBo Shen 		if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
10969e40493fSBo Shen 		    udc->driver && udc->driver->resume) {
10979e40493fSBo Shen 			spin_unlock(&udc->lock);
10989e40493fSBo Shen 			udc->driver->resume(&udc->gadget);
10999e40493fSBo Shen 			spin_lock(&udc->lock);
11009e40493fSBo Shen 		}
11019e40493fSBo Shen 	}
11029e40493fSBo Shen 
11039e40493fSBo Shen 	ep_status = USBA_BFEXT(EPT_INT, status);
11049e40493fSBo Shen 	if (ep_status) {
11059e40493fSBo Shen 		int i;
11069e40493fSBo Shen 
11079e40493fSBo Shen 		for (i = 0; i < USBA_NR_ENDPOINTS; i++)
11089e40493fSBo Shen 			if (ep_status & (1 << i)) {
11099e40493fSBo Shen 				if (ep_is_control(&udc->usba_ep[i]))
11109e40493fSBo Shen 					usba_control_irq(udc, &udc->usba_ep[i]);
11119e40493fSBo Shen 				else
11129e40493fSBo Shen 					usba_ep_irq(udc, &udc->usba_ep[i]);
11139e40493fSBo Shen 			}
11149e40493fSBo Shen 	}
11159e40493fSBo Shen 
11169e40493fSBo Shen 	if (status & USBA_END_OF_RESET) {
11179e40493fSBo Shen 		struct usba_ep *ep0;
11189e40493fSBo Shen 
11199e40493fSBo Shen 		usba_writel(udc, INT_CLR, USBA_END_OF_RESET);
11209e40493fSBo Shen 		reset_all_endpoints(udc);
11219e40493fSBo Shen 
11229e40493fSBo Shen 		if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
11239e40493fSBo Shen 		    udc->driver->disconnect) {
11249e40493fSBo Shen 			udc->gadget.speed = USB_SPEED_UNKNOWN;
11259e40493fSBo Shen 			spin_unlock(&udc->lock);
11269e40493fSBo Shen 			udc->driver->disconnect(&udc->gadget);
11279e40493fSBo Shen 			spin_lock(&udc->lock);
11289e40493fSBo Shen 		}
11299e40493fSBo Shen 
11309e40493fSBo Shen 		if (status & USBA_HIGH_SPEED)
11319e40493fSBo Shen 			udc->gadget.speed = USB_SPEED_HIGH;
11329e40493fSBo Shen 		else
11339e40493fSBo Shen 			udc->gadget.speed = USB_SPEED_FULL;
11349e40493fSBo Shen 
11359e40493fSBo Shen 		ep0 = &udc->usba_ep[0];
11369e40493fSBo Shen 		ep0->desc = &usba_ep0_desc;
11379e40493fSBo Shen 		ep0->state = WAIT_FOR_SETUP;
11389e40493fSBo Shen 		usba_ep_writel(ep0, CFG,
11399e40493fSBo Shen 			       (USBA_BF(EPT_SIZE, EP0_EPT_SIZE)
11409e40493fSBo Shen 				| USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL)
11419e40493fSBo Shen 				| USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE)));
11429e40493fSBo Shen 		usba_ep_writel(ep0, CTL_ENB,
11439e40493fSBo Shen 			       USBA_EPT_ENABLE | USBA_RX_SETUP);
11449e40493fSBo Shen 		usba_writel(udc, INT_ENB,
11459e40493fSBo Shen 			    (usba_readl(udc, INT_ENB)
11469e40493fSBo Shen 			     | USBA_BF(EPT_INT, 1)
11479e40493fSBo Shen 			     | USBA_DET_SUSPEND
11489e40493fSBo Shen 			     | USBA_END_OF_RESUME));
11499e40493fSBo Shen 
11509e40493fSBo Shen 		/*
11519e40493fSBo Shen 		 * Unclear why we hit this irregularly, e.g. in usbtest,
11529e40493fSBo Shen 		 * but it's clearly harmless...
11539e40493fSBo Shen 		 */
11549e40493fSBo Shen 		if (!(usba_ep_readl(ep0, CFG) & USBA_EPT_MAPPED))
11559e40493fSBo Shen 			DBG(DBG_ALL, "ODD: EP0 configuration is invalid!\n");
11569e40493fSBo Shen 	}
11579e40493fSBo Shen 
11589e40493fSBo Shen 	spin_unlock(&udc->lock);
11599e40493fSBo Shen 
11609e40493fSBo Shen 	return 0;
11619e40493fSBo Shen }
11629e40493fSBo Shen 
atmel_usba_start(struct usba_udc * udc)11639e40493fSBo Shen static int atmel_usba_start(struct usba_udc *udc)
11649e40493fSBo Shen {
11659e40493fSBo Shen 	udc->devstatus = 1 << USB_DEVICE_SELF_POWERED;
11669e40493fSBo Shen 
11679e40493fSBo Shen 	udc->vbus_prev = 0;
11689e40493fSBo Shen 
11699e40493fSBo Shen 	/* If Vbus is present, enable the controller and wait for reset */
11709e40493fSBo Shen 	if (vbus_is_present(udc) && udc->vbus_prev == 0) {
11719e40493fSBo Shen 		usba_writel(udc, CTRL, USBA_ENABLE_MASK);
11729e40493fSBo Shen 		usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
11739e40493fSBo Shen 	}
11749e40493fSBo Shen 
11759e40493fSBo Shen 	return 0;
11769e40493fSBo Shen }
11779e40493fSBo Shen 
atmel_usba_stop(struct usba_udc * udc)11789e40493fSBo Shen static int atmel_usba_stop(struct usba_udc *udc)
11799e40493fSBo Shen {
11809e40493fSBo Shen 	udc->gadget.speed = USB_SPEED_UNKNOWN;
11819e40493fSBo Shen 	reset_all_endpoints(udc);
11829e40493fSBo Shen 
11839e40493fSBo Shen 	/* This will also disable the DP pullup */
11849e40493fSBo Shen 	usba_writel(udc, CTRL, USBA_DISABLE_MASK);
11859e40493fSBo Shen 
11869e40493fSBo Shen 	return 0;
11879e40493fSBo Shen }
11889e40493fSBo Shen 
11899e40493fSBo Shen static struct usba_udc controller = {
11909e40493fSBo Shen 	.regs = (unsigned *)ATMEL_BASE_UDPHS,
11919e40493fSBo Shen 	.fifo = (unsigned *)ATMEL_BASE_UDPHS_FIFO,
11929e40493fSBo Shen 	.gadget = {
11939e40493fSBo Shen 		.ops		= &usba_udc_ops,
11949e40493fSBo Shen 		.ep_list	= LIST_HEAD_INIT(controller.gadget.ep_list),
11959e40493fSBo Shen 		.speed		= USB_SPEED_HIGH,
11969e40493fSBo Shen 		.is_dualspeed	= 1,
11979e40493fSBo Shen 		.name		= "atmel_usba_udc",
11989e40493fSBo Shen 	},
11999e40493fSBo Shen };
12009e40493fSBo Shen 
usb_gadget_handle_interrupts(int index)12012d48aa69SKishon Vijay Abraham I int usb_gadget_handle_interrupts(int index)
12029e40493fSBo Shen {
12039e40493fSBo Shen 	struct usba_udc *udc = &controller;
12049e40493fSBo Shen 
12059e40493fSBo Shen 	return usba_udc_irq(udc);
12069e40493fSBo Shen }
12079e40493fSBo Shen 
12089e40493fSBo Shen 
usb_gadget_register_driver(struct usb_gadget_driver * driver)12099e40493fSBo Shen int usb_gadget_register_driver(struct usb_gadget_driver *driver)
12109e40493fSBo Shen {
12119e40493fSBo Shen 	struct usba_udc *udc = &controller;
12129e40493fSBo Shen 	int ret;
12139e40493fSBo Shen 
12149e40493fSBo Shen 	if (!driver || !driver->bind || !driver->setup) {
12159e40493fSBo Shen 		printf("bad paramter\n");
12169e40493fSBo Shen 		return -EINVAL;
12179e40493fSBo Shen 	}
12189e40493fSBo Shen 
12199e40493fSBo Shen 	if (udc->driver) {
12209e40493fSBo Shen 		printf("UDC already has a gadget driver\n");
12219e40493fSBo Shen 		return -EBUSY;
12229e40493fSBo Shen 	}
12239e40493fSBo Shen 
12249e40493fSBo Shen 	atmel_usba_start(udc);
12259e40493fSBo Shen 
12269e40493fSBo Shen 	udc->driver = driver;
12279e40493fSBo Shen 
12289e40493fSBo Shen 	ret = driver->bind(&udc->gadget);
12299e40493fSBo Shen 	if (ret) {
1230*90aa625cSMasahiro Yamada 		pr_err("driver->bind() returned %d\n", ret);
12319e40493fSBo Shen 		udc->driver = NULL;
12329e40493fSBo Shen 	}
12339e40493fSBo Shen 
12349e40493fSBo Shen 	return ret;
12359e40493fSBo Shen }
12369e40493fSBo Shen 
usb_gadget_unregister_driver(struct usb_gadget_driver * driver)12379e40493fSBo Shen int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
12389e40493fSBo Shen {
12399e40493fSBo Shen 	struct usba_udc *udc = &controller;
12409e40493fSBo Shen 
12414585fc58SBo Shen 	if (!driver || !driver->unbind || !driver->disconnect) {
1242*90aa625cSMasahiro Yamada 		pr_err("bad paramter\n");
12439e40493fSBo Shen 		return -EINVAL;
12449e40493fSBo Shen 	}
12459e40493fSBo Shen 
12464585fc58SBo Shen 	driver->disconnect(&udc->gadget);
12479e40493fSBo Shen 	driver->unbind(&udc->gadget);
12489e40493fSBo Shen 	udc->driver = NULL;
12499e40493fSBo Shen 
12509e40493fSBo Shen 	atmel_usba_stop(udc);
12519e40493fSBo Shen 
12529e40493fSBo Shen 	return 0;
12539e40493fSBo Shen }
12549e40493fSBo Shen 
usba_udc_pdata(struct usba_platform_data * pdata,struct usba_udc * udc)12559e40493fSBo Shen static struct usba_ep *usba_udc_pdata(struct usba_platform_data *pdata,
12569e40493fSBo Shen 				      struct usba_udc *udc)
12579e40493fSBo Shen {
12589e40493fSBo Shen 	struct usba_ep *eps;
12599e40493fSBo Shen 	int i;
12609e40493fSBo Shen 
12619e40493fSBo Shen 	eps = malloc(sizeof(struct usba_ep) * pdata->num_ep);
12629e40493fSBo Shen 	if (!eps) {
1263*90aa625cSMasahiro Yamada 		pr_err("failed to alloc eps\n");
12649e40493fSBo Shen 		return NULL;
12659e40493fSBo Shen 	}
12669e40493fSBo Shen 
12679e40493fSBo Shen 	udc->gadget.ep0 = &eps[0].ep;
12689e40493fSBo Shen 
12699e40493fSBo Shen 	INIT_LIST_HEAD(&udc->gadget.ep_list);
12709e40493fSBo Shen 	INIT_LIST_HEAD(&eps[0].ep.ep_list);
12719e40493fSBo Shen 
12729e40493fSBo Shen 	for (i = 0; i < pdata->num_ep; i++) {
12739e40493fSBo Shen 		struct usba_ep *ep = &eps[i];
12749e40493fSBo Shen 
12759e40493fSBo Shen 		ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
12769e40493fSBo Shen 		ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
12779e40493fSBo Shen 		ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
12789e40493fSBo Shen 		ep->ep.ops = &usba_ep_ops;
12799e40493fSBo Shen 		ep->ep.name = pdata->ep[i].name;
12809e40493fSBo Shen 		ep->ep.maxpacket = pdata->ep[i].fifo_size;
12819e40493fSBo Shen 		ep->fifo_size = ep->ep.maxpacket;
12829e40493fSBo Shen 		ep->udc = udc;
12839e40493fSBo Shen 		INIT_LIST_HEAD(&ep->queue);
12849e40493fSBo Shen 		ep->nr_banks = pdata->ep[i].nr_banks;
12859e40493fSBo Shen 		ep->index = pdata->ep[i].index;
12869e40493fSBo Shen 		ep->can_dma = pdata->ep[i].can_dma;
12879e40493fSBo Shen 		ep->can_isoc = pdata->ep[i].can_isoc;
12889e40493fSBo Shen 		if (i)
12899e40493fSBo Shen 			list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
12909e40493fSBo Shen 	};
12919e40493fSBo Shen 
12929e40493fSBo Shen 	return eps;
12939e40493fSBo Shen }
12949e40493fSBo Shen 
usba_udc_probe(struct usba_platform_data * pdata)12959e40493fSBo Shen int usba_udc_probe(struct usba_platform_data *pdata)
12969e40493fSBo Shen {
12979e40493fSBo Shen 	struct usba_udc *udc;
12989e40493fSBo Shen 
12999e40493fSBo Shen 	udc = &controller;
13009e40493fSBo Shen 
13019e40493fSBo Shen 	udc->usba_ep = usba_udc_pdata(pdata, udc);
13029e40493fSBo Shen 
13039e40493fSBo Shen 	return 0;
13049e40493fSBo Shen }
1305