18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * USB Peripheral Controller driver for Aeroflex Gaisler GRUSBDC. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * 2013 (c) Aeroflex Gaisler AB 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * This driver supports GRUSBDC USB Device Controller cores available in the 88c2ecf20Sopenharmony_ci * GRLIB VHDL IP core library. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Full documentation of the GRUSBDC core can be found here: 118c2ecf20Sopenharmony_ci * https://www.gaisler.com/products/grlib/grip.pdf 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Contributors: 148c2ecf20Sopenharmony_ci * - Andreas Larsson <andreas@gaisler.com> 158c2ecf20Sopenharmony_ci * - Marko Isomaki 168c2ecf20Sopenharmony_ci */ 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci/* 198c2ecf20Sopenharmony_ci * A GRUSBDC core can have up to 16 IN endpoints and 16 OUT endpoints each 208c2ecf20Sopenharmony_ci * individually configurable to any of the four USB transfer types. This driver 218c2ecf20Sopenharmony_ci * only supports cores in DMA mode. 228c2ecf20Sopenharmony_ci */ 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include <linux/kernel.h> 258c2ecf20Sopenharmony_ci#include <linux/module.h> 268c2ecf20Sopenharmony_ci#include <linux/slab.h> 278c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 288c2ecf20Sopenharmony_ci#include <linux/errno.h> 298c2ecf20Sopenharmony_ci#include <linux/list.h> 308c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 318c2ecf20Sopenharmony_ci#include <linux/device.h> 328c2ecf20Sopenharmony_ci#include <linux/usb.h> 338c2ecf20Sopenharmony_ci#include <linux/usb/ch9.h> 348c2ecf20Sopenharmony_ci#include <linux/usb/gadget.h> 358c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 368c2ecf20Sopenharmony_ci#include <linux/dmapool.h> 378c2ecf20Sopenharmony_ci#include <linux/debugfs.h> 388c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 398c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 408c2ecf20Sopenharmony_ci#include <linux/of_irq.h> 418c2ecf20Sopenharmony_ci#include <linux/of_address.h> 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#include <asm/byteorder.h> 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#include "gr_udc.h" 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#define DRIVER_NAME "gr_udc" 488c2ecf20Sopenharmony_ci#define DRIVER_DESC "Aeroflex Gaisler GRUSBDC USB Peripheral Controller" 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic const char driver_name[] = DRIVER_NAME; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#define gr_read32(x) (ioread32be((x))) 538c2ecf20Sopenharmony_ci#define gr_write32(x, v) (iowrite32be((v), (x))) 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci/* USB speed and corresponding string calculated from status register value */ 568c2ecf20Sopenharmony_ci#define GR_SPEED(status) \ 578c2ecf20Sopenharmony_ci ((status & GR_STATUS_SP) ? USB_SPEED_FULL : USB_SPEED_HIGH) 588c2ecf20Sopenharmony_ci#define GR_SPEED_STR(status) usb_speed_string(GR_SPEED(status)) 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci/* Size of hardware buffer calculated from epctrl register value */ 618c2ecf20Sopenharmony_ci#define GR_BUFFER_SIZE(epctrl) \ 628c2ecf20Sopenharmony_ci ((((epctrl) & GR_EPCTRL_BUFSZ_MASK) >> GR_EPCTRL_BUFSZ_POS) * \ 638c2ecf20Sopenharmony_ci GR_EPCTRL_BUFSZ_SCALER) 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci/* ---------------------------------------------------------------------- */ 668c2ecf20Sopenharmony_ci/* Debug printout functionality */ 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic const char * const gr_modestring[] = {"control", "iso", "bulk", "int"}; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic const char *gr_ep0state_string(enum gr_ep0state state) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci static const char *const names[] = { 738c2ecf20Sopenharmony_ci [GR_EP0_DISCONNECT] = "disconnect", 748c2ecf20Sopenharmony_ci [GR_EP0_SETUP] = "setup", 758c2ecf20Sopenharmony_ci [GR_EP0_IDATA] = "idata", 768c2ecf20Sopenharmony_ci [GR_EP0_ODATA] = "odata", 778c2ecf20Sopenharmony_ci [GR_EP0_ISTATUS] = "istatus", 788c2ecf20Sopenharmony_ci [GR_EP0_OSTATUS] = "ostatus", 798c2ecf20Sopenharmony_ci [GR_EP0_STALL] = "stall", 808c2ecf20Sopenharmony_ci [GR_EP0_SUSPEND] = "suspend", 818c2ecf20Sopenharmony_ci }; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci if (state < 0 || state >= ARRAY_SIZE(names)) 848c2ecf20Sopenharmony_ci return "UNKNOWN"; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci return names[state]; 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci#ifdef VERBOSE_DEBUG 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic void gr_dbgprint_request(const char *str, struct gr_ep *ep, 928c2ecf20Sopenharmony_ci struct gr_request *req) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci int buflen = ep->is_in ? req->req.length : req->req.actual; 958c2ecf20Sopenharmony_ci int rowlen = 32; 968c2ecf20Sopenharmony_ci int plen = min(rowlen, buflen); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci dev_dbg(ep->dev->dev, "%s: 0x%p, %d bytes data%s:\n", str, req, buflen, 998c2ecf20Sopenharmony_ci (buflen > plen ? " (truncated)" : "")); 1008c2ecf20Sopenharmony_ci print_hex_dump_debug(" ", DUMP_PREFIX_NONE, 1018c2ecf20Sopenharmony_ci rowlen, 4, req->req.buf, plen, false); 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistatic void gr_dbgprint_devreq(struct gr_udc *dev, u8 type, u8 request, 1058c2ecf20Sopenharmony_ci u16 value, u16 index, u16 length) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci dev_vdbg(dev->dev, "REQ: %02x.%02x v%04x i%04x l%04x\n", 1088c2ecf20Sopenharmony_ci type, request, value, index, length); 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci#else /* !VERBOSE_DEBUG */ 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cistatic void gr_dbgprint_request(const char *str, struct gr_ep *ep, 1138c2ecf20Sopenharmony_ci struct gr_request *req) {} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic void gr_dbgprint_devreq(struct gr_udc *dev, u8 type, u8 request, 1168c2ecf20Sopenharmony_ci u16 value, u16 index, u16 length) {} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci#endif /* VERBOSE_DEBUG */ 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci/* ---------------------------------------------------------------------- */ 1218c2ecf20Sopenharmony_ci/* Debugfs functionality */ 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci#ifdef CONFIG_USB_GADGET_DEBUG_FS 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic void gr_seq_ep_show(struct seq_file *seq, struct gr_ep *ep) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci u32 epctrl = gr_read32(&ep->regs->epctrl); 1288c2ecf20Sopenharmony_ci u32 epstat = gr_read32(&ep->regs->epstat); 1298c2ecf20Sopenharmony_ci int mode = (epctrl & GR_EPCTRL_TT_MASK) >> GR_EPCTRL_TT_POS; 1308c2ecf20Sopenharmony_ci struct gr_request *req; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci seq_printf(seq, "%s:\n", ep->ep.name); 1338c2ecf20Sopenharmony_ci seq_printf(seq, " mode = %s\n", gr_modestring[mode]); 1348c2ecf20Sopenharmony_ci seq_printf(seq, " halted: %d\n", !!(epctrl & GR_EPCTRL_EH)); 1358c2ecf20Sopenharmony_ci seq_printf(seq, " disabled: %d\n", !!(epctrl & GR_EPCTRL_ED)); 1368c2ecf20Sopenharmony_ci seq_printf(seq, " valid: %d\n", !!(epctrl & GR_EPCTRL_EV)); 1378c2ecf20Sopenharmony_ci seq_printf(seq, " dma_start = %d\n", ep->dma_start); 1388c2ecf20Sopenharmony_ci seq_printf(seq, " stopped = %d\n", ep->stopped); 1398c2ecf20Sopenharmony_ci seq_printf(seq, " wedged = %d\n", ep->wedged); 1408c2ecf20Sopenharmony_ci seq_printf(seq, " callback = %d\n", ep->callback); 1418c2ecf20Sopenharmony_ci seq_printf(seq, " maxpacket = %d\n", ep->ep.maxpacket); 1428c2ecf20Sopenharmony_ci seq_printf(seq, " maxpacket_limit = %d\n", ep->ep.maxpacket_limit); 1438c2ecf20Sopenharmony_ci seq_printf(seq, " bytes_per_buffer = %d\n", ep->bytes_per_buffer); 1448c2ecf20Sopenharmony_ci if (mode == 1 || mode == 3) 1458c2ecf20Sopenharmony_ci seq_printf(seq, " nt = %d\n", 1468c2ecf20Sopenharmony_ci (epctrl & GR_EPCTRL_NT_MASK) >> GR_EPCTRL_NT_POS); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci seq_printf(seq, " Buffer 0: %s %s%d\n", 1498c2ecf20Sopenharmony_ci epstat & GR_EPSTAT_B0 ? "valid" : "invalid", 1508c2ecf20Sopenharmony_ci epstat & GR_EPSTAT_BS ? " " : "selected ", 1518c2ecf20Sopenharmony_ci (epstat & GR_EPSTAT_B0CNT_MASK) >> GR_EPSTAT_B0CNT_POS); 1528c2ecf20Sopenharmony_ci seq_printf(seq, " Buffer 1: %s %s%d\n", 1538c2ecf20Sopenharmony_ci epstat & GR_EPSTAT_B1 ? "valid" : "invalid", 1548c2ecf20Sopenharmony_ci epstat & GR_EPSTAT_BS ? "selected " : " ", 1558c2ecf20Sopenharmony_ci (epstat & GR_EPSTAT_B1CNT_MASK) >> GR_EPSTAT_B1CNT_POS); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci if (list_empty(&ep->queue)) { 1588c2ecf20Sopenharmony_ci seq_puts(seq, " Queue: empty\n\n"); 1598c2ecf20Sopenharmony_ci return; 1608c2ecf20Sopenharmony_ci } 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci seq_puts(seq, " Queue:\n"); 1638c2ecf20Sopenharmony_ci list_for_each_entry(req, &ep->queue, queue) { 1648c2ecf20Sopenharmony_ci struct gr_dma_desc *desc; 1658c2ecf20Sopenharmony_ci struct gr_dma_desc *next; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci seq_printf(seq, " 0x%p: 0x%p %d %d\n", req, 1688c2ecf20Sopenharmony_ci &req->req.buf, req->req.actual, req->req.length); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci next = req->first_desc; 1718c2ecf20Sopenharmony_ci do { 1728c2ecf20Sopenharmony_ci desc = next; 1738c2ecf20Sopenharmony_ci next = desc->next_desc; 1748c2ecf20Sopenharmony_ci seq_printf(seq, " %c 0x%p (0x%08x): 0x%05x 0x%08x\n", 1758c2ecf20Sopenharmony_ci desc == req->curr_desc ? 'c' : ' ', 1768c2ecf20Sopenharmony_ci desc, desc->paddr, desc->ctrl, desc->data); 1778c2ecf20Sopenharmony_ci } while (desc != req->last_desc); 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci seq_puts(seq, "\n"); 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic int gr_dfs_show(struct seq_file *seq, void *v) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci struct gr_udc *dev = seq->private; 1858c2ecf20Sopenharmony_ci u32 control = gr_read32(&dev->regs->control); 1868c2ecf20Sopenharmony_ci u32 status = gr_read32(&dev->regs->status); 1878c2ecf20Sopenharmony_ci struct gr_ep *ep; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci seq_printf(seq, "usb state = %s\n", 1908c2ecf20Sopenharmony_ci usb_state_string(dev->gadget.state)); 1918c2ecf20Sopenharmony_ci seq_printf(seq, "address = %d\n", 1928c2ecf20Sopenharmony_ci (control & GR_CONTROL_UA_MASK) >> GR_CONTROL_UA_POS); 1938c2ecf20Sopenharmony_ci seq_printf(seq, "speed = %s\n", GR_SPEED_STR(status)); 1948c2ecf20Sopenharmony_ci seq_printf(seq, "ep0state = %s\n", gr_ep0state_string(dev->ep0state)); 1958c2ecf20Sopenharmony_ci seq_printf(seq, "irq_enabled = %d\n", dev->irq_enabled); 1968c2ecf20Sopenharmony_ci seq_printf(seq, "remote_wakeup = %d\n", dev->remote_wakeup); 1978c2ecf20Sopenharmony_ci seq_printf(seq, "test_mode = %d\n", dev->test_mode); 1988c2ecf20Sopenharmony_ci seq_puts(seq, "\n"); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci list_for_each_entry(ep, &dev->ep_list, ep_list) 2018c2ecf20Sopenharmony_ci gr_seq_ep_show(seq, ep); 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci return 0; 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(gr_dfs); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cistatic void gr_dfs_create(struct gr_udc *dev) 2088c2ecf20Sopenharmony_ci{ 2098c2ecf20Sopenharmony_ci const char *name = "gr_udc_state"; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci dev->dfs_root = debugfs_create_dir(dev_name(dev->dev), usb_debug_root); 2128c2ecf20Sopenharmony_ci debugfs_create_file(name, 0444, dev->dfs_root, dev, &gr_dfs_fops); 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic void gr_dfs_delete(struct gr_udc *dev) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci debugfs_remove_recursive(dev->dfs_root); 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci#else /* !CONFIG_USB_GADGET_DEBUG_FS */ 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_cistatic void gr_dfs_create(struct gr_udc *dev) {} 2238c2ecf20Sopenharmony_cistatic void gr_dfs_delete(struct gr_udc *dev) {} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci#endif /* CONFIG_USB_GADGET_DEBUG_FS */ 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci/* ---------------------------------------------------------------------- */ 2288c2ecf20Sopenharmony_ci/* DMA and request handling */ 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci/* Allocates a new struct gr_dma_desc, sets paddr and zeroes the rest */ 2318c2ecf20Sopenharmony_cistatic struct gr_dma_desc *gr_alloc_dma_desc(struct gr_ep *ep, gfp_t gfp_flags) 2328c2ecf20Sopenharmony_ci{ 2338c2ecf20Sopenharmony_ci dma_addr_t paddr; 2348c2ecf20Sopenharmony_ci struct gr_dma_desc *dma_desc; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci dma_desc = dma_pool_zalloc(ep->dev->desc_pool, gfp_flags, &paddr); 2378c2ecf20Sopenharmony_ci if (!dma_desc) { 2388c2ecf20Sopenharmony_ci dev_err(ep->dev->dev, "Could not allocate from DMA pool\n"); 2398c2ecf20Sopenharmony_ci return NULL; 2408c2ecf20Sopenharmony_ci } 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci dma_desc->paddr = paddr; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci return dma_desc; 2458c2ecf20Sopenharmony_ci} 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_cistatic inline void gr_free_dma_desc(struct gr_udc *dev, 2488c2ecf20Sopenharmony_ci struct gr_dma_desc *desc) 2498c2ecf20Sopenharmony_ci{ 2508c2ecf20Sopenharmony_ci dma_pool_free(dev->desc_pool, desc, (dma_addr_t)desc->paddr); 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci/* Frees the chain of struct gr_dma_desc for the given request */ 2548c2ecf20Sopenharmony_cistatic void gr_free_dma_desc_chain(struct gr_udc *dev, struct gr_request *req) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci struct gr_dma_desc *desc; 2578c2ecf20Sopenharmony_ci struct gr_dma_desc *next; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci next = req->first_desc; 2608c2ecf20Sopenharmony_ci if (!next) 2618c2ecf20Sopenharmony_ci return; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci do { 2648c2ecf20Sopenharmony_ci desc = next; 2658c2ecf20Sopenharmony_ci next = desc->next_desc; 2668c2ecf20Sopenharmony_ci gr_free_dma_desc(dev, desc); 2678c2ecf20Sopenharmony_ci } while (desc != req->last_desc); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci req->first_desc = NULL; 2708c2ecf20Sopenharmony_ci req->curr_desc = NULL; 2718c2ecf20Sopenharmony_ci req->last_desc = NULL; 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_cistatic void gr_ep0_setup(struct gr_udc *dev, struct gr_request *req); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci/* 2778c2ecf20Sopenharmony_ci * Frees allocated resources and calls the appropriate completion function/setup 2788c2ecf20Sopenharmony_ci * package handler for a finished request. 2798c2ecf20Sopenharmony_ci * 2808c2ecf20Sopenharmony_ci * Must be called with dev->lock held and irqs disabled. 2818c2ecf20Sopenharmony_ci */ 2828c2ecf20Sopenharmony_cistatic void gr_finish_request(struct gr_ep *ep, struct gr_request *req, 2838c2ecf20Sopenharmony_ci int status) 2848c2ecf20Sopenharmony_ci __releases(&dev->lock) 2858c2ecf20Sopenharmony_ci __acquires(&dev->lock) 2868c2ecf20Sopenharmony_ci{ 2878c2ecf20Sopenharmony_ci struct gr_udc *dev; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci list_del_init(&req->queue); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci if (likely(req->req.status == -EINPROGRESS)) 2928c2ecf20Sopenharmony_ci req->req.status = status; 2938c2ecf20Sopenharmony_ci else 2948c2ecf20Sopenharmony_ci status = req->req.status; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci dev = ep->dev; 2978c2ecf20Sopenharmony_ci usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in); 2988c2ecf20Sopenharmony_ci gr_free_dma_desc_chain(dev, req); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci if (ep->is_in) { /* For OUT, req->req.actual gets updated bit by bit */ 3018c2ecf20Sopenharmony_ci req->req.actual = req->req.length; 3028c2ecf20Sopenharmony_ci } else if (req->oddlen && req->req.actual > req->evenlen) { 3038c2ecf20Sopenharmony_ci /* 3048c2ecf20Sopenharmony_ci * Copy to user buffer in this case where length was not evenly 3058c2ecf20Sopenharmony_ci * divisible by ep->ep.maxpacket and the last descriptor was 3068c2ecf20Sopenharmony_ci * actually used. 3078c2ecf20Sopenharmony_ci */ 3088c2ecf20Sopenharmony_ci char *buftail = ((char *)req->req.buf + req->evenlen); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci memcpy(buftail, ep->tailbuf, req->oddlen); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci if (req->req.actual > req->req.length) { 3138c2ecf20Sopenharmony_ci /* We got more data than was requested */ 3148c2ecf20Sopenharmony_ci dev_dbg(ep->dev->dev, "Overflow for ep %s\n", 3158c2ecf20Sopenharmony_ci ep->ep.name); 3168c2ecf20Sopenharmony_ci gr_dbgprint_request("OVFL", ep, req); 3178c2ecf20Sopenharmony_ci req->req.status = -EOVERFLOW; 3188c2ecf20Sopenharmony_ci } 3198c2ecf20Sopenharmony_ci } 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci if (!status) { 3228c2ecf20Sopenharmony_ci if (ep->is_in) 3238c2ecf20Sopenharmony_ci gr_dbgprint_request("SENT", ep, req); 3248c2ecf20Sopenharmony_ci else 3258c2ecf20Sopenharmony_ci gr_dbgprint_request("RECV", ep, req); 3268c2ecf20Sopenharmony_ci } 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci /* Prevent changes to ep->queue during callback */ 3298c2ecf20Sopenharmony_ci ep->callback = 1; 3308c2ecf20Sopenharmony_ci if (req == dev->ep0reqo && !status) { 3318c2ecf20Sopenharmony_ci if (req->setup) 3328c2ecf20Sopenharmony_ci gr_ep0_setup(dev, req); 3338c2ecf20Sopenharmony_ci else 3348c2ecf20Sopenharmony_ci dev_err(dev->dev, 3358c2ecf20Sopenharmony_ci "Unexpected non setup packet on ep0in\n"); 3368c2ecf20Sopenharmony_ci } else if (req->req.complete) { 3378c2ecf20Sopenharmony_ci spin_unlock(&dev->lock); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci usb_gadget_giveback_request(&ep->ep, &req->req); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci spin_lock(&dev->lock); 3428c2ecf20Sopenharmony_ci } 3438c2ecf20Sopenharmony_ci ep->callback = 0; 3448c2ecf20Sopenharmony_ci} 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_cistatic struct usb_request *gr_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) 3478c2ecf20Sopenharmony_ci{ 3488c2ecf20Sopenharmony_ci struct gr_request *req; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci req = kzalloc(sizeof(*req), gfp_flags); 3518c2ecf20Sopenharmony_ci if (!req) 3528c2ecf20Sopenharmony_ci return NULL; 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&req->queue); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci return &req->req; 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci/* 3608c2ecf20Sopenharmony_ci * Starts DMA for endpoint ep if there are requests in the queue. 3618c2ecf20Sopenharmony_ci * 3628c2ecf20Sopenharmony_ci * Must be called with dev->lock held and with !ep->stopped. 3638c2ecf20Sopenharmony_ci */ 3648c2ecf20Sopenharmony_cistatic void gr_start_dma(struct gr_ep *ep) 3658c2ecf20Sopenharmony_ci{ 3668c2ecf20Sopenharmony_ci struct gr_request *req; 3678c2ecf20Sopenharmony_ci u32 dmactrl; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci if (list_empty(&ep->queue)) { 3708c2ecf20Sopenharmony_ci ep->dma_start = 0; 3718c2ecf20Sopenharmony_ci return; 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci req = list_first_entry(&ep->queue, struct gr_request, queue); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci /* A descriptor should already have been allocated */ 3778c2ecf20Sopenharmony_ci BUG_ON(!req->curr_desc); 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci /* 3808c2ecf20Sopenharmony_ci * The DMA controller can not handle smaller OUT buffers than 3818c2ecf20Sopenharmony_ci * ep->ep.maxpacket. It could lead to buffer overruns if an unexpectedly 3828c2ecf20Sopenharmony_ci * long packet are received. Therefore an internal bounce buffer gets 3838c2ecf20Sopenharmony_ci * used when such a request gets enabled. 3848c2ecf20Sopenharmony_ci */ 3858c2ecf20Sopenharmony_ci if (!ep->is_in && req->oddlen) 3868c2ecf20Sopenharmony_ci req->last_desc->data = ep->tailbuf_paddr; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci wmb(); /* Make sure all is settled before handing it over to DMA */ 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci /* Set the descriptor pointer in the hardware */ 3918c2ecf20Sopenharmony_ci gr_write32(&ep->regs->dmaaddr, req->curr_desc->paddr); 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci /* Announce available descriptors */ 3948c2ecf20Sopenharmony_ci dmactrl = gr_read32(&ep->regs->dmactrl); 3958c2ecf20Sopenharmony_ci gr_write32(&ep->regs->dmactrl, dmactrl | GR_DMACTRL_DA); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci ep->dma_start = 1; 3988c2ecf20Sopenharmony_ci} 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci/* 4018c2ecf20Sopenharmony_ci * Finishes the first request in the ep's queue and, if available, starts the 4028c2ecf20Sopenharmony_ci * next request in queue. 4038c2ecf20Sopenharmony_ci * 4048c2ecf20Sopenharmony_ci * Must be called with dev->lock held, irqs disabled and with !ep->stopped. 4058c2ecf20Sopenharmony_ci */ 4068c2ecf20Sopenharmony_cistatic void gr_dma_advance(struct gr_ep *ep, int status) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci struct gr_request *req; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci req = list_first_entry(&ep->queue, struct gr_request, queue); 4118c2ecf20Sopenharmony_ci gr_finish_request(ep, req, status); 4128c2ecf20Sopenharmony_ci gr_start_dma(ep); /* Regardless of ep->dma_start */ 4138c2ecf20Sopenharmony_ci} 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci/* 4168c2ecf20Sopenharmony_ci * Abort DMA for an endpoint. Sets the abort DMA bit which causes an ongoing DMA 4178c2ecf20Sopenharmony_ci * transfer to be canceled and clears GR_DMACTRL_DA. 4188c2ecf20Sopenharmony_ci * 4198c2ecf20Sopenharmony_ci * Must be called with dev->lock held. 4208c2ecf20Sopenharmony_ci */ 4218c2ecf20Sopenharmony_cistatic void gr_abort_dma(struct gr_ep *ep) 4228c2ecf20Sopenharmony_ci{ 4238c2ecf20Sopenharmony_ci u32 dmactrl; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci dmactrl = gr_read32(&ep->regs->dmactrl); 4268c2ecf20Sopenharmony_ci gr_write32(&ep->regs->dmactrl, dmactrl | GR_DMACTRL_AD); 4278c2ecf20Sopenharmony_ci} 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci/* 4308c2ecf20Sopenharmony_ci * Allocates and sets up a struct gr_dma_desc and putting it on the descriptor 4318c2ecf20Sopenharmony_ci * chain. 4328c2ecf20Sopenharmony_ci * 4338c2ecf20Sopenharmony_ci * Size is not used for OUT endpoints. Hardware can not be instructed to handle 4348c2ecf20Sopenharmony_ci * smaller buffer than MAXPL in the OUT direction. 4358c2ecf20Sopenharmony_ci */ 4368c2ecf20Sopenharmony_cistatic int gr_add_dma_desc(struct gr_ep *ep, struct gr_request *req, 4378c2ecf20Sopenharmony_ci dma_addr_t data, unsigned size, gfp_t gfp_flags) 4388c2ecf20Sopenharmony_ci{ 4398c2ecf20Sopenharmony_ci struct gr_dma_desc *desc; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci desc = gr_alloc_dma_desc(ep, gfp_flags); 4428c2ecf20Sopenharmony_ci if (!desc) 4438c2ecf20Sopenharmony_ci return -ENOMEM; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci desc->data = data; 4468c2ecf20Sopenharmony_ci if (ep->is_in) 4478c2ecf20Sopenharmony_ci desc->ctrl = 4488c2ecf20Sopenharmony_ci (GR_DESC_IN_CTRL_LEN_MASK & size) | GR_DESC_IN_CTRL_EN; 4498c2ecf20Sopenharmony_ci else 4508c2ecf20Sopenharmony_ci desc->ctrl = GR_DESC_OUT_CTRL_IE; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci if (!req->first_desc) { 4538c2ecf20Sopenharmony_ci req->first_desc = desc; 4548c2ecf20Sopenharmony_ci req->curr_desc = desc; 4558c2ecf20Sopenharmony_ci } else { 4568c2ecf20Sopenharmony_ci req->last_desc->next_desc = desc; 4578c2ecf20Sopenharmony_ci req->last_desc->next = desc->paddr; 4588c2ecf20Sopenharmony_ci req->last_desc->ctrl |= GR_DESC_OUT_CTRL_NX; 4598c2ecf20Sopenharmony_ci } 4608c2ecf20Sopenharmony_ci req->last_desc = desc; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci return 0; 4638c2ecf20Sopenharmony_ci} 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci/* 4668c2ecf20Sopenharmony_ci * Sets up a chain of struct gr_dma_descriptors pointing to buffers that 4678c2ecf20Sopenharmony_ci * together covers req->req.length bytes of the buffer at DMA address 4688c2ecf20Sopenharmony_ci * req->req.dma for the OUT direction. 4698c2ecf20Sopenharmony_ci * 4708c2ecf20Sopenharmony_ci * The first descriptor in the chain is enabled, the rest disabled. The 4718c2ecf20Sopenharmony_ci * interrupt handler will later enable them one by one when needed so we can 4728c2ecf20Sopenharmony_ci * find out when the transfer is finished. For OUT endpoints, all descriptors 4738c2ecf20Sopenharmony_ci * therefore generate interrutps. 4748c2ecf20Sopenharmony_ci */ 4758c2ecf20Sopenharmony_cistatic int gr_setup_out_desc_list(struct gr_ep *ep, struct gr_request *req, 4768c2ecf20Sopenharmony_ci gfp_t gfp_flags) 4778c2ecf20Sopenharmony_ci{ 4788c2ecf20Sopenharmony_ci u16 bytes_left; /* Bytes left to provide descriptors for */ 4798c2ecf20Sopenharmony_ci u16 bytes_used; /* Bytes accommodated for */ 4808c2ecf20Sopenharmony_ci int ret = 0; 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci req->first_desc = NULL; /* Signals that no allocation is done yet */ 4838c2ecf20Sopenharmony_ci bytes_left = req->req.length; 4848c2ecf20Sopenharmony_ci bytes_used = 0; 4858c2ecf20Sopenharmony_ci while (bytes_left > 0) { 4868c2ecf20Sopenharmony_ci dma_addr_t start = req->req.dma + bytes_used; 4878c2ecf20Sopenharmony_ci u16 size = min(bytes_left, ep->bytes_per_buffer); 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci if (size < ep->bytes_per_buffer) { 4908c2ecf20Sopenharmony_ci /* Prepare using bounce buffer */ 4918c2ecf20Sopenharmony_ci req->evenlen = req->req.length - bytes_left; 4928c2ecf20Sopenharmony_ci req->oddlen = size; 4938c2ecf20Sopenharmony_ci } 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci ret = gr_add_dma_desc(ep, req, start, size, gfp_flags); 4968c2ecf20Sopenharmony_ci if (ret) 4978c2ecf20Sopenharmony_ci goto alloc_err; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci bytes_left -= size; 5008c2ecf20Sopenharmony_ci bytes_used += size; 5018c2ecf20Sopenharmony_ci } 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci req->first_desc->ctrl |= GR_DESC_OUT_CTRL_EN; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci return 0; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_cialloc_err: 5088c2ecf20Sopenharmony_ci gr_free_dma_desc_chain(ep->dev, req); 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci return ret; 5118c2ecf20Sopenharmony_ci} 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci/* 5148c2ecf20Sopenharmony_ci * Sets up a chain of struct gr_dma_descriptors pointing to buffers that 5158c2ecf20Sopenharmony_ci * together covers req->req.length bytes of the buffer at DMA address 5168c2ecf20Sopenharmony_ci * req->req.dma for the IN direction. 5178c2ecf20Sopenharmony_ci * 5188c2ecf20Sopenharmony_ci * When more data is provided than the maximum payload size, the hardware splits 5198c2ecf20Sopenharmony_ci * this up into several payloads automatically. Moreover, ep->bytes_per_buffer 5208c2ecf20Sopenharmony_ci * is always set to a multiple of the maximum payload (restricted to the valid 5218c2ecf20Sopenharmony_ci * number of maximum payloads during high bandwidth isochronous or interrupt 5228c2ecf20Sopenharmony_ci * transfers) 5238c2ecf20Sopenharmony_ci * 5248c2ecf20Sopenharmony_ci * All descriptors are enabled from the beginning and we only generate an 5258c2ecf20Sopenharmony_ci * interrupt for the last one indicating that the entire request has been pushed 5268c2ecf20Sopenharmony_ci * to hardware. 5278c2ecf20Sopenharmony_ci */ 5288c2ecf20Sopenharmony_cistatic int gr_setup_in_desc_list(struct gr_ep *ep, struct gr_request *req, 5298c2ecf20Sopenharmony_ci gfp_t gfp_flags) 5308c2ecf20Sopenharmony_ci{ 5318c2ecf20Sopenharmony_ci u16 bytes_left; /* Bytes left in req to provide descriptors for */ 5328c2ecf20Sopenharmony_ci u16 bytes_used; /* Bytes in req accommodated for */ 5338c2ecf20Sopenharmony_ci int ret = 0; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci req->first_desc = NULL; /* Signals that no allocation is done yet */ 5368c2ecf20Sopenharmony_ci bytes_left = req->req.length; 5378c2ecf20Sopenharmony_ci bytes_used = 0; 5388c2ecf20Sopenharmony_ci do { /* Allow for zero length packets */ 5398c2ecf20Sopenharmony_ci dma_addr_t start = req->req.dma + bytes_used; 5408c2ecf20Sopenharmony_ci u16 size = min(bytes_left, ep->bytes_per_buffer); 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci ret = gr_add_dma_desc(ep, req, start, size, gfp_flags); 5438c2ecf20Sopenharmony_ci if (ret) 5448c2ecf20Sopenharmony_ci goto alloc_err; 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci bytes_left -= size; 5478c2ecf20Sopenharmony_ci bytes_used += size; 5488c2ecf20Sopenharmony_ci } while (bytes_left > 0); 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci /* 5518c2ecf20Sopenharmony_ci * Send an extra zero length packet to indicate that no more data is 5528c2ecf20Sopenharmony_ci * available when req->req.zero is set and the data length is even 5538c2ecf20Sopenharmony_ci * multiples of ep->ep.maxpacket. 5548c2ecf20Sopenharmony_ci */ 5558c2ecf20Sopenharmony_ci if (req->req.zero && (req->req.length % ep->ep.maxpacket == 0)) { 5568c2ecf20Sopenharmony_ci ret = gr_add_dma_desc(ep, req, 0, 0, gfp_flags); 5578c2ecf20Sopenharmony_ci if (ret) 5588c2ecf20Sopenharmony_ci goto alloc_err; 5598c2ecf20Sopenharmony_ci } 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci /* 5628c2ecf20Sopenharmony_ci * For IN packets we only want to know when the last packet has been 5638c2ecf20Sopenharmony_ci * transmitted (not just put into internal buffers). 5648c2ecf20Sopenharmony_ci */ 5658c2ecf20Sopenharmony_ci req->last_desc->ctrl |= GR_DESC_IN_CTRL_PI; 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci return 0; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_cialloc_err: 5708c2ecf20Sopenharmony_ci gr_free_dma_desc_chain(ep->dev, req); 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci return ret; 5738c2ecf20Sopenharmony_ci} 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci/* Must be called with dev->lock held */ 5768c2ecf20Sopenharmony_cistatic int gr_queue(struct gr_ep *ep, struct gr_request *req, gfp_t gfp_flags) 5778c2ecf20Sopenharmony_ci{ 5788c2ecf20Sopenharmony_ci struct gr_udc *dev = ep->dev; 5798c2ecf20Sopenharmony_ci int ret; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci if (unlikely(!ep->ep.desc && ep->num != 0)) { 5828c2ecf20Sopenharmony_ci dev_err(dev->dev, "No ep descriptor for %s\n", ep->ep.name); 5838c2ecf20Sopenharmony_ci return -EINVAL; 5848c2ecf20Sopenharmony_ci } 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci if (unlikely(!req->req.buf || !list_empty(&req->queue))) { 5878c2ecf20Sopenharmony_ci dev_err(dev->dev, 5888c2ecf20Sopenharmony_ci "Invalid request for %s: buf=%p list_empty=%d\n", 5898c2ecf20Sopenharmony_ci ep->ep.name, req->req.buf, list_empty(&req->queue)); 5908c2ecf20Sopenharmony_ci return -EINVAL; 5918c2ecf20Sopenharmony_ci } 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) { 5948c2ecf20Sopenharmony_ci dev_err(dev->dev, "-ESHUTDOWN"); 5958c2ecf20Sopenharmony_ci return -ESHUTDOWN; 5968c2ecf20Sopenharmony_ci } 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci /* Can't touch registers when suspended */ 5998c2ecf20Sopenharmony_ci if (dev->ep0state == GR_EP0_SUSPEND) { 6008c2ecf20Sopenharmony_ci dev_err(dev->dev, "-EBUSY"); 6018c2ecf20Sopenharmony_ci return -EBUSY; 6028c2ecf20Sopenharmony_ci } 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci /* Set up DMA mapping in case the caller didn't */ 6058c2ecf20Sopenharmony_ci ret = usb_gadget_map_request(&dev->gadget, &req->req, ep->is_in); 6068c2ecf20Sopenharmony_ci if (ret) { 6078c2ecf20Sopenharmony_ci dev_err(dev->dev, "usb_gadget_map_request"); 6088c2ecf20Sopenharmony_ci return ret; 6098c2ecf20Sopenharmony_ci } 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci if (ep->is_in) 6128c2ecf20Sopenharmony_ci ret = gr_setup_in_desc_list(ep, req, gfp_flags); 6138c2ecf20Sopenharmony_ci else 6148c2ecf20Sopenharmony_ci ret = gr_setup_out_desc_list(ep, req, gfp_flags); 6158c2ecf20Sopenharmony_ci if (ret) 6168c2ecf20Sopenharmony_ci return ret; 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci req->req.status = -EINPROGRESS; 6198c2ecf20Sopenharmony_ci req->req.actual = 0; 6208c2ecf20Sopenharmony_ci list_add_tail(&req->queue, &ep->queue); 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci /* Start DMA if not started, otherwise interrupt handler handles it */ 6238c2ecf20Sopenharmony_ci if (!ep->dma_start && likely(!ep->stopped)) 6248c2ecf20Sopenharmony_ci gr_start_dma(ep); 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci return 0; 6278c2ecf20Sopenharmony_ci} 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci/* 6308c2ecf20Sopenharmony_ci * Queue a request from within the driver. 6318c2ecf20Sopenharmony_ci * 6328c2ecf20Sopenharmony_ci * Must be called with dev->lock held. 6338c2ecf20Sopenharmony_ci */ 6348c2ecf20Sopenharmony_cistatic inline int gr_queue_int(struct gr_ep *ep, struct gr_request *req, 6358c2ecf20Sopenharmony_ci gfp_t gfp_flags) 6368c2ecf20Sopenharmony_ci{ 6378c2ecf20Sopenharmony_ci if (ep->is_in) 6388c2ecf20Sopenharmony_ci gr_dbgprint_request("RESP", ep, req); 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci return gr_queue(ep, req, gfp_flags); 6418c2ecf20Sopenharmony_ci} 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci/* ---------------------------------------------------------------------- */ 6448c2ecf20Sopenharmony_ci/* General helper functions */ 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci/* 6478c2ecf20Sopenharmony_ci * Dequeue ALL requests. 6488c2ecf20Sopenharmony_ci * 6498c2ecf20Sopenharmony_ci * Must be called with dev->lock held and irqs disabled. 6508c2ecf20Sopenharmony_ci */ 6518c2ecf20Sopenharmony_cistatic void gr_ep_nuke(struct gr_ep *ep) 6528c2ecf20Sopenharmony_ci{ 6538c2ecf20Sopenharmony_ci struct gr_request *req; 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci ep->stopped = 1; 6568c2ecf20Sopenharmony_ci ep->dma_start = 0; 6578c2ecf20Sopenharmony_ci gr_abort_dma(ep); 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci while (!list_empty(&ep->queue)) { 6608c2ecf20Sopenharmony_ci req = list_first_entry(&ep->queue, struct gr_request, queue); 6618c2ecf20Sopenharmony_ci gr_finish_request(ep, req, -ESHUTDOWN); 6628c2ecf20Sopenharmony_ci } 6638c2ecf20Sopenharmony_ci} 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci/* 6668c2ecf20Sopenharmony_ci * Reset the hardware state of this endpoint. 6678c2ecf20Sopenharmony_ci * 6688c2ecf20Sopenharmony_ci * Must be called with dev->lock held. 6698c2ecf20Sopenharmony_ci */ 6708c2ecf20Sopenharmony_cistatic void gr_ep_reset(struct gr_ep *ep) 6718c2ecf20Sopenharmony_ci{ 6728c2ecf20Sopenharmony_ci gr_write32(&ep->regs->epctrl, 0); 6738c2ecf20Sopenharmony_ci gr_write32(&ep->regs->dmactrl, 0); 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci ep->ep.maxpacket = MAX_CTRL_PL_SIZE; 6768c2ecf20Sopenharmony_ci ep->ep.desc = NULL; 6778c2ecf20Sopenharmony_ci ep->stopped = 1; 6788c2ecf20Sopenharmony_ci ep->dma_start = 0; 6798c2ecf20Sopenharmony_ci} 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci/* 6828c2ecf20Sopenharmony_ci * Generate STALL on ep0in/out. 6838c2ecf20Sopenharmony_ci * 6848c2ecf20Sopenharmony_ci * Must be called with dev->lock held. 6858c2ecf20Sopenharmony_ci */ 6868c2ecf20Sopenharmony_cistatic void gr_control_stall(struct gr_udc *dev) 6878c2ecf20Sopenharmony_ci{ 6888c2ecf20Sopenharmony_ci u32 epctrl; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci epctrl = gr_read32(&dev->epo[0].regs->epctrl); 6918c2ecf20Sopenharmony_ci gr_write32(&dev->epo[0].regs->epctrl, epctrl | GR_EPCTRL_CS); 6928c2ecf20Sopenharmony_ci epctrl = gr_read32(&dev->epi[0].regs->epctrl); 6938c2ecf20Sopenharmony_ci gr_write32(&dev->epi[0].regs->epctrl, epctrl | GR_EPCTRL_CS); 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci dev->ep0state = GR_EP0_STALL; 6968c2ecf20Sopenharmony_ci} 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci/* 6998c2ecf20Sopenharmony_ci * Halts, halts and wedges, or clears halt for an endpoint. 7008c2ecf20Sopenharmony_ci * 7018c2ecf20Sopenharmony_ci * Must be called with dev->lock held. 7028c2ecf20Sopenharmony_ci */ 7038c2ecf20Sopenharmony_cistatic int gr_ep_halt_wedge(struct gr_ep *ep, int halt, int wedge, int fromhost) 7048c2ecf20Sopenharmony_ci{ 7058c2ecf20Sopenharmony_ci u32 epctrl; 7068c2ecf20Sopenharmony_ci int retval = 0; 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci if (ep->num && !ep->ep.desc) 7098c2ecf20Sopenharmony_ci return -EINVAL; 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci if (ep->num && ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) 7128c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci /* Never actually halt ep0, and therefore never clear halt for ep0 */ 7158c2ecf20Sopenharmony_ci if (!ep->num) { 7168c2ecf20Sopenharmony_ci if (halt && !fromhost) { 7178c2ecf20Sopenharmony_ci /* ep0 halt from gadget - generate protocol stall */ 7188c2ecf20Sopenharmony_ci gr_control_stall(ep->dev); 7198c2ecf20Sopenharmony_ci dev_dbg(ep->dev->dev, "EP: stall ep0\n"); 7208c2ecf20Sopenharmony_ci return 0; 7218c2ecf20Sopenharmony_ci } 7228c2ecf20Sopenharmony_ci return -EINVAL; 7238c2ecf20Sopenharmony_ci } 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci dev_dbg(ep->dev->dev, "EP: %s halt %s\n", 7268c2ecf20Sopenharmony_ci (halt ? (wedge ? "wedge" : "set") : "clear"), ep->ep.name); 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci epctrl = gr_read32(&ep->regs->epctrl); 7298c2ecf20Sopenharmony_ci if (halt) { 7308c2ecf20Sopenharmony_ci /* Set HALT */ 7318c2ecf20Sopenharmony_ci gr_write32(&ep->regs->epctrl, epctrl | GR_EPCTRL_EH); 7328c2ecf20Sopenharmony_ci ep->stopped = 1; 7338c2ecf20Sopenharmony_ci if (wedge) 7348c2ecf20Sopenharmony_ci ep->wedged = 1; 7358c2ecf20Sopenharmony_ci } else { 7368c2ecf20Sopenharmony_ci gr_write32(&ep->regs->epctrl, epctrl & ~GR_EPCTRL_EH); 7378c2ecf20Sopenharmony_ci ep->stopped = 0; 7388c2ecf20Sopenharmony_ci ep->wedged = 0; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci /* Things might have been queued up in the meantime */ 7418c2ecf20Sopenharmony_ci if (!ep->dma_start) 7428c2ecf20Sopenharmony_ci gr_start_dma(ep); 7438c2ecf20Sopenharmony_ci } 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci return retval; 7468c2ecf20Sopenharmony_ci} 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci/* Must be called with dev->lock held */ 7498c2ecf20Sopenharmony_cistatic inline void gr_set_ep0state(struct gr_udc *dev, enum gr_ep0state value) 7508c2ecf20Sopenharmony_ci{ 7518c2ecf20Sopenharmony_ci if (dev->ep0state != value) 7528c2ecf20Sopenharmony_ci dev_vdbg(dev->dev, "STATE: ep0state=%s\n", 7538c2ecf20Sopenharmony_ci gr_ep0state_string(value)); 7548c2ecf20Sopenharmony_ci dev->ep0state = value; 7558c2ecf20Sopenharmony_ci} 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci/* 7588c2ecf20Sopenharmony_ci * Should only be called when endpoints can not generate interrupts. 7598c2ecf20Sopenharmony_ci * 7608c2ecf20Sopenharmony_ci * Must be called with dev->lock held. 7618c2ecf20Sopenharmony_ci */ 7628c2ecf20Sopenharmony_cistatic void gr_disable_interrupts_and_pullup(struct gr_udc *dev) 7638c2ecf20Sopenharmony_ci{ 7648c2ecf20Sopenharmony_ci gr_write32(&dev->regs->control, 0); 7658c2ecf20Sopenharmony_ci wmb(); /* Make sure that we do not deny one of our interrupts */ 7668c2ecf20Sopenharmony_ci dev->irq_enabled = 0; 7678c2ecf20Sopenharmony_ci} 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci/* 7708c2ecf20Sopenharmony_ci * Stop all device activity and disable data line pullup. 7718c2ecf20Sopenharmony_ci * 7728c2ecf20Sopenharmony_ci * Must be called with dev->lock held and irqs disabled. 7738c2ecf20Sopenharmony_ci */ 7748c2ecf20Sopenharmony_cistatic void gr_stop_activity(struct gr_udc *dev) 7758c2ecf20Sopenharmony_ci{ 7768c2ecf20Sopenharmony_ci struct gr_ep *ep; 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci list_for_each_entry(ep, &dev->ep_list, ep_list) 7798c2ecf20Sopenharmony_ci gr_ep_nuke(ep); 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci gr_disable_interrupts_and_pullup(dev); 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_DISCONNECT); 7848c2ecf20Sopenharmony_ci usb_gadget_set_state(&dev->gadget, USB_STATE_NOTATTACHED); 7858c2ecf20Sopenharmony_ci} 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci/* ---------------------------------------------------------------------- */ 7888c2ecf20Sopenharmony_ci/* ep0 setup packet handling */ 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_cistatic void gr_ep0_testmode_complete(struct usb_ep *_ep, 7918c2ecf20Sopenharmony_ci struct usb_request *_req) 7928c2ecf20Sopenharmony_ci{ 7938c2ecf20Sopenharmony_ci struct gr_ep *ep; 7948c2ecf20Sopenharmony_ci struct gr_udc *dev; 7958c2ecf20Sopenharmony_ci u32 control; 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci ep = container_of(_ep, struct gr_ep, ep); 7988c2ecf20Sopenharmony_ci dev = ep->dev; 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci spin_lock(&dev->lock); 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci control = gr_read32(&dev->regs->control); 8038c2ecf20Sopenharmony_ci control |= GR_CONTROL_TM | (dev->test_mode << GR_CONTROL_TS_POS); 8048c2ecf20Sopenharmony_ci gr_write32(&dev->regs->control, control); 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci spin_unlock(&dev->lock); 8078c2ecf20Sopenharmony_ci} 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_cistatic void gr_ep0_dummy_complete(struct usb_ep *_ep, struct usb_request *_req) 8108c2ecf20Sopenharmony_ci{ 8118c2ecf20Sopenharmony_ci /* Nothing needs to be done here */ 8128c2ecf20Sopenharmony_ci} 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci/* 8158c2ecf20Sopenharmony_ci * Queue a response on ep0in. 8168c2ecf20Sopenharmony_ci * 8178c2ecf20Sopenharmony_ci * Must be called with dev->lock held. 8188c2ecf20Sopenharmony_ci */ 8198c2ecf20Sopenharmony_cistatic int gr_ep0_respond(struct gr_udc *dev, u8 *buf, int length, 8208c2ecf20Sopenharmony_ci void (*complete)(struct usb_ep *ep, 8218c2ecf20Sopenharmony_ci struct usb_request *req)) 8228c2ecf20Sopenharmony_ci{ 8238c2ecf20Sopenharmony_ci u8 *reqbuf = dev->ep0reqi->req.buf; 8248c2ecf20Sopenharmony_ci int status; 8258c2ecf20Sopenharmony_ci int i; 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci for (i = 0; i < length; i++) 8288c2ecf20Sopenharmony_ci reqbuf[i] = buf[i]; 8298c2ecf20Sopenharmony_ci dev->ep0reqi->req.length = length; 8308c2ecf20Sopenharmony_ci dev->ep0reqi->req.complete = complete; 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci status = gr_queue_int(&dev->epi[0], dev->ep0reqi, GFP_ATOMIC); 8338c2ecf20Sopenharmony_ci if (status < 0) 8348c2ecf20Sopenharmony_ci dev_err(dev->dev, 8358c2ecf20Sopenharmony_ci "Could not queue ep0in setup response: %d\n", status); 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci return status; 8388c2ecf20Sopenharmony_ci} 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci/* 8418c2ecf20Sopenharmony_ci * Queue a 2 byte response on ep0in. 8428c2ecf20Sopenharmony_ci * 8438c2ecf20Sopenharmony_ci * Must be called with dev->lock held. 8448c2ecf20Sopenharmony_ci */ 8458c2ecf20Sopenharmony_cistatic inline int gr_ep0_respond_u16(struct gr_udc *dev, u16 response) 8468c2ecf20Sopenharmony_ci{ 8478c2ecf20Sopenharmony_ci __le16 le_response = cpu_to_le16(response); 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci return gr_ep0_respond(dev, (u8 *)&le_response, 2, 8508c2ecf20Sopenharmony_ci gr_ep0_dummy_complete); 8518c2ecf20Sopenharmony_ci} 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci/* 8548c2ecf20Sopenharmony_ci * Queue a ZLP response on ep0in. 8558c2ecf20Sopenharmony_ci * 8568c2ecf20Sopenharmony_ci * Must be called with dev->lock held. 8578c2ecf20Sopenharmony_ci */ 8588c2ecf20Sopenharmony_cistatic inline int gr_ep0_respond_empty(struct gr_udc *dev) 8598c2ecf20Sopenharmony_ci{ 8608c2ecf20Sopenharmony_ci return gr_ep0_respond(dev, NULL, 0, gr_ep0_dummy_complete); 8618c2ecf20Sopenharmony_ci} 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci/* 8648c2ecf20Sopenharmony_ci * This is run when a SET_ADDRESS request is received. First writes 8658c2ecf20Sopenharmony_ci * the new address to the control register which is updated internally 8668c2ecf20Sopenharmony_ci * when the next IN packet is ACKED. 8678c2ecf20Sopenharmony_ci * 8688c2ecf20Sopenharmony_ci * Must be called with dev->lock held. 8698c2ecf20Sopenharmony_ci */ 8708c2ecf20Sopenharmony_cistatic void gr_set_address(struct gr_udc *dev, u8 address) 8718c2ecf20Sopenharmony_ci{ 8728c2ecf20Sopenharmony_ci u32 control; 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci control = gr_read32(&dev->regs->control) & ~GR_CONTROL_UA_MASK; 8758c2ecf20Sopenharmony_ci control |= (address << GR_CONTROL_UA_POS) & GR_CONTROL_UA_MASK; 8768c2ecf20Sopenharmony_ci control |= GR_CONTROL_SU; 8778c2ecf20Sopenharmony_ci gr_write32(&dev->regs->control, control); 8788c2ecf20Sopenharmony_ci} 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci/* 8818c2ecf20Sopenharmony_ci * Returns negative for STALL, 0 for successful handling and positive for 8828c2ecf20Sopenharmony_ci * delegation. 8838c2ecf20Sopenharmony_ci * 8848c2ecf20Sopenharmony_ci * Must be called with dev->lock held. 8858c2ecf20Sopenharmony_ci */ 8868c2ecf20Sopenharmony_cistatic int gr_device_request(struct gr_udc *dev, u8 type, u8 request, 8878c2ecf20Sopenharmony_ci u16 value, u16 index) 8888c2ecf20Sopenharmony_ci{ 8898c2ecf20Sopenharmony_ci u16 response; 8908c2ecf20Sopenharmony_ci u8 test; 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci switch (request) { 8938c2ecf20Sopenharmony_ci case USB_REQ_SET_ADDRESS: 8948c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "STATUS: address %d\n", value & 0xff); 8958c2ecf20Sopenharmony_ci gr_set_address(dev, value & 0xff); 8968c2ecf20Sopenharmony_ci if (value) 8978c2ecf20Sopenharmony_ci usb_gadget_set_state(&dev->gadget, USB_STATE_ADDRESS); 8988c2ecf20Sopenharmony_ci else 8998c2ecf20Sopenharmony_ci usb_gadget_set_state(&dev->gadget, USB_STATE_DEFAULT); 9008c2ecf20Sopenharmony_ci return gr_ep0_respond_empty(dev); 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci case USB_REQ_GET_STATUS: 9038c2ecf20Sopenharmony_ci /* Self powered | remote wakeup */ 9048c2ecf20Sopenharmony_ci response = 0x0001 | (dev->remote_wakeup ? 0x0002 : 0); 9058c2ecf20Sopenharmony_ci return gr_ep0_respond_u16(dev, response); 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci case USB_REQ_SET_FEATURE: 9088c2ecf20Sopenharmony_ci switch (value) { 9098c2ecf20Sopenharmony_ci case USB_DEVICE_REMOTE_WAKEUP: 9108c2ecf20Sopenharmony_ci /* Allow remote wakeup */ 9118c2ecf20Sopenharmony_ci dev->remote_wakeup = 1; 9128c2ecf20Sopenharmony_ci return gr_ep0_respond_empty(dev); 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci case USB_DEVICE_TEST_MODE: 9158c2ecf20Sopenharmony_ci /* The hardware does not support USB_TEST_FORCE_ENABLE */ 9168c2ecf20Sopenharmony_ci test = index >> 8; 9178c2ecf20Sopenharmony_ci if (test >= USB_TEST_J && test <= USB_TEST_PACKET) { 9188c2ecf20Sopenharmony_ci dev->test_mode = test; 9198c2ecf20Sopenharmony_ci return gr_ep0_respond(dev, NULL, 0, 9208c2ecf20Sopenharmony_ci gr_ep0_testmode_complete); 9218c2ecf20Sopenharmony_ci } 9228c2ecf20Sopenharmony_ci } 9238c2ecf20Sopenharmony_ci break; 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci case USB_REQ_CLEAR_FEATURE: 9268c2ecf20Sopenharmony_ci switch (value) { 9278c2ecf20Sopenharmony_ci case USB_DEVICE_REMOTE_WAKEUP: 9288c2ecf20Sopenharmony_ci /* Disallow remote wakeup */ 9298c2ecf20Sopenharmony_ci dev->remote_wakeup = 0; 9308c2ecf20Sopenharmony_ci return gr_ep0_respond_empty(dev); 9318c2ecf20Sopenharmony_ci } 9328c2ecf20Sopenharmony_ci break; 9338c2ecf20Sopenharmony_ci } 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_ci return 1; /* Delegate the rest */ 9368c2ecf20Sopenharmony_ci} 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci/* 9398c2ecf20Sopenharmony_ci * Returns negative for STALL, 0 for successful handling and positive for 9408c2ecf20Sopenharmony_ci * delegation. 9418c2ecf20Sopenharmony_ci * 9428c2ecf20Sopenharmony_ci * Must be called with dev->lock held. 9438c2ecf20Sopenharmony_ci */ 9448c2ecf20Sopenharmony_cistatic int gr_interface_request(struct gr_udc *dev, u8 type, u8 request, 9458c2ecf20Sopenharmony_ci u16 value, u16 index) 9468c2ecf20Sopenharmony_ci{ 9478c2ecf20Sopenharmony_ci if (dev->gadget.state != USB_STATE_CONFIGURED) 9488c2ecf20Sopenharmony_ci return -1; 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci /* 9518c2ecf20Sopenharmony_ci * Should return STALL for invalid interfaces, but udc driver does not 9528c2ecf20Sopenharmony_ci * know anything about that. However, many gadget drivers do not handle 9538c2ecf20Sopenharmony_ci * GET_STATUS so we need to take care of that. 9548c2ecf20Sopenharmony_ci */ 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci switch (request) { 9578c2ecf20Sopenharmony_ci case USB_REQ_GET_STATUS: 9588c2ecf20Sopenharmony_ci return gr_ep0_respond_u16(dev, 0x0000); 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci case USB_REQ_SET_FEATURE: 9618c2ecf20Sopenharmony_ci case USB_REQ_CLEAR_FEATURE: 9628c2ecf20Sopenharmony_ci /* 9638c2ecf20Sopenharmony_ci * No possible valid standard requests. Still let gadget drivers 9648c2ecf20Sopenharmony_ci * have a go at it. 9658c2ecf20Sopenharmony_ci */ 9668c2ecf20Sopenharmony_ci break; 9678c2ecf20Sopenharmony_ci } 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci return 1; /* Delegate the rest */ 9708c2ecf20Sopenharmony_ci} 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci/* 9738c2ecf20Sopenharmony_ci * Returns negative for STALL, 0 for successful handling and positive for 9748c2ecf20Sopenharmony_ci * delegation. 9758c2ecf20Sopenharmony_ci * 9768c2ecf20Sopenharmony_ci * Must be called with dev->lock held. 9778c2ecf20Sopenharmony_ci */ 9788c2ecf20Sopenharmony_cistatic int gr_endpoint_request(struct gr_udc *dev, u8 type, u8 request, 9798c2ecf20Sopenharmony_ci u16 value, u16 index) 9808c2ecf20Sopenharmony_ci{ 9818c2ecf20Sopenharmony_ci struct gr_ep *ep; 9828c2ecf20Sopenharmony_ci int status; 9838c2ecf20Sopenharmony_ci int halted; 9848c2ecf20Sopenharmony_ci u8 epnum = index & USB_ENDPOINT_NUMBER_MASK; 9858c2ecf20Sopenharmony_ci u8 is_in = index & USB_ENDPOINT_DIR_MASK; 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci if ((is_in && epnum >= dev->nepi) || (!is_in && epnum >= dev->nepo)) 9888c2ecf20Sopenharmony_ci return -1; 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci if (dev->gadget.state != USB_STATE_CONFIGURED && epnum != 0) 9918c2ecf20Sopenharmony_ci return -1; 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci ep = (is_in ? &dev->epi[epnum] : &dev->epo[epnum]); 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci switch (request) { 9968c2ecf20Sopenharmony_ci case USB_REQ_GET_STATUS: 9978c2ecf20Sopenharmony_ci halted = gr_read32(&ep->regs->epctrl) & GR_EPCTRL_EH; 9988c2ecf20Sopenharmony_ci return gr_ep0_respond_u16(dev, halted ? 0x0001 : 0); 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci case USB_REQ_SET_FEATURE: 10018c2ecf20Sopenharmony_ci switch (value) { 10028c2ecf20Sopenharmony_ci case USB_ENDPOINT_HALT: 10038c2ecf20Sopenharmony_ci status = gr_ep_halt_wedge(ep, 1, 0, 1); 10048c2ecf20Sopenharmony_ci if (status >= 0) 10058c2ecf20Sopenharmony_ci status = gr_ep0_respond_empty(dev); 10068c2ecf20Sopenharmony_ci return status; 10078c2ecf20Sopenharmony_ci } 10088c2ecf20Sopenharmony_ci break; 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci case USB_REQ_CLEAR_FEATURE: 10118c2ecf20Sopenharmony_ci switch (value) { 10128c2ecf20Sopenharmony_ci case USB_ENDPOINT_HALT: 10138c2ecf20Sopenharmony_ci if (ep->wedged) 10148c2ecf20Sopenharmony_ci return -1; 10158c2ecf20Sopenharmony_ci status = gr_ep_halt_wedge(ep, 0, 0, 1); 10168c2ecf20Sopenharmony_ci if (status >= 0) 10178c2ecf20Sopenharmony_ci status = gr_ep0_respond_empty(dev); 10188c2ecf20Sopenharmony_ci return status; 10198c2ecf20Sopenharmony_ci } 10208c2ecf20Sopenharmony_ci break; 10218c2ecf20Sopenharmony_ci } 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci return 1; /* Delegate the rest */ 10248c2ecf20Sopenharmony_ci} 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci/* Must be called with dev->lock held */ 10278c2ecf20Sopenharmony_cistatic void gr_ep0out_requeue(struct gr_udc *dev) 10288c2ecf20Sopenharmony_ci{ 10298c2ecf20Sopenharmony_ci int ret = gr_queue_int(&dev->epo[0], dev->ep0reqo, GFP_ATOMIC); 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci if (ret) 10328c2ecf20Sopenharmony_ci dev_err(dev->dev, "Could not queue ep0out setup request: %d\n", 10338c2ecf20Sopenharmony_ci ret); 10348c2ecf20Sopenharmony_ci} 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci/* 10378c2ecf20Sopenharmony_ci * The main function dealing with setup requests on ep0. 10388c2ecf20Sopenharmony_ci * 10398c2ecf20Sopenharmony_ci * Must be called with dev->lock held and irqs disabled 10408c2ecf20Sopenharmony_ci */ 10418c2ecf20Sopenharmony_cistatic void gr_ep0_setup(struct gr_udc *dev, struct gr_request *req) 10428c2ecf20Sopenharmony_ci __releases(&dev->lock) 10438c2ecf20Sopenharmony_ci __acquires(&dev->lock) 10448c2ecf20Sopenharmony_ci{ 10458c2ecf20Sopenharmony_ci union { 10468c2ecf20Sopenharmony_ci struct usb_ctrlrequest ctrl; 10478c2ecf20Sopenharmony_ci u8 raw[8]; 10488c2ecf20Sopenharmony_ci u32 word[2]; 10498c2ecf20Sopenharmony_ci } u; 10508c2ecf20Sopenharmony_ci u8 type; 10518c2ecf20Sopenharmony_ci u8 request; 10528c2ecf20Sopenharmony_ci u16 value; 10538c2ecf20Sopenharmony_ci u16 index; 10548c2ecf20Sopenharmony_ci u16 length; 10558c2ecf20Sopenharmony_ci int i; 10568c2ecf20Sopenharmony_ci int status; 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci /* Restore from ep0 halt */ 10598c2ecf20Sopenharmony_ci if (dev->ep0state == GR_EP0_STALL) { 10608c2ecf20Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_SETUP); 10618c2ecf20Sopenharmony_ci if (!req->req.actual) 10628c2ecf20Sopenharmony_ci goto out; 10638c2ecf20Sopenharmony_ci } 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci if (dev->ep0state == GR_EP0_ISTATUS) { 10668c2ecf20Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_SETUP); 10678c2ecf20Sopenharmony_ci if (req->req.actual > 0) 10688c2ecf20Sopenharmony_ci dev_dbg(dev->dev, 10698c2ecf20Sopenharmony_ci "Unexpected setup packet at state %s\n", 10708c2ecf20Sopenharmony_ci gr_ep0state_string(GR_EP0_ISTATUS)); 10718c2ecf20Sopenharmony_ci else 10728c2ecf20Sopenharmony_ci goto out; /* Got expected ZLP */ 10738c2ecf20Sopenharmony_ci } else if (dev->ep0state != GR_EP0_SETUP) { 10748c2ecf20Sopenharmony_ci dev_info(dev->dev, 10758c2ecf20Sopenharmony_ci "Unexpected ep0out request at state %s - stalling\n", 10768c2ecf20Sopenharmony_ci gr_ep0state_string(dev->ep0state)); 10778c2ecf20Sopenharmony_ci gr_control_stall(dev); 10788c2ecf20Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_SETUP); 10798c2ecf20Sopenharmony_ci goto out; 10808c2ecf20Sopenharmony_ci } else if (!req->req.actual) { 10818c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "Unexpected ZLP at state %s\n", 10828c2ecf20Sopenharmony_ci gr_ep0state_string(dev->ep0state)); 10838c2ecf20Sopenharmony_ci goto out; 10848c2ecf20Sopenharmony_ci } 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci /* Handle SETUP packet */ 10878c2ecf20Sopenharmony_ci for (i = 0; i < req->req.actual; i++) 10888c2ecf20Sopenharmony_ci u.raw[i] = ((u8 *)req->req.buf)[i]; 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci type = u.ctrl.bRequestType; 10918c2ecf20Sopenharmony_ci request = u.ctrl.bRequest; 10928c2ecf20Sopenharmony_ci value = le16_to_cpu(u.ctrl.wValue); 10938c2ecf20Sopenharmony_ci index = le16_to_cpu(u.ctrl.wIndex); 10948c2ecf20Sopenharmony_ci length = le16_to_cpu(u.ctrl.wLength); 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci gr_dbgprint_devreq(dev, type, request, value, index, length); 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci /* Check for data stage */ 10998c2ecf20Sopenharmony_ci if (length) { 11008c2ecf20Sopenharmony_ci if (type & USB_DIR_IN) 11018c2ecf20Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_IDATA); 11028c2ecf20Sopenharmony_ci else 11038c2ecf20Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_ODATA); 11048c2ecf20Sopenharmony_ci } 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci status = 1; /* Positive status flags delegation */ 11078c2ecf20Sopenharmony_ci if ((type & USB_TYPE_MASK) == USB_TYPE_STANDARD) { 11088c2ecf20Sopenharmony_ci switch (type & USB_RECIP_MASK) { 11098c2ecf20Sopenharmony_ci case USB_RECIP_DEVICE: 11108c2ecf20Sopenharmony_ci status = gr_device_request(dev, type, request, 11118c2ecf20Sopenharmony_ci value, index); 11128c2ecf20Sopenharmony_ci break; 11138c2ecf20Sopenharmony_ci case USB_RECIP_ENDPOINT: 11148c2ecf20Sopenharmony_ci status = gr_endpoint_request(dev, type, request, 11158c2ecf20Sopenharmony_ci value, index); 11168c2ecf20Sopenharmony_ci break; 11178c2ecf20Sopenharmony_ci case USB_RECIP_INTERFACE: 11188c2ecf20Sopenharmony_ci status = gr_interface_request(dev, type, request, 11198c2ecf20Sopenharmony_ci value, index); 11208c2ecf20Sopenharmony_ci break; 11218c2ecf20Sopenharmony_ci } 11228c2ecf20Sopenharmony_ci } 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci if (status > 0) { 11258c2ecf20Sopenharmony_ci spin_unlock(&dev->lock); 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci dev_vdbg(dev->dev, "DELEGATE\n"); 11288c2ecf20Sopenharmony_ci status = dev->driver->setup(&dev->gadget, &u.ctrl); 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci spin_lock(&dev->lock); 11318c2ecf20Sopenharmony_ci } 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci /* Generate STALL on both ep0out and ep0in if requested */ 11348c2ecf20Sopenharmony_ci if (unlikely(status < 0)) { 11358c2ecf20Sopenharmony_ci dev_vdbg(dev->dev, "STALL\n"); 11368c2ecf20Sopenharmony_ci gr_control_stall(dev); 11378c2ecf20Sopenharmony_ci } 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci if ((type & USB_TYPE_MASK) == USB_TYPE_STANDARD && 11408c2ecf20Sopenharmony_ci request == USB_REQ_SET_CONFIGURATION) { 11418c2ecf20Sopenharmony_ci if (!value) { 11428c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "STATUS: deconfigured\n"); 11438c2ecf20Sopenharmony_ci usb_gadget_set_state(&dev->gadget, USB_STATE_ADDRESS); 11448c2ecf20Sopenharmony_ci } else if (status >= 0) { 11458c2ecf20Sopenharmony_ci /* Not configured unless gadget OK:s it */ 11468c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "STATUS: configured: %d\n", value); 11478c2ecf20Sopenharmony_ci usb_gadget_set_state(&dev->gadget, 11488c2ecf20Sopenharmony_ci USB_STATE_CONFIGURED); 11498c2ecf20Sopenharmony_ci } 11508c2ecf20Sopenharmony_ci } 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci /* Get ready for next stage */ 11538c2ecf20Sopenharmony_ci if (dev->ep0state == GR_EP0_ODATA) 11548c2ecf20Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_OSTATUS); 11558c2ecf20Sopenharmony_ci else if (dev->ep0state == GR_EP0_IDATA) 11568c2ecf20Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_ISTATUS); 11578c2ecf20Sopenharmony_ci else 11588c2ecf20Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_SETUP); 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ciout: 11618c2ecf20Sopenharmony_ci gr_ep0out_requeue(dev); 11628c2ecf20Sopenharmony_ci} 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ci/* ---------------------------------------------------------------------- */ 11658c2ecf20Sopenharmony_ci/* VBUS and USB reset handling */ 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci/* Must be called with dev->lock held and irqs disabled */ 11688c2ecf20Sopenharmony_cistatic void gr_vbus_connected(struct gr_udc *dev, u32 status) 11698c2ecf20Sopenharmony_ci{ 11708c2ecf20Sopenharmony_ci u32 control; 11718c2ecf20Sopenharmony_ci 11728c2ecf20Sopenharmony_ci dev->gadget.speed = GR_SPEED(status); 11738c2ecf20Sopenharmony_ci usb_gadget_set_state(&dev->gadget, USB_STATE_POWERED); 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci /* Turn on full interrupts and pullup */ 11768c2ecf20Sopenharmony_ci control = (GR_CONTROL_SI | GR_CONTROL_UI | GR_CONTROL_VI | 11778c2ecf20Sopenharmony_ci GR_CONTROL_SP | GR_CONTROL_EP); 11788c2ecf20Sopenharmony_ci gr_write32(&dev->regs->control, control); 11798c2ecf20Sopenharmony_ci} 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci/* Must be called with dev->lock held */ 11828c2ecf20Sopenharmony_cistatic void gr_enable_vbus_detect(struct gr_udc *dev) 11838c2ecf20Sopenharmony_ci{ 11848c2ecf20Sopenharmony_ci u32 status; 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci dev->irq_enabled = 1; 11878c2ecf20Sopenharmony_ci wmb(); /* Make sure we do not ignore an interrupt */ 11888c2ecf20Sopenharmony_ci gr_write32(&dev->regs->control, GR_CONTROL_VI); 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci /* Take care of the case we are already plugged in at this point */ 11918c2ecf20Sopenharmony_ci status = gr_read32(&dev->regs->status); 11928c2ecf20Sopenharmony_ci if (status & GR_STATUS_VB) 11938c2ecf20Sopenharmony_ci gr_vbus_connected(dev, status); 11948c2ecf20Sopenharmony_ci} 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci/* Must be called with dev->lock held and irqs disabled */ 11978c2ecf20Sopenharmony_cistatic void gr_vbus_disconnected(struct gr_udc *dev) 11988c2ecf20Sopenharmony_ci{ 11998c2ecf20Sopenharmony_ci gr_stop_activity(dev); 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci /* Report disconnect */ 12028c2ecf20Sopenharmony_ci if (dev->driver && dev->driver->disconnect) { 12038c2ecf20Sopenharmony_ci spin_unlock(&dev->lock); 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci dev->driver->disconnect(&dev->gadget); 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci spin_lock(&dev->lock); 12088c2ecf20Sopenharmony_ci } 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci gr_enable_vbus_detect(dev); 12118c2ecf20Sopenharmony_ci} 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci/* Must be called with dev->lock held and irqs disabled */ 12148c2ecf20Sopenharmony_cistatic void gr_udc_usbreset(struct gr_udc *dev, u32 status) 12158c2ecf20Sopenharmony_ci{ 12168c2ecf20Sopenharmony_ci gr_set_address(dev, 0); 12178c2ecf20Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_SETUP); 12188c2ecf20Sopenharmony_ci usb_gadget_set_state(&dev->gadget, USB_STATE_DEFAULT); 12198c2ecf20Sopenharmony_ci dev->gadget.speed = GR_SPEED(status); 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_ci gr_ep_nuke(&dev->epo[0]); 12228c2ecf20Sopenharmony_ci gr_ep_nuke(&dev->epi[0]); 12238c2ecf20Sopenharmony_ci dev->epo[0].stopped = 0; 12248c2ecf20Sopenharmony_ci dev->epi[0].stopped = 0; 12258c2ecf20Sopenharmony_ci gr_ep0out_requeue(dev); 12268c2ecf20Sopenharmony_ci} 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci/* ---------------------------------------------------------------------- */ 12298c2ecf20Sopenharmony_ci/* Irq handling */ 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci/* 12328c2ecf20Sopenharmony_ci * Handles interrupts from in endpoints. Returns whether something was handled. 12338c2ecf20Sopenharmony_ci * 12348c2ecf20Sopenharmony_ci * Must be called with dev->lock held, irqs disabled and with !ep->stopped. 12358c2ecf20Sopenharmony_ci */ 12368c2ecf20Sopenharmony_cistatic int gr_handle_in_ep(struct gr_ep *ep) 12378c2ecf20Sopenharmony_ci{ 12388c2ecf20Sopenharmony_ci struct gr_request *req; 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci req = list_first_entry(&ep->queue, struct gr_request, queue); 12418c2ecf20Sopenharmony_ci if (!req->last_desc) 12428c2ecf20Sopenharmony_ci return 0; 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci if (READ_ONCE(req->last_desc->ctrl) & GR_DESC_IN_CTRL_EN) 12458c2ecf20Sopenharmony_ci return 0; /* Not put in hardware buffers yet */ 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci if (gr_read32(&ep->regs->epstat) & (GR_EPSTAT_B1 | GR_EPSTAT_B0)) 12488c2ecf20Sopenharmony_ci return 0; /* Not transmitted yet, still in hardware buffers */ 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci /* Write complete */ 12518c2ecf20Sopenharmony_ci gr_dma_advance(ep, 0); 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci return 1; 12548c2ecf20Sopenharmony_ci} 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci/* 12578c2ecf20Sopenharmony_ci * Handles interrupts from out endpoints. Returns whether something was handled. 12588c2ecf20Sopenharmony_ci * 12598c2ecf20Sopenharmony_ci * Must be called with dev->lock held, irqs disabled and with !ep->stopped. 12608c2ecf20Sopenharmony_ci */ 12618c2ecf20Sopenharmony_cistatic int gr_handle_out_ep(struct gr_ep *ep) 12628c2ecf20Sopenharmony_ci{ 12638c2ecf20Sopenharmony_ci u32 ep_dmactrl; 12648c2ecf20Sopenharmony_ci u32 ctrl; 12658c2ecf20Sopenharmony_ci u16 len; 12668c2ecf20Sopenharmony_ci struct gr_request *req; 12678c2ecf20Sopenharmony_ci struct gr_udc *dev = ep->dev; 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci req = list_first_entry(&ep->queue, struct gr_request, queue); 12708c2ecf20Sopenharmony_ci if (!req->curr_desc) 12718c2ecf20Sopenharmony_ci return 0; 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci ctrl = READ_ONCE(req->curr_desc->ctrl); 12748c2ecf20Sopenharmony_ci if (ctrl & GR_DESC_OUT_CTRL_EN) 12758c2ecf20Sopenharmony_ci return 0; /* Not received yet */ 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci /* Read complete */ 12788c2ecf20Sopenharmony_ci len = ctrl & GR_DESC_OUT_CTRL_LEN_MASK; 12798c2ecf20Sopenharmony_ci req->req.actual += len; 12808c2ecf20Sopenharmony_ci if (ctrl & GR_DESC_OUT_CTRL_SE) 12818c2ecf20Sopenharmony_ci req->setup = 1; 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci if (len < ep->ep.maxpacket || req->req.actual >= req->req.length) { 12848c2ecf20Sopenharmony_ci /* Short packet or >= expected size - we are done */ 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ci if ((ep == &dev->epo[0]) && (dev->ep0state == GR_EP0_OSTATUS)) { 12878c2ecf20Sopenharmony_ci /* 12888c2ecf20Sopenharmony_ci * Send a status stage ZLP to ack the DATA stage in the 12898c2ecf20Sopenharmony_ci * OUT direction. This needs to be done before 12908c2ecf20Sopenharmony_ci * gr_dma_advance as that can lead to a call to 12918c2ecf20Sopenharmony_ci * ep0_setup that can change dev->ep0state. 12928c2ecf20Sopenharmony_ci */ 12938c2ecf20Sopenharmony_ci gr_ep0_respond_empty(dev); 12948c2ecf20Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_SETUP); 12958c2ecf20Sopenharmony_ci } 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci gr_dma_advance(ep, 0); 12988c2ecf20Sopenharmony_ci } else { 12998c2ecf20Sopenharmony_ci /* Not done yet. Enable the next descriptor to receive more. */ 13008c2ecf20Sopenharmony_ci req->curr_desc = req->curr_desc->next_desc; 13018c2ecf20Sopenharmony_ci req->curr_desc->ctrl |= GR_DESC_OUT_CTRL_EN; 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_ci ep_dmactrl = gr_read32(&ep->regs->dmactrl); 13048c2ecf20Sopenharmony_ci gr_write32(&ep->regs->dmactrl, ep_dmactrl | GR_DMACTRL_DA); 13058c2ecf20Sopenharmony_ci } 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci return 1; 13088c2ecf20Sopenharmony_ci} 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci/* 13118c2ecf20Sopenharmony_ci * Handle state changes. Returns whether something was handled. 13128c2ecf20Sopenharmony_ci * 13138c2ecf20Sopenharmony_ci * Must be called with dev->lock held and irqs disabled. 13148c2ecf20Sopenharmony_ci */ 13158c2ecf20Sopenharmony_cistatic int gr_handle_state_changes(struct gr_udc *dev) 13168c2ecf20Sopenharmony_ci{ 13178c2ecf20Sopenharmony_ci u32 status = gr_read32(&dev->regs->status); 13188c2ecf20Sopenharmony_ci int handled = 0; 13198c2ecf20Sopenharmony_ci int powstate = !(dev->gadget.state == USB_STATE_NOTATTACHED || 13208c2ecf20Sopenharmony_ci dev->gadget.state == USB_STATE_ATTACHED); 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci /* VBUS valid detected */ 13238c2ecf20Sopenharmony_ci if (!powstate && (status & GR_STATUS_VB)) { 13248c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "STATUS: vbus valid detected\n"); 13258c2ecf20Sopenharmony_ci gr_vbus_connected(dev, status); 13268c2ecf20Sopenharmony_ci handled = 1; 13278c2ecf20Sopenharmony_ci } 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_ci /* Disconnect */ 13308c2ecf20Sopenharmony_ci if (powstate && !(status & GR_STATUS_VB)) { 13318c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "STATUS: vbus invalid detected\n"); 13328c2ecf20Sopenharmony_ci gr_vbus_disconnected(dev); 13338c2ecf20Sopenharmony_ci handled = 1; 13348c2ecf20Sopenharmony_ci } 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci /* USB reset detected */ 13378c2ecf20Sopenharmony_ci if (status & GR_STATUS_UR) { 13388c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "STATUS: USB reset - speed is %s\n", 13398c2ecf20Sopenharmony_ci GR_SPEED_STR(status)); 13408c2ecf20Sopenharmony_ci gr_write32(&dev->regs->status, GR_STATUS_UR); 13418c2ecf20Sopenharmony_ci gr_udc_usbreset(dev, status); 13428c2ecf20Sopenharmony_ci handled = 1; 13438c2ecf20Sopenharmony_ci } 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_ci /* Speed change */ 13468c2ecf20Sopenharmony_ci if (dev->gadget.speed != GR_SPEED(status)) { 13478c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "STATUS: USB Speed change to %s\n", 13488c2ecf20Sopenharmony_ci GR_SPEED_STR(status)); 13498c2ecf20Sopenharmony_ci dev->gadget.speed = GR_SPEED(status); 13508c2ecf20Sopenharmony_ci handled = 1; 13518c2ecf20Sopenharmony_ci } 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci /* Going into suspend */ 13548c2ecf20Sopenharmony_ci if ((dev->ep0state != GR_EP0_SUSPEND) && !(status & GR_STATUS_SU)) { 13558c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "STATUS: USB suspend\n"); 13568c2ecf20Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_SUSPEND); 13578c2ecf20Sopenharmony_ci dev->suspended_from = dev->gadget.state; 13588c2ecf20Sopenharmony_ci usb_gadget_set_state(&dev->gadget, USB_STATE_SUSPENDED); 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_ci if ((dev->gadget.speed != USB_SPEED_UNKNOWN) && 13618c2ecf20Sopenharmony_ci dev->driver && dev->driver->suspend) { 13628c2ecf20Sopenharmony_ci spin_unlock(&dev->lock); 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci dev->driver->suspend(&dev->gadget); 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_ci spin_lock(&dev->lock); 13678c2ecf20Sopenharmony_ci } 13688c2ecf20Sopenharmony_ci handled = 1; 13698c2ecf20Sopenharmony_ci } 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci /* Coming out of suspend */ 13728c2ecf20Sopenharmony_ci if ((dev->ep0state == GR_EP0_SUSPEND) && (status & GR_STATUS_SU)) { 13738c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "STATUS: USB resume\n"); 13748c2ecf20Sopenharmony_ci if (dev->suspended_from == USB_STATE_POWERED) 13758c2ecf20Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_DISCONNECT); 13768c2ecf20Sopenharmony_ci else 13778c2ecf20Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_SETUP); 13788c2ecf20Sopenharmony_ci usb_gadget_set_state(&dev->gadget, dev->suspended_from); 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_ci if ((dev->gadget.speed != USB_SPEED_UNKNOWN) && 13818c2ecf20Sopenharmony_ci dev->driver && dev->driver->resume) { 13828c2ecf20Sopenharmony_ci spin_unlock(&dev->lock); 13838c2ecf20Sopenharmony_ci 13848c2ecf20Sopenharmony_ci dev->driver->resume(&dev->gadget); 13858c2ecf20Sopenharmony_ci 13868c2ecf20Sopenharmony_ci spin_lock(&dev->lock); 13878c2ecf20Sopenharmony_ci } 13888c2ecf20Sopenharmony_ci handled = 1; 13898c2ecf20Sopenharmony_ci } 13908c2ecf20Sopenharmony_ci 13918c2ecf20Sopenharmony_ci return handled; 13928c2ecf20Sopenharmony_ci} 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci/* Non-interrupt context irq handler */ 13958c2ecf20Sopenharmony_cistatic irqreturn_t gr_irq_handler(int irq, void *_dev) 13968c2ecf20Sopenharmony_ci{ 13978c2ecf20Sopenharmony_ci struct gr_udc *dev = _dev; 13988c2ecf20Sopenharmony_ci struct gr_ep *ep; 13998c2ecf20Sopenharmony_ci int handled = 0; 14008c2ecf20Sopenharmony_ci int i; 14018c2ecf20Sopenharmony_ci unsigned long flags; 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci spin_lock_irqsave(&dev->lock, flags); 14048c2ecf20Sopenharmony_ci 14058c2ecf20Sopenharmony_ci if (!dev->irq_enabled) 14068c2ecf20Sopenharmony_ci goto out; 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_ci /* 14098c2ecf20Sopenharmony_ci * Check IN ep interrupts. We check these before the OUT eps because 14108c2ecf20Sopenharmony_ci * some gadgets reuse the request that might already be currently 14118c2ecf20Sopenharmony_ci * outstanding and needs to be completed (mainly setup requests). 14128c2ecf20Sopenharmony_ci */ 14138c2ecf20Sopenharmony_ci for (i = 0; i < dev->nepi; i++) { 14148c2ecf20Sopenharmony_ci ep = &dev->epi[i]; 14158c2ecf20Sopenharmony_ci if (!ep->stopped && !ep->callback && !list_empty(&ep->queue)) 14168c2ecf20Sopenharmony_ci handled = gr_handle_in_ep(ep) || handled; 14178c2ecf20Sopenharmony_ci } 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci /* Check OUT ep interrupts */ 14208c2ecf20Sopenharmony_ci for (i = 0; i < dev->nepo; i++) { 14218c2ecf20Sopenharmony_ci ep = &dev->epo[i]; 14228c2ecf20Sopenharmony_ci if (!ep->stopped && !ep->callback && !list_empty(&ep->queue)) 14238c2ecf20Sopenharmony_ci handled = gr_handle_out_ep(ep) || handled; 14248c2ecf20Sopenharmony_ci } 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci /* Check status interrupts */ 14278c2ecf20Sopenharmony_ci handled = gr_handle_state_changes(dev) || handled; 14288c2ecf20Sopenharmony_ci 14298c2ecf20Sopenharmony_ci /* 14308c2ecf20Sopenharmony_ci * Check AMBA DMA errors. Only check if we didn't find anything else to 14318c2ecf20Sopenharmony_ci * handle because this shouldn't happen if we did everything right. 14328c2ecf20Sopenharmony_ci */ 14338c2ecf20Sopenharmony_ci if (!handled) { 14348c2ecf20Sopenharmony_ci list_for_each_entry(ep, &dev->ep_list, ep_list) { 14358c2ecf20Sopenharmony_ci if (gr_read32(&ep->regs->dmactrl) & GR_DMACTRL_AE) { 14368c2ecf20Sopenharmony_ci dev_err(dev->dev, 14378c2ecf20Sopenharmony_ci "AMBA Error occurred for %s\n", 14388c2ecf20Sopenharmony_ci ep->ep.name); 14398c2ecf20Sopenharmony_ci handled = 1; 14408c2ecf20Sopenharmony_ci } 14418c2ecf20Sopenharmony_ci } 14428c2ecf20Sopenharmony_ci } 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ciout: 14458c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dev->lock, flags); 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci return handled ? IRQ_HANDLED : IRQ_NONE; 14488c2ecf20Sopenharmony_ci} 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_ci/* Interrupt context irq handler */ 14518c2ecf20Sopenharmony_cistatic irqreturn_t gr_irq(int irq, void *_dev) 14528c2ecf20Sopenharmony_ci{ 14538c2ecf20Sopenharmony_ci struct gr_udc *dev = _dev; 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci if (!dev->irq_enabled) 14568c2ecf20Sopenharmony_ci return IRQ_NONE; 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci return IRQ_WAKE_THREAD; 14598c2ecf20Sopenharmony_ci} 14608c2ecf20Sopenharmony_ci 14618c2ecf20Sopenharmony_ci/* ---------------------------------------------------------------------- */ 14628c2ecf20Sopenharmony_ci/* USB ep ops */ 14638c2ecf20Sopenharmony_ci 14648c2ecf20Sopenharmony_ci/* Enable endpoint. Not for ep0in and ep0out that are handled separately. */ 14658c2ecf20Sopenharmony_cistatic int gr_ep_enable(struct usb_ep *_ep, 14668c2ecf20Sopenharmony_ci const struct usb_endpoint_descriptor *desc) 14678c2ecf20Sopenharmony_ci{ 14688c2ecf20Sopenharmony_ci struct gr_udc *dev; 14698c2ecf20Sopenharmony_ci struct gr_ep *ep; 14708c2ecf20Sopenharmony_ci u8 mode; 14718c2ecf20Sopenharmony_ci u8 nt; 14728c2ecf20Sopenharmony_ci u16 max; 14738c2ecf20Sopenharmony_ci u16 buffer_size = 0; 14748c2ecf20Sopenharmony_ci u32 epctrl; 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci ep = container_of(_ep, struct gr_ep, ep); 14778c2ecf20Sopenharmony_ci if (!_ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT) 14788c2ecf20Sopenharmony_ci return -EINVAL; 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_ci dev = ep->dev; 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_ci /* 'ep0' IN and OUT are reserved */ 14838c2ecf20Sopenharmony_ci if (ep == &dev->epo[0] || ep == &dev->epi[0]) 14848c2ecf20Sopenharmony_ci return -EINVAL; 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) 14878c2ecf20Sopenharmony_ci return -ESHUTDOWN; 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ci /* Make sure we are clear for enabling */ 14908c2ecf20Sopenharmony_ci epctrl = gr_read32(&ep->regs->epctrl); 14918c2ecf20Sopenharmony_ci if (epctrl & GR_EPCTRL_EV) 14928c2ecf20Sopenharmony_ci return -EBUSY; 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci /* Check that directions match */ 14958c2ecf20Sopenharmony_ci if (!ep->is_in != !usb_endpoint_dir_in(desc)) 14968c2ecf20Sopenharmony_ci return -EINVAL; 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci /* Check ep num */ 14998c2ecf20Sopenharmony_ci if ((!ep->is_in && ep->num >= dev->nepo) || 15008c2ecf20Sopenharmony_ci (ep->is_in && ep->num >= dev->nepi)) 15018c2ecf20Sopenharmony_ci return -EINVAL; 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci if (usb_endpoint_xfer_control(desc)) { 15048c2ecf20Sopenharmony_ci mode = 0; 15058c2ecf20Sopenharmony_ci } else if (usb_endpoint_xfer_isoc(desc)) { 15068c2ecf20Sopenharmony_ci mode = 1; 15078c2ecf20Sopenharmony_ci } else if (usb_endpoint_xfer_bulk(desc)) { 15088c2ecf20Sopenharmony_ci mode = 2; 15098c2ecf20Sopenharmony_ci } else if (usb_endpoint_xfer_int(desc)) { 15108c2ecf20Sopenharmony_ci mode = 3; 15118c2ecf20Sopenharmony_ci } else { 15128c2ecf20Sopenharmony_ci dev_err(dev->dev, "Unknown transfer type for %s\n", 15138c2ecf20Sopenharmony_ci ep->ep.name); 15148c2ecf20Sopenharmony_ci return -EINVAL; 15158c2ecf20Sopenharmony_ci } 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_ci /* 15188c2ecf20Sopenharmony_ci * Bits 10-0 set the max payload. 12-11 set the number of 15198c2ecf20Sopenharmony_ci * additional transactions. 15208c2ecf20Sopenharmony_ci */ 15218c2ecf20Sopenharmony_ci max = usb_endpoint_maxp(desc); 15228c2ecf20Sopenharmony_ci nt = usb_endpoint_maxp_mult(desc) - 1; 15238c2ecf20Sopenharmony_ci buffer_size = GR_BUFFER_SIZE(epctrl); 15248c2ecf20Sopenharmony_ci if (nt && (mode == 0 || mode == 2)) { 15258c2ecf20Sopenharmony_ci dev_err(dev->dev, 15268c2ecf20Sopenharmony_ci "%s mode: multiple trans./microframe not valid\n", 15278c2ecf20Sopenharmony_ci (mode == 2 ? "Bulk" : "Control")); 15288c2ecf20Sopenharmony_ci return -EINVAL; 15298c2ecf20Sopenharmony_ci } else if (nt == 0x3) { 15308c2ecf20Sopenharmony_ci dev_err(dev->dev, 15318c2ecf20Sopenharmony_ci "Invalid value 0x3 for additional trans./microframe\n"); 15328c2ecf20Sopenharmony_ci return -EINVAL; 15338c2ecf20Sopenharmony_ci } else if ((nt + 1) * max > buffer_size) { 15348c2ecf20Sopenharmony_ci dev_err(dev->dev, "Hw buffer size %d < max payload %d * %d\n", 15358c2ecf20Sopenharmony_ci buffer_size, (nt + 1), max); 15368c2ecf20Sopenharmony_ci return -EINVAL; 15378c2ecf20Sopenharmony_ci } else if (max == 0) { 15388c2ecf20Sopenharmony_ci dev_err(dev->dev, "Max payload cannot be set to 0\n"); 15398c2ecf20Sopenharmony_ci return -EINVAL; 15408c2ecf20Sopenharmony_ci } else if (max > ep->ep.maxpacket_limit) { 15418c2ecf20Sopenharmony_ci dev_err(dev->dev, "Requested max payload %d > limit %d\n", 15428c2ecf20Sopenharmony_ci max, ep->ep.maxpacket_limit); 15438c2ecf20Sopenharmony_ci return -EINVAL; 15448c2ecf20Sopenharmony_ci } 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci spin_lock(&ep->dev->lock); 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_ci if (!ep->stopped) { 15498c2ecf20Sopenharmony_ci spin_unlock(&ep->dev->lock); 15508c2ecf20Sopenharmony_ci return -EBUSY; 15518c2ecf20Sopenharmony_ci } 15528c2ecf20Sopenharmony_ci 15538c2ecf20Sopenharmony_ci ep->stopped = 0; 15548c2ecf20Sopenharmony_ci ep->wedged = 0; 15558c2ecf20Sopenharmony_ci ep->ep.desc = desc; 15568c2ecf20Sopenharmony_ci ep->ep.maxpacket = max; 15578c2ecf20Sopenharmony_ci ep->dma_start = 0; 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_ci if (nt) { 15618c2ecf20Sopenharmony_ci /* 15628c2ecf20Sopenharmony_ci * Maximum possible size of all payloads in one microframe 15638c2ecf20Sopenharmony_ci * regardless of direction when using high-bandwidth mode. 15648c2ecf20Sopenharmony_ci */ 15658c2ecf20Sopenharmony_ci ep->bytes_per_buffer = (nt + 1) * max; 15668c2ecf20Sopenharmony_ci } else if (ep->is_in) { 15678c2ecf20Sopenharmony_ci /* 15688c2ecf20Sopenharmony_ci * The biggest multiple of maximum packet size that fits into 15698c2ecf20Sopenharmony_ci * the buffer. The hardware will split up into many packets in 15708c2ecf20Sopenharmony_ci * the IN direction. 15718c2ecf20Sopenharmony_ci */ 15728c2ecf20Sopenharmony_ci ep->bytes_per_buffer = (buffer_size / max) * max; 15738c2ecf20Sopenharmony_ci } else { 15748c2ecf20Sopenharmony_ci /* 15758c2ecf20Sopenharmony_ci * Only single packets will be placed the buffers in the OUT 15768c2ecf20Sopenharmony_ci * direction. 15778c2ecf20Sopenharmony_ci */ 15788c2ecf20Sopenharmony_ci ep->bytes_per_buffer = max; 15798c2ecf20Sopenharmony_ci } 15808c2ecf20Sopenharmony_ci 15818c2ecf20Sopenharmony_ci epctrl = (max << GR_EPCTRL_MAXPL_POS) 15828c2ecf20Sopenharmony_ci | (nt << GR_EPCTRL_NT_POS) 15838c2ecf20Sopenharmony_ci | (mode << GR_EPCTRL_TT_POS) 15848c2ecf20Sopenharmony_ci | GR_EPCTRL_EV; 15858c2ecf20Sopenharmony_ci if (ep->is_in) 15868c2ecf20Sopenharmony_ci epctrl |= GR_EPCTRL_PI; 15878c2ecf20Sopenharmony_ci gr_write32(&ep->regs->epctrl, epctrl); 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci gr_write32(&ep->regs->dmactrl, GR_DMACTRL_IE | GR_DMACTRL_AI); 15908c2ecf20Sopenharmony_ci 15918c2ecf20Sopenharmony_ci spin_unlock(&ep->dev->lock); 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci dev_dbg(ep->dev->dev, "EP: %s enabled - %s with %d bytes/buffer\n", 15948c2ecf20Sopenharmony_ci ep->ep.name, gr_modestring[mode], ep->bytes_per_buffer); 15958c2ecf20Sopenharmony_ci return 0; 15968c2ecf20Sopenharmony_ci} 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci/* Disable endpoint. Not for ep0in and ep0out that are handled separately. */ 15998c2ecf20Sopenharmony_cistatic int gr_ep_disable(struct usb_ep *_ep) 16008c2ecf20Sopenharmony_ci{ 16018c2ecf20Sopenharmony_ci struct gr_ep *ep; 16028c2ecf20Sopenharmony_ci struct gr_udc *dev; 16038c2ecf20Sopenharmony_ci unsigned long flags; 16048c2ecf20Sopenharmony_ci 16058c2ecf20Sopenharmony_ci ep = container_of(_ep, struct gr_ep, ep); 16068c2ecf20Sopenharmony_ci if (!_ep || !ep->ep.desc) 16078c2ecf20Sopenharmony_ci return -ENODEV; 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci dev = ep->dev; 16108c2ecf20Sopenharmony_ci 16118c2ecf20Sopenharmony_ci /* 'ep0' IN and OUT are reserved */ 16128c2ecf20Sopenharmony_ci if (ep == &dev->epo[0] || ep == &dev->epi[0]) 16138c2ecf20Sopenharmony_ci return -EINVAL; 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci if (dev->ep0state == GR_EP0_SUSPEND) 16168c2ecf20Sopenharmony_ci return -EBUSY; 16178c2ecf20Sopenharmony_ci 16188c2ecf20Sopenharmony_ci dev_dbg(ep->dev->dev, "EP: disable %s\n", ep->ep.name); 16198c2ecf20Sopenharmony_ci 16208c2ecf20Sopenharmony_ci spin_lock_irqsave(&dev->lock, flags); 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ci gr_ep_nuke(ep); 16238c2ecf20Sopenharmony_ci gr_ep_reset(ep); 16248c2ecf20Sopenharmony_ci ep->ep.desc = NULL; 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dev->lock, flags); 16278c2ecf20Sopenharmony_ci 16288c2ecf20Sopenharmony_ci return 0; 16298c2ecf20Sopenharmony_ci} 16308c2ecf20Sopenharmony_ci 16318c2ecf20Sopenharmony_ci/* 16328c2ecf20Sopenharmony_ci * Frees a request, but not any DMA buffers associated with it 16338c2ecf20Sopenharmony_ci * (gr_finish_request should already have taken care of that). 16348c2ecf20Sopenharmony_ci */ 16358c2ecf20Sopenharmony_cistatic void gr_free_request(struct usb_ep *_ep, struct usb_request *_req) 16368c2ecf20Sopenharmony_ci{ 16378c2ecf20Sopenharmony_ci struct gr_request *req; 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ci if (!_ep || !_req) 16408c2ecf20Sopenharmony_ci return; 16418c2ecf20Sopenharmony_ci req = container_of(_req, struct gr_request, req); 16428c2ecf20Sopenharmony_ci 16438c2ecf20Sopenharmony_ci /* Leads to memory leak */ 16448c2ecf20Sopenharmony_ci WARN(!list_empty(&req->queue), 16458c2ecf20Sopenharmony_ci "request not dequeued properly before freeing\n"); 16468c2ecf20Sopenharmony_ci 16478c2ecf20Sopenharmony_ci kfree(req); 16488c2ecf20Sopenharmony_ci} 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ci/* Queue a request from the gadget */ 16518c2ecf20Sopenharmony_cistatic int gr_queue_ext(struct usb_ep *_ep, struct usb_request *_req, 16528c2ecf20Sopenharmony_ci gfp_t gfp_flags) 16538c2ecf20Sopenharmony_ci{ 16548c2ecf20Sopenharmony_ci struct gr_ep *ep; 16558c2ecf20Sopenharmony_ci struct gr_request *req; 16568c2ecf20Sopenharmony_ci struct gr_udc *dev; 16578c2ecf20Sopenharmony_ci int ret; 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_ci if (unlikely(!_ep || !_req)) 16608c2ecf20Sopenharmony_ci return -EINVAL; 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_ci ep = container_of(_ep, struct gr_ep, ep); 16638c2ecf20Sopenharmony_ci req = container_of(_req, struct gr_request, req); 16648c2ecf20Sopenharmony_ci dev = ep->dev; 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci spin_lock(&ep->dev->lock); 16678c2ecf20Sopenharmony_ci 16688c2ecf20Sopenharmony_ci /* 16698c2ecf20Sopenharmony_ci * The ep0 pointer in the gadget struct is used both for ep0in and 16708c2ecf20Sopenharmony_ci * ep0out. In a data stage in the out direction ep0out needs to be used 16718c2ecf20Sopenharmony_ci * instead of the default ep0in. Completion functions might use 16728c2ecf20Sopenharmony_ci * driver_data, so that needs to be copied as well. 16738c2ecf20Sopenharmony_ci */ 16748c2ecf20Sopenharmony_ci if ((ep == &dev->epi[0]) && (dev->ep0state == GR_EP0_ODATA)) { 16758c2ecf20Sopenharmony_ci ep = &dev->epo[0]; 16768c2ecf20Sopenharmony_ci ep->ep.driver_data = dev->epi[0].ep.driver_data; 16778c2ecf20Sopenharmony_ci } 16788c2ecf20Sopenharmony_ci 16798c2ecf20Sopenharmony_ci if (ep->is_in) 16808c2ecf20Sopenharmony_ci gr_dbgprint_request("EXTERN", ep, req); 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci ret = gr_queue(ep, req, GFP_ATOMIC); 16838c2ecf20Sopenharmony_ci 16848c2ecf20Sopenharmony_ci spin_unlock(&ep->dev->lock); 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_ci return ret; 16878c2ecf20Sopenharmony_ci} 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci/* Dequeue JUST ONE request */ 16908c2ecf20Sopenharmony_cistatic int gr_dequeue(struct usb_ep *_ep, struct usb_request *_req) 16918c2ecf20Sopenharmony_ci{ 16928c2ecf20Sopenharmony_ci struct gr_request *req; 16938c2ecf20Sopenharmony_ci struct gr_ep *ep; 16948c2ecf20Sopenharmony_ci struct gr_udc *dev; 16958c2ecf20Sopenharmony_ci int ret = 0; 16968c2ecf20Sopenharmony_ci unsigned long flags; 16978c2ecf20Sopenharmony_ci 16988c2ecf20Sopenharmony_ci ep = container_of(_ep, struct gr_ep, ep); 16998c2ecf20Sopenharmony_ci if (!_ep || !_req || (!ep->ep.desc && ep->num != 0)) 17008c2ecf20Sopenharmony_ci return -EINVAL; 17018c2ecf20Sopenharmony_ci dev = ep->dev; 17028c2ecf20Sopenharmony_ci if (!dev->driver) 17038c2ecf20Sopenharmony_ci return -ESHUTDOWN; 17048c2ecf20Sopenharmony_ci 17058c2ecf20Sopenharmony_ci /* We can't touch (DMA) registers when suspended */ 17068c2ecf20Sopenharmony_ci if (dev->ep0state == GR_EP0_SUSPEND) 17078c2ecf20Sopenharmony_ci return -EBUSY; 17088c2ecf20Sopenharmony_ci 17098c2ecf20Sopenharmony_ci spin_lock_irqsave(&dev->lock, flags); 17108c2ecf20Sopenharmony_ci 17118c2ecf20Sopenharmony_ci /* Make sure it's actually queued on this endpoint */ 17128c2ecf20Sopenharmony_ci list_for_each_entry(req, &ep->queue, queue) { 17138c2ecf20Sopenharmony_ci if (&req->req == _req) 17148c2ecf20Sopenharmony_ci break; 17158c2ecf20Sopenharmony_ci } 17168c2ecf20Sopenharmony_ci if (&req->req != _req) { 17178c2ecf20Sopenharmony_ci ret = -EINVAL; 17188c2ecf20Sopenharmony_ci goto out; 17198c2ecf20Sopenharmony_ci } 17208c2ecf20Sopenharmony_ci 17218c2ecf20Sopenharmony_ci if (list_first_entry(&ep->queue, struct gr_request, queue) == req) { 17228c2ecf20Sopenharmony_ci /* This request is currently being processed */ 17238c2ecf20Sopenharmony_ci gr_abort_dma(ep); 17248c2ecf20Sopenharmony_ci if (ep->stopped) 17258c2ecf20Sopenharmony_ci gr_finish_request(ep, req, -ECONNRESET); 17268c2ecf20Sopenharmony_ci else 17278c2ecf20Sopenharmony_ci gr_dma_advance(ep, -ECONNRESET); 17288c2ecf20Sopenharmony_ci } else if (!list_empty(&req->queue)) { 17298c2ecf20Sopenharmony_ci /* Not being processed - gr_finish_request dequeues it */ 17308c2ecf20Sopenharmony_ci gr_finish_request(ep, req, -ECONNRESET); 17318c2ecf20Sopenharmony_ci } else { 17328c2ecf20Sopenharmony_ci ret = -EOPNOTSUPP; 17338c2ecf20Sopenharmony_ci } 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ciout: 17368c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dev->lock, flags); 17378c2ecf20Sopenharmony_ci 17388c2ecf20Sopenharmony_ci return ret; 17398c2ecf20Sopenharmony_ci} 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_ci/* Helper for gr_set_halt and gr_set_wedge */ 17428c2ecf20Sopenharmony_cistatic int gr_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge) 17438c2ecf20Sopenharmony_ci{ 17448c2ecf20Sopenharmony_ci int ret; 17458c2ecf20Sopenharmony_ci struct gr_ep *ep; 17468c2ecf20Sopenharmony_ci 17478c2ecf20Sopenharmony_ci if (!_ep) 17488c2ecf20Sopenharmony_ci return -ENODEV; 17498c2ecf20Sopenharmony_ci ep = container_of(_ep, struct gr_ep, ep); 17508c2ecf20Sopenharmony_ci 17518c2ecf20Sopenharmony_ci spin_lock(&ep->dev->lock); 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_ci /* Halting an IN endpoint should fail if queue is not empty */ 17548c2ecf20Sopenharmony_ci if (halt && ep->is_in && !list_empty(&ep->queue)) { 17558c2ecf20Sopenharmony_ci ret = -EAGAIN; 17568c2ecf20Sopenharmony_ci goto out; 17578c2ecf20Sopenharmony_ci } 17588c2ecf20Sopenharmony_ci 17598c2ecf20Sopenharmony_ci ret = gr_ep_halt_wedge(ep, halt, wedge, 0); 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_ciout: 17628c2ecf20Sopenharmony_ci spin_unlock(&ep->dev->lock); 17638c2ecf20Sopenharmony_ci 17648c2ecf20Sopenharmony_ci return ret; 17658c2ecf20Sopenharmony_ci} 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_ci/* Halt endpoint */ 17688c2ecf20Sopenharmony_cistatic int gr_set_halt(struct usb_ep *_ep, int halt) 17698c2ecf20Sopenharmony_ci{ 17708c2ecf20Sopenharmony_ci return gr_set_halt_wedge(_ep, halt, 0); 17718c2ecf20Sopenharmony_ci} 17728c2ecf20Sopenharmony_ci 17738c2ecf20Sopenharmony_ci/* Halt and wedge endpoint */ 17748c2ecf20Sopenharmony_cistatic int gr_set_wedge(struct usb_ep *_ep) 17758c2ecf20Sopenharmony_ci{ 17768c2ecf20Sopenharmony_ci return gr_set_halt_wedge(_ep, 1, 1); 17778c2ecf20Sopenharmony_ci} 17788c2ecf20Sopenharmony_ci 17798c2ecf20Sopenharmony_ci/* 17808c2ecf20Sopenharmony_ci * Return the total number of bytes currently stored in the internal buffers of 17818c2ecf20Sopenharmony_ci * the endpoint. 17828c2ecf20Sopenharmony_ci */ 17838c2ecf20Sopenharmony_cistatic int gr_fifo_status(struct usb_ep *_ep) 17848c2ecf20Sopenharmony_ci{ 17858c2ecf20Sopenharmony_ci struct gr_ep *ep; 17868c2ecf20Sopenharmony_ci u32 epstat; 17878c2ecf20Sopenharmony_ci u32 bytes = 0; 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_ci if (!_ep) 17908c2ecf20Sopenharmony_ci return -ENODEV; 17918c2ecf20Sopenharmony_ci ep = container_of(_ep, struct gr_ep, ep); 17928c2ecf20Sopenharmony_ci 17938c2ecf20Sopenharmony_ci epstat = gr_read32(&ep->regs->epstat); 17948c2ecf20Sopenharmony_ci 17958c2ecf20Sopenharmony_ci if (epstat & GR_EPSTAT_B0) 17968c2ecf20Sopenharmony_ci bytes += (epstat & GR_EPSTAT_B0CNT_MASK) >> GR_EPSTAT_B0CNT_POS; 17978c2ecf20Sopenharmony_ci if (epstat & GR_EPSTAT_B1) 17988c2ecf20Sopenharmony_ci bytes += (epstat & GR_EPSTAT_B1CNT_MASK) >> GR_EPSTAT_B1CNT_POS; 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci return bytes; 18018c2ecf20Sopenharmony_ci} 18028c2ecf20Sopenharmony_ci 18038c2ecf20Sopenharmony_ci 18048c2ecf20Sopenharmony_ci/* Empty data from internal buffers of an endpoint. */ 18058c2ecf20Sopenharmony_cistatic void gr_fifo_flush(struct usb_ep *_ep) 18068c2ecf20Sopenharmony_ci{ 18078c2ecf20Sopenharmony_ci struct gr_ep *ep; 18088c2ecf20Sopenharmony_ci u32 epctrl; 18098c2ecf20Sopenharmony_ci 18108c2ecf20Sopenharmony_ci if (!_ep) 18118c2ecf20Sopenharmony_ci return; 18128c2ecf20Sopenharmony_ci ep = container_of(_ep, struct gr_ep, ep); 18138c2ecf20Sopenharmony_ci dev_vdbg(ep->dev->dev, "EP: flush fifo %s\n", ep->ep.name); 18148c2ecf20Sopenharmony_ci 18158c2ecf20Sopenharmony_ci spin_lock(&ep->dev->lock); 18168c2ecf20Sopenharmony_ci 18178c2ecf20Sopenharmony_ci epctrl = gr_read32(&ep->regs->epctrl); 18188c2ecf20Sopenharmony_ci epctrl |= GR_EPCTRL_CB; 18198c2ecf20Sopenharmony_ci gr_write32(&ep->regs->epctrl, epctrl); 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_ci spin_unlock(&ep->dev->lock); 18228c2ecf20Sopenharmony_ci} 18238c2ecf20Sopenharmony_ci 18248c2ecf20Sopenharmony_cistatic const struct usb_ep_ops gr_ep_ops = { 18258c2ecf20Sopenharmony_ci .enable = gr_ep_enable, 18268c2ecf20Sopenharmony_ci .disable = gr_ep_disable, 18278c2ecf20Sopenharmony_ci 18288c2ecf20Sopenharmony_ci .alloc_request = gr_alloc_request, 18298c2ecf20Sopenharmony_ci .free_request = gr_free_request, 18308c2ecf20Sopenharmony_ci 18318c2ecf20Sopenharmony_ci .queue = gr_queue_ext, 18328c2ecf20Sopenharmony_ci .dequeue = gr_dequeue, 18338c2ecf20Sopenharmony_ci 18348c2ecf20Sopenharmony_ci .set_halt = gr_set_halt, 18358c2ecf20Sopenharmony_ci .set_wedge = gr_set_wedge, 18368c2ecf20Sopenharmony_ci .fifo_status = gr_fifo_status, 18378c2ecf20Sopenharmony_ci .fifo_flush = gr_fifo_flush, 18388c2ecf20Sopenharmony_ci}; 18398c2ecf20Sopenharmony_ci 18408c2ecf20Sopenharmony_ci/* ---------------------------------------------------------------------- */ 18418c2ecf20Sopenharmony_ci/* USB Gadget ops */ 18428c2ecf20Sopenharmony_ci 18438c2ecf20Sopenharmony_cistatic int gr_get_frame(struct usb_gadget *_gadget) 18448c2ecf20Sopenharmony_ci{ 18458c2ecf20Sopenharmony_ci struct gr_udc *dev; 18468c2ecf20Sopenharmony_ci 18478c2ecf20Sopenharmony_ci if (!_gadget) 18488c2ecf20Sopenharmony_ci return -ENODEV; 18498c2ecf20Sopenharmony_ci dev = container_of(_gadget, struct gr_udc, gadget); 18508c2ecf20Sopenharmony_ci return gr_read32(&dev->regs->status) & GR_STATUS_FN_MASK; 18518c2ecf20Sopenharmony_ci} 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_cistatic int gr_wakeup(struct usb_gadget *_gadget) 18548c2ecf20Sopenharmony_ci{ 18558c2ecf20Sopenharmony_ci struct gr_udc *dev; 18568c2ecf20Sopenharmony_ci 18578c2ecf20Sopenharmony_ci if (!_gadget) 18588c2ecf20Sopenharmony_ci return -ENODEV; 18598c2ecf20Sopenharmony_ci dev = container_of(_gadget, struct gr_udc, gadget); 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci /* Remote wakeup feature not enabled by host*/ 18628c2ecf20Sopenharmony_ci if (!dev->remote_wakeup) 18638c2ecf20Sopenharmony_ci return -EINVAL; 18648c2ecf20Sopenharmony_ci 18658c2ecf20Sopenharmony_ci spin_lock(&dev->lock); 18668c2ecf20Sopenharmony_ci 18678c2ecf20Sopenharmony_ci gr_write32(&dev->regs->control, 18688c2ecf20Sopenharmony_ci gr_read32(&dev->regs->control) | GR_CONTROL_RW); 18698c2ecf20Sopenharmony_ci 18708c2ecf20Sopenharmony_ci spin_unlock(&dev->lock); 18718c2ecf20Sopenharmony_ci 18728c2ecf20Sopenharmony_ci return 0; 18738c2ecf20Sopenharmony_ci} 18748c2ecf20Sopenharmony_ci 18758c2ecf20Sopenharmony_cistatic int gr_pullup(struct usb_gadget *_gadget, int is_on) 18768c2ecf20Sopenharmony_ci{ 18778c2ecf20Sopenharmony_ci struct gr_udc *dev; 18788c2ecf20Sopenharmony_ci u32 control; 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_ci if (!_gadget) 18818c2ecf20Sopenharmony_ci return -ENODEV; 18828c2ecf20Sopenharmony_ci dev = container_of(_gadget, struct gr_udc, gadget); 18838c2ecf20Sopenharmony_ci 18848c2ecf20Sopenharmony_ci spin_lock(&dev->lock); 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_ci control = gr_read32(&dev->regs->control); 18878c2ecf20Sopenharmony_ci if (is_on) 18888c2ecf20Sopenharmony_ci control |= GR_CONTROL_EP; 18898c2ecf20Sopenharmony_ci else 18908c2ecf20Sopenharmony_ci control &= ~GR_CONTROL_EP; 18918c2ecf20Sopenharmony_ci gr_write32(&dev->regs->control, control); 18928c2ecf20Sopenharmony_ci 18938c2ecf20Sopenharmony_ci spin_unlock(&dev->lock); 18948c2ecf20Sopenharmony_ci 18958c2ecf20Sopenharmony_ci return 0; 18968c2ecf20Sopenharmony_ci} 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_cistatic int gr_udc_start(struct usb_gadget *gadget, 18998c2ecf20Sopenharmony_ci struct usb_gadget_driver *driver) 19008c2ecf20Sopenharmony_ci{ 19018c2ecf20Sopenharmony_ci struct gr_udc *dev = to_gr_udc(gadget); 19028c2ecf20Sopenharmony_ci 19038c2ecf20Sopenharmony_ci spin_lock(&dev->lock); 19048c2ecf20Sopenharmony_ci 19058c2ecf20Sopenharmony_ci /* Hook up the driver */ 19068c2ecf20Sopenharmony_ci driver->driver.bus = NULL; 19078c2ecf20Sopenharmony_ci dev->driver = driver; 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci /* Get ready for host detection */ 19108c2ecf20Sopenharmony_ci gr_enable_vbus_detect(dev); 19118c2ecf20Sopenharmony_ci 19128c2ecf20Sopenharmony_ci spin_unlock(&dev->lock); 19138c2ecf20Sopenharmony_ci 19148c2ecf20Sopenharmony_ci return 0; 19158c2ecf20Sopenharmony_ci} 19168c2ecf20Sopenharmony_ci 19178c2ecf20Sopenharmony_cistatic int gr_udc_stop(struct usb_gadget *gadget) 19188c2ecf20Sopenharmony_ci{ 19198c2ecf20Sopenharmony_ci struct gr_udc *dev = to_gr_udc(gadget); 19208c2ecf20Sopenharmony_ci unsigned long flags; 19218c2ecf20Sopenharmony_ci 19228c2ecf20Sopenharmony_ci spin_lock_irqsave(&dev->lock, flags); 19238c2ecf20Sopenharmony_ci 19248c2ecf20Sopenharmony_ci dev->driver = NULL; 19258c2ecf20Sopenharmony_ci gr_stop_activity(dev); 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dev->lock, flags); 19288c2ecf20Sopenharmony_ci 19298c2ecf20Sopenharmony_ci return 0; 19308c2ecf20Sopenharmony_ci} 19318c2ecf20Sopenharmony_ci 19328c2ecf20Sopenharmony_cistatic const struct usb_gadget_ops gr_ops = { 19338c2ecf20Sopenharmony_ci .get_frame = gr_get_frame, 19348c2ecf20Sopenharmony_ci .wakeup = gr_wakeup, 19358c2ecf20Sopenharmony_ci .pullup = gr_pullup, 19368c2ecf20Sopenharmony_ci .udc_start = gr_udc_start, 19378c2ecf20Sopenharmony_ci .udc_stop = gr_udc_stop, 19388c2ecf20Sopenharmony_ci /* Other operations not supported */ 19398c2ecf20Sopenharmony_ci}; 19408c2ecf20Sopenharmony_ci 19418c2ecf20Sopenharmony_ci/* ---------------------------------------------------------------------- */ 19428c2ecf20Sopenharmony_ci/* Module probe, removal and of-matching */ 19438c2ecf20Sopenharmony_ci 19448c2ecf20Sopenharmony_cistatic const char * const onames[] = { 19458c2ecf20Sopenharmony_ci "ep0out", "ep1out", "ep2out", "ep3out", "ep4out", "ep5out", 19468c2ecf20Sopenharmony_ci "ep6out", "ep7out", "ep8out", "ep9out", "ep10out", "ep11out", 19478c2ecf20Sopenharmony_ci "ep12out", "ep13out", "ep14out", "ep15out" 19488c2ecf20Sopenharmony_ci}; 19498c2ecf20Sopenharmony_ci 19508c2ecf20Sopenharmony_cistatic const char * const inames[] = { 19518c2ecf20Sopenharmony_ci "ep0in", "ep1in", "ep2in", "ep3in", "ep4in", "ep5in", 19528c2ecf20Sopenharmony_ci "ep6in", "ep7in", "ep8in", "ep9in", "ep10in", "ep11in", 19538c2ecf20Sopenharmony_ci "ep12in", "ep13in", "ep14in", "ep15in" 19548c2ecf20Sopenharmony_ci}; 19558c2ecf20Sopenharmony_ci 19568c2ecf20Sopenharmony_ci/* Must be called with dev->lock held */ 19578c2ecf20Sopenharmony_cistatic int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit) 19588c2ecf20Sopenharmony_ci{ 19598c2ecf20Sopenharmony_ci struct gr_ep *ep; 19608c2ecf20Sopenharmony_ci struct gr_request *req; 19618c2ecf20Sopenharmony_ci struct usb_request *_req; 19628c2ecf20Sopenharmony_ci void *buf; 19638c2ecf20Sopenharmony_ci 19648c2ecf20Sopenharmony_ci if (is_in) { 19658c2ecf20Sopenharmony_ci ep = &dev->epi[num]; 19668c2ecf20Sopenharmony_ci ep->ep.name = inames[num]; 19678c2ecf20Sopenharmony_ci ep->regs = &dev->regs->epi[num]; 19688c2ecf20Sopenharmony_ci } else { 19698c2ecf20Sopenharmony_ci ep = &dev->epo[num]; 19708c2ecf20Sopenharmony_ci ep->ep.name = onames[num]; 19718c2ecf20Sopenharmony_ci ep->regs = &dev->regs->epo[num]; 19728c2ecf20Sopenharmony_ci } 19738c2ecf20Sopenharmony_ci 19748c2ecf20Sopenharmony_ci gr_ep_reset(ep); 19758c2ecf20Sopenharmony_ci ep->num = num; 19768c2ecf20Sopenharmony_ci ep->is_in = is_in; 19778c2ecf20Sopenharmony_ci ep->dev = dev; 19788c2ecf20Sopenharmony_ci ep->ep.ops = &gr_ep_ops; 19798c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ep->queue); 19808c2ecf20Sopenharmony_ci 19818c2ecf20Sopenharmony_ci if (num == 0) { 19828c2ecf20Sopenharmony_ci _req = gr_alloc_request(&ep->ep, GFP_ATOMIC); 19838c2ecf20Sopenharmony_ci if (!_req) 19848c2ecf20Sopenharmony_ci return -ENOMEM; 19858c2ecf20Sopenharmony_ci 19868c2ecf20Sopenharmony_ci buf = devm_kzalloc(dev->dev, PAGE_SIZE, GFP_DMA | GFP_ATOMIC); 19878c2ecf20Sopenharmony_ci if (!buf) { 19888c2ecf20Sopenharmony_ci gr_free_request(&ep->ep, _req); 19898c2ecf20Sopenharmony_ci return -ENOMEM; 19908c2ecf20Sopenharmony_ci } 19918c2ecf20Sopenharmony_ci 19928c2ecf20Sopenharmony_ci req = container_of(_req, struct gr_request, req); 19938c2ecf20Sopenharmony_ci req->req.buf = buf; 19948c2ecf20Sopenharmony_ci req->req.length = MAX_CTRL_PL_SIZE; 19958c2ecf20Sopenharmony_ci 19968c2ecf20Sopenharmony_ci if (is_in) 19978c2ecf20Sopenharmony_ci dev->ep0reqi = req; /* Complete gets set as used */ 19988c2ecf20Sopenharmony_ci else 19998c2ecf20Sopenharmony_ci dev->ep0reqo = req; /* Completion treated separately */ 20008c2ecf20Sopenharmony_ci 20018c2ecf20Sopenharmony_ci usb_ep_set_maxpacket_limit(&ep->ep, MAX_CTRL_PL_SIZE); 20028c2ecf20Sopenharmony_ci ep->bytes_per_buffer = MAX_CTRL_PL_SIZE; 20038c2ecf20Sopenharmony_ci 20048c2ecf20Sopenharmony_ci ep->ep.caps.type_control = true; 20058c2ecf20Sopenharmony_ci } else { 20068c2ecf20Sopenharmony_ci usb_ep_set_maxpacket_limit(&ep->ep, (u16)maxplimit); 20078c2ecf20Sopenharmony_ci list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list); 20088c2ecf20Sopenharmony_ci 20098c2ecf20Sopenharmony_ci ep->ep.caps.type_iso = true; 20108c2ecf20Sopenharmony_ci ep->ep.caps.type_bulk = true; 20118c2ecf20Sopenharmony_ci ep->ep.caps.type_int = true; 20128c2ecf20Sopenharmony_ci } 20138c2ecf20Sopenharmony_ci list_add_tail(&ep->ep_list, &dev->ep_list); 20148c2ecf20Sopenharmony_ci 20158c2ecf20Sopenharmony_ci if (is_in) 20168c2ecf20Sopenharmony_ci ep->ep.caps.dir_in = true; 20178c2ecf20Sopenharmony_ci else 20188c2ecf20Sopenharmony_ci ep->ep.caps.dir_out = true; 20198c2ecf20Sopenharmony_ci 20208c2ecf20Sopenharmony_ci ep->tailbuf = dma_alloc_coherent(dev->dev, ep->ep.maxpacket_limit, 20218c2ecf20Sopenharmony_ci &ep->tailbuf_paddr, GFP_ATOMIC); 20228c2ecf20Sopenharmony_ci if (!ep->tailbuf) 20238c2ecf20Sopenharmony_ci return -ENOMEM; 20248c2ecf20Sopenharmony_ci 20258c2ecf20Sopenharmony_ci return 0; 20268c2ecf20Sopenharmony_ci} 20278c2ecf20Sopenharmony_ci 20288c2ecf20Sopenharmony_ci/* Must be called with dev->lock held */ 20298c2ecf20Sopenharmony_cistatic int gr_udc_init(struct gr_udc *dev) 20308c2ecf20Sopenharmony_ci{ 20318c2ecf20Sopenharmony_ci struct device_node *np = dev->dev->of_node; 20328c2ecf20Sopenharmony_ci u32 epctrl_val; 20338c2ecf20Sopenharmony_ci u32 dmactrl_val; 20348c2ecf20Sopenharmony_ci int i; 20358c2ecf20Sopenharmony_ci int ret = 0; 20368c2ecf20Sopenharmony_ci u32 bufsize; 20378c2ecf20Sopenharmony_ci 20388c2ecf20Sopenharmony_ci gr_set_address(dev, 0); 20398c2ecf20Sopenharmony_ci 20408c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&dev->gadget.ep_list); 20418c2ecf20Sopenharmony_ci dev->gadget.speed = USB_SPEED_UNKNOWN; 20428c2ecf20Sopenharmony_ci dev->gadget.ep0 = &dev->epi[0].ep; 20438c2ecf20Sopenharmony_ci 20448c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&dev->ep_list); 20458c2ecf20Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_DISCONNECT); 20468c2ecf20Sopenharmony_ci 20478c2ecf20Sopenharmony_ci for (i = 0; i < dev->nepo; i++) { 20488c2ecf20Sopenharmony_ci if (of_property_read_u32_index(np, "epobufsizes", i, &bufsize)) 20498c2ecf20Sopenharmony_ci bufsize = 1024; 20508c2ecf20Sopenharmony_ci ret = gr_ep_init(dev, i, 0, bufsize); 20518c2ecf20Sopenharmony_ci if (ret) 20528c2ecf20Sopenharmony_ci return ret; 20538c2ecf20Sopenharmony_ci } 20548c2ecf20Sopenharmony_ci 20558c2ecf20Sopenharmony_ci for (i = 0; i < dev->nepi; i++) { 20568c2ecf20Sopenharmony_ci if (of_property_read_u32_index(np, "epibufsizes", i, &bufsize)) 20578c2ecf20Sopenharmony_ci bufsize = 1024; 20588c2ecf20Sopenharmony_ci ret = gr_ep_init(dev, i, 1, bufsize); 20598c2ecf20Sopenharmony_ci if (ret) 20608c2ecf20Sopenharmony_ci return ret; 20618c2ecf20Sopenharmony_ci } 20628c2ecf20Sopenharmony_ci 20638c2ecf20Sopenharmony_ci /* Must be disabled by default */ 20648c2ecf20Sopenharmony_ci dev->remote_wakeup = 0; 20658c2ecf20Sopenharmony_ci 20668c2ecf20Sopenharmony_ci /* Enable ep0out and ep0in */ 20678c2ecf20Sopenharmony_ci epctrl_val = (MAX_CTRL_PL_SIZE << GR_EPCTRL_MAXPL_POS) | GR_EPCTRL_EV; 20688c2ecf20Sopenharmony_ci dmactrl_val = GR_DMACTRL_IE | GR_DMACTRL_AI; 20698c2ecf20Sopenharmony_ci gr_write32(&dev->epo[0].regs->epctrl, epctrl_val); 20708c2ecf20Sopenharmony_ci gr_write32(&dev->epi[0].regs->epctrl, epctrl_val | GR_EPCTRL_PI); 20718c2ecf20Sopenharmony_ci gr_write32(&dev->epo[0].regs->dmactrl, dmactrl_val); 20728c2ecf20Sopenharmony_ci gr_write32(&dev->epi[0].regs->dmactrl, dmactrl_val); 20738c2ecf20Sopenharmony_ci 20748c2ecf20Sopenharmony_ci return 0; 20758c2ecf20Sopenharmony_ci} 20768c2ecf20Sopenharmony_ci 20778c2ecf20Sopenharmony_cistatic void gr_ep_remove(struct gr_udc *dev, int num, int is_in) 20788c2ecf20Sopenharmony_ci{ 20798c2ecf20Sopenharmony_ci struct gr_ep *ep; 20808c2ecf20Sopenharmony_ci 20818c2ecf20Sopenharmony_ci if (is_in) 20828c2ecf20Sopenharmony_ci ep = &dev->epi[num]; 20838c2ecf20Sopenharmony_ci else 20848c2ecf20Sopenharmony_ci ep = &dev->epo[num]; 20858c2ecf20Sopenharmony_ci 20868c2ecf20Sopenharmony_ci if (ep->tailbuf) 20878c2ecf20Sopenharmony_ci dma_free_coherent(dev->dev, ep->ep.maxpacket_limit, 20888c2ecf20Sopenharmony_ci ep->tailbuf, ep->tailbuf_paddr); 20898c2ecf20Sopenharmony_ci} 20908c2ecf20Sopenharmony_ci 20918c2ecf20Sopenharmony_cistatic int gr_remove(struct platform_device *pdev) 20928c2ecf20Sopenharmony_ci{ 20938c2ecf20Sopenharmony_ci struct gr_udc *dev = platform_get_drvdata(pdev); 20948c2ecf20Sopenharmony_ci int i; 20958c2ecf20Sopenharmony_ci 20968c2ecf20Sopenharmony_ci if (dev->added) 20978c2ecf20Sopenharmony_ci usb_del_gadget_udc(&dev->gadget); /* Shuts everything down */ 20988c2ecf20Sopenharmony_ci if (dev->driver) 20998c2ecf20Sopenharmony_ci return -EBUSY; 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_ci gr_dfs_delete(dev); 21028c2ecf20Sopenharmony_ci dma_pool_destroy(dev->desc_pool); 21038c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, NULL); 21048c2ecf20Sopenharmony_ci 21058c2ecf20Sopenharmony_ci gr_free_request(&dev->epi[0].ep, &dev->ep0reqi->req); 21068c2ecf20Sopenharmony_ci gr_free_request(&dev->epo[0].ep, &dev->ep0reqo->req); 21078c2ecf20Sopenharmony_ci 21088c2ecf20Sopenharmony_ci for (i = 0; i < dev->nepo; i++) 21098c2ecf20Sopenharmony_ci gr_ep_remove(dev, i, 0); 21108c2ecf20Sopenharmony_ci for (i = 0; i < dev->nepi; i++) 21118c2ecf20Sopenharmony_ci gr_ep_remove(dev, i, 1); 21128c2ecf20Sopenharmony_ci 21138c2ecf20Sopenharmony_ci return 0; 21148c2ecf20Sopenharmony_ci} 21158c2ecf20Sopenharmony_cistatic int gr_request_irq(struct gr_udc *dev, int irq) 21168c2ecf20Sopenharmony_ci{ 21178c2ecf20Sopenharmony_ci return devm_request_threaded_irq(dev->dev, irq, gr_irq, gr_irq_handler, 21188c2ecf20Sopenharmony_ci IRQF_SHARED, driver_name, dev); 21198c2ecf20Sopenharmony_ci} 21208c2ecf20Sopenharmony_ci 21218c2ecf20Sopenharmony_cistatic int gr_probe(struct platform_device *pdev) 21228c2ecf20Sopenharmony_ci{ 21238c2ecf20Sopenharmony_ci struct gr_udc *dev; 21248c2ecf20Sopenharmony_ci struct gr_regs __iomem *regs; 21258c2ecf20Sopenharmony_ci int retval; 21268c2ecf20Sopenharmony_ci u32 status; 21278c2ecf20Sopenharmony_ci 21288c2ecf20Sopenharmony_ci dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); 21298c2ecf20Sopenharmony_ci if (!dev) 21308c2ecf20Sopenharmony_ci return -ENOMEM; 21318c2ecf20Sopenharmony_ci dev->dev = &pdev->dev; 21328c2ecf20Sopenharmony_ci 21338c2ecf20Sopenharmony_ci regs = devm_platform_ioremap_resource(pdev, 0); 21348c2ecf20Sopenharmony_ci if (IS_ERR(regs)) 21358c2ecf20Sopenharmony_ci return PTR_ERR(regs); 21368c2ecf20Sopenharmony_ci 21378c2ecf20Sopenharmony_ci dev->irq = platform_get_irq(pdev, 0); 21388c2ecf20Sopenharmony_ci if (dev->irq <= 0) 21398c2ecf20Sopenharmony_ci return -ENODEV; 21408c2ecf20Sopenharmony_ci 21418c2ecf20Sopenharmony_ci /* Some core configurations has separate irqs for IN and OUT events */ 21428c2ecf20Sopenharmony_ci dev->irqi = platform_get_irq(pdev, 1); 21438c2ecf20Sopenharmony_ci if (dev->irqi > 0) { 21448c2ecf20Sopenharmony_ci dev->irqo = platform_get_irq(pdev, 2); 21458c2ecf20Sopenharmony_ci if (dev->irqo <= 0) 21468c2ecf20Sopenharmony_ci return -ENODEV; 21478c2ecf20Sopenharmony_ci } else { 21488c2ecf20Sopenharmony_ci dev->irqi = 0; 21498c2ecf20Sopenharmony_ci } 21508c2ecf20Sopenharmony_ci 21518c2ecf20Sopenharmony_ci dev->gadget.name = driver_name; 21528c2ecf20Sopenharmony_ci dev->gadget.max_speed = USB_SPEED_HIGH; 21538c2ecf20Sopenharmony_ci dev->gadget.ops = &gr_ops; 21548c2ecf20Sopenharmony_ci 21558c2ecf20Sopenharmony_ci spin_lock_init(&dev->lock); 21568c2ecf20Sopenharmony_ci dev->regs = regs; 21578c2ecf20Sopenharmony_ci 21588c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, dev); 21598c2ecf20Sopenharmony_ci 21608c2ecf20Sopenharmony_ci /* Determine number of endpoints and data interface mode */ 21618c2ecf20Sopenharmony_ci status = gr_read32(&dev->regs->status); 21628c2ecf20Sopenharmony_ci dev->nepi = ((status & GR_STATUS_NEPI_MASK) >> GR_STATUS_NEPI_POS) + 1; 21638c2ecf20Sopenharmony_ci dev->nepo = ((status & GR_STATUS_NEPO_MASK) >> GR_STATUS_NEPO_POS) + 1; 21648c2ecf20Sopenharmony_ci 21658c2ecf20Sopenharmony_ci if (!(status & GR_STATUS_DM)) { 21668c2ecf20Sopenharmony_ci dev_err(dev->dev, "Slave mode cores are not supported\n"); 21678c2ecf20Sopenharmony_ci return -ENODEV; 21688c2ecf20Sopenharmony_ci } 21698c2ecf20Sopenharmony_ci 21708c2ecf20Sopenharmony_ci /* --- Effects of the following calls might need explicit cleanup --- */ 21718c2ecf20Sopenharmony_ci 21728c2ecf20Sopenharmony_ci /* Create DMA pool for descriptors */ 21738c2ecf20Sopenharmony_ci dev->desc_pool = dma_pool_create("desc_pool", dev->dev, 21748c2ecf20Sopenharmony_ci sizeof(struct gr_dma_desc), 4, 0); 21758c2ecf20Sopenharmony_ci if (!dev->desc_pool) { 21768c2ecf20Sopenharmony_ci dev_err(dev->dev, "Could not allocate DMA pool"); 21778c2ecf20Sopenharmony_ci return -ENOMEM; 21788c2ecf20Sopenharmony_ci } 21798c2ecf20Sopenharmony_ci 21808c2ecf20Sopenharmony_ci /* Inside lock so that no gadget can use this udc until probe is done */ 21818c2ecf20Sopenharmony_ci retval = usb_add_gadget_udc(dev->dev, &dev->gadget); 21828c2ecf20Sopenharmony_ci if (retval) { 21838c2ecf20Sopenharmony_ci dev_err(dev->dev, "Could not add gadget udc"); 21848c2ecf20Sopenharmony_ci goto out; 21858c2ecf20Sopenharmony_ci } 21868c2ecf20Sopenharmony_ci dev->added = 1; 21878c2ecf20Sopenharmony_ci 21888c2ecf20Sopenharmony_ci spin_lock(&dev->lock); 21898c2ecf20Sopenharmony_ci 21908c2ecf20Sopenharmony_ci retval = gr_udc_init(dev); 21918c2ecf20Sopenharmony_ci if (retval) { 21928c2ecf20Sopenharmony_ci spin_unlock(&dev->lock); 21938c2ecf20Sopenharmony_ci goto out; 21948c2ecf20Sopenharmony_ci } 21958c2ecf20Sopenharmony_ci 21968c2ecf20Sopenharmony_ci /* Clear all interrupt enables that might be left on since last boot */ 21978c2ecf20Sopenharmony_ci gr_disable_interrupts_and_pullup(dev); 21988c2ecf20Sopenharmony_ci 21998c2ecf20Sopenharmony_ci spin_unlock(&dev->lock); 22008c2ecf20Sopenharmony_ci 22018c2ecf20Sopenharmony_ci gr_dfs_create(dev); 22028c2ecf20Sopenharmony_ci 22038c2ecf20Sopenharmony_ci retval = gr_request_irq(dev, dev->irq); 22048c2ecf20Sopenharmony_ci if (retval) { 22058c2ecf20Sopenharmony_ci dev_err(dev->dev, "Failed to request irq %d\n", dev->irq); 22068c2ecf20Sopenharmony_ci goto out; 22078c2ecf20Sopenharmony_ci } 22088c2ecf20Sopenharmony_ci 22098c2ecf20Sopenharmony_ci if (dev->irqi) { 22108c2ecf20Sopenharmony_ci retval = gr_request_irq(dev, dev->irqi); 22118c2ecf20Sopenharmony_ci if (retval) { 22128c2ecf20Sopenharmony_ci dev_err(dev->dev, "Failed to request irqi %d\n", 22138c2ecf20Sopenharmony_ci dev->irqi); 22148c2ecf20Sopenharmony_ci goto out; 22158c2ecf20Sopenharmony_ci } 22168c2ecf20Sopenharmony_ci retval = gr_request_irq(dev, dev->irqo); 22178c2ecf20Sopenharmony_ci if (retval) { 22188c2ecf20Sopenharmony_ci dev_err(dev->dev, "Failed to request irqo %d\n", 22198c2ecf20Sopenharmony_ci dev->irqo); 22208c2ecf20Sopenharmony_ci goto out; 22218c2ecf20Sopenharmony_ci } 22228c2ecf20Sopenharmony_ci } 22238c2ecf20Sopenharmony_ci 22248c2ecf20Sopenharmony_ci if (dev->irqi) 22258c2ecf20Sopenharmony_ci dev_info(dev->dev, "regs: %p, irqs %d, %d, %d\n", dev->regs, 22268c2ecf20Sopenharmony_ci dev->irq, dev->irqi, dev->irqo); 22278c2ecf20Sopenharmony_ci else 22288c2ecf20Sopenharmony_ci dev_info(dev->dev, "regs: %p, irq %d\n", dev->regs, dev->irq); 22298c2ecf20Sopenharmony_ci 22308c2ecf20Sopenharmony_ciout: 22318c2ecf20Sopenharmony_ci if (retval) 22328c2ecf20Sopenharmony_ci gr_remove(pdev); 22338c2ecf20Sopenharmony_ci 22348c2ecf20Sopenharmony_ci return retval; 22358c2ecf20Sopenharmony_ci} 22368c2ecf20Sopenharmony_ci 22378c2ecf20Sopenharmony_cistatic const struct of_device_id gr_match[] = { 22388c2ecf20Sopenharmony_ci {.name = "GAISLER_USBDC"}, 22398c2ecf20Sopenharmony_ci {.name = "01_021"}, 22408c2ecf20Sopenharmony_ci {}, 22418c2ecf20Sopenharmony_ci}; 22428c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, gr_match); 22438c2ecf20Sopenharmony_ci 22448c2ecf20Sopenharmony_cistatic struct platform_driver gr_driver = { 22458c2ecf20Sopenharmony_ci .driver = { 22468c2ecf20Sopenharmony_ci .name = DRIVER_NAME, 22478c2ecf20Sopenharmony_ci .of_match_table = gr_match, 22488c2ecf20Sopenharmony_ci }, 22498c2ecf20Sopenharmony_ci .probe = gr_probe, 22508c2ecf20Sopenharmony_ci .remove = gr_remove, 22518c2ecf20Sopenharmony_ci}; 22528c2ecf20Sopenharmony_cimodule_platform_driver(gr_driver); 22538c2ecf20Sopenharmony_ci 22548c2ecf20Sopenharmony_ciMODULE_AUTHOR("Aeroflex Gaisler AB."); 22558c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(DRIVER_DESC); 22568c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 2257