162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * USB Peripheral Controller driver for Aeroflex Gaisler GRUSBDC. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * 2013 (c) Aeroflex Gaisler AB 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * This driver supports GRUSBDC USB Device Controller cores available in the 862306a36Sopenharmony_ci * GRLIB VHDL IP core library. 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Full documentation of the GRUSBDC core can be found here: 1162306a36Sopenharmony_ci * https://www.gaisler.com/products/grlib/grip.pdf 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * Contributors: 1462306a36Sopenharmony_ci * - Andreas Larsson <andreas@gaisler.com> 1562306a36Sopenharmony_ci * - Marko Isomaki 1662306a36Sopenharmony_ci */ 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* 1962306a36Sopenharmony_ci * A GRUSBDC core can have up to 16 IN endpoints and 16 OUT endpoints each 2062306a36Sopenharmony_ci * individually configurable to any of the four USB transfer types. This driver 2162306a36Sopenharmony_ci * only supports cores in DMA mode. 2262306a36Sopenharmony_ci */ 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include <linux/kernel.h> 2562306a36Sopenharmony_ci#include <linux/module.h> 2662306a36Sopenharmony_ci#include <linux/platform_device.h> 2762306a36Sopenharmony_ci#include <linux/slab.h> 2862306a36Sopenharmony_ci#include <linux/spinlock.h> 2962306a36Sopenharmony_ci#include <linux/errno.h> 3062306a36Sopenharmony_ci#include <linux/list.h> 3162306a36Sopenharmony_ci#include <linux/interrupt.h> 3262306a36Sopenharmony_ci#include <linux/device.h> 3362306a36Sopenharmony_ci#include <linux/usb.h> 3462306a36Sopenharmony_ci#include <linux/usb/ch9.h> 3562306a36Sopenharmony_ci#include <linux/usb/gadget.h> 3662306a36Sopenharmony_ci#include <linux/dma-mapping.h> 3762306a36Sopenharmony_ci#include <linux/dmapool.h> 3862306a36Sopenharmony_ci#include <linux/debugfs.h> 3962306a36Sopenharmony_ci#include <linux/seq_file.h> 4062306a36Sopenharmony_ci#include <linux/of.h> 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#include <asm/byteorder.h> 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#include "gr_udc.h" 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define DRIVER_NAME "gr_udc" 4762306a36Sopenharmony_ci#define DRIVER_DESC "Aeroflex Gaisler GRUSBDC USB Peripheral Controller" 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic const char driver_name[] = DRIVER_NAME; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci#define gr_read32(x) (ioread32be((x))) 5262306a36Sopenharmony_ci#define gr_write32(x, v) (iowrite32be((v), (x))) 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/* USB speed and corresponding string calculated from status register value */ 5562306a36Sopenharmony_ci#define GR_SPEED(status) \ 5662306a36Sopenharmony_ci ((status & GR_STATUS_SP) ? USB_SPEED_FULL : USB_SPEED_HIGH) 5762306a36Sopenharmony_ci#define GR_SPEED_STR(status) usb_speed_string(GR_SPEED(status)) 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci/* Size of hardware buffer calculated from epctrl register value */ 6062306a36Sopenharmony_ci#define GR_BUFFER_SIZE(epctrl) \ 6162306a36Sopenharmony_ci ((((epctrl) & GR_EPCTRL_BUFSZ_MASK) >> GR_EPCTRL_BUFSZ_POS) * \ 6262306a36Sopenharmony_ci GR_EPCTRL_BUFSZ_SCALER) 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/* ---------------------------------------------------------------------- */ 6562306a36Sopenharmony_ci/* Debug printout functionality */ 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic const char * const gr_modestring[] = {"control", "iso", "bulk", "int"}; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic const char *gr_ep0state_string(enum gr_ep0state state) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci static const char *const names[] = { 7262306a36Sopenharmony_ci [GR_EP0_DISCONNECT] = "disconnect", 7362306a36Sopenharmony_ci [GR_EP0_SETUP] = "setup", 7462306a36Sopenharmony_ci [GR_EP0_IDATA] = "idata", 7562306a36Sopenharmony_ci [GR_EP0_ODATA] = "odata", 7662306a36Sopenharmony_ci [GR_EP0_ISTATUS] = "istatus", 7762306a36Sopenharmony_ci [GR_EP0_OSTATUS] = "ostatus", 7862306a36Sopenharmony_ci [GR_EP0_STALL] = "stall", 7962306a36Sopenharmony_ci [GR_EP0_SUSPEND] = "suspend", 8062306a36Sopenharmony_ci }; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci if (state < 0 || state >= ARRAY_SIZE(names)) 8362306a36Sopenharmony_ci return "UNKNOWN"; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci return names[state]; 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci#ifdef VERBOSE_DEBUG 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic void gr_dbgprint_request(const char *str, struct gr_ep *ep, 9162306a36Sopenharmony_ci struct gr_request *req) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci int buflen = ep->is_in ? req->req.length : req->req.actual; 9462306a36Sopenharmony_ci int rowlen = 32; 9562306a36Sopenharmony_ci int plen = min(rowlen, buflen); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci dev_dbg(ep->dev->dev, "%s: 0x%p, %d bytes data%s:\n", str, req, buflen, 9862306a36Sopenharmony_ci (buflen > plen ? " (truncated)" : "")); 9962306a36Sopenharmony_ci print_hex_dump_debug(" ", DUMP_PREFIX_NONE, 10062306a36Sopenharmony_ci rowlen, 4, req->req.buf, plen, false); 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic void gr_dbgprint_devreq(struct gr_udc *dev, u8 type, u8 request, 10462306a36Sopenharmony_ci u16 value, u16 index, u16 length) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci dev_vdbg(dev->dev, "REQ: %02x.%02x v%04x i%04x l%04x\n", 10762306a36Sopenharmony_ci type, request, value, index, length); 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci#else /* !VERBOSE_DEBUG */ 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic void gr_dbgprint_request(const char *str, struct gr_ep *ep, 11262306a36Sopenharmony_ci struct gr_request *req) {} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistatic void gr_dbgprint_devreq(struct gr_udc *dev, u8 type, u8 request, 11562306a36Sopenharmony_ci u16 value, u16 index, u16 length) {} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci#endif /* VERBOSE_DEBUG */ 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci/* ---------------------------------------------------------------------- */ 12062306a36Sopenharmony_ci/* Debugfs functionality */ 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci#ifdef CONFIG_USB_GADGET_DEBUG_FS 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic void gr_seq_ep_show(struct seq_file *seq, struct gr_ep *ep) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci u32 epctrl = gr_read32(&ep->regs->epctrl); 12762306a36Sopenharmony_ci u32 epstat = gr_read32(&ep->regs->epstat); 12862306a36Sopenharmony_ci int mode = (epctrl & GR_EPCTRL_TT_MASK) >> GR_EPCTRL_TT_POS; 12962306a36Sopenharmony_ci struct gr_request *req; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci seq_printf(seq, "%s:\n", ep->ep.name); 13262306a36Sopenharmony_ci seq_printf(seq, " mode = %s\n", gr_modestring[mode]); 13362306a36Sopenharmony_ci seq_printf(seq, " halted: %d\n", !!(epctrl & GR_EPCTRL_EH)); 13462306a36Sopenharmony_ci seq_printf(seq, " disabled: %d\n", !!(epctrl & GR_EPCTRL_ED)); 13562306a36Sopenharmony_ci seq_printf(seq, " valid: %d\n", !!(epctrl & GR_EPCTRL_EV)); 13662306a36Sopenharmony_ci seq_printf(seq, " dma_start = %d\n", ep->dma_start); 13762306a36Sopenharmony_ci seq_printf(seq, " stopped = %d\n", ep->stopped); 13862306a36Sopenharmony_ci seq_printf(seq, " wedged = %d\n", ep->wedged); 13962306a36Sopenharmony_ci seq_printf(seq, " callback = %d\n", ep->callback); 14062306a36Sopenharmony_ci seq_printf(seq, " maxpacket = %d\n", ep->ep.maxpacket); 14162306a36Sopenharmony_ci seq_printf(seq, " maxpacket_limit = %d\n", ep->ep.maxpacket_limit); 14262306a36Sopenharmony_ci seq_printf(seq, " bytes_per_buffer = %d\n", ep->bytes_per_buffer); 14362306a36Sopenharmony_ci if (mode == 1 || mode == 3) 14462306a36Sopenharmony_ci seq_printf(seq, " nt = %d\n", 14562306a36Sopenharmony_ci (epctrl & GR_EPCTRL_NT_MASK) >> GR_EPCTRL_NT_POS); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci seq_printf(seq, " Buffer 0: %s %s%d\n", 14862306a36Sopenharmony_ci epstat & GR_EPSTAT_B0 ? "valid" : "invalid", 14962306a36Sopenharmony_ci epstat & GR_EPSTAT_BS ? " " : "selected ", 15062306a36Sopenharmony_ci (epstat & GR_EPSTAT_B0CNT_MASK) >> GR_EPSTAT_B0CNT_POS); 15162306a36Sopenharmony_ci seq_printf(seq, " Buffer 1: %s %s%d\n", 15262306a36Sopenharmony_ci epstat & GR_EPSTAT_B1 ? "valid" : "invalid", 15362306a36Sopenharmony_ci epstat & GR_EPSTAT_BS ? "selected " : " ", 15462306a36Sopenharmony_ci (epstat & GR_EPSTAT_B1CNT_MASK) >> GR_EPSTAT_B1CNT_POS); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci if (list_empty(&ep->queue)) { 15762306a36Sopenharmony_ci seq_puts(seq, " Queue: empty\n\n"); 15862306a36Sopenharmony_ci return; 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci seq_puts(seq, " Queue:\n"); 16262306a36Sopenharmony_ci list_for_each_entry(req, &ep->queue, queue) { 16362306a36Sopenharmony_ci struct gr_dma_desc *desc; 16462306a36Sopenharmony_ci struct gr_dma_desc *next; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci seq_printf(seq, " 0x%p: 0x%p %d %d\n", req, 16762306a36Sopenharmony_ci &req->req.buf, req->req.actual, req->req.length); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci next = req->first_desc; 17062306a36Sopenharmony_ci do { 17162306a36Sopenharmony_ci desc = next; 17262306a36Sopenharmony_ci next = desc->next_desc; 17362306a36Sopenharmony_ci seq_printf(seq, " %c 0x%p (0x%08x): 0x%05x 0x%08x\n", 17462306a36Sopenharmony_ci desc == req->curr_desc ? 'c' : ' ', 17562306a36Sopenharmony_ci desc, desc->paddr, desc->ctrl, desc->data); 17662306a36Sopenharmony_ci } while (desc != req->last_desc); 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_ci seq_puts(seq, "\n"); 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic int gr_dfs_show(struct seq_file *seq, void *v) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci struct gr_udc *dev = seq->private; 18462306a36Sopenharmony_ci u32 control = gr_read32(&dev->regs->control); 18562306a36Sopenharmony_ci u32 status = gr_read32(&dev->regs->status); 18662306a36Sopenharmony_ci struct gr_ep *ep; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci seq_printf(seq, "usb state = %s\n", 18962306a36Sopenharmony_ci usb_state_string(dev->gadget.state)); 19062306a36Sopenharmony_ci seq_printf(seq, "address = %d\n", 19162306a36Sopenharmony_ci (control & GR_CONTROL_UA_MASK) >> GR_CONTROL_UA_POS); 19262306a36Sopenharmony_ci seq_printf(seq, "speed = %s\n", GR_SPEED_STR(status)); 19362306a36Sopenharmony_ci seq_printf(seq, "ep0state = %s\n", gr_ep0state_string(dev->ep0state)); 19462306a36Sopenharmony_ci seq_printf(seq, "irq_enabled = %d\n", dev->irq_enabled); 19562306a36Sopenharmony_ci seq_printf(seq, "remote_wakeup = %d\n", dev->remote_wakeup); 19662306a36Sopenharmony_ci seq_printf(seq, "test_mode = %d\n", dev->test_mode); 19762306a36Sopenharmony_ci seq_puts(seq, "\n"); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci list_for_each_entry(ep, &dev->ep_list, ep_list) 20062306a36Sopenharmony_ci gr_seq_ep_show(seq, ep); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci return 0; 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(gr_dfs); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_cistatic void gr_dfs_create(struct gr_udc *dev) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci const char *name = "gr_udc_state"; 20962306a36Sopenharmony_ci struct dentry *root; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci root = debugfs_create_dir(dev_name(dev->dev), usb_debug_root); 21262306a36Sopenharmony_ci debugfs_create_file(name, 0444, root, dev, &gr_dfs_fops); 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistatic void gr_dfs_delete(struct gr_udc *dev) 21662306a36Sopenharmony_ci{ 21762306a36Sopenharmony_ci debugfs_lookup_and_remove(dev_name(dev->dev), usb_debug_root); 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci#else /* !CONFIG_USB_GADGET_DEBUG_FS */ 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic void gr_dfs_create(struct gr_udc *dev) {} 22362306a36Sopenharmony_cistatic void gr_dfs_delete(struct gr_udc *dev) {} 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci#endif /* CONFIG_USB_GADGET_DEBUG_FS */ 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci/* ---------------------------------------------------------------------- */ 22862306a36Sopenharmony_ci/* DMA and request handling */ 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci/* Allocates a new struct gr_dma_desc, sets paddr and zeroes the rest */ 23162306a36Sopenharmony_cistatic struct gr_dma_desc *gr_alloc_dma_desc(struct gr_ep *ep, gfp_t gfp_flags) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci dma_addr_t paddr; 23462306a36Sopenharmony_ci struct gr_dma_desc *dma_desc; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci dma_desc = dma_pool_zalloc(ep->dev->desc_pool, gfp_flags, &paddr); 23762306a36Sopenharmony_ci if (!dma_desc) { 23862306a36Sopenharmony_ci dev_err(ep->dev->dev, "Could not allocate from DMA pool\n"); 23962306a36Sopenharmony_ci return NULL; 24062306a36Sopenharmony_ci } 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci dma_desc->paddr = paddr; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci return dma_desc; 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic inline void gr_free_dma_desc(struct gr_udc *dev, 24862306a36Sopenharmony_ci struct gr_dma_desc *desc) 24962306a36Sopenharmony_ci{ 25062306a36Sopenharmony_ci dma_pool_free(dev->desc_pool, desc, (dma_addr_t)desc->paddr); 25162306a36Sopenharmony_ci} 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci/* Frees the chain of struct gr_dma_desc for the given request */ 25462306a36Sopenharmony_cistatic void gr_free_dma_desc_chain(struct gr_udc *dev, struct gr_request *req) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci struct gr_dma_desc *desc; 25762306a36Sopenharmony_ci struct gr_dma_desc *next; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci next = req->first_desc; 26062306a36Sopenharmony_ci if (!next) 26162306a36Sopenharmony_ci return; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci do { 26462306a36Sopenharmony_ci desc = next; 26562306a36Sopenharmony_ci next = desc->next_desc; 26662306a36Sopenharmony_ci gr_free_dma_desc(dev, desc); 26762306a36Sopenharmony_ci } while (desc != req->last_desc); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci req->first_desc = NULL; 27062306a36Sopenharmony_ci req->curr_desc = NULL; 27162306a36Sopenharmony_ci req->last_desc = NULL; 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_cistatic void gr_ep0_setup(struct gr_udc *dev, struct gr_request *req); 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci/* 27762306a36Sopenharmony_ci * Frees allocated resources and calls the appropriate completion function/setup 27862306a36Sopenharmony_ci * package handler for a finished request. 27962306a36Sopenharmony_ci * 28062306a36Sopenharmony_ci * Must be called with dev->lock held and irqs disabled. 28162306a36Sopenharmony_ci */ 28262306a36Sopenharmony_cistatic void gr_finish_request(struct gr_ep *ep, struct gr_request *req, 28362306a36Sopenharmony_ci int status) 28462306a36Sopenharmony_ci __releases(&dev->lock) 28562306a36Sopenharmony_ci __acquires(&dev->lock) 28662306a36Sopenharmony_ci{ 28762306a36Sopenharmony_ci struct gr_udc *dev; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci list_del_init(&req->queue); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci if (likely(req->req.status == -EINPROGRESS)) 29262306a36Sopenharmony_ci req->req.status = status; 29362306a36Sopenharmony_ci else 29462306a36Sopenharmony_ci status = req->req.status; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci dev = ep->dev; 29762306a36Sopenharmony_ci usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in); 29862306a36Sopenharmony_ci gr_free_dma_desc_chain(dev, req); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci if (ep->is_in) { /* For OUT, req->req.actual gets updated bit by bit */ 30162306a36Sopenharmony_ci req->req.actual = req->req.length; 30262306a36Sopenharmony_ci } else if (req->oddlen && req->req.actual > req->evenlen) { 30362306a36Sopenharmony_ci /* 30462306a36Sopenharmony_ci * Copy to user buffer in this case where length was not evenly 30562306a36Sopenharmony_ci * divisible by ep->ep.maxpacket and the last descriptor was 30662306a36Sopenharmony_ci * actually used. 30762306a36Sopenharmony_ci */ 30862306a36Sopenharmony_ci char *buftail = ((char *)req->req.buf + req->evenlen); 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci memcpy(buftail, ep->tailbuf, req->oddlen); 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci if (req->req.actual > req->req.length) { 31362306a36Sopenharmony_ci /* We got more data than was requested */ 31462306a36Sopenharmony_ci dev_dbg(ep->dev->dev, "Overflow for ep %s\n", 31562306a36Sopenharmony_ci ep->ep.name); 31662306a36Sopenharmony_ci gr_dbgprint_request("OVFL", ep, req); 31762306a36Sopenharmony_ci req->req.status = -EOVERFLOW; 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci if (!status) { 32262306a36Sopenharmony_ci if (ep->is_in) 32362306a36Sopenharmony_ci gr_dbgprint_request("SENT", ep, req); 32462306a36Sopenharmony_ci else 32562306a36Sopenharmony_ci gr_dbgprint_request("RECV", ep, req); 32662306a36Sopenharmony_ci } 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci /* Prevent changes to ep->queue during callback */ 32962306a36Sopenharmony_ci ep->callback = 1; 33062306a36Sopenharmony_ci if (req == dev->ep0reqo && !status) { 33162306a36Sopenharmony_ci if (req->setup) 33262306a36Sopenharmony_ci gr_ep0_setup(dev, req); 33362306a36Sopenharmony_ci else 33462306a36Sopenharmony_ci dev_err(dev->dev, 33562306a36Sopenharmony_ci "Unexpected non setup packet on ep0in\n"); 33662306a36Sopenharmony_ci } else if (req->req.complete) { 33762306a36Sopenharmony_ci spin_unlock(&dev->lock); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci usb_gadget_giveback_request(&ep->ep, &req->req); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci spin_lock(&dev->lock); 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci ep->callback = 0; 34462306a36Sopenharmony_ci} 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_cistatic struct usb_request *gr_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) 34762306a36Sopenharmony_ci{ 34862306a36Sopenharmony_ci struct gr_request *req; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci req = kzalloc(sizeof(*req), gfp_flags); 35162306a36Sopenharmony_ci if (!req) 35262306a36Sopenharmony_ci return NULL; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci INIT_LIST_HEAD(&req->queue); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci return &req->req; 35762306a36Sopenharmony_ci} 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci/* 36062306a36Sopenharmony_ci * Starts DMA for endpoint ep if there are requests in the queue. 36162306a36Sopenharmony_ci * 36262306a36Sopenharmony_ci * Must be called with dev->lock held and with !ep->stopped. 36362306a36Sopenharmony_ci */ 36462306a36Sopenharmony_cistatic void gr_start_dma(struct gr_ep *ep) 36562306a36Sopenharmony_ci{ 36662306a36Sopenharmony_ci struct gr_request *req; 36762306a36Sopenharmony_ci u32 dmactrl; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci if (list_empty(&ep->queue)) { 37062306a36Sopenharmony_ci ep->dma_start = 0; 37162306a36Sopenharmony_ci return; 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci req = list_first_entry(&ep->queue, struct gr_request, queue); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci /* A descriptor should already have been allocated */ 37762306a36Sopenharmony_ci BUG_ON(!req->curr_desc); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci /* 38062306a36Sopenharmony_ci * The DMA controller can not handle smaller OUT buffers than 38162306a36Sopenharmony_ci * ep->ep.maxpacket. It could lead to buffer overruns if an unexpectedly 38262306a36Sopenharmony_ci * long packet are received. Therefore an internal bounce buffer gets 38362306a36Sopenharmony_ci * used when such a request gets enabled. 38462306a36Sopenharmony_ci */ 38562306a36Sopenharmony_ci if (!ep->is_in && req->oddlen) 38662306a36Sopenharmony_ci req->last_desc->data = ep->tailbuf_paddr; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci wmb(); /* Make sure all is settled before handing it over to DMA */ 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci /* Set the descriptor pointer in the hardware */ 39162306a36Sopenharmony_ci gr_write32(&ep->regs->dmaaddr, req->curr_desc->paddr); 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci /* Announce available descriptors */ 39462306a36Sopenharmony_ci dmactrl = gr_read32(&ep->regs->dmactrl); 39562306a36Sopenharmony_ci gr_write32(&ep->regs->dmactrl, dmactrl | GR_DMACTRL_DA); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci ep->dma_start = 1; 39862306a36Sopenharmony_ci} 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci/* 40162306a36Sopenharmony_ci * Finishes the first request in the ep's queue and, if available, starts the 40262306a36Sopenharmony_ci * next request in queue. 40362306a36Sopenharmony_ci * 40462306a36Sopenharmony_ci * Must be called with dev->lock held, irqs disabled and with !ep->stopped. 40562306a36Sopenharmony_ci */ 40662306a36Sopenharmony_cistatic void gr_dma_advance(struct gr_ep *ep, int status) 40762306a36Sopenharmony_ci{ 40862306a36Sopenharmony_ci struct gr_request *req; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci req = list_first_entry(&ep->queue, struct gr_request, queue); 41162306a36Sopenharmony_ci gr_finish_request(ep, req, status); 41262306a36Sopenharmony_ci gr_start_dma(ep); /* Regardless of ep->dma_start */ 41362306a36Sopenharmony_ci} 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci/* 41662306a36Sopenharmony_ci * Abort DMA for an endpoint. Sets the abort DMA bit which causes an ongoing DMA 41762306a36Sopenharmony_ci * transfer to be canceled and clears GR_DMACTRL_DA. 41862306a36Sopenharmony_ci * 41962306a36Sopenharmony_ci * Must be called with dev->lock held. 42062306a36Sopenharmony_ci */ 42162306a36Sopenharmony_cistatic void gr_abort_dma(struct gr_ep *ep) 42262306a36Sopenharmony_ci{ 42362306a36Sopenharmony_ci u32 dmactrl; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci dmactrl = gr_read32(&ep->regs->dmactrl); 42662306a36Sopenharmony_ci gr_write32(&ep->regs->dmactrl, dmactrl | GR_DMACTRL_AD); 42762306a36Sopenharmony_ci} 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci/* 43062306a36Sopenharmony_ci * Allocates and sets up a struct gr_dma_desc and putting it on the descriptor 43162306a36Sopenharmony_ci * chain. 43262306a36Sopenharmony_ci * 43362306a36Sopenharmony_ci * Size is not used for OUT endpoints. Hardware can not be instructed to handle 43462306a36Sopenharmony_ci * smaller buffer than MAXPL in the OUT direction. 43562306a36Sopenharmony_ci */ 43662306a36Sopenharmony_cistatic int gr_add_dma_desc(struct gr_ep *ep, struct gr_request *req, 43762306a36Sopenharmony_ci dma_addr_t data, unsigned size, gfp_t gfp_flags) 43862306a36Sopenharmony_ci{ 43962306a36Sopenharmony_ci struct gr_dma_desc *desc; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci desc = gr_alloc_dma_desc(ep, gfp_flags); 44262306a36Sopenharmony_ci if (!desc) 44362306a36Sopenharmony_ci return -ENOMEM; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci desc->data = data; 44662306a36Sopenharmony_ci if (ep->is_in) 44762306a36Sopenharmony_ci desc->ctrl = 44862306a36Sopenharmony_ci (GR_DESC_IN_CTRL_LEN_MASK & size) | GR_DESC_IN_CTRL_EN; 44962306a36Sopenharmony_ci else 45062306a36Sopenharmony_ci desc->ctrl = GR_DESC_OUT_CTRL_IE; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci if (!req->first_desc) { 45362306a36Sopenharmony_ci req->first_desc = desc; 45462306a36Sopenharmony_ci req->curr_desc = desc; 45562306a36Sopenharmony_ci } else { 45662306a36Sopenharmony_ci req->last_desc->next_desc = desc; 45762306a36Sopenharmony_ci req->last_desc->next = desc->paddr; 45862306a36Sopenharmony_ci req->last_desc->ctrl |= GR_DESC_OUT_CTRL_NX; 45962306a36Sopenharmony_ci } 46062306a36Sopenharmony_ci req->last_desc = desc; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci return 0; 46362306a36Sopenharmony_ci} 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci/* 46662306a36Sopenharmony_ci * Sets up a chain of struct gr_dma_descriptors pointing to buffers that 46762306a36Sopenharmony_ci * together covers req->req.length bytes of the buffer at DMA address 46862306a36Sopenharmony_ci * req->req.dma for the OUT direction. 46962306a36Sopenharmony_ci * 47062306a36Sopenharmony_ci * The first descriptor in the chain is enabled, the rest disabled. The 47162306a36Sopenharmony_ci * interrupt handler will later enable them one by one when needed so we can 47262306a36Sopenharmony_ci * find out when the transfer is finished. For OUT endpoints, all descriptors 47362306a36Sopenharmony_ci * therefore generate interrutps. 47462306a36Sopenharmony_ci */ 47562306a36Sopenharmony_cistatic int gr_setup_out_desc_list(struct gr_ep *ep, struct gr_request *req, 47662306a36Sopenharmony_ci gfp_t gfp_flags) 47762306a36Sopenharmony_ci{ 47862306a36Sopenharmony_ci u16 bytes_left; /* Bytes left to provide descriptors for */ 47962306a36Sopenharmony_ci u16 bytes_used; /* Bytes accommodated for */ 48062306a36Sopenharmony_ci int ret = 0; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci req->first_desc = NULL; /* Signals that no allocation is done yet */ 48362306a36Sopenharmony_ci bytes_left = req->req.length; 48462306a36Sopenharmony_ci bytes_used = 0; 48562306a36Sopenharmony_ci while (bytes_left > 0) { 48662306a36Sopenharmony_ci dma_addr_t start = req->req.dma + bytes_used; 48762306a36Sopenharmony_ci u16 size = min(bytes_left, ep->bytes_per_buffer); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci if (size < ep->bytes_per_buffer) { 49062306a36Sopenharmony_ci /* Prepare using bounce buffer */ 49162306a36Sopenharmony_ci req->evenlen = req->req.length - bytes_left; 49262306a36Sopenharmony_ci req->oddlen = size; 49362306a36Sopenharmony_ci } 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci ret = gr_add_dma_desc(ep, req, start, size, gfp_flags); 49662306a36Sopenharmony_ci if (ret) 49762306a36Sopenharmony_ci goto alloc_err; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci bytes_left -= size; 50062306a36Sopenharmony_ci bytes_used += size; 50162306a36Sopenharmony_ci } 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci req->first_desc->ctrl |= GR_DESC_OUT_CTRL_EN; 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci return 0; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_cialloc_err: 50862306a36Sopenharmony_ci gr_free_dma_desc_chain(ep->dev, req); 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci return ret; 51162306a36Sopenharmony_ci} 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci/* 51462306a36Sopenharmony_ci * Sets up a chain of struct gr_dma_descriptors pointing to buffers that 51562306a36Sopenharmony_ci * together covers req->req.length bytes of the buffer at DMA address 51662306a36Sopenharmony_ci * req->req.dma for the IN direction. 51762306a36Sopenharmony_ci * 51862306a36Sopenharmony_ci * When more data is provided than the maximum payload size, the hardware splits 51962306a36Sopenharmony_ci * this up into several payloads automatically. Moreover, ep->bytes_per_buffer 52062306a36Sopenharmony_ci * is always set to a multiple of the maximum payload (restricted to the valid 52162306a36Sopenharmony_ci * number of maximum payloads during high bandwidth isochronous or interrupt 52262306a36Sopenharmony_ci * transfers) 52362306a36Sopenharmony_ci * 52462306a36Sopenharmony_ci * All descriptors are enabled from the beginning and we only generate an 52562306a36Sopenharmony_ci * interrupt for the last one indicating that the entire request has been pushed 52662306a36Sopenharmony_ci * to hardware. 52762306a36Sopenharmony_ci */ 52862306a36Sopenharmony_cistatic int gr_setup_in_desc_list(struct gr_ep *ep, struct gr_request *req, 52962306a36Sopenharmony_ci gfp_t gfp_flags) 53062306a36Sopenharmony_ci{ 53162306a36Sopenharmony_ci u16 bytes_left; /* Bytes left in req to provide descriptors for */ 53262306a36Sopenharmony_ci u16 bytes_used; /* Bytes in req accommodated for */ 53362306a36Sopenharmony_ci int ret = 0; 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci req->first_desc = NULL; /* Signals that no allocation is done yet */ 53662306a36Sopenharmony_ci bytes_left = req->req.length; 53762306a36Sopenharmony_ci bytes_used = 0; 53862306a36Sopenharmony_ci do { /* Allow for zero length packets */ 53962306a36Sopenharmony_ci dma_addr_t start = req->req.dma + bytes_used; 54062306a36Sopenharmony_ci u16 size = min(bytes_left, ep->bytes_per_buffer); 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci ret = gr_add_dma_desc(ep, req, start, size, gfp_flags); 54362306a36Sopenharmony_ci if (ret) 54462306a36Sopenharmony_ci goto alloc_err; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci bytes_left -= size; 54762306a36Sopenharmony_ci bytes_used += size; 54862306a36Sopenharmony_ci } while (bytes_left > 0); 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci /* 55162306a36Sopenharmony_ci * Send an extra zero length packet to indicate that no more data is 55262306a36Sopenharmony_ci * available when req->req.zero is set and the data length is even 55362306a36Sopenharmony_ci * multiples of ep->ep.maxpacket. 55462306a36Sopenharmony_ci */ 55562306a36Sopenharmony_ci if (req->req.zero && (req->req.length % ep->ep.maxpacket == 0)) { 55662306a36Sopenharmony_ci ret = gr_add_dma_desc(ep, req, 0, 0, gfp_flags); 55762306a36Sopenharmony_ci if (ret) 55862306a36Sopenharmony_ci goto alloc_err; 55962306a36Sopenharmony_ci } 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci /* 56262306a36Sopenharmony_ci * For IN packets we only want to know when the last packet has been 56362306a36Sopenharmony_ci * transmitted (not just put into internal buffers). 56462306a36Sopenharmony_ci */ 56562306a36Sopenharmony_ci req->last_desc->ctrl |= GR_DESC_IN_CTRL_PI; 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci return 0; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_cialloc_err: 57062306a36Sopenharmony_ci gr_free_dma_desc_chain(ep->dev, req); 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci return ret; 57362306a36Sopenharmony_ci} 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci/* Must be called with dev->lock held */ 57662306a36Sopenharmony_cistatic int gr_queue(struct gr_ep *ep, struct gr_request *req, gfp_t gfp_flags) 57762306a36Sopenharmony_ci{ 57862306a36Sopenharmony_ci struct gr_udc *dev = ep->dev; 57962306a36Sopenharmony_ci int ret; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci if (unlikely(!ep->ep.desc && ep->num != 0)) { 58262306a36Sopenharmony_ci dev_err(dev->dev, "No ep descriptor for %s\n", ep->ep.name); 58362306a36Sopenharmony_ci return -EINVAL; 58462306a36Sopenharmony_ci } 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci if (unlikely(!req->req.buf || !list_empty(&req->queue))) { 58762306a36Sopenharmony_ci dev_err(dev->dev, 58862306a36Sopenharmony_ci "Invalid request for %s: buf=%p list_empty=%d\n", 58962306a36Sopenharmony_ci ep->ep.name, req->req.buf, list_empty(&req->queue)); 59062306a36Sopenharmony_ci return -EINVAL; 59162306a36Sopenharmony_ci } 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) { 59462306a36Sopenharmony_ci dev_err(dev->dev, "-ESHUTDOWN"); 59562306a36Sopenharmony_ci return -ESHUTDOWN; 59662306a36Sopenharmony_ci } 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci /* Can't touch registers when suspended */ 59962306a36Sopenharmony_ci if (dev->ep0state == GR_EP0_SUSPEND) { 60062306a36Sopenharmony_ci dev_err(dev->dev, "-EBUSY"); 60162306a36Sopenharmony_ci return -EBUSY; 60262306a36Sopenharmony_ci } 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci /* Set up DMA mapping in case the caller didn't */ 60562306a36Sopenharmony_ci ret = usb_gadget_map_request(&dev->gadget, &req->req, ep->is_in); 60662306a36Sopenharmony_ci if (ret) { 60762306a36Sopenharmony_ci dev_err(dev->dev, "usb_gadget_map_request"); 60862306a36Sopenharmony_ci return ret; 60962306a36Sopenharmony_ci } 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci if (ep->is_in) 61262306a36Sopenharmony_ci ret = gr_setup_in_desc_list(ep, req, gfp_flags); 61362306a36Sopenharmony_ci else 61462306a36Sopenharmony_ci ret = gr_setup_out_desc_list(ep, req, gfp_flags); 61562306a36Sopenharmony_ci if (ret) 61662306a36Sopenharmony_ci return ret; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci req->req.status = -EINPROGRESS; 61962306a36Sopenharmony_ci req->req.actual = 0; 62062306a36Sopenharmony_ci list_add_tail(&req->queue, &ep->queue); 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci /* Start DMA if not started, otherwise interrupt handler handles it */ 62362306a36Sopenharmony_ci if (!ep->dma_start && likely(!ep->stopped)) 62462306a36Sopenharmony_ci gr_start_dma(ep); 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci return 0; 62762306a36Sopenharmony_ci} 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci/* 63062306a36Sopenharmony_ci * Queue a request from within the driver. 63162306a36Sopenharmony_ci * 63262306a36Sopenharmony_ci * Must be called with dev->lock held. 63362306a36Sopenharmony_ci */ 63462306a36Sopenharmony_cistatic inline int gr_queue_int(struct gr_ep *ep, struct gr_request *req, 63562306a36Sopenharmony_ci gfp_t gfp_flags) 63662306a36Sopenharmony_ci{ 63762306a36Sopenharmony_ci if (ep->is_in) 63862306a36Sopenharmony_ci gr_dbgprint_request("RESP", ep, req); 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci return gr_queue(ep, req, gfp_flags); 64162306a36Sopenharmony_ci} 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci/* ---------------------------------------------------------------------- */ 64462306a36Sopenharmony_ci/* General helper functions */ 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci/* 64762306a36Sopenharmony_ci * Dequeue ALL requests. 64862306a36Sopenharmony_ci * 64962306a36Sopenharmony_ci * Must be called with dev->lock held and irqs disabled. 65062306a36Sopenharmony_ci */ 65162306a36Sopenharmony_cistatic void gr_ep_nuke(struct gr_ep *ep) 65262306a36Sopenharmony_ci{ 65362306a36Sopenharmony_ci struct gr_request *req; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci ep->stopped = 1; 65662306a36Sopenharmony_ci ep->dma_start = 0; 65762306a36Sopenharmony_ci gr_abort_dma(ep); 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci while (!list_empty(&ep->queue)) { 66062306a36Sopenharmony_ci req = list_first_entry(&ep->queue, struct gr_request, queue); 66162306a36Sopenharmony_ci gr_finish_request(ep, req, -ESHUTDOWN); 66262306a36Sopenharmony_ci } 66362306a36Sopenharmony_ci} 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci/* 66662306a36Sopenharmony_ci * Reset the hardware state of this endpoint. 66762306a36Sopenharmony_ci * 66862306a36Sopenharmony_ci * Must be called with dev->lock held. 66962306a36Sopenharmony_ci */ 67062306a36Sopenharmony_cistatic void gr_ep_reset(struct gr_ep *ep) 67162306a36Sopenharmony_ci{ 67262306a36Sopenharmony_ci gr_write32(&ep->regs->epctrl, 0); 67362306a36Sopenharmony_ci gr_write32(&ep->regs->dmactrl, 0); 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci ep->ep.maxpacket = MAX_CTRL_PL_SIZE; 67662306a36Sopenharmony_ci ep->ep.desc = NULL; 67762306a36Sopenharmony_ci ep->stopped = 1; 67862306a36Sopenharmony_ci ep->dma_start = 0; 67962306a36Sopenharmony_ci} 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci/* 68262306a36Sopenharmony_ci * Generate STALL on ep0in/out. 68362306a36Sopenharmony_ci * 68462306a36Sopenharmony_ci * Must be called with dev->lock held. 68562306a36Sopenharmony_ci */ 68662306a36Sopenharmony_cistatic void gr_control_stall(struct gr_udc *dev) 68762306a36Sopenharmony_ci{ 68862306a36Sopenharmony_ci u32 epctrl; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci epctrl = gr_read32(&dev->epo[0].regs->epctrl); 69162306a36Sopenharmony_ci gr_write32(&dev->epo[0].regs->epctrl, epctrl | GR_EPCTRL_CS); 69262306a36Sopenharmony_ci epctrl = gr_read32(&dev->epi[0].regs->epctrl); 69362306a36Sopenharmony_ci gr_write32(&dev->epi[0].regs->epctrl, epctrl | GR_EPCTRL_CS); 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci dev->ep0state = GR_EP0_STALL; 69662306a36Sopenharmony_ci} 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci/* 69962306a36Sopenharmony_ci * Halts, halts and wedges, or clears halt for an endpoint. 70062306a36Sopenharmony_ci * 70162306a36Sopenharmony_ci * Must be called with dev->lock held. 70262306a36Sopenharmony_ci */ 70362306a36Sopenharmony_cistatic int gr_ep_halt_wedge(struct gr_ep *ep, int halt, int wedge, int fromhost) 70462306a36Sopenharmony_ci{ 70562306a36Sopenharmony_ci u32 epctrl; 70662306a36Sopenharmony_ci int retval = 0; 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci if (ep->num && !ep->ep.desc) 70962306a36Sopenharmony_ci return -EINVAL; 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci if (ep->num && ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) 71262306a36Sopenharmony_ci return -EOPNOTSUPP; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci /* Never actually halt ep0, and therefore never clear halt for ep0 */ 71562306a36Sopenharmony_ci if (!ep->num) { 71662306a36Sopenharmony_ci if (halt && !fromhost) { 71762306a36Sopenharmony_ci /* ep0 halt from gadget - generate protocol stall */ 71862306a36Sopenharmony_ci gr_control_stall(ep->dev); 71962306a36Sopenharmony_ci dev_dbg(ep->dev->dev, "EP: stall ep0\n"); 72062306a36Sopenharmony_ci return 0; 72162306a36Sopenharmony_ci } 72262306a36Sopenharmony_ci return -EINVAL; 72362306a36Sopenharmony_ci } 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci dev_dbg(ep->dev->dev, "EP: %s halt %s\n", 72662306a36Sopenharmony_ci (halt ? (wedge ? "wedge" : "set") : "clear"), ep->ep.name); 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci epctrl = gr_read32(&ep->regs->epctrl); 72962306a36Sopenharmony_ci if (halt) { 73062306a36Sopenharmony_ci /* Set HALT */ 73162306a36Sopenharmony_ci gr_write32(&ep->regs->epctrl, epctrl | GR_EPCTRL_EH); 73262306a36Sopenharmony_ci ep->stopped = 1; 73362306a36Sopenharmony_ci if (wedge) 73462306a36Sopenharmony_ci ep->wedged = 1; 73562306a36Sopenharmony_ci } else { 73662306a36Sopenharmony_ci gr_write32(&ep->regs->epctrl, epctrl & ~GR_EPCTRL_EH); 73762306a36Sopenharmony_ci ep->stopped = 0; 73862306a36Sopenharmony_ci ep->wedged = 0; 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci /* Things might have been queued up in the meantime */ 74162306a36Sopenharmony_ci if (!ep->dma_start) 74262306a36Sopenharmony_ci gr_start_dma(ep); 74362306a36Sopenharmony_ci } 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci return retval; 74662306a36Sopenharmony_ci} 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci/* Must be called with dev->lock held */ 74962306a36Sopenharmony_cistatic inline void gr_set_ep0state(struct gr_udc *dev, enum gr_ep0state value) 75062306a36Sopenharmony_ci{ 75162306a36Sopenharmony_ci if (dev->ep0state != value) 75262306a36Sopenharmony_ci dev_vdbg(dev->dev, "STATE: ep0state=%s\n", 75362306a36Sopenharmony_ci gr_ep0state_string(value)); 75462306a36Sopenharmony_ci dev->ep0state = value; 75562306a36Sopenharmony_ci} 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci/* 75862306a36Sopenharmony_ci * Should only be called when endpoints can not generate interrupts. 75962306a36Sopenharmony_ci * 76062306a36Sopenharmony_ci * Must be called with dev->lock held. 76162306a36Sopenharmony_ci */ 76262306a36Sopenharmony_cistatic void gr_disable_interrupts_and_pullup(struct gr_udc *dev) 76362306a36Sopenharmony_ci{ 76462306a36Sopenharmony_ci gr_write32(&dev->regs->control, 0); 76562306a36Sopenharmony_ci wmb(); /* Make sure that we do not deny one of our interrupts */ 76662306a36Sopenharmony_ci dev->irq_enabled = 0; 76762306a36Sopenharmony_ci} 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci/* 77062306a36Sopenharmony_ci * Stop all device activity and disable data line pullup. 77162306a36Sopenharmony_ci * 77262306a36Sopenharmony_ci * Must be called with dev->lock held and irqs disabled. 77362306a36Sopenharmony_ci */ 77462306a36Sopenharmony_cistatic void gr_stop_activity(struct gr_udc *dev) 77562306a36Sopenharmony_ci{ 77662306a36Sopenharmony_ci struct gr_ep *ep; 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci list_for_each_entry(ep, &dev->ep_list, ep_list) 77962306a36Sopenharmony_ci gr_ep_nuke(ep); 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci gr_disable_interrupts_and_pullup(dev); 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_DISCONNECT); 78462306a36Sopenharmony_ci usb_gadget_set_state(&dev->gadget, USB_STATE_NOTATTACHED); 78562306a36Sopenharmony_ci} 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci/* ---------------------------------------------------------------------- */ 78862306a36Sopenharmony_ci/* ep0 setup packet handling */ 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_cistatic void gr_ep0_testmode_complete(struct usb_ep *_ep, 79162306a36Sopenharmony_ci struct usb_request *_req) 79262306a36Sopenharmony_ci{ 79362306a36Sopenharmony_ci struct gr_ep *ep; 79462306a36Sopenharmony_ci struct gr_udc *dev; 79562306a36Sopenharmony_ci u32 control; 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci ep = container_of(_ep, struct gr_ep, ep); 79862306a36Sopenharmony_ci dev = ep->dev; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci spin_lock(&dev->lock); 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci control = gr_read32(&dev->regs->control); 80362306a36Sopenharmony_ci control |= GR_CONTROL_TM | (dev->test_mode << GR_CONTROL_TS_POS); 80462306a36Sopenharmony_ci gr_write32(&dev->regs->control, control); 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci spin_unlock(&dev->lock); 80762306a36Sopenharmony_ci} 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_cistatic void gr_ep0_dummy_complete(struct usb_ep *_ep, struct usb_request *_req) 81062306a36Sopenharmony_ci{ 81162306a36Sopenharmony_ci /* Nothing needs to be done here */ 81262306a36Sopenharmony_ci} 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci/* 81562306a36Sopenharmony_ci * Queue a response on ep0in. 81662306a36Sopenharmony_ci * 81762306a36Sopenharmony_ci * Must be called with dev->lock held. 81862306a36Sopenharmony_ci */ 81962306a36Sopenharmony_cistatic int gr_ep0_respond(struct gr_udc *dev, u8 *buf, int length, 82062306a36Sopenharmony_ci void (*complete)(struct usb_ep *ep, 82162306a36Sopenharmony_ci struct usb_request *req)) 82262306a36Sopenharmony_ci{ 82362306a36Sopenharmony_ci u8 *reqbuf = dev->ep0reqi->req.buf; 82462306a36Sopenharmony_ci int status; 82562306a36Sopenharmony_ci int i; 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci for (i = 0; i < length; i++) 82862306a36Sopenharmony_ci reqbuf[i] = buf[i]; 82962306a36Sopenharmony_ci dev->ep0reqi->req.length = length; 83062306a36Sopenharmony_ci dev->ep0reqi->req.complete = complete; 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci status = gr_queue_int(&dev->epi[0], dev->ep0reqi, GFP_ATOMIC); 83362306a36Sopenharmony_ci if (status < 0) 83462306a36Sopenharmony_ci dev_err(dev->dev, 83562306a36Sopenharmony_ci "Could not queue ep0in setup response: %d\n", status); 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci return status; 83862306a36Sopenharmony_ci} 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci/* 84162306a36Sopenharmony_ci * Queue a 2 byte response on ep0in. 84262306a36Sopenharmony_ci * 84362306a36Sopenharmony_ci * Must be called with dev->lock held. 84462306a36Sopenharmony_ci */ 84562306a36Sopenharmony_cistatic inline int gr_ep0_respond_u16(struct gr_udc *dev, u16 response) 84662306a36Sopenharmony_ci{ 84762306a36Sopenharmony_ci __le16 le_response = cpu_to_le16(response); 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci return gr_ep0_respond(dev, (u8 *)&le_response, 2, 85062306a36Sopenharmony_ci gr_ep0_dummy_complete); 85162306a36Sopenharmony_ci} 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci/* 85462306a36Sopenharmony_ci * Queue a ZLP response on ep0in. 85562306a36Sopenharmony_ci * 85662306a36Sopenharmony_ci * Must be called with dev->lock held. 85762306a36Sopenharmony_ci */ 85862306a36Sopenharmony_cistatic inline int gr_ep0_respond_empty(struct gr_udc *dev) 85962306a36Sopenharmony_ci{ 86062306a36Sopenharmony_ci return gr_ep0_respond(dev, NULL, 0, gr_ep0_dummy_complete); 86162306a36Sopenharmony_ci} 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci/* 86462306a36Sopenharmony_ci * This is run when a SET_ADDRESS request is received. First writes 86562306a36Sopenharmony_ci * the new address to the control register which is updated internally 86662306a36Sopenharmony_ci * when the next IN packet is ACKED. 86762306a36Sopenharmony_ci * 86862306a36Sopenharmony_ci * Must be called with dev->lock held. 86962306a36Sopenharmony_ci */ 87062306a36Sopenharmony_cistatic void gr_set_address(struct gr_udc *dev, u8 address) 87162306a36Sopenharmony_ci{ 87262306a36Sopenharmony_ci u32 control; 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci control = gr_read32(&dev->regs->control) & ~GR_CONTROL_UA_MASK; 87562306a36Sopenharmony_ci control |= (address << GR_CONTROL_UA_POS) & GR_CONTROL_UA_MASK; 87662306a36Sopenharmony_ci control |= GR_CONTROL_SU; 87762306a36Sopenharmony_ci gr_write32(&dev->regs->control, control); 87862306a36Sopenharmony_ci} 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci/* 88162306a36Sopenharmony_ci * Returns negative for STALL, 0 for successful handling and positive for 88262306a36Sopenharmony_ci * delegation. 88362306a36Sopenharmony_ci * 88462306a36Sopenharmony_ci * Must be called with dev->lock held. 88562306a36Sopenharmony_ci */ 88662306a36Sopenharmony_cistatic int gr_device_request(struct gr_udc *dev, u8 type, u8 request, 88762306a36Sopenharmony_ci u16 value, u16 index) 88862306a36Sopenharmony_ci{ 88962306a36Sopenharmony_ci u16 response; 89062306a36Sopenharmony_ci u8 test; 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci switch (request) { 89362306a36Sopenharmony_ci case USB_REQ_SET_ADDRESS: 89462306a36Sopenharmony_ci dev_dbg(dev->dev, "STATUS: address %d\n", value & 0xff); 89562306a36Sopenharmony_ci gr_set_address(dev, value & 0xff); 89662306a36Sopenharmony_ci if (value) 89762306a36Sopenharmony_ci usb_gadget_set_state(&dev->gadget, USB_STATE_ADDRESS); 89862306a36Sopenharmony_ci else 89962306a36Sopenharmony_ci usb_gadget_set_state(&dev->gadget, USB_STATE_DEFAULT); 90062306a36Sopenharmony_ci return gr_ep0_respond_empty(dev); 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ci case USB_REQ_GET_STATUS: 90362306a36Sopenharmony_ci /* Self powered | remote wakeup */ 90462306a36Sopenharmony_ci response = 0x0001 | (dev->remote_wakeup ? 0x0002 : 0); 90562306a36Sopenharmony_ci return gr_ep0_respond_u16(dev, response); 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci case USB_REQ_SET_FEATURE: 90862306a36Sopenharmony_ci switch (value) { 90962306a36Sopenharmony_ci case USB_DEVICE_REMOTE_WAKEUP: 91062306a36Sopenharmony_ci /* Allow remote wakeup */ 91162306a36Sopenharmony_ci dev->remote_wakeup = 1; 91262306a36Sopenharmony_ci return gr_ep0_respond_empty(dev); 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci case USB_DEVICE_TEST_MODE: 91562306a36Sopenharmony_ci /* The hardware does not support USB_TEST_FORCE_ENABLE */ 91662306a36Sopenharmony_ci test = index >> 8; 91762306a36Sopenharmony_ci if (test >= USB_TEST_J && test <= USB_TEST_PACKET) { 91862306a36Sopenharmony_ci dev->test_mode = test; 91962306a36Sopenharmony_ci return gr_ep0_respond(dev, NULL, 0, 92062306a36Sopenharmony_ci gr_ep0_testmode_complete); 92162306a36Sopenharmony_ci } 92262306a36Sopenharmony_ci } 92362306a36Sopenharmony_ci break; 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci case USB_REQ_CLEAR_FEATURE: 92662306a36Sopenharmony_ci switch (value) { 92762306a36Sopenharmony_ci case USB_DEVICE_REMOTE_WAKEUP: 92862306a36Sopenharmony_ci /* Disallow remote wakeup */ 92962306a36Sopenharmony_ci dev->remote_wakeup = 0; 93062306a36Sopenharmony_ci return gr_ep0_respond_empty(dev); 93162306a36Sopenharmony_ci } 93262306a36Sopenharmony_ci break; 93362306a36Sopenharmony_ci } 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci return 1; /* Delegate the rest */ 93662306a36Sopenharmony_ci} 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ci/* 93962306a36Sopenharmony_ci * Returns negative for STALL, 0 for successful handling and positive for 94062306a36Sopenharmony_ci * delegation. 94162306a36Sopenharmony_ci * 94262306a36Sopenharmony_ci * Must be called with dev->lock held. 94362306a36Sopenharmony_ci */ 94462306a36Sopenharmony_cistatic int gr_interface_request(struct gr_udc *dev, u8 type, u8 request, 94562306a36Sopenharmony_ci u16 value, u16 index) 94662306a36Sopenharmony_ci{ 94762306a36Sopenharmony_ci if (dev->gadget.state != USB_STATE_CONFIGURED) 94862306a36Sopenharmony_ci return -1; 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci /* 95162306a36Sopenharmony_ci * Should return STALL for invalid interfaces, but udc driver does not 95262306a36Sopenharmony_ci * know anything about that. However, many gadget drivers do not handle 95362306a36Sopenharmony_ci * GET_STATUS so we need to take care of that. 95462306a36Sopenharmony_ci */ 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci switch (request) { 95762306a36Sopenharmony_ci case USB_REQ_GET_STATUS: 95862306a36Sopenharmony_ci return gr_ep0_respond_u16(dev, 0x0000); 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci case USB_REQ_SET_FEATURE: 96162306a36Sopenharmony_ci case USB_REQ_CLEAR_FEATURE: 96262306a36Sopenharmony_ci /* 96362306a36Sopenharmony_ci * No possible valid standard requests. Still let gadget drivers 96462306a36Sopenharmony_ci * have a go at it. 96562306a36Sopenharmony_ci */ 96662306a36Sopenharmony_ci break; 96762306a36Sopenharmony_ci } 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci return 1; /* Delegate the rest */ 97062306a36Sopenharmony_ci} 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci/* 97362306a36Sopenharmony_ci * Returns negative for STALL, 0 for successful handling and positive for 97462306a36Sopenharmony_ci * delegation. 97562306a36Sopenharmony_ci * 97662306a36Sopenharmony_ci * Must be called with dev->lock held. 97762306a36Sopenharmony_ci */ 97862306a36Sopenharmony_cistatic int gr_endpoint_request(struct gr_udc *dev, u8 type, u8 request, 97962306a36Sopenharmony_ci u16 value, u16 index) 98062306a36Sopenharmony_ci{ 98162306a36Sopenharmony_ci struct gr_ep *ep; 98262306a36Sopenharmony_ci int status; 98362306a36Sopenharmony_ci int halted; 98462306a36Sopenharmony_ci u8 epnum = index & USB_ENDPOINT_NUMBER_MASK; 98562306a36Sopenharmony_ci u8 is_in = index & USB_ENDPOINT_DIR_MASK; 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci if ((is_in && epnum >= dev->nepi) || (!is_in && epnum >= dev->nepo)) 98862306a36Sopenharmony_ci return -1; 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci if (dev->gadget.state != USB_STATE_CONFIGURED && epnum != 0) 99162306a36Sopenharmony_ci return -1; 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci ep = (is_in ? &dev->epi[epnum] : &dev->epo[epnum]); 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci switch (request) { 99662306a36Sopenharmony_ci case USB_REQ_GET_STATUS: 99762306a36Sopenharmony_ci halted = gr_read32(&ep->regs->epctrl) & GR_EPCTRL_EH; 99862306a36Sopenharmony_ci return gr_ep0_respond_u16(dev, halted ? 0x0001 : 0); 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci case USB_REQ_SET_FEATURE: 100162306a36Sopenharmony_ci switch (value) { 100262306a36Sopenharmony_ci case USB_ENDPOINT_HALT: 100362306a36Sopenharmony_ci status = gr_ep_halt_wedge(ep, 1, 0, 1); 100462306a36Sopenharmony_ci if (status >= 0) 100562306a36Sopenharmony_ci status = gr_ep0_respond_empty(dev); 100662306a36Sopenharmony_ci return status; 100762306a36Sopenharmony_ci } 100862306a36Sopenharmony_ci break; 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci case USB_REQ_CLEAR_FEATURE: 101162306a36Sopenharmony_ci switch (value) { 101262306a36Sopenharmony_ci case USB_ENDPOINT_HALT: 101362306a36Sopenharmony_ci if (ep->wedged) 101462306a36Sopenharmony_ci return -1; 101562306a36Sopenharmony_ci status = gr_ep_halt_wedge(ep, 0, 0, 1); 101662306a36Sopenharmony_ci if (status >= 0) 101762306a36Sopenharmony_ci status = gr_ep0_respond_empty(dev); 101862306a36Sopenharmony_ci return status; 101962306a36Sopenharmony_ci } 102062306a36Sopenharmony_ci break; 102162306a36Sopenharmony_ci } 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci return 1; /* Delegate the rest */ 102462306a36Sopenharmony_ci} 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci/* Must be called with dev->lock held */ 102762306a36Sopenharmony_cistatic void gr_ep0out_requeue(struct gr_udc *dev) 102862306a36Sopenharmony_ci{ 102962306a36Sopenharmony_ci int ret = gr_queue_int(&dev->epo[0], dev->ep0reqo, GFP_ATOMIC); 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci if (ret) 103262306a36Sopenharmony_ci dev_err(dev->dev, "Could not queue ep0out setup request: %d\n", 103362306a36Sopenharmony_ci ret); 103462306a36Sopenharmony_ci} 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci/* 103762306a36Sopenharmony_ci * The main function dealing with setup requests on ep0. 103862306a36Sopenharmony_ci * 103962306a36Sopenharmony_ci * Must be called with dev->lock held and irqs disabled 104062306a36Sopenharmony_ci */ 104162306a36Sopenharmony_cistatic void gr_ep0_setup(struct gr_udc *dev, struct gr_request *req) 104262306a36Sopenharmony_ci __releases(&dev->lock) 104362306a36Sopenharmony_ci __acquires(&dev->lock) 104462306a36Sopenharmony_ci{ 104562306a36Sopenharmony_ci union { 104662306a36Sopenharmony_ci struct usb_ctrlrequest ctrl; 104762306a36Sopenharmony_ci u8 raw[8]; 104862306a36Sopenharmony_ci u32 word[2]; 104962306a36Sopenharmony_ci } u; 105062306a36Sopenharmony_ci u8 type; 105162306a36Sopenharmony_ci u8 request; 105262306a36Sopenharmony_ci u16 value; 105362306a36Sopenharmony_ci u16 index; 105462306a36Sopenharmony_ci u16 length; 105562306a36Sopenharmony_ci int i; 105662306a36Sopenharmony_ci int status; 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ci /* Restore from ep0 halt */ 105962306a36Sopenharmony_ci if (dev->ep0state == GR_EP0_STALL) { 106062306a36Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_SETUP); 106162306a36Sopenharmony_ci if (!req->req.actual) 106262306a36Sopenharmony_ci goto out; 106362306a36Sopenharmony_ci } 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci if (dev->ep0state == GR_EP0_ISTATUS) { 106662306a36Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_SETUP); 106762306a36Sopenharmony_ci if (req->req.actual > 0) 106862306a36Sopenharmony_ci dev_dbg(dev->dev, 106962306a36Sopenharmony_ci "Unexpected setup packet at state %s\n", 107062306a36Sopenharmony_ci gr_ep0state_string(GR_EP0_ISTATUS)); 107162306a36Sopenharmony_ci else 107262306a36Sopenharmony_ci goto out; /* Got expected ZLP */ 107362306a36Sopenharmony_ci } else if (dev->ep0state != GR_EP0_SETUP) { 107462306a36Sopenharmony_ci dev_info(dev->dev, 107562306a36Sopenharmony_ci "Unexpected ep0out request at state %s - stalling\n", 107662306a36Sopenharmony_ci gr_ep0state_string(dev->ep0state)); 107762306a36Sopenharmony_ci gr_control_stall(dev); 107862306a36Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_SETUP); 107962306a36Sopenharmony_ci goto out; 108062306a36Sopenharmony_ci } else if (!req->req.actual) { 108162306a36Sopenharmony_ci dev_dbg(dev->dev, "Unexpected ZLP at state %s\n", 108262306a36Sopenharmony_ci gr_ep0state_string(dev->ep0state)); 108362306a36Sopenharmony_ci goto out; 108462306a36Sopenharmony_ci } 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci /* Handle SETUP packet */ 108762306a36Sopenharmony_ci for (i = 0; i < req->req.actual; i++) 108862306a36Sopenharmony_ci u.raw[i] = ((u8 *)req->req.buf)[i]; 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci type = u.ctrl.bRequestType; 109162306a36Sopenharmony_ci request = u.ctrl.bRequest; 109262306a36Sopenharmony_ci value = le16_to_cpu(u.ctrl.wValue); 109362306a36Sopenharmony_ci index = le16_to_cpu(u.ctrl.wIndex); 109462306a36Sopenharmony_ci length = le16_to_cpu(u.ctrl.wLength); 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_ci gr_dbgprint_devreq(dev, type, request, value, index, length); 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci /* Check for data stage */ 109962306a36Sopenharmony_ci if (length) { 110062306a36Sopenharmony_ci if (type & USB_DIR_IN) 110162306a36Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_IDATA); 110262306a36Sopenharmony_ci else 110362306a36Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_ODATA); 110462306a36Sopenharmony_ci } 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci status = 1; /* Positive status flags delegation */ 110762306a36Sopenharmony_ci if ((type & USB_TYPE_MASK) == USB_TYPE_STANDARD) { 110862306a36Sopenharmony_ci switch (type & USB_RECIP_MASK) { 110962306a36Sopenharmony_ci case USB_RECIP_DEVICE: 111062306a36Sopenharmony_ci status = gr_device_request(dev, type, request, 111162306a36Sopenharmony_ci value, index); 111262306a36Sopenharmony_ci break; 111362306a36Sopenharmony_ci case USB_RECIP_ENDPOINT: 111462306a36Sopenharmony_ci status = gr_endpoint_request(dev, type, request, 111562306a36Sopenharmony_ci value, index); 111662306a36Sopenharmony_ci break; 111762306a36Sopenharmony_ci case USB_RECIP_INTERFACE: 111862306a36Sopenharmony_ci status = gr_interface_request(dev, type, request, 111962306a36Sopenharmony_ci value, index); 112062306a36Sopenharmony_ci break; 112162306a36Sopenharmony_ci } 112262306a36Sopenharmony_ci } 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci if (status > 0) { 112562306a36Sopenharmony_ci spin_unlock(&dev->lock); 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci dev_vdbg(dev->dev, "DELEGATE\n"); 112862306a36Sopenharmony_ci status = dev->driver->setup(&dev->gadget, &u.ctrl); 112962306a36Sopenharmony_ci 113062306a36Sopenharmony_ci spin_lock(&dev->lock); 113162306a36Sopenharmony_ci } 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci /* Generate STALL on both ep0out and ep0in if requested */ 113462306a36Sopenharmony_ci if (unlikely(status < 0)) { 113562306a36Sopenharmony_ci dev_vdbg(dev->dev, "STALL\n"); 113662306a36Sopenharmony_ci gr_control_stall(dev); 113762306a36Sopenharmony_ci } 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_ci if ((type & USB_TYPE_MASK) == USB_TYPE_STANDARD && 114062306a36Sopenharmony_ci request == USB_REQ_SET_CONFIGURATION) { 114162306a36Sopenharmony_ci if (!value) { 114262306a36Sopenharmony_ci dev_dbg(dev->dev, "STATUS: deconfigured\n"); 114362306a36Sopenharmony_ci usb_gadget_set_state(&dev->gadget, USB_STATE_ADDRESS); 114462306a36Sopenharmony_ci } else if (status >= 0) { 114562306a36Sopenharmony_ci /* Not configured unless gadget OK:s it */ 114662306a36Sopenharmony_ci dev_dbg(dev->dev, "STATUS: configured: %d\n", value); 114762306a36Sopenharmony_ci usb_gadget_set_state(&dev->gadget, 114862306a36Sopenharmony_ci USB_STATE_CONFIGURED); 114962306a36Sopenharmony_ci } 115062306a36Sopenharmony_ci } 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_ci /* Get ready for next stage */ 115362306a36Sopenharmony_ci if (dev->ep0state == GR_EP0_ODATA) 115462306a36Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_OSTATUS); 115562306a36Sopenharmony_ci else if (dev->ep0state == GR_EP0_IDATA) 115662306a36Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_ISTATUS); 115762306a36Sopenharmony_ci else 115862306a36Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_SETUP); 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_ciout: 116162306a36Sopenharmony_ci gr_ep0out_requeue(dev); 116262306a36Sopenharmony_ci} 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_ci/* ---------------------------------------------------------------------- */ 116562306a36Sopenharmony_ci/* VBUS and USB reset handling */ 116662306a36Sopenharmony_ci 116762306a36Sopenharmony_ci/* Must be called with dev->lock held and irqs disabled */ 116862306a36Sopenharmony_cistatic void gr_vbus_connected(struct gr_udc *dev, u32 status) 116962306a36Sopenharmony_ci{ 117062306a36Sopenharmony_ci u32 control; 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci dev->gadget.speed = GR_SPEED(status); 117362306a36Sopenharmony_ci usb_gadget_set_state(&dev->gadget, USB_STATE_POWERED); 117462306a36Sopenharmony_ci 117562306a36Sopenharmony_ci /* Turn on full interrupts and pullup */ 117662306a36Sopenharmony_ci control = (GR_CONTROL_SI | GR_CONTROL_UI | GR_CONTROL_VI | 117762306a36Sopenharmony_ci GR_CONTROL_SP | GR_CONTROL_EP); 117862306a36Sopenharmony_ci gr_write32(&dev->regs->control, control); 117962306a36Sopenharmony_ci} 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci/* Must be called with dev->lock held */ 118262306a36Sopenharmony_cistatic void gr_enable_vbus_detect(struct gr_udc *dev) 118362306a36Sopenharmony_ci{ 118462306a36Sopenharmony_ci u32 status; 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci dev->irq_enabled = 1; 118762306a36Sopenharmony_ci wmb(); /* Make sure we do not ignore an interrupt */ 118862306a36Sopenharmony_ci gr_write32(&dev->regs->control, GR_CONTROL_VI); 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_ci /* Take care of the case we are already plugged in at this point */ 119162306a36Sopenharmony_ci status = gr_read32(&dev->regs->status); 119262306a36Sopenharmony_ci if (status & GR_STATUS_VB) 119362306a36Sopenharmony_ci gr_vbus_connected(dev, status); 119462306a36Sopenharmony_ci} 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci/* Must be called with dev->lock held and irqs disabled */ 119762306a36Sopenharmony_cistatic void gr_vbus_disconnected(struct gr_udc *dev) 119862306a36Sopenharmony_ci{ 119962306a36Sopenharmony_ci gr_stop_activity(dev); 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci /* Report disconnect */ 120262306a36Sopenharmony_ci if (dev->driver && dev->driver->disconnect) { 120362306a36Sopenharmony_ci spin_unlock(&dev->lock); 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci dev->driver->disconnect(&dev->gadget); 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci spin_lock(&dev->lock); 120862306a36Sopenharmony_ci } 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci gr_enable_vbus_detect(dev); 121162306a36Sopenharmony_ci} 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_ci/* Must be called with dev->lock held and irqs disabled */ 121462306a36Sopenharmony_cistatic void gr_udc_usbreset(struct gr_udc *dev, u32 status) 121562306a36Sopenharmony_ci{ 121662306a36Sopenharmony_ci gr_set_address(dev, 0); 121762306a36Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_SETUP); 121862306a36Sopenharmony_ci usb_gadget_set_state(&dev->gadget, USB_STATE_DEFAULT); 121962306a36Sopenharmony_ci dev->gadget.speed = GR_SPEED(status); 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_ci gr_ep_nuke(&dev->epo[0]); 122262306a36Sopenharmony_ci gr_ep_nuke(&dev->epi[0]); 122362306a36Sopenharmony_ci dev->epo[0].stopped = 0; 122462306a36Sopenharmony_ci dev->epi[0].stopped = 0; 122562306a36Sopenharmony_ci gr_ep0out_requeue(dev); 122662306a36Sopenharmony_ci} 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci/* ---------------------------------------------------------------------- */ 122962306a36Sopenharmony_ci/* Irq handling */ 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci/* 123262306a36Sopenharmony_ci * Handles interrupts from in endpoints. Returns whether something was handled. 123362306a36Sopenharmony_ci * 123462306a36Sopenharmony_ci * Must be called with dev->lock held, irqs disabled and with !ep->stopped. 123562306a36Sopenharmony_ci */ 123662306a36Sopenharmony_cistatic int gr_handle_in_ep(struct gr_ep *ep) 123762306a36Sopenharmony_ci{ 123862306a36Sopenharmony_ci struct gr_request *req; 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci req = list_first_entry(&ep->queue, struct gr_request, queue); 124162306a36Sopenharmony_ci if (!req->last_desc) 124262306a36Sopenharmony_ci return 0; 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci if (READ_ONCE(req->last_desc->ctrl) & GR_DESC_IN_CTRL_EN) 124562306a36Sopenharmony_ci return 0; /* Not put in hardware buffers yet */ 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci if (gr_read32(&ep->regs->epstat) & (GR_EPSTAT_B1 | GR_EPSTAT_B0)) 124862306a36Sopenharmony_ci return 0; /* Not transmitted yet, still in hardware buffers */ 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ci /* Write complete */ 125162306a36Sopenharmony_ci gr_dma_advance(ep, 0); 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci return 1; 125462306a36Sopenharmony_ci} 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci/* 125762306a36Sopenharmony_ci * Handles interrupts from out endpoints. Returns whether something was handled. 125862306a36Sopenharmony_ci * 125962306a36Sopenharmony_ci * Must be called with dev->lock held, irqs disabled and with !ep->stopped. 126062306a36Sopenharmony_ci */ 126162306a36Sopenharmony_cistatic int gr_handle_out_ep(struct gr_ep *ep) 126262306a36Sopenharmony_ci{ 126362306a36Sopenharmony_ci u32 ep_dmactrl; 126462306a36Sopenharmony_ci u32 ctrl; 126562306a36Sopenharmony_ci u16 len; 126662306a36Sopenharmony_ci struct gr_request *req; 126762306a36Sopenharmony_ci struct gr_udc *dev = ep->dev; 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci req = list_first_entry(&ep->queue, struct gr_request, queue); 127062306a36Sopenharmony_ci if (!req->curr_desc) 127162306a36Sopenharmony_ci return 0; 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_ci ctrl = READ_ONCE(req->curr_desc->ctrl); 127462306a36Sopenharmony_ci if (ctrl & GR_DESC_OUT_CTRL_EN) 127562306a36Sopenharmony_ci return 0; /* Not received yet */ 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_ci /* Read complete */ 127862306a36Sopenharmony_ci len = ctrl & GR_DESC_OUT_CTRL_LEN_MASK; 127962306a36Sopenharmony_ci req->req.actual += len; 128062306a36Sopenharmony_ci if (ctrl & GR_DESC_OUT_CTRL_SE) 128162306a36Sopenharmony_ci req->setup = 1; 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci if (len < ep->ep.maxpacket || req->req.actual >= req->req.length) { 128462306a36Sopenharmony_ci /* Short packet or >= expected size - we are done */ 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_ci if ((ep == &dev->epo[0]) && (dev->ep0state == GR_EP0_OSTATUS)) { 128762306a36Sopenharmony_ci /* 128862306a36Sopenharmony_ci * Send a status stage ZLP to ack the DATA stage in the 128962306a36Sopenharmony_ci * OUT direction. This needs to be done before 129062306a36Sopenharmony_ci * gr_dma_advance as that can lead to a call to 129162306a36Sopenharmony_ci * ep0_setup that can change dev->ep0state. 129262306a36Sopenharmony_ci */ 129362306a36Sopenharmony_ci gr_ep0_respond_empty(dev); 129462306a36Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_SETUP); 129562306a36Sopenharmony_ci } 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_ci gr_dma_advance(ep, 0); 129862306a36Sopenharmony_ci } else { 129962306a36Sopenharmony_ci /* Not done yet. Enable the next descriptor to receive more. */ 130062306a36Sopenharmony_ci req->curr_desc = req->curr_desc->next_desc; 130162306a36Sopenharmony_ci req->curr_desc->ctrl |= GR_DESC_OUT_CTRL_EN; 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci ep_dmactrl = gr_read32(&ep->regs->dmactrl); 130462306a36Sopenharmony_ci gr_write32(&ep->regs->dmactrl, ep_dmactrl | GR_DMACTRL_DA); 130562306a36Sopenharmony_ci } 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci return 1; 130862306a36Sopenharmony_ci} 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_ci/* 131162306a36Sopenharmony_ci * Handle state changes. Returns whether something was handled. 131262306a36Sopenharmony_ci * 131362306a36Sopenharmony_ci * Must be called with dev->lock held and irqs disabled. 131462306a36Sopenharmony_ci */ 131562306a36Sopenharmony_cistatic int gr_handle_state_changes(struct gr_udc *dev) 131662306a36Sopenharmony_ci{ 131762306a36Sopenharmony_ci u32 status = gr_read32(&dev->regs->status); 131862306a36Sopenharmony_ci int handled = 0; 131962306a36Sopenharmony_ci int powstate = !(dev->gadget.state == USB_STATE_NOTATTACHED || 132062306a36Sopenharmony_ci dev->gadget.state == USB_STATE_ATTACHED); 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci /* VBUS valid detected */ 132362306a36Sopenharmony_ci if (!powstate && (status & GR_STATUS_VB)) { 132462306a36Sopenharmony_ci dev_dbg(dev->dev, "STATUS: vbus valid detected\n"); 132562306a36Sopenharmony_ci gr_vbus_connected(dev, status); 132662306a36Sopenharmony_ci handled = 1; 132762306a36Sopenharmony_ci } 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci /* Disconnect */ 133062306a36Sopenharmony_ci if (powstate && !(status & GR_STATUS_VB)) { 133162306a36Sopenharmony_ci dev_dbg(dev->dev, "STATUS: vbus invalid detected\n"); 133262306a36Sopenharmony_ci gr_vbus_disconnected(dev); 133362306a36Sopenharmony_ci handled = 1; 133462306a36Sopenharmony_ci } 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ci /* USB reset detected */ 133762306a36Sopenharmony_ci if (status & GR_STATUS_UR) { 133862306a36Sopenharmony_ci dev_dbg(dev->dev, "STATUS: USB reset - speed is %s\n", 133962306a36Sopenharmony_ci GR_SPEED_STR(status)); 134062306a36Sopenharmony_ci gr_write32(&dev->regs->status, GR_STATUS_UR); 134162306a36Sopenharmony_ci gr_udc_usbreset(dev, status); 134262306a36Sopenharmony_ci handled = 1; 134362306a36Sopenharmony_ci } 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci /* Speed change */ 134662306a36Sopenharmony_ci if (dev->gadget.speed != GR_SPEED(status)) { 134762306a36Sopenharmony_ci dev_dbg(dev->dev, "STATUS: USB Speed change to %s\n", 134862306a36Sopenharmony_ci GR_SPEED_STR(status)); 134962306a36Sopenharmony_ci dev->gadget.speed = GR_SPEED(status); 135062306a36Sopenharmony_ci handled = 1; 135162306a36Sopenharmony_ci } 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_ci /* Going into suspend */ 135462306a36Sopenharmony_ci if ((dev->ep0state != GR_EP0_SUSPEND) && !(status & GR_STATUS_SU)) { 135562306a36Sopenharmony_ci dev_dbg(dev->dev, "STATUS: USB suspend\n"); 135662306a36Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_SUSPEND); 135762306a36Sopenharmony_ci dev->suspended_from = dev->gadget.state; 135862306a36Sopenharmony_ci usb_gadget_set_state(&dev->gadget, USB_STATE_SUSPENDED); 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci if ((dev->gadget.speed != USB_SPEED_UNKNOWN) && 136162306a36Sopenharmony_ci dev->driver && dev->driver->suspend) { 136262306a36Sopenharmony_ci spin_unlock(&dev->lock); 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_ci dev->driver->suspend(&dev->gadget); 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_ci spin_lock(&dev->lock); 136762306a36Sopenharmony_ci } 136862306a36Sopenharmony_ci handled = 1; 136962306a36Sopenharmony_ci } 137062306a36Sopenharmony_ci 137162306a36Sopenharmony_ci /* Coming out of suspend */ 137262306a36Sopenharmony_ci if ((dev->ep0state == GR_EP0_SUSPEND) && (status & GR_STATUS_SU)) { 137362306a36Sopenharmony_ci dev_dbg(dev->dev, "STATUS: USB resume\n"); 137462306a36Sopenharmony_ci if (dev->suspended_from == USB_STATE_POWERED) 137562306a36Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_DISCONNECT); 137662306a36Sopenharmony_ci else 137762306a36Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_SETUP); 137862306a36Sopenharmony_ci usb_gadget_set_state(&dev->gadget, dev->suspended_from); 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ci if ((dev->gadget.speed != USB_SPEED_UNKNOWN) && 138162306a36Sopenharmony_ci dev->driver && dev->driver->resume) { 138262306a36Sopenharmony_ci spin_unlock(&dev->lock); 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci dev->driver->resume(&dev->gadget); 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci spin_lock(&dev->lock); 138762306a36Sopenharmony_ci } 138862306a36Sopenharmony_ci handled = 1; 138962306a36Sopenharmony_ci } 139062306a36Sopenharmony_ci 139162306a36Sopenharmony_ci return handled; 139262306a36Sopenharmony_ci} 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci/* Non-interrupt context irq handler */ 139562306a36Sopenharmony_cistatic irqreturn_t gr_irq_handler(int irq, void *_dev) 139662306a36Sopenharmony_ci{ 139762306a36Sopenharmony_ci struct gr_udc *dev = _dev; 139862306a36Sopenharmony_ci struct gr_ep *ep; 139962306a36Sopenharmony_ci int handled = 0; 140062306a36Sopenharmony_ci int i; 140162306a36Sopenharmony_ci unsigned long flags; 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci spin_lock_irqsave(&dev->lock, flags); 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_ci if (!dev->irq_enabled) 140662306a36Sopenharmony_ci goto out; 140762306a36Sopenharmony_ci 140862306a36Sopenharmony_ci /* 140962306a36Sopenharmony_ci * Check IN ep interrupts. We check these before the OUT eps because 141062306a36Sopenharmony_ci * some gadgets reuse the request that might already be currently 141162306a36Sopenharmony_ci * outstanding and needs to be completed (mainly setup requests). 141262306a36Sopenharmony_ci */ 141362306a36Sopenharmony_ci for (i = 0; i < dev->nepi; i++) { 141462306a36Sopenharmony_ci ep = &dev->epi[i]; 141562306a36Sopenharmony_ci if (!ep->stopped && !ep->callback && !list_empty(&ep->queue)) 141662306a36Sopenharmony_ci handled = gr_handle_in_ep(ep) || handled; 141762306a36Sopenharmony_ci } 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci /* Check OUT ep interrupts */ 142062306a36Sopenharmony_ci for (i = 0; i < dev->nepo; i++) { 142162306a36Sopenharmony_ci ep = &dev->epo[i]; 142262306a36Sopenharmony_ci if (!ep->stopped && !ep->callback && !list_empty(&ep->queue)) 142362306a36Sopenharmony_ci handled = gr_handle_out_ep(ep) || handled; 142462306a36Sopenharmony_ci } 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_ci /* Check status interrupts */ 142762306a36Sopenharmony_ci handled = gr_handle_state_changes(dev) || handled; 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci /* 143062306a36Sopenharmony_ci * Check AMBA DMA errors. Only check if we didn't find anything else to 143162306a36Sopenharmony_ci * handle because this shouldn't happen if we did everything right. 143262306a36Sopenharmony_ci */ 143362306a36Sopenharmony_ci if (!handled) { 143462306a36Sopenharmony_ci list_for_each_entry(ep, &dev->ep_list, ep_list) { 143562306a36Sopenharmony_ci if (gr_read32(&ep->regs->dmactrl) & GR_DMACTRL_AE) { 143662306a36Sopenharmony_ci dev_err(dev->dev, 143762306a36Sopenharmony_ci "AMBA Error occurred for %s\n", 143862306a36Sopenharmony_ci ep->ep.name); 143962306a36Sopenharmony_ci handled = 1; 144062306a36Sopenharmony_ci } 144162306a36Sopenharmony_ci } 144262306a36Sopenharmony_ci } 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ciout: 144562306a36Sopenharmony_ci spin_unlock_irqrestore(&dev->lock, flags); 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_ci return handled ? IRQ_HANDLED : IRQ_NONE; 144862306a36Sopenharmony_ci} 144962306a36Sopenharmony_ci 145062306a36Sopenharmony_ci/* Interrupt context irq handler */ 145162306a36Sopenharmony_cistatic irqreturn_t gr_irq(int irq, void *_dev) 145262306a36Sopenharmony_ci{ 145362306a36Sopenharmony_ci struct gr_udc *dev = _dev; 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci if (!dev->irq_enabled) 145662306a36Sopenharmony_ci return IRQ_NONE; 145762306a36Sopenharmony_ci 145862306a36Sopenharmony_ci return IRQ_WAKE_THREAD; 145962306a36Sopenharmony_ci} 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci/* ---------------------------------------------------------------------- */ 146262306a36Sopenharmony_ci/* USB ep ops */ 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_ci/* Enable endpoint. Not for ep0in and ep0out that are handled separately. */ 146562306a36Sopenharmony_cistatic int gr_ep_enable(struct usb_ep *_ep, 146662306a36Sopenharmony_ci const struct usb_endpoint_descriptor *desc) 146762306a36Sopenharmony_ci{ 146862306a36Sopenharmony_ci struct gr_udc *dev; 146962306a36Sopenharmony_ci struct gr_ep *ep; 147062306a36Sopenharmony_ci u8 mode; 147162306a36Sopenharmony_ci u8 nt; 147262306a36Sopenharmony_ci u16 max; 147362306a36Sopenharmony_ci u16 buffer_size = 0; 147462306a36Sopenharmony_ci u32 epctrl; 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci ep = container_of(_ep, struct gr_ep, ep); 147762306a36Sopenharmony_ci if (!_ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT) 147862306a36Sopenharmony_ci return -EINVAL; 147962306a36Sopenharmony_ci 148062306a36Sopenharmony_ci dev = ep->dev; 148162306a36Sopenharmony_ci 148262306a36Sopenharmony_ci /* 'ep0' IN and OUT are reserved */ 148362306a36Sopenharmony_ci if (ep == &dev->epo[0] || ep == &dev->epi[0]) 148462306a36Sopenharmony_ci return -EINVAL; 148562306a36Sopenharmony_ci 148662306a36Sopenharmony_ci if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) 148762306a36Sopenharmony_ci return -ESHUTDOWN; 148862306a36Sopenharmony_ci 148962306a36Sopenharmony_ci /* Make sure we are clear for enabling */ 149062306a36Sopenharmony_ci epctrl = gr_read32(&ep->regs->epctrl); 149162306a36Sopenharmony_ci if (epctrl & GR_EPCTRL_EV) 149262306a36Sopenharmony_ci return -EBUSY; 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ci /* Check that directions match */ 149562306a36Sopenharmony_ci if (!ep->is_in != !usb_endpoint_dir_in(desc)) 149662306a36Sopenharmony_ci return -EINVAL; 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_ci /* Check ep num */ 149962306a36Sopenharmony_ci if ((!ep->is_in && ep->num >= dev->nepo) || 150062306a36Sopenharmony_ci (ep->is_in && ep->num >= dev->nepi)) 150162306a36Sopenharmony_ci return -EINVAL; 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci if (usb_endpoint_xfer_control(desc)) { 150462306a36Sopenharmony_ci mode = 0; 150562306a36Sopenharmony_ci } else if (usb_endpoint_xfer_isoc(desc)) { 150662306a36Sopenharmony_ci mode = 1; 150762306a36Sopenharmony_ci } else if (usb_endpoint_xfer_bulk(desc)) { 150862306a36Sopenharmony_ci mode = 2; 150962306a36Sopenharmony_ci } else if (usb_endpoint_xfer_int(desc)) { 151062306a36Sopenharmony_ci mode = 3; 151162306a36Sopenharmony_ci } else { 151262306a36Sopenharmony_ci dev_err(dev->dev, "Unknown transfer type for %s\n", 151362306a36Sopenharmony_ci ep->ep.name); 151462306a36Sopenharmony_ci return -EINVAL; 151562306a36Sopenharmony_ci } 151662306a36Sopenharmony_ci 151762306a36Sopenharmony_ci /* 151862306a36Sopenharmony_ci * Bits 10-0 set the max payload. 12-11 set the number of 151962306a36Sopenharmony_ci * additional transactions. 152062306a36Sopenharmony_ci */ 152162306a36Sopenharmony_ci max = usb_endpoint_maxp(desc); 152262306a36Sopenharmony_ci nt = usb_endpoint_maxp_mult(desc) - 1; 152362306a36Sopenharmony_ci buffer_size = GR_BUFFER_SIZE(epctrl); 152462306a36Sopenharmony_ci if (nt && (mode == 0 || mode == 2)) { 152562306a36Sopenharmony_ci dev_err(dev->dev, 152662306a36Sopenharmony_ci "%s mode: multiple trans./microframe not valid\n", 152762306a36Sopenharmony_ci (mode == 2 ? "Bulk" : "Control")); 152862306a36Sopenharmony_ci return -EINVAL; 152962306a36Sopenharmony_ci } else if (nt == 0x3) { 153062306a36Sopenharmony_ci dev_err(dev->dev, 153162306a36Sopenharmony_ci "Invalid value 0x3 for additional trans./microframe\n"); 153262306a36Sopenharmony_ci return -EINVAL; 153362306a36Sopenharmony_ci } else if ((nt + 1) * max > buffer_size) { 153462306a36Sopenharmony_ci dev_err(dev->dev, "Hw buffer size %d < max payload %d * %d\n", 153562306a36Sopenharmony_ci buffer_size, (nt + 1), max); 153662306a36Sopenharmony_ci return -EINVAL; 153762306a36Sopenharmony_ci } else if (max == 0) { 153862306a36Sopenharmony_ci dev_err(dev->dev, "Max payload cannot be set to 0\n"); 153962306a36Sopenharmony_ci return -EINVAL; 154062306a36Sopenharmony_ci } else if (max > ep->ep.maxpacket_limit) { 154162306a36Sopenharmony_ci dev_err(dev->dev, "Requested max payload %d > limit %d\n", 154262306a36Sopenharmony_ci max, ep->ep.maxpacket_limit); 154362306a36Sopenharmony_ci return -EINVAL; 154462306a36Sopenharmony_ci } 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci spin_lock(&ep->dev->lock); 154762306a36Sopenharmony_ci 154862306a36Sopenharmony_ci if (!ep->stopped) { 154962306a36Sopenharmony_ci spin_unlock(&ep->dev->lock); 155062306a36Sopenharmony_ci return -EBUSY; 155162306a36Sopenharmony_ci } 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_ci ep->stopped = 0; 155462306a36Sopenharmony_ci ep->wedged = 0; 155562306a36Sopenharmony_ci ep->ep.desc = desc; 155662306a36Sopenharmony_ci ep->ep.maxpacket = max; 155762306a36Sopenharmony_ci ep->dma_start = 0; 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci if (nt) { 156162306a36Sopenharmony_ci /* 156262306a36Sopenharmony_ci * Maximum possible size of all payloads in one microframe 156362306a36Sopenharmony_ci * regardless of direction when using high-bandwidth mode. 156462306a36Sopenharmony_ci */ 156562306a36Sopenharmony_ci ep->bytes_per_buffer = (nt + 1) * max; 156662306a36Sopenharmony_ci } else if (ep->is_in) { 156762306a36Sopenharmony_ci /* 156862306a36Sopenharmony_ci * The biggest multiple of maximum packet size that fits into 156962306a36Sopenharmony_ci * the buffer. The hardware will split up into many packets in 157062306a36Sopenharmony_ci * the IN direction. 157162306a36Sopenharmony_ci */ 157262306a36Sopenharmony_ci ep->bytes_per_buffer = (buffer_size / max) * max; 157362306a36Sopenharmony_ci } else { 157462306a36Sopenharmony_ci /* 157562306a36Sopenharmony_ci * Only single packets will be placed the buffers in the OUT 157662306a36Sopenharmony_ci * direction. 157762306a36Sopenharmony_ci */ 157862306a36Sopenharmony_ci ep->bytes_per_buffer = max; 157962306a36Sopenharmony_ci } 158062306a36Sopenharmony_ci 158162306a36Sopenharmony_ci epctrl = (max << GR_EPCTRL_MAXPL_POS) 158262306a36Sopenharmony_ci | (nt << GR_EPCTRL_NT_POS) 158362306a36Sopenharmony_ci | (mode << GR_EPCTRL_TT_POS) 158462306a36Sopenharmony_ci | GR_EPCTRL_EV; 158562306a36Sopenharmony_ci if (ep->is_in) 158662306a36Sopenharmony_ci epctrl |= GR_EPCTRL_PI; 158762306a36Sopenharmony_ci gr_write32(&ep->regs->epctrl, epctrl); 158862306a36Sopenharmony_ci 158962306a36Sopenharmony_ci gr_write32(&ep->regs->dmactrl, GR_DMACTRL_IE | GR_DMACTRL_AI); 159062306a36Sopenharmony_ci 159162306a36Sopenharmony_ci spin_unlock(&ep->dev->lock); 159262306a36Sopenharmony_ci 159362306a36Sopenharmony_ci dev_dbg(ep->dev->dev, "EP: %s enabled - %s with %d bytes/buffer\n", 159462306a36Sopenharmony_ci ep->ep.name, gr_modestring[mode], ep->bytes_per_buffer); 159562306a36Sopenharmony_ci return 0; 159662306a36Sopenharmony_ci} 159762306a36Sopenharmony_ci 159862306a36Sopenharmony_ci/* Disable endpoint. Not for ep0in and ep0out that are handled separately. */ 159962306a36Sopenharmony_cistatic int gr_ep_disable(struct usb_ep *_ep) 160062306a36Sopenharmony_ci{ 160162306a36Sopenharmony_ci struct gr_ep *ep; 160262306a36Sopenharmony_ci struct gr_udc *dev; 160362306a36Sopenharmony_ci unsigned long flags; 160462306a36Sopenharmony_ci 160562306a36Sopenharmony_ci ep = container_of(_ep, struct gr_ep, ep); 160662306a36Sopenharmony_ci if (!_ep || !ep->ep.desc) 160762306a36Sopenharmony_ci return -ENODEV; 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_ci dev = ep->dev; 161062306a36Sopenharmony_ci 161162306a36Sopenharmony_ci /* 'ep0' IN and OUT are reserved */ 161262306a36Sopenharmony_ci if (ep == &dev->epo[0] || ep == &dev->epi[0]) 161362306a36Sopenharmony_ci return -EINVAL; 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ci if (dev->ep0state == GR_EP0_SUSPEND) 161662306a36Sopenharmony_ci return -EBUSY; 161762306a36Sopenharmony_ci 161862306a36Sopenharmony_ci dev_dbg(ep->dev->dev, "EP: disable %s\n", ep->ep.name); 161962306a36Sopenharmony_ci 162062306a36Sopenharmony_ci spin_lock_irqsave(&dev->lock, flags); 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_ci gr_ep_nuke(ep); 162362306a36Sopenharmony_ci gr_ep_reset(ep); 162462306a36Sopenharmony_ci ep->ep.desc = NULL; 162562306a36Sopenharmony_ci 162662306a36Sopenharmony_ci spin_unlock_irqrestore(&dev->lock, flags); 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci return 0; 162962306a36Sopenharmony_ci} 163062306a36Sopenharmony_ci 163162306a36Sopenharmony_ci/* 163262306a36Sopenharmony_ci * Frees a request, but not any DMA buffers associated with it 163362306a36Sopenharmony_ci * (gr_finish_request should already have taken care of that). 163462306a36Sopenharmony_ci */ 163562306a36Sopenharmony_cistatic void gr_free_request(struct usb_ep *_ep, struct usb_request *_req) 163662306a36Sopenharmony_ci{ 163762306a36Sopenharmony_ci struct gr_request *req; 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_ci if (!_ep || !_req) 164062306a36Sopenharmony_ci return; 164162306a36Sopenharmony_ci req = container_of(_req, struct gr_request, req); 164262306a36Sopenharmony_ci 164362306a36Sopenharmony_ci /* Leads to memory leak */ 164462306a36Sopenharmony_ci WARN(!list_empty(&req->queue), 164562306a36Sopenharmony_ci "request not dequeued properly before freeing\n"); 164662306a36Sopenharmony_ci 164762306a36Sopenharmony_ci kfree(req); 164862306a36Sopenharmony_ci} 164962306a36Sopenharmony_ci 165062306a36Sopenharmony_ci/* Queue a request from the gadget */ 165162306a36Sopenharmony_cistatic int gr_queue_ext(struct usb_ep *_ep, struct usb_request *_req, 165262306a36Sopenharmony_ci gfp_t gfp_flags) 165362306a36Sopenharmony_ci{ 165462306a36Sopenharmony_ci struct gr_ep *ep; 165562306a36Sopenharmony_ci struct gr_request *req; 165662306a36Sopenharmony_ci struct gr_udc *dev; 165762306a36Sopenharmony_ci int ret; 165862306a36Sopenharmony_ci 165962306a36Sopenharmony_ci if (unlikely(!_ep || !_req)) 166062306a36Sopenharmony_ci return -EINVAL; 166162306a36Sopenharmony_ci 166262306a36Sopenharmony_ci ep = container_of(_ep, struct gr_ep, ep); 166362306a36Sopenharmony_ci req = container_of(_req, struct gr_request, req); 166462306a36Sopenharmony_ci dev = ep->dev; 166562306a36Sopenharmony_ci 166662306a36Sopenharmony_ci spin_lock(&ep->dev->lock); 166762306a36Sopenharmony_ci 166862306a36Sopenharmony_ci /* 166962306a36Sopenharmony_ci * The ep0 pointer in the gadget struct is used both for ep0in and 167062306a36Sopenharmony_ci * ep0out. In a data stage in the out direction ep0out needs to be used 167162306a36Sopenharmony_ci * instead of the default ep0in. Completion functions might use 167262306a36Sopenharmony_ci * driver_data, so that needs to be copied as well. 167362306a36Sopenharmony_ci */ 167462306a36Sopenharmony_ci if ((ep == &dev->epi[0]) && (dev->ep0state == GR_EP0_ODATA)) { 167562306a36Sopenharmony_ci ep = &dev->epo[0]; 167662306a36Sopenharmony_ci ep->ep.driver_data = dev->epi[0].ep.driver_data; 167762306a36Sopenharmony_ci } 167862306a36Sopenharmony_ci 167962306a36Sopenharmony_ci if (ep->is_in) 168062306a36Sopenharmony_ci gr_dbgprint_request("EXTERN", ep, req); 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_ci ret = gr_queue(ep, req, GFP_ATOMIC); 168362306a36Sopenharmony_ci 168462306a36Sopenharmony_ci spin_unlock(&ep->dev->lock); 168562306a36Sopenharmony_ci 168662306a36Sopenharmony_ci return ret; 168762306a36Sopenharmony_ci} 168862306a36Sopenharmony_ci 168962306a36Sopenharmony_ci/* Dequeue JUST ONE request */ 169062306a36Sopenharmony_cistatic int gr_dequeue(struct usb_ep *_ep, struct usb_request *_req) 169162306a36Sopenharmony_ci{ 169262306a36Sopenharmony_ci struct gr_request *req = NULL, *iter; 169362306a36Sopenharmony_ci struct gr_ep *ep; 169462306a36Sopenharmony_ci struct gr_udc *dev; 169562306a36Sopenharmony_ci int ret = 0; 169662306a36Sopenharmony_ci unsigned long flags; 169762306a36Sopenharmony_ci 169862306a36Sopenharmony_ci ep = container_of(_ep, struct gr_ep, ep); 169962306a36Sopenharmony_ci if (!_ep || !_req || (!ep->ep.desc && ep->num != 0)) 170062306a36Sopenharmony_ci return -EINVAL; 170162306a36Sopenharmony_ci dev = ep->dev; 170262306a36Sopenharmony_ci if (!dev->driver) 170362306a36Sopenharmony_ci return -ESHUTDOWN; 170462306a36Sopenharmony_ci 170562306a36Sopenharmony_ci /* We can't touch (DMA) registers when suspended */ 170662306a36Sopenharmony_ci if (dev->ep0state == GR_EP0_SUSPEND) 170762306a36Sopenharmony_ci return -EBUSY; 170862306a36Sopenharmony_ci 170962306a36Sopenharmony_ci spin_lock_irqsave(&dev->lock, flags); 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_ci /* Make sure it's actually queued on this endpoint */ 171262306a36Sopenharmony_ci list_for_each_entry(iter, &ep->queue, queue) { 171362306a36Sopenharmony_ci if (&iter->req != _req) 171462306a36Sopenharmony_ci continue; 171562306a36Sopenharmony_ci req = iter; 171662306a36Sopenharmony_ci break; 171762306a36Sopenharmony_ci } 171862306a36Sopenharmony_ci if (!req) { 171962306a36Sopenharmony_ci ret = -EINVAL; 172062306a36Sopenharmony_ci goto out; 172162306a36Sopenharmony_ci } 172262306a36Sopenharmony_ci 172362306a36Sopenharmony_ci if (list_first_entry(&ep->queue, struct gr_request, queue) == req) { 172462306a36Sopenharmony_ci /* This request is currently being processed */ 172562306a36Sopenharmony_ci gr_abort_dma(ep); 172662306a36Sopenharmony_ci if (ep->stopped) 172762306a36Sopenharmony_ci gr_finish_request(ep, req, -ECONNRESET); 172862306a36Sopenharmony_ci else 172962306a36Sopenharmony_ci gr_dma_advance(ep, -ECONNRESET); 173062306a36Sopenharmony_ci } else if (!list_empty(&req->queue)) { 173162306a36Sopenharmony_ci /* Not being processed - gr_finish_request dequeues it */ 173262306a36Sopenharmony_ci gr_finish_request(ep, req, -ECONNRESET); 173362306a36Sopenharmony_ci } else { 173462306a36Sopenharmony_ci ret = -EOPNOTSUPP; 173562306a36Sopenharmony_ci } 173662306a36Sopenharmony_ci 173762306a36Sopenharmony_ciout: 173862306a36Sopenharmony_ci spin_unlock_irqrestore(&dev->lock, flags); 173962306a36Sopenharmony_ci 174062306a36Sopenharmony_ci return ret; 174162306a36Sopenharmony_ci} 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci/* Helper for gr_set_halt and gr_set_wedge */ 174462306a36Sopenharmony_cistatic int gr_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge) 174562306a36Sopenharmony_ci{ 174662306a36Sopenharmony_ci int ret; 174762306a36Sopenharmony_ci struct gr_ep *ep; 174862306a36Sopenharmony_ci 174962306a36Sopenharmony_ci if (!_ep) 175062306a36Sopenharmony_ci return -ENODEV; 175162306a36Sopenharmony_ci ep = container_of(_ep, struct gr_ep, ep); 175262306a36Sopenharmony_ci 175362306a36Sopenharmony_ci spin_lock(&ep->dev->lock); 175462306a36Sopenharmony_ci 175562306a36Sopenharmony_ci /* Halting an IN endpoint should fail if queue is not empty */ 175662306a36Sopenharmony_ci if (halt && ep->is_in && !list_empty(&ep->queue)) { 175762306a36Sopenharmony_ci ret = -EAGAIN; 175862306a36Sopenharmony_ci goto out; 175962306a36Sopenharmony_ci } 176062306a36Sopenharmony_ci 176162306a36Sopenharmony_ci ret = gr_ep_halt_wedge(ep, halt, wedge, 0); 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_ciout: 176462306a36Sopenharmony_ci spin_unlock(&ep->dev->lock); 176562306a36Sopenharmony_ci 176662306a36Sopenharmony_ci return ret; 176762306a36Sopenharmony_ci} 176862306a36Sopenharmony_ci 176962306a36Sopenharmony_ci/* Halt endpoint */ 177062306a36Sopenharmony_cistatic int gr_set_halt(struct usb_ep *_ep, int halt) 177162306a36Sopenharmony_ci{ 177262306a36Sopenharmony_ci return gr_set_halt_wedge(_ep, halt, 0); 177362306a36Sopenharmony_ci} 177462306a36Sopenharmony_ci 177562306a36Sopenharmony_ci/* Halt and wedge endpoint */ 177662306a36Sopenharmony_cistatic int gr_set_wedge(struct usb_ep *_ep) 177762306a36Sopenharmony_ci{ 177862306a36Sopenharmony_ci return gr_set_halt_wedge(_ep, 1, 1); 177962306a36Sopenharmony_ci} 178062306a36Sopenharmony_ci 178162306a36Sopenharmony_ci/* 178262306a36Sopenharmony_ci * Return the total number of bytes currently stored in the internal buffers of 178362306a36Sopenharmony_ci * the endpoint. 178462306a36Sopenharmony_ci */ 178562306a36Sopenharmony_cistatic int gr_fifo_status(struct usb_ep *_ep) 178662306a36Sopenharmony_ci{ 178762306a36Sopenharmony_ci struct gr_ep *ep; 178862306a36Sopenharmony_ci u32 epstat; 178962306a36Sopenharmony_ci u32 bytes = 0; 179062306a36Sopenharmony_ci 179162306a36Sopenharmony_ci if (!_ep) 179262306a36Sopenharmony_ci return -ENODEV; 179362306a36Sopenharmony_ci ep = container_of(_ep, struct gr_ep, ep); 179462306a36Sopenharmony_ci 179562306a36Sopenharmony_ci epstat = gr_read32(&ep->regs->epstat); 179662306a36Sopenharmony_ci 179762306a36Sopenharmony_ci if (epstat & GR_EPSTAT_B0) 179862306a36Sopenharmony_ci bytes += (epstat & GR_EPSTAT_B0CNT_MASK) >> GR_EPSTAT_B0CNT_POS; 179962306a36Sopenharmony_ci if (epstat & GR_EPSTAT_B1) 180062306a36Sopenharmony_ci bytes += (epstat & GR_EPSTAT_B1CNT_MASK) >> GR_EPSTAT_B1CNT_POS; 180162306a36Sopenharmony_ci 180262306a36Sopenharmony_ci return bytes; 180362306a36Sopenharmony_ci} 180462306a36Sopenharmony_ci 180562306a36Sopenharmony_ci 180662306a36Sopenharmony_ci/* Empty data from internal buffers of an endpoint. */ 180762306a36Sopenharmony_cistatic void gr_fifo_flush(struct usb_ep *_ep) 180862306a36Sopenharmony_ci{ 180962306a36Sopenharmony_ci struct gr_ep *ep; 181062306a36Sopenharmony_ci u32 epctrl; 181162306a36Sopenharmony_ci 181262306a36Sopenharmony_ci if (!_ep) 181362306a36Sopenharmony_ci return; 181462306a36Sopenharmony_ci ep = container_of(_ep, struct gr_ep, ep); 181562306a36Sopenharmony_ci dev_vdbg(ep->dev->dev, "EP: flush fifo %s\n", ep->ep.name); 181662306a36Sopenharmony_ci 181762306a36Sopenharmony_ci spin_lock(&ep->dev->lock); 181862306a36Sopenharmony_ci 181962306a36Sopenharmony_ci epctrl = gr_read32(&ep->regs->epctrl); 182062306a36Sopenharmony_ci epctrl |= GR_EPCTRL_CB; 182162306a36Sopenharmony_ci gr_write32(&ep->regs->epctrl, epctrl); 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci spin_unlock(&ep->dev->lock); 182462306a36Sopenharmony_ci} 182562306a36Sopenharmony_ci 182662306a36Sopenharmony_cistatic const struct usb_ep_ops gr_ep_ops = { 182762306a36Sopenharmony_ci .enable = gr_ep_enable, 182862306a36Sopenharmony_ci .disable = gr_ep_disable, 182962306a36Sopenharmony_ci 183062306a36Sopenharmony_ci .alloc_request = gr_alloc_request, 183162306a36Sopenharmony_ci .free_request = gr_free_request, 183262306a36Sopenharmony_ci 183362306a36Sopenharmony_ci .queue = gr_queue_ext, 183462306a36Sopenharmony_ci .dequeue = gr_dequeue, 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ci .set_halt = gr_set_halt, 183762306a36Sopenharmony_ci .set_wedge = gr_set_wedge, 183862306a36Sopenharmony_ci .fifo_status = gr_fifo_status, 183962306a36Sopenharmony_ci .fifo_flush = gr_fifo_flush, 184062306a36Sopenharmony_ci}; 184162306a36Sopenharmony_ci 184262306a36Sopenharmony_ci/* ---------------------------------------------------------------------- */ 184362306a36Sopenharmony_ci/* USB Gadget ops */ 184462306a36Sopenharmony_ci 184562306a36Sopenharmony_cistatic int gr_get_frame(struct usb_gadget *_gadget) 184662306a36Sopenharmony_ci{ 184762306a36Sopenharmony_ci struct gr_udc *dev; 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ci if (!_gadget) 185062306a36Sopenharmony_ci return -ENODEV; 185162306a36Sopenharmony_ci dev = container_of(_gadget, struct gr_udc, gadget); 185262306a36Sopenharmony_ci return gr_read32(&dev->regs->status) & GR_STATUS_FN_MASK; 185362306a36Sopenharmony_ci} 185462306a36Sopenharmony_ci 185562306a36Sopenharmony_cistatic int gr_wakeup(struct usb_gadget *_gadget) 185662306a36Sopenharmony_ci{ 185762306a36Sopenharmony_ci struct gr_udc *dev; 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_ci if (!_gadget) 186062306a36Sopenharmony_ci return -ENODEV; 186162306a36Sopenharmony_ci dev = container_of(_gadget, struct gr_udc, gadget); 186262306a36Sopenharmony_ci 186362306a36Sopenharmony_ci /* Remote wakeup feature not enabled by host*/ 186462306a36Sopenharmony_ci if (!dev->remote_wakeup) 186562306a36Sopenharmony_ci return -EINVAL; 186662306a36Sopenharmony_ci 186762306a36Sopenharmony_ci spin_lock(&dev->lock); 186862306a36Sopenharmony_ci 186962306a36Sopenharmony_ci gr_write32(&dev->regs->control, 187062306a36Sopenharmony_ci gr_read32(&dev->regs->control) | GR_CONTROL_RW); 187162306a36Sopenharmony_ci 187262306a36Sopenharmony_ci spin_unlock(&dev->lock); 187362306a36Sopenharmony_ci 187462306a36Sopenharmony_ci return 0; 187562306a36Sopenharmony_ci} 187662306a36Sopenharmony_ci 187762306a36Sopenharmony_cistatic int gr_pullup(struct usb_gadget *_gadget, int is_on) 187862306a36Sopenharmony_ci{ 187962306a36Sopenharmony_ci struct gr_udc *dev; 188062306a36Sopenharmony_ci u32 control; 188162306a36Sopenharmony_ci 188262306a36Sopenharmony_ci if (!_gadget) 188362306a36Sopenharmony_ci return -ENODEV; 188462306a36Sopenharmony_ci dev = container_of(_gadget, struct gr_udc, gadget); 188562306a36Sopenharmony_ci 188662306a36Sopenharmony_ci spin_lock(&dev->lock); 188762306a36Sopenharmony_ci 188862306a36Sopenharmony_ci control = gr_read32(&dev->regs->control); 188962306a36Sopenharmony_ci if (is_on) 189062306a36Sopenharmony_ci control |= GR_CONTROL_EP; 189162306a36Sopenharmony_ci else 189262306a36Sopenharmony_ci control &= ~GR_CONTROL_EP; 189362306a36Sopenharmony_ci gr_write32(&dev->regs->control, control); 189462306a36Sopenharmony_ci 189562306a36Sopenharmony_ci spin_unlock(&dev->lock); 189662306a36Sopenharmony_ci 189762306a36Sopenharmony_ci return 0; 189862306a36Sopenharmony_ci} 189962306a36Sopenharmony_ci 190062306a36Sopenharmony_cistatic int gr_udc_start(struct usb_gadget *gadget, 190162306a36Sopenharmony_ci struct usb_gadget_driver *driver) 190262306a36Sopenharmony_ci{ 190362306a36Sopenharmony_ci struct gr_udc *dev = to_gr_udc(gadget); 190462306a36Sopenharmony_ci 190562306a36Sopenharmony_ci spin_lock(&dev->lock); 190662306a36Sopenharmony_ci 190762306a36Sopenharmony_ci /* Hook up the driver */ 190862306a36Sopenharmony_ci dev->driver = driver; 190962306a36Sopenharmony_ci 191062306a36Sopenharmony_ci /* Get ready for host detection */ 191162306a36Sopenharmony_ci gr_enable_vbus_detect(dev); 191262306a36Sopenharmony_ci 191362306a36Sopenharmony_ci spin_unlock(&dev->lock); 191462306a36Sopenharmony_ci 191562306a36Sopenharmony_ci return 0; 191662306a36Sopenharmony_ci} 191762306a36Sopenharmony_ci 191862306a36Sopenharmony_cistatic int gr_udc_stop(struct usb_gadget *gadget) 191962306a36Sopenharmony_ci{ 192062306a36Sopenharmony_ci struct gr_udc *dev = to_gr_udc(gadget); 192162306a36Sopenharmony_ci unsigned long flags; 192262306a36Sopenharmony_ci 192362306a36Sopenharmony_ci spin_lock_irqsave(&dev->lock, flags); 192462306a36Sopenharmony_ci 192562306a36Sopenharmony_ci dev->driver = NULL; 192662306a36Sopenharmony_ci gr_stop_activity(dev); 192762306a36Sopenharmony_ci 192862306a36Sopenharmony_ci spin_unlock_irqrestore(&dev->lock, flags); 192962306a36Sopenharmony_ci 193062306a36Sopenharmony_ci return 0; 193162306a36Sopenharmony_ci} 193262306a36Sopenharmony_ci 193362306a36Sopenharmony_cistatic const struct usb_gadget_ops gr_ops = { 193462306a36Sopenharmony_ci .get_frame = gr_get_frame, 193562306a36Sopenharmony_ci .wakeup = gr_wakeup, 193662306a36Sopenharmony_ci .pullup = gr_pullup, 193762306a36Sopenharmony_ci .udc_start = gr_udc_start, 193862306a36Sopenharmony_ci .udc_stop = gr_udc_stop, 193962306a36Sopenharmony_ci /* Other operations not supported */ 194062306a36Sopenharmony_ci}; 194162306a36Sopenharmony_ci 194262306a36Sopenharmony_ci/* ---------------------------------------------------------------------- */ 194362306a36Sopenharmony_ci/* Module probe, removal and of-matching */ 194462306a36Sopenharmony_ci 194562306a36Sopenharmony_cistatic const char * const onames[] = { 194662306a36Sopenharmony_ci "ep0out", "ep1out", "ep2out", "ep3out", "ep4out", "ep5out", 194762306a36Sopenharmony_ci "ep6out", "ep7out", "ep8out", "ep9out", "ep10out", "ep11out", 194862306a36Sopenharmony_ci "ep12out", "ep13out", "ep14out", "ep15out" 194962306a36Sopenharmony_ci}; 195062306a36Sopenharmony_ci 195162306a36Sopenharmony_cistatic const char * const inames[] = { 195262306a36Sopenharmony_ci "ep0in", "ep1in", "ep2in", "ep3in", "ep4in", "ep5in", 195362306a36Sopenharmony_ci "ep6in", "ep7in", "ep8in", "ep9in", "ep10in", "ep11in", 195462306a36Sopenharmony_ci "ep12in", "ep13in", "ep14in", "ep15in" 195562306a36Sopenharmony_ci}; 195662306a36Sopenharmony_ci 195762306a36Sopenharmony_ci/* Must be called with dev->lock held */ 195862306a36Sopenharmony_cistatic int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit) 195962306a36Sopenharmony_ci{ 196062306a36Sopenharmony_ci struct gr_ep *ep; 196162306a36Sopenharmony_ci struct gr_request *req; 196262306a36Sopenharmony_ci struct usb_request *_req; 196362306a36Sopenharmony_ci void *buf; 196462306a36Sopenharmony_ci 196562306a36Sopenharmony_ci if (is_in) { 196662306a36Sopenharmony_ci ep = &dev->epi[num]; 196762306a36Sopenharmony_ci ep->ep.name = inames[num]; 196862306a36Sopenharmony_ci ep->regs = &dev->regs->epi[num]; 196962306a36Sopenharmony_ci } else { 197062306a36Sopenharmony_ci ep = &dev->epo[num]; 197162306a36Sopenharmony_ci ep->ep.name = onames[num]; 197262306a36Sopenharmony_ci ep->regs = &dev->regs->epo[num]; 197362306a36Sopenharmony_ci } 197462306a36Sopenharmony_ci 197562306a36Sopenharmony_ci gr_ep_reset(ep); 197662306a36Sopenharmony_ci ep->num = num; 197762306a36Sopenharmony_ci ep->is_in = is_in; 197862306a36Sopenharmony_ci ep->dev = dev; 197962306a36Sopenharmony_ci ep->ep.ops = &gr_ep_ops; 198062306a36Sopenharmony_ci INIT_LIST_HEAD(&ep->queue); 198162306a36Sopenharmony_ci 198262306a36Sopenharmony_ci if (num == 0) { 198362306a36Sopenharmony_ci _req = gr_alloc_request(&ep->ep, GFP_ATOMIC); 198462306a36Sopenharmony_ci if (!_req) 198562306a36Sopenharmony_ci return -ENOMEM; 198662306a36Sopenharmony_ci 198762306a36Sopenharmony_ci buf = devm_kzalloc(dev->dev, PAGE_SIZE, GFP_DMA | GFP_ATOMIC); 198862306a36Sopenharmony_ci if (!buf) { 198962306a36Sopenharmony_ci gr_free_request(&ep->ep, _req); 199062306a36Sopenharmony_ci return -ENOMEM; 199162306a36Sopenharmony_ci } 199262306a36Sopenharmony_ci 199362306a36Sopenharmony_ci req = container_of(_req, struct gr_request, req); 199462306a36Sopenharmony_ci req->req.buf = buf; 199562306a36Sopenharmony_ci req->req.length = MAX_CTRL_PL_SIZE; 199662306a36Sopenharmony_ci 199762306a36Sopenharmony_ci if (is_in) 199862306a36Sopenharmony_ci dev->ep0reqi = req; /* Complete gets set as used */ 199962306a36Sopenharmony_ci else 200062306a36Sopenharmony_ci dev->ep0reqo = req; /* Completion treated separately */ 200162306a36Sopenharmony_ci 200262306a36Sopenharmony_ci usb_ep_set_maxpacket_limit(&ep->ep, MAX_CTRL_PL_SIZE); 200362306a36Sopenharmony_ci ep->bytes_per_buffer = MAX_CTRL_PL_SIZE; 200462306a36Sopenharmony_ci 200562306a36Sopenharmony_ci ep->ep.caps.type_control = true; 200662306a36Sopenharmony_ci } else { 200762306a36Sopenharmony_ci usb_ep_set_maxpacket_limit(&ep->ep, (u16)maxplimit); 200862306a36Sopenharmony_ci list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list); 200962306a36Sopenharmony_ci 201062306a36Sopenharmony_ci ep->ep.caps.type_iso = true; 201162306a36Sopenharmony_ci ep->ep.caps.type_bulk = true; 201262306a36Sopenharmony_ci ep->ep.caps.type_int = true; 201362306a36Sopenharmony_ci } 201462306a36Sopenharmony_ci list_add_tail(&ep->ep_list, &dev->ep_list); 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_ci if (is_in) 201762306a36Sopenharmony_ci ep->ep.caps.dir_in = true; 201862306a36Sopenharmony_ci else 201962306a36Sopenharmony_ci ep->ep.caps.dir_out = true; 202062306a36Sopenharmony_ci 202162306a36Sopenharmony_ci ep->tailbuf = dma_alloc_coherent(dev->dev, ep->ep.maxpacket_limit, 202262306a36Sopenharmony_ci &ep->tailbuf_paddr, GFP_ATOMIC); 202362306a36Sopenharmony_ci if (!ep->tailbuf) 202462306a36Sopenharmony_ci return -ENOMEM; 202562306a36Sopenharmony_ci 202662306a36Sopenharmony_ci return 0; 202762306a36Sopenharmony_ci} 202862306a36Sopenharmony_ci 202962306a36Sopenharmony_ci/* Must be called with dev->lock held */ 203062306a36Sopenharmony_cistatic int gr_udc_init(struct gr_udc *dev) 203162306a36Sopenharmony_ci{ 203262306a36Sopenharmony_ci struct device_node *np = dev->dev->of_node; 203362306a36Sopenharmony_ci u32 epctrl_val; 203462306a36Sopenharmony_ci u32 dmactrl_val; 203562306a36Sopenharmony_ci int i; 203662306a36Sopenharmony_ci int ret = 0; 203762306a36Sopenharmony_ci u32 bufsize; 203862306a36Sopenharmony_ci 203962306a36Sopenharmony_ci gr_set_address(dev, 0); 204062306a36Sopenharmony_ci 204162306a36Sopenharmony_ci INIT_LIST_HEAD(&dev->gadget.ep_list); 204262306a36Sopenharmony_ci dev->gadget.speed = USB_SPEED_UNKNOWN; 204362306a36Sopenharmony_ci dev->gadget.ep0 = &dev->epi[0].ep; 204462306a36Sopenharmony_ci 204562306a36Sopenharmony_ci INIT_LIST_HEAD(&dev->ep_list); 204662306a36Sopenharmony_ci gr_set_ep0state(dev, GR_EP0_DISCONNECT); 204762306a36Sopenharmony_ci 204862306a36Sopenharmony_ci for (i = 0; i < dev->nepo; i++) { 204962306a36Sopenharmony_ci if (of_property_read_u32_index(np, "epobufsizes", i, &bufsize)) 205062306a36Sopenharmony_ci bufsize = 1024; 205162306a36Sopenharmony_ci ret = gr_ep_init(dev, i, 0, bufsize); 205262306a36Sopenharmony_ci if (ret) 205362306a36Sopenharmony_ci return ret; 205462306a36Sopenharmony_ci } 205562306a36Sopenharmony_ci 205662306a36Sopenharmony_ci for (i = 0; i < dev->nepi; i++) { 205762306a36Sopenharmony_ci if (of_property_read_u32_index(np, "epibufsizes", i, &bufsize)) 205862306a36Sopenharmony_ci bufsize = 1024; 205962306a36Sopenharmony_ci ret = gr_ep_init(dev, i, 1, bufsize); 206062306a36Sopenharmony_ci if (ret) 206162306a36Sopenharmony_ci return ret; 206262306a36Sopenharmony_ci } 206362306a36Sopenharmony_ci 206462306a36Sopenharmony_ci /* Must be disabled by default */ 206562306a36Sopenharmony_ci dev->remote_wakeup = 0; 206662306a36Sopenharmony_ci 206762306a36Sopenharmony_ci /* Enable ep0out and ep0in */ 206862306a36Sopenharmony_ci epctrl_val = (MAX_CTRL_PL_SIZE << GR_EPCTRL_MAXPL_POS) | GR_EPCTRL_EV; 206962306a36Sopenharmony_ci dmactrl_val = GR_DMACTRL_IE | GR_DMACTRL_AI; 207062306a36Sopenharmony_ci gr_write32(&dev->epo[0].regs->epctrl, epctrl_val); 207162306a36Sopenharmony_ci gr_write32(&dev->epi[0].regs->epctrl, epctrl_val | GR_EPCTRL_PI); 207262306a36Sopenharmony_ci gr_write32(&dev->epo[0].regs->dmactrl, dmactrl_val); 207362306a36Sopenharmony_ci gr_write32(&dev->epi[0].regs->dmactrl, dmactrl_val); 207462306a36Sopenharmony_ci 207562306a36Sopenharmony_ci return 0; 207662306a36Sopenharmony_ci} 207762306a36Sopenharmony_ci 207862306a36Sopenharmony_cistatic void gr_ep_remove(struct gr_udc *dev, int num, int is_in) 207962306a36Sopenharmony_ci{ 208062306a36Sopenharmony_ci struct gr_ep *ep; 208162306a36Sopenharmony_ci 208262306a36Sopenharmony_ci if (is_in) 208362306a36Sopenharmony_ci ep = &dev->epi[num]; 208462306a36Sopenharmony_ci else 208562306a36Sopenharmony_ci ep = &dev->epo[num]; 208662306a36Sopenharmony_ci 208762306a36Sopenharmony_ci if (ep->tailbuf) 208862306a36Sopenharmony_ci dma_free_coherent(dev->dev, ep->ep.maxpacket_limit, 208962306a36Sopenharmony_ci ep->tailbuf, ep->tailbuf_paddr); 209062306a36Sopenharmony_ci} 209162306a36Sopenharmony_ci 209262306a36Sopenharmony_cistatic int gr_remove(struct platform_device *pdev) 209362306a36Sopenharmony_ci{ 209462306a36Sopenharmony_ci struct gr_udc *dev = platform_get_drvdata(pdev); 209562306a36Sopenharmony_ci int i; 209662306a36Sopenharmony_ci 209762306a36Sopenharmony_ci if (dev->added) 209862306a36Sopenharmony_ci usb_del_gadget_udc(&dev->gadget); /* Shuts everything down */ 209962306a36Sopenharmony_ci if (dev->driver) 210062306a36Sopenharmony_ci return -EBUSY; 210162306a36Sopenharmony_ci 210262306a36Sopenharmony_ci gr_dfs_delete(dev); 210362306a36Sopenharmony_ci dma_pool_destroy(dev->desc_pool); 210462306a36Sopenharmony_ci platform_set_drvdata(pdev, NULL); 210562306a36Sopenharmony_ci 210662306a36Sopenharmony_ci gr_free_request(&dev->epi[0].ep, &dev->ep0reqi->req); 210762306a36Sopenharmony_ci gr_free_request(&dev->epo[0].ep, &dev->ep0reqo->req); 210862306a36Sopenharmony_ci 210962306a36Sopenharmony_ci for (i = 0; i < dev->nepo; i++) 211062306a36Sopenharmony_ci gr_ep_remove(dev, i, 0); 211162306a36Sopenharmony_ci for (i = 0; i < dev->nepi; i++) 211262306a36Sopenharmony_ci gr_ep_remove(dev, i, 1); 211362306a36Sopenharmony_ci 211462306a36Sopenharmony_ci return 0; 211562306a36Sopenharmony_ci} 211662306a36Sopenharmony_cistatic int gr_request_irq(struct gr_udc *dev, int irq) 211762306a36Sopenharmony_ci{ 211862306a36Sopenharmony_ci return devm_request_threaded_irq(dev->dev, irq, gr_irq, gr_irq_handler, 211962306a36Sopenharmony_ci IRQF_SHARED, driver_name, dev); 212062306a36Sopenharmony_ci} 212162306a36Sopenharmony_ci 212262306a36Sopenharmony_cistatic int gr_probe(struct platform_device *pdev) 212362306a36Sopenharmony_ci{ 212462306a36Sopenharmony_ci struct gr_udc *dev; 212562306a36Sopenharmony_ci struct gr_regs __iomem *regs; 212662306a36Sopenharmony_ci int retval; 212762306a36Sopenharmony_ci u32 status; 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); 213062306a36Sopenharmony_ci if (!dev) 213162306a36Sopenharmony_ci return -ENOMEM; 213262306a36Sopenharmony_ci dev->dev = &pdev->dev; 213362306a36Sopenharmony_ci 213462306a36Sopenharmony_ci regs = devm_platform_ioremap_resource(pdev, 0); 213562306a36Sopenharmony_ci if (IS_ERR(regs)) 213662306a36Sopenharmony_ci return PTR_ERR(regs); 213762306a36Sopenharmony_ci 213862306a36Sopenharmony_ci dev->irq = platform_get_irq(pdev, 0); 213962306a36Sopenharmony_ci if (dev->irq < 0) 214062306a36Sopenharmony_ci return dev->irq; 214162306a36Sopenharmony_ci 214262306a36Sopenharmony_ci /* Some core configurations has separate irqs for IN and OUT events */ 214362306a36Sopenharmony_ci dev->irqi = platform_get_irq(pdev, 1); 214462306a36Sopenharmony_ci if (dev->irqi > 0) { 214562306a36Sopenharmony_ci dev->irqo = platform_get_irq(pdev, 2); 214662306a36Sopenharmony_ci if (dev->irqo < 0) 214762306a36Sopenharmony_ci return dev->irqo; 214862306a36Sopenharmony_ci } else { 214962306a36Sopenharmony_ci dev->irqi = 0; 215062306a36Sopenharmony_ci } 215162306a36Sopenharmony_ci 215262306a36Sopenharmony_ci dev->gadget.name = driver_name; 215362306a36Sopenharmony_ci dev->gadget.max_speed = USB_SPEED_HIGH; 215462306a36Sopenharmony_ci dev->gadget.ops = &gr_ops; 215562306a36Sopenharmony_ci 215662306a36Sopenharmony_ci spin_lock_init(&dev->lock); 215762306a36Sopenharmony_ci dev->regs = regs; 215862306a36Sopenharmony_ci 215962306a36Sopenharmony_ci platform_set_drvdata(pdev, dev); 216062306a36Sopenharmony_ci 216162306a36Sopenharmony_ci /* Determine number of endpoints and data interface mode */ 216262306a36Sopenharmony_ci status = gr_read32(&dev->regs->status); 216362306a36Sopenharmony_ci dev->nepi = ((status & GR_STATUS_NEPI_MASK) >> GR_STATUS_NEPI_POS) + 1; 216462306a36Sopenharmony_ci dev->nepo = ((status & GR_STATUS_NEPO_MASK) >> GR_STATUS_NEPO_POS) + 1; 216562306a36Sopenharmony_ci 216662306a36Sopenharmony_ci if (!(status & GR_STATUS_DM)) { 216762306a36Sopenharmony_ci dev_err(dev->dev, "Slave mode cores are not supported\n"); 216862306a36Sopenharmony_ci return -ENODEV; 216962306a36Sopenharmony_ci } 217062306a36Sopenharmony_ci 217162306a36Sopenharmony_ci /* --- Effects of the following calls might need explicit cleanup --- */ 217262306a36Sopenharmony_ci 217362306a36Sopenharmony_ci /* Create DMA pool for descriptors */ 217462306a36Sopenharmony_ci dev->desc_pool = dma_pool_create("desc_pool", dev->dev, 217562306a36Sopenharmony_ci sizeof(struct gr_dma_desc), 4, 0); 217662306a36Sopenharmony_ci if (!dev->desc_pool) { 217762306a36Sopenharmony_ci dev_err(dev->dev, "Could not allocate DMA pool"); 217862306a36Sopenharmony_ci return -ENOMEM; 217962306a36Sopenharmony_ci } 218062306a36Sopenharmony_ci 218162306a36Sopenharmony_ci /* Inside lock so that no gadget can use this udc until probe is done */ 218262306a36Sopenharmony_ci retval = usb_add_gadget_udc(dev->dev, &dev->gadget); 218362306a36Sopenharmony_ci if (retval) { 218462306a36Sopenharmony_ci dev_err(dev->dev, "Could not add gadget udc"); 218562306a36Sopenharmony_ci goto out; 218662306a36Sopenharmony_ci } 218762306a36Sopenharmony_ci dev->added = 1; 218862306a36Sopenharmony_ci 218962306a36Sopenharmony_ci spin_lock(&dev->lock); 219062306a36Sopenharmony_ci 219162306a36Sopenharmony_ci retval = gr_udc_init(dev); 219262306a36Sopenharmony_ci if (retval) { 219362306a36Sopenharmony_ci spin_unlock(&dev->lock); 219462306a36Sopenharmony_ci goto out; 219562306a36Sopenharmony_ci } 219662306a36Sopenharmony_ci 219762306a36Sopenharmony_ci /* Clear all interrupt enables that might be left on since last boot */ 219862306a36Sopenharmony_ci gr_disable_interrupts_and_pullup(dev); 219962306a36Sopenharmony_ci 220062306a36Sopenharmony_ci spin_unlock(&dev->lock); 220162306a36Sopenharmony_ci 220262306a36Sopenharmony_ci gr_dfs_create(dev); 220362306a36Sopenharmony_ci 220462306a36Sopenharmony_ci retval = gr_request_irq(dev, dev->irq); 220562306a36Sopenharmony_ci if (retval) { 220662306a36Sopenharmony_ci dev_err(dev->dev, "Failed to request irq %d\n", dev->irq); 220762306a36Sopenharmony_ci goto out; 220862306a36Sopenharmony_ci } 220962306a36Sopenharmony_ci 221062306a36Sopenharmony_ci if (dev->irqi) { 221162306a36Sopenharmony_ci retval = gr_request_irq(dev, dev->irqi); 221262306a36Sopenharmony_ci if (retval) { 221362306a36Sopenharmony_ci dev_err(dev->dev, "Failed to request irqi %d\n", 221462306a36Sopenharmony_ci dev->irqi); 221562306a36Sopenharmony_ci goto out; 221662306a36Sopenharmony_ci } 221762306a36Sopenharmony_ci retval = gr_request_irq(dev, dev->irqo); 221862306a36Sopenharmony_ci if (retval) { 221962306a36Sopenharmony_ci dev_err(dev->dev, "Failed to request irqo %d\n", 222062306a36Sopenharmony_ci dev->irqo); 222162306a36Sopenharmony_ci goto out; 222262306a36Sopenharmony_ci } 222362306a36Sopenharmony_ci } 222462306a36Sopenharmony_ci 222562306a36Sopenharmony_ci if (dev->irqi) 222662306a36Sopenharmony_ci dev_info(dev->dev, "regs: %p, irqs %d, %d, %d\n", dev->regs, 222762306a36Sopenharmony_ci dev->irq, dev->irqi, dev->irqo); 222862306a36Sopenharmony_ci else 222962306a36Sopenharmony_ci dev_info(dev->dev, "regs: %p, irq %d\n", dev->regs, dev->irq); 223062306a36Sopenharmony_ci 223162306a36Sopenharmony_ciout: 223262306a36Sopenharmony_ci if (retval) 223362306a36Sopenharmony_ci gr_remove(pdev); 223462306a36Sopenharmony_ci 223562306a36Sopenharmony_ci return retval; 223662306a36Sopenharmony_ci} 223762306a36Sopenharmony_ci 223862306a36Sopenharmony_cistatic const struct of_device_id gr_match[] = { 223962306a36Sopenharmony_ci {.name = "GAISLER_USBDC"}, 224062306a36Sopenharmony_ci {.name = "01_021"}, 224162306a36Sopenharmony_ci {}, 224262306a36Sopenharmony_ci}; 224362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, gr_match); 224462306a36Sopenharmony_ci 224562306a36Sopenharmony_cistatic struct platform_driver gr_driver = { 224662306a36Sopenharmony_ci .driver = { 224762306a36Sopenharmony_ci .name = DRIVER_NAME, 224862306a36Sopenharmony_ci .of_match_table = gr_match, 224962306a36Sopenharmony_ci }, 225062306a36Sopenharmony_ci .probe = gr_probe, 225162306a36Sopenharmony_ci .remove = gr_remove, 225262306a36Sopenharmony_ci}; 225362306a36Sopenharmony_cimodule_platform_driver(gr_driver); 225462306a36Sopenharmony_ci 225562306a36Sopenharmony_ciMODULE_AUTHOR("Aeroflex Gaisler AB."); 225662306a36Sopenharmony_ciMODULE_DESCRIPTION(DRIVER_DESC); 225762306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 2258