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