162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * at91_udc -- driver for at91-series USB peripheral controller 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2004 by Thomas Rathbone 662306a36Sopenharmony_ci * Copyright (C) 2005 by HP Labs 762306a36Sopenharmony_ci * Copyright (C) 2005 by David Brownell 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#undef VERBOSE_DEBUG 1162306a36Sopenharmony_ci#undef PACKET_TRACE 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/kernel.h> 1462306a36Sopenharmony_ci#include <linux/module.h> 1562306a36Sopenharmony_ci#include <linux/platform_device.h> 1662306a36Sopenharmony_ci#include <linux/delay.h> 1762306a36Sopenharmony_ci#include <linux/ioport.h> 1862306a36Sopenharmony_ci#include <linux/slab.h> 1962306a36Sopenharmony_ci#include <linux/errno.h> 2062306a36Sopenharmony_ci#include <linux/list.h> 2162306a36Sopenharmony_ci#include <linux/interrupt.h> 2262306a36Sopenharmony_ci#include <linux/proc_fs.h> 2362306a36Sopenharmony_ci#include <linux/prefetch.h> 2462306a36Sopenharmony_ci#include <linux/clk.h> 2562306a36Sopenharmony_ci#include <linux/usb/ch9.h> 2662306a36Sopenharmony_ci#include <linux/usb/gadget.h> 2762306a36Sopenharmony_ci#include <linux/of.h> 2862306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 2962306a36Sopenharmony_ci#include <linux/platform_data/atmel.h> 3062306a36Sopenharmony_ci#include <linux/regmap.h> 3162306a36Sopenharmony_ci#include <linux/mfd/syscon.h> 3262306a36Sopenharmony_ci#include <linux/mfd/syscon/atmel-matrix.h> 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#include "at91_udc.h" 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* 3862306a36Sopenharmony_ci * This controller is simple and PIO-only. It's used in many AT91-series 3962306a36Sopenharmony_ci * full speed USB controllers, including the at91rm9200 (arm920T, with MMU), 4062306a36Sopenharmony_ci * at91sam926x (arm926ejs, with MMU), and several no-mmu versions. 4162306a36Sopenharmony_ci * 4262306a36Sopenharmony_ci * This driver expects the board has been wired with two GPIOs supporting 4362306a36Sopenharmony_ci * a VBUS sensing IRQ, and a D+ pullup. (They may be omitted, but the 4462306a36Sopenharmony_ci * testing hasn't covered such cases.) 4562306a36Sopenharmony_ci * 4662306a36Sopenharmony_ci * The pullup is most important (so it's integrated on sam926x parts). It 4762306a36Sopenharmony_ci * provides software control over whether the host enumerates the device. 4862306a36Sopenharmony_ci * 4962306a36Sopenharmony_ci * The VBUS sensing helps during enumeration, and allows both USB clocks 5062306a36Sopenharmony_ci * (and the transceiver) to stay gated off until they're necessary, saving 5162306a36Sopenharmony_ci * power. During USB suspend, the 48 MHz clock is gated off in hardware; 5262306a36Sopenharmony_ci * it may also be gated off by software during some Linux sleep states. 5362306a36Sopenharmony_ci */ 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#define DRIVER_VERSION "3 May 2006" 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic const char driver_name [] = "at91_udc"; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistatic const struct { 6062306a36Sopenharmony_ci const char *name; 6162306a36Sopenharmony_ci const struct usb_ep_caps caps; 6262306a36Sopenharmony_ci} ep_info[] = { 6362306a36Sopenharmony_ci#define EP_INFO(_name, _caps) \ 6462306a36Sopenharmony_ci { \ 6562306a36Sopenharmony_ci .name = _name, \ 6662306a36Sopenharmony_ci .caps = _caps, \ 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci EP_INFO("ep0", 7062306a36Sopenharmony_ci USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)), 7162306a36Sopenharmony_ci EP_INFO("ep1", 7262306a36Sopenharmony_ci USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), 7362306a36Sopenharmony_ci EP_INFO("ep2", 7462306a36Sopenharmony_ci USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), 7562306a36Sopenharmony_ci EP_INFO("ep3-int", 7662306a36Sopenharmony_ci USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_ALL)), 7762306a36Sopenharmony_ci EP_INFO("ep4", 7862306a36Sopenharmony_ci USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), 7962306a36Sopenharmony_ci EP_INFO("ep5", 8062306a36Sopenharmony_ci USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci#undef EP_INFO 8362306a36Sopenharmony_ci}; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci#define ep0name ep_info[0].name 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci#define VBUS_POLL_TIMEOUT msecs_to_jiffies(1000) 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci#define at91_udp_read(udc, reg) \ 9062306a36Sopenharmony_ci __raw_readl((udc)->udp_baseaddr + (reg)) 9162306a36Sopenharmony_ci#define at91_udp_write(udc, reg, val) \ 9262306a36Sopenharmony_ci __raw_writel((val), (udc)->udp_baseaddr + (reg)) 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci/*-------------------------------------------------------------------------*/ 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci#ifdef CONFIG_USB_GADGET_DEBUG_FILES 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci#include <linux/seq_file.h> 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic const char debug_filename[] = "driver/udc"; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci#define FOURBITS "%s%s%s%s" 10362306a36Sopenharmony_ci#define EIGHTBITS FOURBITS FOURBITS 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic void proc_ep_show(struct seq_file *s, struct at91_ep *ep) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci static char *types[] = { 10862306a36Sopenharmony_ci "control", "out-iso", "out-bulk", "out-int", 10962306a36Sopenharmony_ci "BOGUS", "in-iso", "in-bulk", "in-int"}; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci u32 csr; 11262306a36Sopenharmony_ci struct at91_request *req; 11362306a36Sopenharmony_ci unsigned long flags; 11462306a36Sopenharmony_ci struct at91_udc *udc = ep->udc; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci spin_lock_irqsave(&udc->lock, flags); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci csr = __raw_readl(ep->creg); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci /* NOTE: not collecting per-endpoint irq statistics... */ 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci seq_printf(s, "\n"); 12362306a36Sopenharmony_ci seq_printf(s, "%s, maxpacket %d %s%s %s%s\n", 12462306a36Sopenharmony_ci ep->ep.name, ep->ep.maxpacket, 12562306a36Sopenharmony_ci ep->is_in ? "in" : "out", 12662306a36Sopenharmony_ci ep->is_iso ? " iso" : "", 12762306a36Sopenharmony_ci ep->is_pingpong 12862306a36Sopenharmony_ci ? (ep->fifo_bank ? "pong" : "ping") 12962306a36Sopenharmony_ci : "", 13062306a36Sopenharmony_ci ep->stopped ? " stopped" : ""); 13162306a36Sopenharmony_ci seq_printf(s, "csr %08x rxbytes=%d %s %s %s" EIGHTBITS "\n", 13262306a36Sopenharmony_ci csr, 13362306a36Sopenharmony_ci (csr & 0x07ff0000) >> 16, 13462306a36Sopenharmony_ci (csr & (1 << 15)) ? "enabled" : "disabled", 13562306a36Sopenharmony_ci (csr & (1 << 11)) ? "DATA1" : "DATA0", 13662306a36Sopenharmony_ci types[(csr & 0x700) >> 8], 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci /* iff type is control then print current direction */ 13962306a36Sopenharmony_ci (!(csr & 0x700)) 14062306a36Sopenharmony_ci ? ((csr & (1 << 7)) ? " IN" : " OUT") 14162306a36Sopenharmony_ci : "", 14262306a36Sopenharmony_ci (csr & (1 << 6)) ? " rxdatabk1" : "", 14362306a36Sopenharmony_ci (csr & (1 << 5)) ? " forcestall" : "", 14462306a36Sopenharmony_ci (csr & (1 << 4)) ? " txpktrdy" : "", 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci (csr & (1 << 3)) ? " stallsent" : "", 14762306a36Sopenharmony_ci (csr & (1 << 2)) ? " rxsetup" : "", 14862306a36Sopenharmony_ci (csr & (1 << 1)) ? " rxdatabk0" : "", 14962306a36Sopenharmony_ci (csr & (1 << 0)) ? " txcomp" : ""); 15062306a36Sopenharmony_ci if (list_empty (&ep->queue)) 15162306a36Sopenharmony_ci seq_printf(s, "\t(queue empty)\n"); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci else list_for_each_entry (req, &ep->queue, queue) { 15462306a36Sopenharmony_ci unsigned length = req->req.actual; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci seq_printf(s, "\treq %p len %d/%d buf %p\n", 15762306a36Sopenharmony_ci &req->req, length, 15862306a36Sopenharmony_ci req->req.length, req->req.buf); 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci spin_unlock_irqrestore(&udc->lock, flags); 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic void proc_irq_show(struct seq_file *s, const char *label, u32 mask) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci int i; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci seq_printf(s, "%s %04x:%s%s" FOURBITS, label, mask, 16862306a36Sopenharmony_ci (mask & (1 << 13)) ? " wakeup" : "", 16962306a36Sopenharmony_ci (mask & (1 << 12)) ? " endbusres" : "", 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci (mask & (1 << 11)) ? " sofint" : "", 17262306a36Sopenharmony_ci (mask & (1 << 10)) ? " extrsm" : "", 17362306a36Sopenharmony_ci (mask & (1 << 9)) ? " rxrsm" : "", 17462306a36Sopenharmony_ci (mask & (1 << 8)) ? " rxsusp" : ""); 17562306a36Sopenharmony_ci for (i = 0; i < 8; i++) { 17662306a36Sopenharmony_ci if (mask & (1 << i)) 17762306a36Sopenharmony_ci seq_printf(s, " ep%d", i); 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci seq_printf(s, "\n"); 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic int proc_udc_show(struct seq_file *s, void *unused) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci struct at91_udc *udc = s->private; 18562306a36Sopenharmony_ci struct at91_ep *ep; 18662306a36Sopenharmony_ci u32 tmp; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci seq_printf(s, "%s: version %s\n", driver_name, DRIVER_VERSION); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci seq_printf(s, "vbus %s, pullup %s, %s powered%s, gadget %s\n\n", 19162306a36Sopenharmony_ci udc->vbus ? "present" : "off", 19262306a36Sopenharmony_ci udc->enabled 19362306a36Sopenharmony_ci ? (udc->vbus ? "active" : "enabled") 19462306a36Sopenharmony_ci : "disabled", 19562306a36Sopenharmony_ci udc->gadget.is_selfpowered ? "self" : "VBUS", 19662306a36Sopenharmony_ci udc->suspended ? ", suspended" : "", 19762306a36Sopenharmony_ci udc->driver ? udc->driver->driver.name : "(none)"); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci /* don't access registers when interface isn't clocked */ 20062306a36Sopenharmony_ci if (!udc->clocked) { 20162306a36Sopenharmony_ci seq_printf(s, "(not clocked)\n"); 20262306a36Sopenharmony_ci return 0; 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci tmp = at91_udp_read(udc, AT91_UDP_FRM_NUM); 20662306a36Sopenharmony_ci seq_printf(s, "frame %05x:%s%s frame=%d\n", tmp, 20762306a36Sopenharmony_ci (tmp & AT91_UDP_FRM_OK) ? " ok" : "", 20862306a36Sopenharmony_ci (tmp & AT91_UDP_FRM_ERR) ? " err" : "", 20962306a36Sopenharmony_ci (tmp & AT91_UDP_NUM)); 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT); 21262306a36Sopenharmony_ci seq_printf(s, "glbstate %02x:%s" FOURBITS "\n", tmp, 21362306a36Sopenharmony_ci (tmp & AT91_UDP_RMWUPE) ? " rmwupe" : "", 21462306a36Sopenharmony_ci (tmp & AT91_UDP_RSMINPR) ? " rsminpr" : "", 21562306a36Sopenharmony_ci (tmp & AT91_UDP_ESR) ? " esr" : "", 21662306a36Sopenharmony_ci (tmp & AT91_UDP_CONFG) ? " confg" : "", 21762306a36Sopenharmony_ci (tmp & AT91_UDP_FADDEN) ? " fadden" : ""); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci tmp = at91_udp_read(udc, AT91_UDP_FADDR); 22062306a36Sopenharmony_ci seq_printf(s, "faddr %03x:%s fadd=%d\n", tmp, 22162306a36Sopenharmony_ci (tmp & AT91_UDP_FEN) ? " fen" : "", 22262306a36Sopenharmony_ci (tmp & AT91_UDP_FADD)); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci proc_irq_show(s, "imr ", at91_udp_read(udc, AT91_UDP_IMR)); 22562306a36Sopenharmony_ci proc_irq_show(s, "isr ", at91_udp_read(udc, AT91_UDP_ISR)); 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci if (udc->enabled && udc->vbus) { 22862306a36Sopenharmony_ci proc_ep_show(s, &udc->ep[0]); 22962306a36Sopenharmony_ci list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) { 23062306a36Sopenharmony_ci if (ep->ep.desc) 23162306a36Sopenharmony_ci proc_ep_show(s, ep); 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci return 0; 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cistatic void create_debug_file(struct at91_udc *udc) 23862306a36Sopenharmony_ci{ 23962306a36Sopenharmony_ci udc->pde = proc_create_single_data(debug_filename, 0, NULL, 24062306a36Sopenharmony_ci proc_udc_show, udc); 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_cistatic void remove_debug_file(struct at91_udc *udc) 24462306a36Sopenharmony_ci{ 24562306a36Sopenharmony_ci if (udc->pde) 24662306a36Sopenharmony_ci remove_proc_entry(debug_filename, NULL); 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci#else 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic inline void create_debug_file(struct at91_udc *udc) {} 25262306a36Sopenharmony_cistatic inline void remove_debug_file(struct at91_udc *udc) {} 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci#endif 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci/*-------------------------------------------------------------------------*/ 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cistatic void done(struct at91_ep *ep, struct at91_request *req, int status) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci unsigned stopped = ep->stopped; 26262306a36Sopenharmony_ci struct at91_udc *udc = ep->udc; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci list_del_init(&req->queue); 26562306a36Sopenharmony_ci if (req->req.status == -EINPROGRESS) 26662306a36Sopenharmony_ci req->req.status = status; 26762306a36Sopenharmony_ci else 26862306a36Sopenharmony_ci status = req->req.status; 26962306a36Sopenharmony_ci if (status && status != -ESHUTDOWN) 27062306a36Sopenharmony_ci VDBG("%s done %p, status %d\n", ep->ep.name, req, status); 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci ep->stopped = 1; 27362306a36Sopenharmony_ci spin_unlock(&udc->lock); 27462306a36Sopenharmony_ci usb_gadget_giveback_request(&ep->ep, &req->req); 27562306a36Sopenharmony_ci spin_lock(&udc->lock); 27662306a36Sopenharmony_ci ep->stopped = stopped; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci /* ep0 is always ready; other endpoints need a non-empty queue */ 27962306a36Sopenharmony_ci if (list_empty(&ep->queue) && ep->int_mask != (1 << 0)) 28062306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_IDR, ep->int_mask); 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci/*-------------------------------------------------------------------------*/ 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci/* bits indicating OUT fifo has data ready */ 28662306a36Sopenharmony_ci#define RX_DATA_READY (AT91_UDP_RX_DATA_BK0 | AT91_UDP_RX_DATA_BK1) 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci/* 28962306a36Sopenharmony_ci * Endpoint FIFO CSR bits have a mix of bits, making it unsafe to just write 29062306a36Sopenharmony_ci * back most of the value you just read (because of side effects, including 29162306a36Sopenharmony_ci * bits that may change after reading and before writing). 29262306a36Sopenharmony_ci * 29362306a36Sopenharmony_ci * Except when changing a specific bit, always write values which: 29462306a36Sopenharmony_ci * - clear SET_FX bits (setting them could change something) 29562306a36Sopenharmony_ci * - set CLR_FX bits (clearing them could change something) 29662306a36Sopenharmony_ci * 29762306a36Sopenharmony_ci * There are also state bits like FORCESTALL, EPEDS, DIR, and EPTYPE 29862306a36Sopenharmony_ci * that shouldn't normally be changed. 29962306a36Sopenharmony_ci * 30062306a36Sopenharmony_ci * NOTE at91sam9260 docs mention synch between UDPCK and MCK clock domains, 30162306a36Sopenharmony_ci * implying a need to wait for one write to complete (test relevant bits) 30262306a36Sopenharmony_ci * before starting the next write. This shouldn't be an issue given how 30362306a36Sopenharmony_ci * infrequently we write, except maybe for write-then-read idioms. 30462306a36Sopenharmony_ci */ 30562306a36Sopenharmony_ci#define SET_FX (AT91_UDP_TXPKTRDY) 30662306a36Sopenharmony_ci#define CLR_FX (RX_DATA_READY | AT91_UDP_RXSETUP \ 30762306a36Sopenharmony_ci | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP) 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci/* pull OUT packet data from the endpoint's fifo */ 31062306a36Sopenharmony_cistatic int read_fifo (struct at91_ep *ep, struct at91_request *req) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci u32 __iomem *creg = ep->creg; 31362306a36Sopenharmony_ci u8 __iomem *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0)); 31462306a36Sopenharmony_ci u32 csr; 31562306a36Sopenharmony_ci u8 *buf; 31662306a36Sopenharmony_ci unsigned int count, bufferspace, is_done; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci buf = req->req.buf + req->req.actual; 31962306a36Sopenharmony_ci bufferspace = req->req.length - req->req.actual; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci /* 32262306a36Sopenharmony_ci * there might be nothing to read if ep_queue() calls us, 32362306a36Sopenharmony_ci * or if we already emptied both pingpong buffers 32462306a36Sopenharmony_ci */ 32562306a36Sopenharmony_cirescan: 32662306a36Sopenharmony_ci csr = __raw_readl(creg); 32762306a36Sopenharmony_ci if ((csr & RX_DATA_READY) == 0) 32862306a36Sopenharmony_ci return 0; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci count = (csr & AT91_UDP_RXBYTECNT) >> 16; 33162306a36Sopenharmony_ci if (count > ep->ep.maxpacket) 33262306a36Sopenharmony_ci count = ep->ep.maxpacket; 33362306a36Sopenharmony_ci if (count > bufferspace) { 33462306a36Sopenharmony_ci DBG("%s buffer overflow\n", ep->ep.name); 33562306a36Sopenharmony_ci req->req.status = -EOVERFLOW; 33662306a36Sopenharmony_ci count = bufferspace; 33762306a36Sopenharmony_ci } 33862306a36Sopenharmony_ci __raw_readsb(dreg, buf, count); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci /* release and swap pingpong mem bank */ 34162306a36Sopenharmony_ci csr |= CLR_FX; 34262306a36Sopenharmony_ci if (ep->is_pingpong) { 34362306a36Sopenharmony_ci if (ep->fifo_bank == 0) { 34462306a36Sopenharmony_ci csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0); 34562306a36Sopenharmony_ci ep->fifo_bank = 1; 34662306a36Sopenharmony_ci } else { 34762306a36Sopenharmony_ci csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK1); 34862306a36Sopenharmony_ci ep->fifo_bank = 0; 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci } else 35162306a36Sopenharmony_ci csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0); 35262306a36Sopenharmony_ci __raw_writel(csr, creg); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci req->req.actual += count; 35562306a36Sopenharmony_ci is_done = (count < ep->ep.maxpacket); 35662306a36Sopenharmony_ci if (count == bufferspace) 35762306a36Sopenharmony_ci is_done = 1; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci PACKET("%s %p out/%d%s\n", ep->ep.name, &req->req, count, 36062306a36Sopenharmony_ci is_done ? " (done)" : ""); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci /* 36362306a36Sopenharmony_ci * avoid extra trips through IRQ logic for packets already in 36462306a36Sopenharmony_ci * the fifo ... maybe preventing an extra (expensive) OUT-NAK 36562306a36Sopenharmony_ci */ 36662306a36Sopenharmony_ci if (is_done) 36762306a36Sopenharmony_ci done(ep, req, 0); 36862306a36Sopenharmony_ci else if (ep->is_pingpong) { 36962306a36Sopenharmony_ci /* 37062306a36Sopenharmony_ci * One dummy read to delay the code because of a HW glitch: 37162306a36Sopenharmony_ci * CSR returns bad RXCOUNT when read too soon after updating 37262306a36Sopenharmony_ci * RX_DATA_BK flags. 37362306a36Sopenharmony_ci */ 37462306a36Sopenharmony_ci csr = __raw_readl(creg); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci bufferspace -= count; 37762306a36Sopenharmony_ci buf += count; 37862306a36Sopenharmony_ci goto rescan; 37962306a36Sopenharmony_ci } 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci return is_done; 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci/* load fifo for an IN packet */ 38562306a36Sopenharmony_cistatic int write_fifo(struct at91_ep *ep, struct at91_request *req) 38662306a36Sopenharmony_ci{ 38762306a36Sopenharmony_ci u32 __iomem *creg = ep->creg; 38862306a36Sopenharmony_ci u32 csr = __raw_readl(creg); 38962306a36Sopenharmony_ci u8 __iomem *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0)); 39062306a36Sopenharmony_ci unsigned total, count, is_last; 39162306a36Sopenharmony_ci u8 *buf; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci /* 39462306a36Sopenharmony_ci * TODO: allow for writing two packets to the fifo ... that'll 39562306a36Sopenharmony_ci * reduce the amount of IN-NAKing, but probably won't affect 39662306a36Sopenharmony_ci * throughput much. (Unlike preventing OUT-NAKing!) 39762306a36Sopenharmony_ci */ 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci /* 40062306a36Sopenharmony_ci * If ep_queue() calls us, the queue is empty and possibly in 40162306a36Sopenharmony_ci * odd states like TXCOMP not yet cleared (we do it, saving at 40262306a36Sopenharmony_ci * least one IRQ) or the fifo not yet being free. Those aren't 40362306a36Sopenharmony_ci * issues normally (IRQ handler fast path). 40462306a36Sopenharmony_ci */ 40562306a36Sopenharmony_ci if (unlikely(csr & (AT91_UDP_TXCOMP | AT91_UDP_TXPKTRDY))) { 40662306a36Sopenharmony_ci if (csr & AT91_UDP_TXCOMP) { 40762306a36Sopenharmony_ci csr |= CLR_FX; 40862306a36Sopenharmony_ci csr &= ~(SET_FX | AT91_UDP_TXCOMP); 40962306a36Sopenharmony_ci __raw_writel(csr, creg); 41062306a36Sopenharmony_ci csr = __raw_readl(creg); 41162306a36Sopenharmony_ci } 41262306a36Sopenharmony_ci if (csr & AT91_UDP_TXPKTRDY) 41362306a36Sopenharmony_ci return 0; 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci buf = req->req.buf + req->req.actual; 41762306a36Sopenharmony_ci prefetch(buf); 41862306a36Sopenharmony_ci total = req->req.length - req->req.actual; 41962306a36Sopenharmony_ci if (ep->ep.maxpacket < total) { 42062306a36Sopenharmony_ci count = ep->ep.maxpacket; 42162306a36Sopenharmony_ci is_last = 0; 42262306a36Sopenharmony_ci } else { 42362306a36Sopenharmony_ci count = total; 42462306a36Sopenharmony_ci is_last = (count < ep->ep.maxpacket) || !req->req.zero; 42562306a36Sopenharmony_ci } 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci /* 42862306a36Sopenharmony_ci * Write the packet, maybe it's a ZLP. 42962306a36Sopenharmony_ci * 43062306a36Sopenharmony_ci * NOTE: incrementing req->actual before we receive the ACK means 43162306a36Sopenharmony_ci * gadget driver IN bytecounts can be wrong in fault cases. That's 43262306a36Sopenharmony_ci * fixable with PIO drivers like this one (save "count" here, and 43362306a36Sopenharmony_ci * do the increment later on TX irq), but not for most DMA hardware. 43462306a36Sopenharmony_ci * 43562306a36Sopenharmony_ci * So all gadget drivers must accept that potential error. Some 43662306a36Sopenharmony_ci * hardware supports precise fifo status reporting, letting them 43762306a36Sopenharmony_ci * recover when the actual bytecount matters (e.g. for USB Test 43862306a36Sopenharmony_ci * and Measurement Class devices). 43962306a36Sopenharmony_ci */ 44062306a36Sopenharmony_ci __raw_writesb(dreg, buf, count); 44162306a36Sopenharmony_ci csr &= ~SET_FX; 44262306a36Sopenharmony_ci csr |= CLR_FX | AT91_UDP_TXPKTRDY; 44362306a36Sopenharmony_ci __raw_writel(csr, creg); 44462306a36Sopenharmony_ci req->req.actual += count; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci PACKET("%s %p in/%d%s\n", ep->ep.name, &req->req, count, 44762306a36Sopenharmony_ci is_last ? " (done)" : ""); 44862306a36Sopenharmony_ci if (is_last) 44962306a36Sopenharmony_ci done(ep, req, 0); 45062306a36Sopenharmony_ci return is_last; 45162306a36Sopenharmony_ci} 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_cistatic void nuke(struct at91_ep *ep, int status) 45462306a36Sopenharmony_ci{ 45562306a36Sopenharmony_ci struct at91_request *req; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci /* terminate any request in the queue */ 45862306a36Sopenharmony_ci ep->stopped = 1; 45962306a36Sopenharmony_ci if (list_empty(&ep->queue)) 46062306a36Sopenharmony_ci return; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci VDBG("%s %s\n", __func__, ep->ep.name); 46362306a36Sopenharmony_ci while (!list_empty(&ep->queue)) { 46462306a36Sopenharmony_ci req = list_entry(ep->queue.next, struct at91_request, queue); 46562306a36Sopenharmony_ci done(ep, req, status); 46662306a36Sopenharmony_ci } 46762306a36Sopenharmony_ci} 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci/*-------------------------------------------------------------------------*/ 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_cistatic int at91_ep_enable(struct usb_ep *_ep, 47262306a36Sopenharmony_ci const struct usb_endpoint_descriptor *desc) 47362306a36Sopenharmony_ci{ 47462306a36Sopenharmony_ci struct at91_ep *ep = container_of(_ep, struct at91_ep, ep); 47562306a36Sopenharmony_ci struct at91_udc *udc; 47662306a36Sopenharmony_ci u16 maxpacket; 47762306a36Sopenharmony_ci u32 tmp; 47862306a36Sopenharmony_ci unsigned long flags; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci if (!_ep || !ep 48162306a36Sopenharmony_ci || !desc || _ep->name == ep0name 48262306a36Sopenharmony_ci || desc->bDescriptorType != USB_DT_ENDPOINT 48362306a36Sopenharmony_ci || (maxpacket = usb_endpoint_maxp(desc)) == 0 48462306a36Sopenharmony_ci || maxpacket > ep->maxpacket) { 48562306a36Sopenharmony_ci DBG("bad ep or descriptor\n"); 48662306a36Sopenharmony_ci return -EINVAL; 48762306a36Sopenharmony_ci } 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci udc = ep->udc; 49062306a36Sopenharmony_ci if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) { 49162306a36Sopenharmony_ci DBG("bogus device state\n"); 49262306a36Sopenharmony_ci return -ESHUTDOWN; 49362306a36Sopenharmony_ci } 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci tmp = usb_endpoint_type(desc); 49662306a36Sopenharmony_ci switch (tmp) { 49762306a36Sopenharmony_ci case USB_ENDPOINT_XFER_CONTROL: 49862306a36Sopenharmony_ci DBG("only one control endpoint\n"); 49962306a36Sopenharmony_ci return -EINVAL; 50062306a36Sopenharmony_ci case USB_ENDPOINT_XFER_INT: 50162306a36Sopenharmony_ci if (maxpacket > 64) 50262306a36Sopenharmony_ci goto bogus_max; 50362306a36Sopenharmony_ci break; 50462306a36Sopenharmony_ci case USB_ENDPOINT_XFER_BULK: 50562306a36Sopenharmony_ci switch (maxpacket) { 50662306a36Sopenharmony_ci case 8: 50762306a36Sopenharmony_ci case 16: 50862306a36Sopenharmony_ci case 32: 50962306a36Sopenharmony_ci case 64: 51062306a36Sopenharmony_ci goto ok; 51162306a36Sopenharmony_ci } 51262306a36Sopenharmony_cibogus_max: 51362306a36Sopenharmony_ci DBG("bogus maxpacket %d\n", maxpacket); 51462306a36Sopenharmony_ci return -EINVAL; 51562306a36Sopenharmony_ci case USB_ENDPOINT_XFER_ISOC: 51662306a36Sopenharmony_ci if (!ep->is_pingpong) { 51762306a36Sopenharmony_ci DBG("iso requires double buffering\n"); 51862306a36Sopenharmony_ci return -EINVAL; 51962306a36Sopenharmony_ci } 52062306a36Sopenharmony_ci break; 52162306a36Sopenharmony_ci } 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ciok: 52462306a36Sopenharmony_ci spin_lock_irqsave(&udc->lock, flags); 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci /* initialize endpoint to match this descriptor */ 52762306a36Sopenharmony_ci ep->is_in = usb_endpoint_dir_in(desc); 52862306a36Sopenharmony_ci ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC); 52962306a36Sopenharmony_ci ep->stopped = 0; 53062306a36Sopenharmony_ci if (ep->is_in) 53162306a36Sopenharmony_ci tmp |= 0x04; 53262306a36Sopenharmony_ci tmp <<= 8; 53362306a36Sopenharmony_ci tmp |= AT91_UDP_EPEDS; 53462306a36Sopenharmony_ci __raw_writel(tmp, ep->creg); 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci ep->ep.maxpacket = maxpacket; 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci /* 53962306a36Sopenharmony_ci * reset/init endpoint fifo. NOTE: leaves fifo_bank alone, 54062306a36Sopenharmony_ci * since endpoint resets don't reset hw pingpong state. 54162306a36Sopenharmony_ci */ 54262306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask); 54362306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_RST_EP, 0); 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci spin_unlock_irqrestore(&udc->lock, flags); 54662306a36Sopenharmony_ci return 0; 54762306a36Sopenharmony_ci} 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_cistatic int at91_ep_disable (struct usb_ep * _ep) 55062306a36Sopenharmony_ci{ 55162306a36Sopenharmony_ci struct at91_ep *ep = container_of(_ep, struct at91_ep, ep); 55262306a36Sopenharmony_ci struct at91_udc *udc = ep->udc; 55362306a36Sopenharmony_ci unsigned long flags; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci if (ep == &ep->udc->ep[0]) 55662306a36Sopenharmony_ci return -EINVAL; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci spin_lock_irqsave(&udc->lock, flags); 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci nuke(ep, -ESHUTDOWN); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci /* restore the endpoint's pristine config */ 56362306a36Sopenharmony_ci ep->ep.desc = NULL; 56462306a36Sopenharmony_ci ep->ep.maxpacket = ep->maxpacket; 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci /* reset fifos and endpoint */ 56762306a36Sopenharmony_ci if (ep->udc->clocked) { 56862306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask); 56962306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_RST_EP, 0); 57062306a36Sopenharmony_ci __raw_writel(0, ep->creg); 57162306a36Sopenharmony_ci } 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci spin_unlock_irqrestore(&udc->lock, flags); 57462306a36Sopenharmony_ci return 0; 57562306a36Sopenharmony_ci} 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci/* 57862306a36Sopenharmony_ci * this is a PIO-only driver, so there's nothing 57962306a36Sopenharmony_ci * interesting for request or buffer allocation. 58062306a36Sopenharmony_ci */ 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_cistatic struct usb_request * 58362306a36Sopenharmony_ciat91_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) 58462306a36Sopenharmony_ci{ 58562306a36Sopenharmony_ci struct at91_request *req; 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci req = kzalloc(sizeof (struct at91_request), gfp_flags); 58862306a36Sopenharmony_ci if (!req) 58962306a36Sopenharmony_ci return NULL; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci INIT_LIST_HEAD(&req->queue); 59262306a36Sopenharmony_ci return &req->req; 59362306a36Sopenharmony_ci} 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_cistatic void at91_ep_free_request(struct usb_ep *_ep, struct usb_request *_req) 59662306a36Sopenharmony_ci{ 59762306a36Sopenharmony_ci struct at91_request *req; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci req = container_of(_req, struct at91_request, req); 60062306a36Sopenharmony_ci BUG_ON(!list_empty(&req->queue)); 60162306a36Sopenharmony_ci kfree(req); 60262306a36Sopenharmony_ci} 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_cistatic int at91_ep_queue(struct usb_ep *_ep, 60562306a36Sopenharmony_ci struct usb_request *_req, gfp_t gfp_flags) 60662306a36Sopenharmony_ci{ 60762306a36Sopenharmony_ci struct at91_request *req; 60862306a36Sopenharmony_ci struct at91_ep *ep; 60962306a36Sopenharmony_ci struct at91_udc *udc; 61062306a36Sopenharmony_ci int status; 61162306a36Sopenharmony_ci unsigned long flags; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci req = container_of(_req, struct at91_request, req); 61462306a36Sopenharmony_ci ep = container_of(_ep, struct at91_ep, ep); 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci if (!_req || !_req->complete 61762306a36Sopenharmony_ci || !_req->buf || !list_empty(&req->queue)) { 61862306a36Sopenharmony_ci DBG("invalid request\n"); 61962306a36Sopenharmony_ci return -EINVAL; 62062306a36Sopenharmony_ci } 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci if (!_ep || (!ep->ep.desc && ep->ep.name != ep0name)) { 62362306a36Sopenharmony_ci DBG("invalid ep\n"); 62462306a36Sopenharmony_ci return -EINVAL; 62562306a36Sopenharmony_ci } 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci udc = ep->udc; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci if (!udc || !udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) { 63062306a36Sopenharmony_ci DBG("invalid device\n"); 63162306a36Sopenharmony_ci return -EINVAL; 63262306a36Sopenharmony_ci } 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci _req->status = -EINPROGRESS; 63562306a36Sopenharmony_ci _req->actual = 0; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci spin_lock_irqsave(&udc->lock, flags); 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci /* try to kickstart any empty and idle queue */ 64062306a36Sopenharmony_ci if (list_empty(&ep->queue) && !ep->stopped) { 64162306a36Sopenharmony_ci int is_ep0; 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci /* 64462306a36Sopenharmony_ci * If this control request has a non-empty DATA stage, this 64562306a36Sopenharmony_ci * will start that stage. It works just like a non-control 64662306a36Sopenharmony_ci * request (until the status stage starts, maybe early). 64762306a36Sopenharmony_ci * 64862306a36Sopenharmony_ci * If the data stage is empty, then this starts a successful 64962306a36Sopenharmony_ci * IN/STATUS stage. (Unsuccessful ones use set_halt.) 65062306a36Sopenharmony_ci */ 65162306a36Sopenharmony_ci is_ep0 = (ep->ep.name == ep0name); 65262306a36Sopenharmony_ci if (is_ep0) { 65362306a36Sopenharmony_ci u32 tmp; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci if (!udc->req_pending) { 65662306a36Sopenharmony_ci status = -EINVAL; 65762306a36Sopenharmony_ci goto done; 65862306a36Sopenharmony_ci } 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci /* 66162306a36Sopenharmony_ci * defer changing CONFG until after the gadget driver 66262306a36Sopenharmony_ci * reconfigures the endpoints. 66362306a36Sopenharmony_ci */ 66462306a36Sopenharmony_ci if (udc->wait_for_config_ack) { 66562306a36Sopenharmony_ci tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT); 66662306a36Sopenharmony_ci tmp ^= AT91_UDP_CONFG; 66762306a36Sopenharmony_ci VDBG("toggle config\n"); 66862306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp); 66962306a36Sopenharmony_ci } 67062306a36Sopenharmony_ci if (req->req.length == 0) { 67162306a36Sopenharmony_ciep0_in_status: 67262306a36Sopenharmony_ci PACKET("ep0 in/status\n"); 67362306a36Sopenharmony_ci status = 0; 67462306a36Sopenharmony_ci tmp = __raw_readl(ep->creg); 67562306a36Sopenharmony_ci tmp &= ~SET_FX; 67662306a36Sopenharmony_ci tmp |= CLR_FX | AT91_UDP_TXPKTRDY; 67762306a36Sopenharmony_ci __raw_writel(tmp, ep->creg); 67862306a36Sopenharmony_ci udc->req_pending = 0; 67962306a36Sopenharmony_ci goto done; 68062306a36Sopenharmony_ci } 68162306a36Sopenharmony_ci } 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci if (ep->is_in) 68462306a36Sopenharmony_ci status = write_fifo(ep, req); 68562306a36Sopenharmony_ci else { 68662306a36Sopenharmony_ci status = read_fifo(ep, req); 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci /* IN/STATUS stage is otherwise triggered by irq */ 68962306a36Sopenharmony_ci if (status && is_ep0) 69062306a36Sopenharmony_ci goto ep0_in_status; 69162306a36Sopenharmony_ci } 69262306a36Sopenharmony_ci } else 69362306a36Sopenharmony_ci status = 0; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci if (req && !status) { 69662306a36Sopenharmony_ci list_add_tail (&req->queue, &ep->queue); 69762306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_IER, ep->int_mask); 69862306a36Sopenharmony_ci } 69962306a36Sopenharmony_cidone: 70062306a36Sopenharmony_ci spin_unlock_irqrestore(&udc->lock, flags); 70162306a36Sopenharmony_ci return (status < 0) ? status : 0; 70262306a36Sopenharmony_ci} 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_cistatic int at91_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) 70562306a36Sopenharmony_ci{ 70662306a36Sopenharmony_ci struct at91_ep *ep; 70762306a36Sopenharmony_ci struct at91_request *req = NULL, *iter; 70862306a36Sopenharmony_ci unsigned long flags; 70962306a36Sopenharmony_ci struct at91_udc *udc; 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci ep = container_of(_ep, struct at91_ep, ep); 71262306a36Sopenharmony_ci if (!_ep || ep->ep.name == ep0name) 71362306a36Sopenharmony_ci return -EINVAL; 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci udc = ep->udc; 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci spin_lock_irqsave(&udc->lock, flags); 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci /* make sure it's actually queued on this endpoint */ 72062306a36Sopenharmony_ci list_for_each_entry(iter, &ep->queue, queue) { 72162306a36Sopenharmony_ci if (&iter->req != _req) 72262306a36Sopenharmony_ci continue; 72362306a36Sopenharmony_ci req = iter; 72462306a36Sopenharmony_ci break; 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci if (!req) { 72762306a36Sopenharmony_ci spin_unlock_irqrestore(&udc->lock, flags); 72862306a36Sopenharmony_ci return -EINVAL; 72962306a36Sopenharmony_ci } 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci done(ep, req, -ECONNRESET); 73262306a36Sopenharmony_ci spin_unlock_irqrestore(&udc->lock, flags); 73362306a36Sopenharmony_ci return 0; 73462306a36Sopenharmony_ci} 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_cistatic int at91_ep_set_halt(struct usb_ep *_ep, int value) 73762306a36Sopenharmony_ci{ 73862306a36Sopenharmony_ci struct at91_ep *ep = container_of(_ep, struct at91_ep, ep); 73962306a36Sopenharmony_ci struct at91_udc *udc = ep->udc; 74062306a36Sopenharmony_ci u32 __iomem *creg; 74162306a36Sopenharmony_ci u32 csr; 74262306a36Sopenharmony_ci unsigned long flags; 74362306a36Sopenharmony_ci int status = 0; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci if (!_ep || ep->is_iso || !ep->udc->clocked) 74662306a36Sopenharmony_ci return -EINVAL; 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci creg = ep->creg; 74962306a36Sopenharmony_ci spin_lock_irqsave(&udc->lock, flags); 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci csr = __raw_readl(creg); 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci /* 75462306a36Sopenharmony_ci * fail with still-busy IN endpoints, ensuring correct sequencing 75562306a36Sopenharmony_ci * of data tx then stall. note that the fifo rx bytecount isn't 75662306a36Sopenharmony_ci * completely accurate as a tx bytecount. 75762306a36Sopenharmony_ci */ 75862306a36Sopenharmony_ci if (ep->is_in && (!list_empty(&ep->queue) || (csr >> 16) != 0)) 75962306a36Sopenharmony_ci status = -EAGAIN; 76062306a36Sopenharmony_ci else { 76162306a36Sopenharmony_ci csr |= CLR_FX; 76262306a36Sopenharmony_ci csr &= ~SET_FX; 76362306a36Sopenharmony_ci if (value) { 76462306a36Sopenharmony_ci csr |= AT91_UDP_FORCESTALL; 76562306a36Sopenharmony_ci VDBG("halt %s\n", ep->ep.name); 76662306a36Sopenharmony_ci } else { 76762306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask); 76862306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_RST_EP, 0); 76962306a36Sopenharmony_ci csr &= ~AT91_UDP_FORCESTALL; 77062306a36Sopenharmony_ci } 77162306a36Sopenharmony_ci __raw_writel(csr, creg); 77262306a36Sopenharmony_ci } 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci spin_unlock_irqrestore(&udc->lock, flags); 77562306a36Sopenharmony_ci return status; 77662306a36Sopenharmony_ci} 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_cistatic const struct usb_ep_ops at91_ep_ops = { 77962306a36Sopenharmony_ci .enable = at91_ep_enable, 78062306a36Sopenharmony_ci .disable = at91_ep_disable, 78162306a36Sopenharmony_ci .alloc_request = at91_ep_alloc_request, 78262306a36Sopenharmony_ci .free_request = at91_ep_free_request, 78362306a36Sopenharmony_ci .queue = at91_ep_queue, 78462306a36Sopenharmony_ci .dequeue = at91_ep_dequeue, 78562306a36Sopenharmony_ci .set_halt = at91_ep_set_halt, 78662306a36Sopenharmony_ci /* there's only imprecise fifo status reporting */ 78762306a36Sopenharmony_ci}; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci/*-------------------------------------------------------------------------*/ 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_cistatic int at91_get_frame(struct usb_gadget *gadget) 79262306a36Sopenharmony_ci{ 79362306a36Sopenharmony_ci struct at91_udc *udc = to_udc(gadget); 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci if (!to_udc(gadget)->clocked) 79662306a36Sopenharmony_ci return -EINVAL; 79762306a36Sopenharmony_ci return at91_udp_read(udc, AT91_UDP_FRM_NUM) & AT91_UDP_NUM; 79862306a36Sopenharmony_ci} 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_cistatic int at91_wakeup(struct usb_gadget *gadget) 80162306a36Sopenharmony_ci{ 80262306a36Sopenharmony_ci struct at91_udc *udc = to_udc(gadget); 80362306a36Sopenharmony_ci u32 glbstate; 80462306a36Sopenharmony_ci unsigned long flags; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci DBG("%s\n", __func__ ); 80762306a36Sopenharmony_ci spin_lock_irqsave(&udc->lock, flags); 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci if (!udc->clocked || !udc->suspended) 81062306a36Sopenharmony_ci goto done; 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci /* NOTE: some "early versions" handle ESR differently ... */ 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci glbstate = at91_udp_read(udc, AT91_UDP_GLB_STAT); 81562306a36Sopenharmony_ci if (!(glbstate & AT91_UDP_ESR)) 81662306a36Sopenharmony_ci goto done; 81762306a36Sopenharmony_ci glbstate |= AT91_UDP_ESR; 81862306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_GLB_STAT, glbstate); 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_cidone: 82162306a36Sopenharmony_ci spin_unlock_irqrestore(&udc->lock, flags); 82262306a36Sopenharmony_ci return 0; 82362306a36Sopenharmony_ci} 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci/* reinit == restore initial software state */ 82662306a36Sopenharmony_cistatic void udc_reinit(struct at91_udc *udc) 82762306a36Sopenharmony_ci{ 82862306a36Sopenharmony_ci u32 i; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci INIT_LIST_HEAD(&udc->gadget.ep_list); 83162306a36Sopenharmony_ci INIT_LIST_HEAD(&udc->gadget.ep0->ep_list); 83262306a36Sopenharmony_ci udc->gadget.quirk_stall_not_supp = 1; 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci for (i = 0; i < NUM_ENDPOINTS; i++) { 83562306a36Sopenharmony_ci struct at91_ep *ep = &udc->ep[i]; 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci if (i != 0) 83862306a36Sopenharmony_ci list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); 83962306a36Sopenharmony_ci ep->ep.desc = NULL; 84062306a36Sopenharmony_ci ep->stopped = 0; 84162306a36Sopenharmony_ci ep->fifo_bank = 0; 84262306a36Sopenharmony_ci usb_ep_set_maxpacket_limit(&ep->ep, ep->maxpacket); 84362306a36Sopenharmony_ci ep->creg = (void __iomem *) udc->udp_baseaddr + AT91_UDP_CSR(i); 84462306a36Sopenharmony_ci /* initialize one queue per endpoint */ 84562306a36Sopenharmony_ci INIT_LIST_HEAD(&ep->queue); 84662306a36Sopenharmony_ci } 84762306a36Sopenharmony_ci} 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_cistatic void reset_gadget(struct at91_udc *udc) 85062306a36Sopenharmony_ci{ 85162306a36Sopenharmony_ci struct usb_gadget_driver *driver = udc->driver; 85262306a36Sopenharmony_ci int i; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci if (udc->gadget.speed == USB_SPEED_UNKNOWN) 85562306a36Sopenharmony_ci driver = NULL; 85662306a36Sopenharmony_ci udc->gadget.speed = USB_SPEED_UNKNOWN; 85762306a36Sopenharmony_ci udc->suspended = 0; 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci for (i = 0; i < NUM_ENDPOINTS; i++) { 86062306a36Sopenharmony_ci struct at91_ep *ep = &udc->ep[i]; 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci ep->stopped = 1; 86362306a36Sopenharmony_ci nuke(ep, -ESHUTDOWN); 86462306a36Sopenharmony_ci } 86562306a36Sopenharmony_ci if (driver) { 86662306a36Sopenharmony_ci spin_unlock(&udc->lock); 86762306a36Sopenharmony_ci usb_gadget_udc_reset(&udc->gadget, driver); 86862306a36Sopenharmony_ci spin_lock(&udc->lock); 86962306a36Sopenharmony_ci } 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci udc_reinit(udc); 87262306a36Sopenharmony_ci} 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_cistatic void stop_activity(struct at91_udc *udc) 87562306a36Sopenharmony_ci{ 87662306a36Sopenharmony_ci struct usb_gadget_driver *driver = udc->driver; 87762306a36Sopenharmony_ci int i; 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci if (udc->gadget.speed == USB_SPEED_UNKNOWN) 88062306a36Sopenharmony_ci driver = NULL; 88162306a36Sopenharmony_ci udc->gadget.speed = USB_SPEED_UNKNOWN; 88262306a36Sopenharmony_ci udc->suspended = 0; 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci for (i = 0; i < NUM_ENDPOINTS; i++) { 88562306a36Sopenharmony_ci struct at91_ep *ep = &udc->ep[i]; 88662306a36Sopenharmony_ci ep->stopped = 1; 88762306a36Sopenharmony_ci nuke(ep, -ESHUTDOWN); 88862306a36Sopenharmony_ci } 88962306a36Sopenharmony_ci if (driver) { 89062306a36Sopenharmony_ci spin_unlock(&udc->lock); 89162306a36Sopenharmony_ci driver->disconnect(&udc->gadget); 89262306a36Sopenharmony_ci spin_lock(&udc->lock); 89362306a36Sopenharmony_ci } 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci udc_reinit(udc); 89662306a36Sopenharmony_ci} 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_cistatic void clk_on(struct at91_udc *udc) 89962306a36Sopenharmony_ci{ 90062306a36Sopenharmony_ci if (udc->clocked) 90162306a36Sopenharmony_ci return; 90262306a36Sopenharmony_ci udc->clocked = 1; 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci clk_enable(udc->iclk); 90562306a36Sopenharmony_ci clk_enable(udc->fclk); 90662306a36Sopenharmony_ci} 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_cistatic void clk_off(struct at91_udc *udc) 90962306a36Sopenharmony_ci{ 91062306a36Sopenharmony_ci if (!udc->clocked) 91162306a36Sopenharmony_ci return; 91262306a36Sopenharmony_ci udc->clocked = 0; 91362306a36Sopenharmony_ci udc->gadget.speed = USB_SPEED_UNKNOWN; 91462306a36Sopenharmony_ci clk_disable(udc->fclk); 91562306a36Sopenharmony_ci clk_disable(udc->iclk); 91662306a36Sopenharmony_ci} 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci/* 91962306a36Sopenharmony_ci * activate/deactivate link with host; minimize power usage for 92062306a36Sopenharmony_ci * inactive links by cutting clocks and transceiver power. 92162306a36Sopenharmony_ci */ 92262306a36Sopenharmony_cistatic void pullup(struct at91_udc *udc, int is_on) 92362306a36Sopenharmony_ci{ 92462306a36Sopenharmony_ci if (!udc->enabled || !udc->vbus) 92562306a36Sopenharmony_ci is_on = 0; 92662306a36Sopenharmony_ci DBG("%sactive\n", is_on ? "" : "in"); 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci if (is_on) { 92962306a36Sopenharmony_ci clk_on(udc); 93062306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM); 93162306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_TXVC, 0); 93262306a36Sopenharmony_ci } else { 93362306a36Sopenharmony_ci stop_activity(udc); 93462306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM); 93562306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); 93662306a36Sopenharmony_ci clk_off(udc); 93762306a36Sopenharmony_ci } 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci if (udc->caps && udc->caps->pullup) 94062306a36Sopenharmony_ci udc->caps->pullup(udc, is_on); 94162306a36Sopenharmony_ci} 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci/* vbus is here! turn everything on that's ready */ 94462306a36Sopenharmony_cistatic int at91_vbus_session(struct usb_gadget *gadget, int is_active) 94562306a36Sopenharmony_ci{ 94662306a36Sopenharmony_ci struct at91_udc *udc = to_udc(gadget); 94762306a36Sopenharmony_ci unsigned long flags; 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci /* VDBG("vbus %s\n", is_active ? "on" : "off"); */ 95062306a36Sopenharmony_ci spin_lock_irqsave(&udc->lock, flags); 95162306a36Sopenharmony_ci udc->vbus = (is_active != 0); 95262306a36Sopenharmony_ci if (udc->driver) 95362306a36Sopenharmony_ci pullup(udc, is_active); 95462306a36Sopenharmony_ci else 95562306a36Sopenharmony_ci pullup(udc, 0); 95662306a36Sopenharmony_ci spin_unlock_irqrestore(&udc->lock, flags); 95762306a36Sopenharmony_ci return 0; 95862306a36Sopenharmony_ci} 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_cistatic int at91_pullup(struct usb_gadget *gadget, int is_on) 96162306a36Sopenharmony_ci{ 96262306a36Sopenharmony_ci struct at91_udc *udc = to_udc(gadget); 96362306a36Sopenharmony_ci unsigned long flags; 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci spin_lock_irqsave(&udc->lock, flags); 96662306a36Sopenharmony_ci udc->enabled = is_on = !!is_on; 96762306a36Sopenharmony_ci pullup(udc, is_on); 96862306a36Sopenharmony_ci spin_unlock_irqrestore(&udc->lock, flags); 96962306a36Sopenharmony_ci return 0; 97062306a36Sopenharmony_ci} 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_cistatic int at91_set_selfpowered(struct usb_gadget *gadget, int is_on) 97362306a36Sopenharmony_ci{ 97462306a36Sopenharmony_ci struct at91_udc *udc = to_udc(gadget); 97562306a36Sopenharmony_ci unsigned long flags; 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci spin_lock_irqsave(&udc->lock, flags); 97862306a36Sopenharmony_ci gadget->is_selfpowered = (is_on != 0); 97962306a36Sopenharmony_ci spin_unlock_irqrestore(&udc->lock, flags); 98062306a36Sopenharmony_ci return 0; 98162306a36Sopenharmony_ci} 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_cistatic int at91_start(struct usb_gadget *gadget, 98462306a36Sopenharmony_ci struct usb_gadget_driver *driver); 98562306a36Sopenharmony_cistatic int at91_stop(struct usb_gadget *gadget); 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_cistatic const struct usb_gadget_ops at91_udc_ops = { 98862306a36Sopenharmony_ci .get_frame = at91_get_frame, 98962306a36Sopenharmony_ci .wakeup = at91_wakeup, 99062306a36Sopenharmony_ci .set_selfpowered = at91_set_selfpowered, 99162306a36Sopenharmony_ci .vbus_session = at91_vbus_session, 99262306a36Sopenharmony_ci .pullup = at91_pullup, 99362306a36Sopenharmony_ci .udc_start = at91_start, 99462306a36Sopenharmony_ci .udc_stop = at91_stop, 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci /* 99762306a36Sopenharmony_ci * VBUS-powered devices may also want to support bigger 99862306a36Sopenharmony_ci * power budgets after an appropriate SET_CONFIGURATION. 99962306a36Sopenharmony_ci */ 100062306a36Sopenharmony_ci /* .vbus_power = at91_vbus_power, */ 100162306a36Sopenharmony_ci}; 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_ci/*-------------------------------------------------------------------------*/ 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_cistatic int handle_ep(struct at91_ep *ep) 100662306a36Sopenharmony_ci{ 100762306a36Sopenharmony_ci struct at91_request *req; 100862306a36Sopenharmony_ci u32 __iomem *creg = ep->creg; 100962306a36Sopenharmony_ci u32 csr = __raw_readl(creg); 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci if (!list_empty(&ep->queue)) 101262306a36Sopenharmony_ci req = list_entry(ep->queue.next, 101362306a36Sopenharmony_ci struct at91_request, queue); 101462306a36Sopenharmony_ci else 101562306a36Sopenharmony_ci req = NULL; 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci if (ep->is_in) { 101862306a36Sopenharmony_ci if (csr & (AT91_UDP_STALLSENT | AT91_UDP_TXCOMP)) { 101962306a36Sopenharmony_ci csr |= CLR_FX; 102062306a36Sopenharmony_ci csr &= ~(SET_FX | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP); 102162306a36Sopenharmony_ci __raw_writel(csr, creg); 102262306a36Sopenharmony_ci } 102362306a36Sopenharmony_ci if (req) 102462306a36Sopenharmony_ci return write_fifo(ep, req); 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci } else { 102762306a36Sopenharmony_ci if (csr & AT91_UDP_STALLSENT) { 102862306a36Sopenharmony_ci /* STALLSENT bit == ISOERR */ 102962306a36Sopenharmony_ci if (ep->is_iso && req) 103062306a36Sopenharmony_ci req->req.status = -EILSEQ; 103162306a36Sopenharmony_ci csr |= CLR_FX; 103262306a36Sopenharmony_ci csr &= ~(SET_FX | AT91_UDP_STALLSENT); 103362306a36Sopenharmony_ci __raw_writel(csr, creg); 103462306a36Sopenharmony_ci csr = __raw_readl(creg); 103562306a36Sopenharmony_ci } 103662306a36Sopenharmony_ci if (req && (csr & RX_DATA_READY)) 103762306a36Sopenharmony_ci return read_fifo(ep, req); 103862306a36Sopenharmony_ci } 103962306a36Sopenharmony_ci return 0; 104062306a36Sopenharmony_ci} 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ciunion setup { 104362306a36Sopenharmony_ci u8 raw[8]; 104462306a36Sopenharmony_ci struct usb_ctrlrequest r; 104562306a36Sopenharmony_ci}; 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_cistatic void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr) 104862306a36Sopenharmony_ci{ 104962306a36Sopenharmony_ci u32 __iomem *creg = ep->creg; 105062306a36Sopenharmony_ci u8 __iomem *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0)); 105162306a36Sopenharmony_ci unsigned rxcount, i = 0; 105262306a36Sopenharmony_ci u32 tmp; 105362306a36Sopenharmony_ci union setup pkt; 105462306a36Sopenharmony_ci int status = 0; 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_ci /* read and ack SETUP; hard-fail for bogus packets */ 105762306a36Sopenharmony_ci rxcount = (csr & AT91_UDP_RXBYTECNT) >> 16; 105862306a36Sopenharmony_ci if (likely(rxcount == 8)) { 105962306a36Sopenharmony_ci while (rxcount--) 106062306a36Sopenharmony_ci pkt.raw[i++] = __raw_readb(dreg); 106162306a36Sopenharmony_ci if (pkt.r.bRequestType & USB_DIR_IN) { 106262306a36Sopenharmony_ci csr |= AT91_UDP_DIR; 106362306a36Sopenharmony_ci ep->is_in = 1; 106462306a36Sopenharmony_ci } else { 106562306a36Sopenharmony_ci csr &= ~AT91_UDP_DIR; 106662306a36Sopenharmony_ci ep->is_in = 0; 106762306a36Sopenharmony_ci } 106862306a36Sopenharmony_ci } else { 106962306a36Sopenharmony_ci /* REVISIT this happens sometimes under load; why?? */ 107062306a36Sopenharmony_ci ERR("SETUP len %d, csr %08x\n", rxcount, csr); 107162306a36Sopenharmony_ci status = -EINVAL; 107262306a36Sopenharmony_ci } 107362306a36Sopenharmony_ci csr |= CLR_FX; 107462306a36Sopenharmony_ci csr &= ~(SET_FX | AT91_UDP_RXSETUP); 107562306a36Sopenharmony_ci __raw_writel(csr, creg); 107662306a36Sopenharmony_ci udc->wait_for_addr_ack = 0; 107762306a36Sopenharmony_ci udc->wait_for_config_ack = 0; 107862306a36Sopenharmony_ci ep->stopped = 0; 107962306a36Sopenharmony_ci if (unlikely(status != 0)) 108062306a36Sopenharmony_ci goto stall; 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci#define w_index le16_to_cpu(pkt.r.wIndex) 108362306a36Sopenharmony_ci#define w_value le16_to_cpu(pkt.r.wValue) 108462306a36Sopenharmony_ci#define w_length le16_to_cpu(pkt.r.wLength) 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci VDBG("SETUP %02x.%02x v%04x i%04x l%04x\n", 108762306a36Sopenharmony_ci pkt.r.bRequestType, pkt.r.bRequest, 108862306a36Sopenharmony_ci w_value, w_index, w_length); 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci /* 109162306a36Sopenharmony_ci * A few standard requests get handled here, ones that touch 109262306a36Sopenharmony_ci * hardware ... notably for device and endpoint features. 109362306a36Sopenharmony_ci */ 109462306a36Sopenharmony_ci udc->req_pending = 1; 109562306a36Sopenharmony_ci csr = __raw_readl(creg); 109662306a36Sopenharmony_ci csr |= CLR_FX; 109762306a36Sopenharmony_ci csr &= ~SET_FX; 109862306a36Sopenharmony_ci switch ((pkt.r.bRequestType << 8) | pkt.r.bRequest) { 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) 110162306a36Sopenharmony_ci | USB_REQ_SET_ADDRESS: 110262306a36Sopenharmony_ci __raw_writel(csr | AT91_UDP_TXPKTRDY, creg); 110362306a36Sopenharmony_ci udc->addr = w_value; 110462306a36Sopenharmony_ci udc->wait_for_addr_ack = 1; 110562306a36Sopenharmony_ci udc->req_pending = 0; 110662306a36Sopenharmony_ci /* FADDR is set later, when we ack host STATUS */ 110762306a36Sopenharmony_ci return; 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) 111062306a36Sopenharmony_ci | USB_REQ_SET_CONFIGURATION: 111162306a36Sopenharmony_ci tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_CONFG; 111262306a36Sopenharmony_ci if (pkt.r.wValue) 111362306a36Sopenharmony_ci udc->wait_for_config_ack = (tmp == 0); 111462306a36Sopenharmony_ci else 111562306a36Sopenharmony_ci udc->wait_for_config_ack = (tmp != 0); 111662306a36Sopenharmony_ci if (udc->wait_for_config_ack) 111762306a36Sopenharmony_ci VDBG("wait for config\n"); 111862306a36Sopenharmony_ci /* CONFG is toggled later, if gadget driver succeeds */ 111962306a36Sopenharmony_ci break; 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci /* 112262306a36Sopenharmony_ci * Hosts may set or clear remote wakeup status, and 112362306a36Sopenharmony_ci * devices may report they're VBUS powered. 112462306a36Sopenharmony_ci */ 112562306a36Sopenharmony_ci case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) 112662306a36Sopenharmony_ci | USB_REQ_GET_STATUS: 112762306a36Sopenharmony_ci tmp = (udc->gadget.is_selfpowered << USB_DEVICE_SELF_POWERED); 112862306a36Sopenharmony_ci if (at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_ESR) 112962306a36Sopenharmony_ci tmp |= (1 << USB_DEVICE_REMOTE_WAKEUP); 113062306a36Sopenharmony_ci PACKET("get device status\n"); 113162306a36Sopenharmony_ci __raw_writeb(tmp, dreg); 113262306a36Sopenharmony_ci __raw_writeb(0, dreg); 113362306a36Sopenharmony_ci goto write_in; 113462306a36Sopenharmony_ci /* then STATUS starts later, automatically */ 113562306a36Sopenharmony_ci case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) 113662306a36Sopenharmony_ci | USB_REQ_SET_FEATURE: 113762306a36Sopenharmony_ci if (w_value != USB_DEVICE_REMOTE_WAKEUP) 113862306a36Sopenharmony_ci goto stall; 113962306a36Sopenharmony_ci tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT); 114062306a36Sopenharmony_ci tmp |= AT91_UDP_ESR; 114162306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp); 114262306a36Sopenharmony_ci goto succeed; 114362306a36Sopenharmony_ci case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) 114462306a36Sopenharmony_ci | USB_REQ_CLEAR_FEATURE: 114562306a36Sopenharmony_ci if (w_value != USB_DEVICE_REMOTE_WAKEUP) 114662306a36Sopenharmony_ci goto stall; 114762306a36Sopenharmony_ci tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT); 114862306a36Sopenharmony_ci tmp &= ~AT91_UDP_ESR; 114962306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp); 115062306a36Sopenharmony_ci goto succeed; 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_ci /* 115362306a36Sopenharmony_ci * Interfaces have no feature settings; this is pretty useless. 115462306a36Sopenharmony_ci * we won't even insist the interface exists... 115562306a36Sopenharmony_ci */ 115662306a36Sopenharmony_ci case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8) 115762306a36Sopenharmony_ci | USB_REQ_GET_STATUS: 115862306a36Sopenharmony_ci PACKET("get interface status\n"); 115962306a36Sopenharmony_ci __raw_writeb(0, dreg); 116062306a36Sopenharmony_ci __raw_writeb(0, dreg); 116162306a36Sopenharmony_ci goto write_in; 116262306a36Sopenharmony_ci /* then STATUS starts later, automatically */ 116362306a36Sopenharmony_ci case ((USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8) 116462306a36Sopenharmony_ci | USB_REQ_SET_FEATURE: 116562306a36Sopenharmony_ci case ((USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8) 116662306a36Sopenharmony_ci | USB_REQ_CLEAR_FEATURE: 116762306a36Sopenharmony_ci goto stall; 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci /* 117062306a36Sopenharmony_ci * Hosts may clear bulk/intr endpoint halt after the gadget 117162306a36Sopenharmony_ci * driver sets it (not widely used); or set it (for testing) 117262306a36Sopenharmony_ci */ 117362306a36Sopenharmony_ci case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8) 117462306a36Sopenharmony_ci | USB_REQ_GET_STATUS: 117562306a36Sopenharmony_ci tmp = w_index & USB_ENDPOINT_NUMBER_MASK; 117662306a36Sopenharmony_ci ep = &udc->ep[tmp]; 117762306a36Sopenharmony_ci if (tmp >= NUM_ENDPOINTS || (tmp && !ep->ep.desc)) 117862306a36Sopenharmony_ci goto stall; 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci if (tmp) { 118162306a36Sopenharmony_ci if ((w_index & USB_DIR_IN)) { 118262306a36Sopenharmony_ci if (!ep->is_in) 118362306a36Sopenharmony_ci goto stall; 118462306a36Sopenharmony_ci } else if (ep->is_in) 118562306a36Sopenharmony_ci goto stall; 118662306a36Sopenharmony_ci } 118762306a36Sopenharmony_ci PACKET("get %s status\n", ep->ep.name); 118862306a36Sopenharmony_ci if (__raw_readl(ep->creg) & AT91_UDP_FORCESTALL) 118962306a36Sopenharmony_ci tmp = (1 << USB_ENDPOINT_HALT); 119062306a36Sopenharmony_ci else 119162306a36Sopenharmony_ci tmp = 0; 119262306a36Sopenharmony_ci __raw_writeb(tmp, dreg); 119362306a36Sopenharmony_ci __raw_writeb(0, dreg); 119462306a36Sopenharmony_ci goto write_in; 119562306a36Sopenharmony_ci /* then STATUS starts later, automatically */ 119662306a36Sopenharmony_ci case ((USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8) 119762306a36Sopenharmony_ci | USB_REQ_SET_FEATURE: 119862306a36Sopenharmony_ci tmp = w_index & USB_ENDPOINT_NUMBER_MASK; 119962306a36Sopenharmony_ci ep = &udc->ep[tmp]; 120062306a36Sopenharmony_ci if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS) 120162306a36Sopenharmony_ci goto stall; 120262306a36Sopenharmony_ci if (!ep->ep.desc || ep->is_iso) 120362306a36Sopenharmony_ci goto stall; 120462306a36Sopenharmony_ci if ((w_index & USB_DIR_IN)) { 120562306a36Sopenharmony_ci if (!ep->is_in) 120662306a36Sopenharmony_ci goto stall; 120762306a36Sopenharmony_ci } else if (ep->is_in) 120862306a36Sopenharmony_ci goto stall; 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci tmp = __raw_readl(ep->creg); 121162306a36Sopenharmony_ci tmp &= ~SET_FX; 121262306a36Sopenharmony_ci tmp |= CLR_FX | AT91_UDP_FORCESTALL; 121362306a36Sopenharmony_ci __raw_writel(tmp, ep->creg); 121462306a36Sopenharmony_ci goto succeed; 121562306a36Sopenharmony_ci case ((USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8) 121662306a36Sopenharmony_ci | USB_REQ_CLEAR_FEATURE: 121762306a36Sopenharmony_ci tmp = w_index & USB_ENDPOINT_NUMBER_MASK; 121862306a36Sopenharmony_ci ep = &udc->ep[tmp]; 121962306a36Sopenharmony_ci if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS) 122062306a36Sopenharmony_ci goto stall; 122162306a36Sopenharmony_ci if (tmp == 0) 122262306a36Sopenharmony_ci goto succeed; 122362306a36Sopenharmony_ci if (!ep->ep.desc || ep->is_iso) 122462306a36Sopenharmony_ci goto stall; 122562306a36Sopenharmony_ci if ((w_index & USB_DIR_IN)) { 122662306a36Sopenharmony_ci if (!ep->is_in) 122762306a36Sopenharmony_ci goto stall; 122862306a36Sopenharmony_ci } else if (ep->is_in) 122962306a36Sopenharmony_ci goto stall; 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask); 123262306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_RST_EP, 0); 123362306a36Sopenharmony_ci tmp = __raw_readl(ep->creg); 123462306a36Sopenharmony_ci tmp |= CLR_FX; 123562306a36Sopenharmony_ci tmp &= ~(SET_FX | AT91_UDP_FORCESTALL); 123662306a36Sopenharmony_ci __raw_writel(tmp, ep->creg); 123762306a36Sopenharmony_ci if (!list_empty(&ep->queue)) 123862306a36Sopenharmony_ci handle_ep(ep); 123962306a36Sopenharmony_ci goto succeed; 124062306a36Sopenharmony_ci } 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci#undef w_value 124362306a36Sopenharmony_ci#undef w_index 124462306a36Sopenharmony_ci#undef w_length 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci /* pass request up to the gadget driver */ 124762306a36Sopenharmony_ci if (udc->driver) { 124862306a36Sopenharmony_ci spin_unlock(&udc->lock); 124962306a36Sopenharmony_ci status = udc->driver->setup(&udc->gadget, &pkt.r); 125062306a36Sopenharmony_ci spin_lock(&udc->lock); 125162306a36Sopenharmony_ci } 125262306a36Sopenharmony_ci else 125362306a36Sopenharmony_ci status = -ENODEV; 125462306a36Sopenharmony_ci if (status < 0) { 125562306a36Sopenharmony_cistall: 125662306a36Sopenharmony_ci VDBG("req %02x.%02x protocol STALL; stat %d\n", 125762306a36Sopenharmony_ci pkt.r.bRequestType, pkt.r.bRequest, status); 125862306a36Sopenharmony_ci csr |= AT91_UDP_FORCESTALL; 125962306a36Sopenharmony_ci __raw_writel(csr, creg); 126062306a36Sopenharmony_ci udc->req_pending = 0; 126162306a36Sopenharmony_ci } 126262306a36Sopenharmony_ci return; 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_cisucceed: 126562306a36Sopenharmony_ci /* immediate successful (IN) STATUS after zero length DATA */ 126662306a36Sopenharmony_ci PACKET("ep0 in/status\n"); 126762306a36Sopenharmony_ciwrite_in: 126862306a36Sopenharmony_ci csr |= AT91_UDP_TXPKTRDY; 126962306a36Sopenharmony_ci __raw_writel(csr, creg); 127062306a36Sopenharmony_ci udc->req_pending = 0; 127162306a36Sopenharmony_ci} 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_cistatic void handle_ep0(struct at91_udc *udc) 127462306a36Sopenharmony_ci{ 127562306a36Sopenharmony_ci struct at91_ep *ep0 = &udc->ep[0]; 127662306a36Sopenharmony_ci u32 __iomem *creg = ep0->creg; 127762306a36Sopenharmony_ci u32 csr = __raw_readl(creg); 127862306a36Sopenharmony_ci struct at91_request *req; 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci if (unlikely(csr & AT91_UDP_STALLSENT)) { 128162306a36Sopenharmony_ci nuke(ep0, -EPROTO); 128262306a36Sopenharmony_ci udc->req_pending = 0; 128362306a36Sopenharmony_ci csr |= CLR_FX; 128462306a36Sopenharmony_ci csr &= ~(SET_FX | AT91_UDP_STALLSENT | AT91_UDP_FORCESTALL); 128562306a36Sopenharmony_ci __raw_writel(csr, creg); 128662306a36Sopenharmony_ci VDBG("ep0 stalled\n"); 128762306a36Sopenharmony_ci csr = __raw_readl(creg); 128862306a36Sopenharmony_ci } 128962306a36Sopenharmony_ci if (csr & AT91_UDP_RXSETUP) { 129062306a36Sopenharmony_ci nuke(ep0, 0); 129162306a36Sopenharmony_ci udc->req_pending = 0; 129262306a36Sopenharmony_ci handle_setup(udc, ep0, csr); 129362306a36Sopenharmony_ci return; 129462306a36Sopenharmony_ci } 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_ci if (list_empty(&ep0->queue)) 129762306a36Sopenharmony_ci req = NULL; 129862306a36Sopenharmony_ci else 129962306a36Sopenharmony_ci req = list_entry(ep0->queue.next, struct at91_request, queue); 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci /* host ACKed an IN packet that we sent */ 130262306a36Sopenharmony_ci if (csr & AT91_UDP_TXCOMP) { 130362306a36Sopenharmony_ci csr |= CLR_FX; 130462306a36Sopenharmony_ci csr &= ~(SET_FX | AT91_UDP_TXCOMP); 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci /* write more IN DATA? */ 130762306a36Sopenharmony_ci if (req && ep0->is_in) { 130862306a36Sopenharmony_ci if (handle_ep(ep0)) 130962306a36Sopenharmony_ci udc->req_pending = 0; 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci /* 131262306a36Sopenharmony_ci * Ack after: 131362306a36Sopenharmony_ci * - last IN DATA packet (including GET_STATUS) 131462306a36Sopenharmony_ci * - IN/STATUS for OUT DATA 131562306a36Sopenharmony_ci * - IN/STATUS for any zero-length DATA stage 131662306a36Sopenharmony_ci * except for the IN DATA case, the host should send 131762306a36Sopenharmony_ci * an OUT status later, which we'll ack. 131862306a36Sopenharmony_ci */ 131962306a36Sopenharmony_ci } else { 132062306a36Sopenharmony_ci udc->req_pending = 0; 132162306a36Sopenharmony_ci __raw_writel(csr, creg); 132262306a36Sopenharmony_ci 132362306a36Sopenharmony_ci /* 132462306a36Sopenharmony_ci * SET_ADDRESS takes effect only after the STATUS 132562306a36Sopenharmony_ci * (to the original address) gets acked. 132662306a36Sopenharmony_ci */ 132762306a36Sopenharmony_ci if (udc->wait_for_addr_ack) { 132862306a36Sopenharmony_ci u32 tmp; 132962306a36Sopenharmony_ci 133062306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_FADDR, 133162306a36Sopenharmony_ci AT91_UDP_FEN | udc->addr); 133262306a36Sopenharmony_ci tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT); 133362306a36Sopenharmony_ci tmp &= ~AT91_UDP_FADDEN; 133462306a36Sopenharmony_ci if (udc->addr) 133562306a36Sopenharmony_ci tmp |= AT91_UDP_FADDEN; 133662306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp); 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_ci udc->wait_for_addr_ack = 0; 133962306a36Sopenharmony_ci VDBG("address %d\n", udc->addr); 134062306a36Sopenharmony_ci } 134162306a36Sopenharmony_ci } 134262306a36Sopenharmony_ci } 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci /* OUT packet arrived ... */ 134562306a36Sopenharmony_ci else if (csr & AT91_UDP_RX_DATA_BK0) { 134662306a36Sopenharmony_ci csr |= CLR_FX; 134762306a36Sopenharmony_ci csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0); 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_ci /* OUT DATA stage */ 135062306a36Sopenharmony_ci if (!ep0->is_in) { 135162306a36Sopenharmony_ci if (req) { 135262306a36Sopenharmony_ci if (handle_ep(ep0)) { 135362306a36Sopenharmony_ci /* send IN/STATUS */ 135462306a36Sopenharmony_ci PACKET("ep0 in/status\n"); 135562306a36Sopenharmony_ci csr = __raw_readl(creg); 135662306a36Sopenharmony_ci csr &= ~SET_FX; 135762306a36Sopenharmony_ci csr |= CLR_FX | AT91_UDP_TXPKTRDY; 135862306a36Sopenharmony_ci __raw_writel(csr, creg); 135962306a36Sopenharmony_ci udc->req_pending = 0; 136062306a36Sopenharmony_ci } 136162306a36Sopenharmony_ci } else if (udc->req_pending) { 136262306a36Sopenharmony_ci /* 136362306a36Sopenharmony_ci * AT91 hardware has a hard time with this 136462306a36Sopenharmony_ci * "deferred response" mode for control-OUT 136562306a36Sopenharmony_ci * transfers. (For control-IN it's fine.) 136662306a36Sopenharmony_ci * 136762306a36Sopenharmony_ci * The normal solution leaves OUT data in the 136862306a36Sopenharmony_ci * fifo until the gadget driver is ready. 136962306a36Sopenharmony_ci * We couldn't do that here without disabling 137062306a36Sopenharmony_ci * the IRQ that tells about SETUP packets, 137162306a36Sopenharmony_ci * e.g. when the host gets impatient... 137262306a36Sopenharmony_ci * 137362306a36Sopenharmony_ci * Working around it by copying into a buffer 137462306a36Sopenharmony_ci * would almost be a non-deferred response, 137562306a36Sopenharmony_ci * except that it wouldn't permit reliable 137662306a36Sopenharmony_ci * stalling of the request. Instead, demand 137762306a36Sopenharmony_ci * that gadget drivers not use this mode. 137862306a36Sopenharmony_ci */ 137962306a36Sopenharmony_ci DBG("no control-OUT deferred responses!\n"); 138062306a36Sopenharmony_ci __raw_writel(csr | AT91_UDP_FORCESTALL, creg); 138162306a36Sopenharmony_ci udc->req_pending = 0; 138262306a36Sopenharmony_ci } 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci /* STATUS stage for control-IN; ack. */ 138562306a36Sopenharmony_ci } else { 138662306a36Sopenharmony_ci PACKET("ep0 out/status ACK\n"); 138762306a36Sopenharmony_ci __raw_writel(csr, creg); 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci /* "early" status stage */ 139062306a36Sopenharmony_ci if (req) 139162306a36Sopenharmony_ci done(ep0, req, 0); 139262306a36Sopenharmony_ci } 139362306a36Sopenharmony_ci } 139462306a36Sopenharmony_ci} 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_cistatic irqreturn_t at91_udc_irq (int irq, void *_udc) 139762306a36Sopenharmony_ci{ 139862306a36Sopenharmony_ci struct at91_udc *udc = _udc; 139962306a36Sopenharmony_ci u32 rescans = 5; 140062306a36Sopenharmony_ci int disable_clock = 0; 140162306a36Sopenharmony_ci unsigned long flags; 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci spin_lock_irqsave(&udc->lock, flags); 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_ci if (!udc->clocked) { 140662306a36Sopenharmony_ci clk_on(udc); 140762306a36Sopenharmony_ci disable_clock = 1; 140862306a36Sopenharmony_ci } 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ci while (rescans--) { 141162306a36Sopenharmony_ci u32 status; 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci status = at91_udp_read(udc, AT91_UDP_ISR) 141462306a36Sopenharmony_ci & at91_udp_read(udc, AT91_UDP_IMR); 141562306a36Sopenharmony_ci if (!status) 141662306a36Sopenharmony_ci break; 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci /* USB reset irq: not maskable */ 141962306a36Sopenharmony_ci if (status & AT91_UDP_ENDBUSRES) { 142062306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_IDR, ~MINIMUS_INTERRUPTUS); 142162306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_IER, MINIMUS_INTERRUPTUS); 142262306a36Sopenharmony_ci /* Atmel code clears this irq twice */ 142362306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES); 142462306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES); 142562306a36Sopenharmony_ci VDBG("end bus reset\n"); 142662306a36Sopenharmony_ci udc->addr = 0; 142762306a36Sopenharmony_ci reset_gadget(udc); 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci /* enable ep0 */ 143062306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_CSR(0), 143162306a36Sopenharmony_ci AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL); 143262306a36Sopenharmony_ci udc->gadget.speed = USB_SPEED_FULL; 143362306a36Sopenharmony_ci udc->suspended = 0; 143462306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_EP(0)); 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci /* 143762306a36Sopenharmony_ci * NOTE: this driver keeps clocks off unless the 143862306a36Sopenharmony_ci * USB host is present. That saves power, but for 143962306a36Sopenharmony_ci * boards that don't support VBUS detection, both 144062306a36Sopenharmony_ci * clocks need to be active most of the time. 144162306a36Sopenharmony_ci */ 144262306a36Sopenharmony_ci 144362306a36Sopenharmony_ci /* host initiated suspend (3+ms bus idle) */ 144462306a36Sopenharmony_ci } else if (status & AT91_UDP_RXSUSP) { 144562306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXSUSP); 144662306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXRSM); 144762306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXSUSP); 144862306a36Sopenharmony_ci /* VDBG("bus suspend\n"); */ 144962306a36Sopenharmony_ci if (udc->suspended) 145062306a36Sopenharmony_ci continue; 145162306a36Sopenharmony_ci udc->suspended = 1; 145262306a36Sopenharmony_ci 145362306a36Sopenharmony_ci /* 145462306a36Sopenharmony_ci * NOTE: when suspending a VBUS-powered device, the 145562306a36Sopenharmony_ci * gadget driver should switch into slow clock mode 145662306a36Sopenharmony_ci * and then into standby to avoid drawing more than 145762306a36Sopenharmony_ci * 500uA power (2500uA for some high-power configs). 145862306a36Sopenharmony_ci */ 145962306a36Sopenharmony_ci if (udc->driver && udc->driver->suspend) { 146062306a36Sopenharmony_ci spin_unlock(&udc->lock); 146162306a36Sopenharmony_ci udc->driver->suspend(&udc->gadget); 146262306a36Sopenharmony_ci spin_lock(&udc->lock); 146362306a36Sopenharmony_ci } 146462306a36Sopenharmony_ci 146562306a36Sopenharmony_ci /* host initiated resume */ 146662306a36Sopenharmony_ci } else if (status & AT91_UDP_RXRSM) { 146762306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM); 146862306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXSUSP); 146962306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM); 147062306a36Sopenharmony_ci /* VDBG("bus resume\n"); */ 147162306a36Sopenharmony_ci if (!udc->suspended) 147262306a36Sopenharmony_ci continue; 147362306a36Sopenharmony_ci udc->suspended = 0; 147462306a36Sopenharmony_ci 147562306a36Sopenharmony_ci /* 147662306a36Sopenharmony_ci * NOTE: for a VBUS-powered device, the gadget driver 147762306a36Sopenharmony_ci * would normally want to switch out of slow clock 147862306a36Sopenharmony_ci * mode into normal mode. 147962306a36Sopenharmony_ci */ 148062306a36Sopenharmony_ci if (udc->driver && udc->driver->resume) { 148162306a36Sopenharmony_ci spin_unlock(&udc->lock); 148262306a36Sopenharmony_ci udc->driver->resume(&udc->gadget); 148362306a36Sopenharmony_ci spin_lock(&udc->lock); 148462306a36Sopenharmony_ci } 148562306a36Sopenharmony_ci 148662306a36Sopenharmony_ci /* endpoint IRQs are cleared by handling them */ 148762306a36Sopenharmony_ci } else { 148862306a36Sopenharmony_ci int i; 148962306a36Sopenharmony_ci unsigned mask = 1; 149062306a36Sopenharmony_ci struct at91_ep *ep = &udc->ep[1]; 149162306a36Sopenharmony_ci 149262306a36Sopenharmony_ci if (status & mask) 149362306a36Sopenharmony_ci handle_ep0(udc); 149462306a36Sopenharmony_ci for (i = 1; i < NUM_ENDPOINTS; i++) { 149562306a36Sopenharmony_ci mask <<= 1; 149662306a36Sopenharmony_ci if (status & mask) 149762306a36Sopenharmony_ci handle_ep(ep); 149862306a36Sopenharmony_ci ep++; 149962306a36Sopenharmony_ci } 150062306a36Sopenharmony_ci } 150162306a36Sopenharmony_ci } 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci if (disable_clock) 150462306a36Sopenharmony_ci clk_off(udc); 150562306a36Sopenharmony_ci 150662306a36Sopenharmony_ci spin_unlock_irqrestore(&udc->lock, flags); 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_ci return IRQ_HANDLED; 150962306a36Sopenharmony_ci} 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_ci/*-------------------------------------------------------------------------*/ 151262306a36Sopenharmony_ci 151362306a36Sopenharmony_cistatic void at91_vbus_update(struct at91_udc *udc, unsigned value) 151462306a36Sopenharmony_ci{ 151562306a36Sopenharmony_ci if (value != udc->vbus) 151662306a36Sopenharmony_ci at91_vbus_session(&udc->gadget, value); 151762306a36Sopenharmony_ci} 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_cistatic irqreturn_t at91_vbus_irq(int irq, void *_udc) 152062306a36Sopenharmony_ci{ 152162306a36Sopenharmony_ci struct at91_udc *udc = _udc; 152262306a36Sopenharmony_ci 152362306a36Sopenharmony_ci /* vbus needs at least brief debouncing */ 152462306a36Sopenharmony_ci udelay(10); 152562306a36Sopenharmony_ci at91_vbus_update(udc, gpiod_get_value(udc->board.vbus_pin)); 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci return IRQ_HANDLED; 152862306a36Sopenharmony_ci} 152962306a36Sopenharmony_ci 153062306a36Sopenharmony_cistatic void at91_vbus_timer_work(struct work_struct *work) 153162306a36Sopenharmony_ci{ 153262306a36Sopenharmony_ci struct at91_udc *udc = container_of(work, struct at91_udc, 153362306a36Sopenharmony_ci vbus_timer_work); 153462306a36Sopenharmony_ci 153562306a36Sopenharmony_ci at91_vbus_update(udc, gpiod_get_value_cansleep(udc->board.vbus_pin)); 153662306a36Sopenharmony_ci 153762306a36Sopenharmony_ci if (!timer_pending(&udc->vbus_timer)) 153862306a36Sopenharmony_ci mod_timer(&udc->vbus_timer, jiffies + VBUS_POLL_TIMEOUT); 153962306a36Sopenharmony_ci} 154062306a36Sopenharmony_ci 154162306a36Sopenharmony_cistatic void at91_vbus_timer(struct timer_list *t) 154262306a36Sopenharmony_ci{ 154362306a36Sopenharmony_ci struct at91_udc *udc = from_timer(udc, t, vbus_timer); 154462306a36Sopenharmony_ci 154562306a36Sopenharmony_ci /* 154662306a36Sopenharmony_ci * If we are polling vbus it is likely that the gpio is on an 154762306a36Sopenharmony_ci * bus such as i2c or spi which may sleep, so schedule some work 154862306a36Sopenharmony_ci * to read the vbus gpio 154962306a36Sopenharmony_ci */ 155062306a36Sopenharmony_ci schedule_work(&udc->vbus_timer_work); 155162306a36Sopenharmony_ci} 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_cistatic int at91_start(struct usb_gadget *gadget, 155462306a36Sopenharmony_ci struct usb_gadget_driver *driver) 155562306a36Sopenharmony_ci{ 155662306a36Sopenharmony_ci struct at91_udc *udc; 155762306a36Sopenharmony_ci 155862306a36Sopenharmony_ci udc = container_of(gadget, struct at91_udc, gadget); 155962306a36Sopenharmony_ci udc->driver = driver; 156062306a36Sopenharmony_ci udc->gadget.dev.of_node = udc->pdev->dev.of_node; 156162306a36Sopenharmony_ci udc->enabled = 1; 156262306a36Sopenharmony_ci udc->gadget.is_selfpowered = 1; 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci return 0; 156562306a36Sopenharmony_ci} 156662306a36Sopenharmony_ci 156762306a36Sopenharmony_cistatic int at91_stop(struct usb_gadget *gadget) 156862306a36Sopenharmony_ci{ 156962306a36Sopenharmony_ci struct at91_udc *udc; 157062306a36Sopenharmony_ci unsigned long flags; 157162306a36Sopenharmony_ci 157262306a36Sopenharmony_ci udc = container_of(gadget, struct at91_udc, gadget); 157362306a36Sopenharmony_ci spin_lock_irqsave(&udc->lock, flags); 157462306a36Sopenharmony_ci udc->enabled = 0; 157562306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_IDR, ~0); 157662306a36Sopenharmony_ci spin_unlock_irqrestore(&udc->lock, flags); 157762306a36Sopenharmony_ci 157862306a36Sopenharmony_ci udc->driver = NULL; 157962306a36Sopenharmony_ci 158062306a36Sopenharmony_ci return 0; 158162306a36Sopenharmony_ci} 158262306a36Sopenharmony_ci 158362306a36Sopenharmony_ci/*-------------------------------------------------------------------------*/ 158462306a36Sopenharmony_ci 158562306a36Sopenharmony_cistatic void at91udc_shutdown(struct platform_device *dev) 158662306a36Sopenharmony_ci{ 158762306a36Sopenharmony_ci struct at91_udc *udc = platform_get_drvdata(dev); 158862306a36Sopenharmony_ci unsigned long flags; 158962306a36Sopenharmony_ci 159062306a36Sopenharmony_ci /* force disconnect on reboot */ 159162306a36Sopenharmony_ci spin_lock_irqsave(&udc->lock, flags); 159262306a36Sopenharmony_ci pullup(platform_get_drvdata(dev), 0); 159362306a36Sopenharmony_ci spin_unlock_irqrestore(&udc->lock, flags); 159462306a36Sopenharmony_ci} 159562306a36Sopenharmony_ci 159662306a36Sopenharmony_cistatic int at91rm9200_udc_init(struct at91_udc *udc) 159762306a36Sopenharmony_ci{ 159862306a36Sopenharmony_ci struct at91_ep *ep; 159962306a36Sopenharmony_ci int i; 160062306a36Sopenharmony_ci 160162306a36Sopenharmony_ci for (i = 0; i < NUM_ENDPOINTS; i++) { 160262306a36Sopenharmony_ci ep = &udc->ep[i]; 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci switch (i) { 160562306a36Sopenharmony_ci case 0: 160662306a36Sopenharmony_ci case 3: 160762306a36Sopenharmony_ci ep->maxpacket = 8; 160862306a36Sopenharmony_ci break; 160962306a36Sopenharmony_ci case 1 ... 2: 161062306a36Sopenharmony_ci ep->maxpacket = 64; 161162306a36Sopenharmony_ci break; 161262306a36Sopenharmony_ci case 4 ... 5: 161362306a36Sopenharmony_ci ep->maxpacket = 256; 161462306a36Sopenharmony_ci break; 161562306a36Sopenharmony_ci } 161662306a36Sopenharmony_ci } 161762306a36Sopenharmony_ci 161862306a36Sopenharmony_ci if (!udc->board.pullup_pin) { 161962306a36Sopenharmony_ci DBG("no D+ pullup?\n"); 162062306a36Sopenharmony_ci return -ENODEV; 162162306a36Sopenharmony_ci } 162262306a36Sopenharmony_ci 162362306a36Sopenharmony_ci gpiod_direction_output(udc->board.pullup_pin, 162462306a36Sopenharmony_ci gpiod_is_active_low(udc->board.pullup_pin)); 162562306a36Sopenharmony_ci 162662306a36Sopenharmony_ci return 0; 162762306a36Sopenharmony_ci} 162862306a36Sopenharmony_ci 162962306a36Sopenharmony_cistatic void at91rm9200_udc_pullup(struct at91_udc *udc, int is_on) 163062306a36Sopenharmony_ci{ 163162306a36Sopenharmony_ci gpiod_set_value(udc->board.pullup_pin, is_on); 163262306a36Sopenharmony_ci} 163362306a36Sopenharmony_ci 163462306a36Sopenharmony_cistatic const struct at91_udc_caps at91rm9200_udc_caps = { 163562306a36Sopenharmony_ci .init = at91rm9200_udc_init, 163662306a36Sopenharmony_ci .pullup = at91rm9200_udc_pullup, 163762306a36Sopenharmony_ci}; 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_cistatic int at91sam9260_udc_init(struct at91_udc *udc) 164062306a36Sopenharmony_ci{ 164162306a36Sopenharmony_ci struct at91_ep *ep; 164262306a36Sopenharmony_ci int i; 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_ci for (i = 0; i < NUM_ENDPOINTS; i++) { 164562306a36Sopenharmony_ci ep = &udc->ep[i]; 164662306a36Sopenharmony_ci 164762306a36Sopenharmony_ci switch (i) { 164862306a36Sopenharmony_ci case 0 ... 3: 164962306a36Sopenharmony_ci ep->maxpacket = 64; 165062306a36Sopenharmony_ci break; 165162306a36Sopenharmony_ci case 4 ... 5: 165262306a36Sopenharmony_ci ep->maxpacket = 512; 165362306a36Sopenharmony_ci break; 165462306a36Sopenharmony_ci } 165562306a36Sopenharmony_ci } 165662306a36Sopenharmony_ci 165762306a36Sopenharmony_ci return 0; 165862306a36Sopenharmony_ci} 165962306a36Sopenharmony_ci 166062306a36Sopenharmony_cistatic void at91sam9260_udc_pullup(struct at91_udc *udc, int is_on) 166162306a36Sopenharmony_ci{ 166262306a36Sopenharmony_ci u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); 166362306a36Sopenharmony_ci 166462306a36Sopenharmony_ci if (is_on) 166562306a36Sopenharmony_ci txvc |= AT91_UDP_TXVC_PUON; 166662306a36Sopenharmony_ci else 166762306a36Sopenharmony_ci txvc &= ~AT91_UDP_TXVC_PUON; 166862306a36Sopenharmony_ci 166962306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_TXVC, txvc); 167062306a36Sopenharmony_ci} 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_cistatic const struct at91_udc_caps at91sam9260_udc_caps = { 167362306a36Sopenharmony_ci .init = at91sam9260_udc_init, 167462306a36Sopenharmony_ci .pullup = at91sam9260_udc_pullup, 167562306a36Sopenharmony_ci}; 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_cistatic int at91sam9261_udc_init(struct at91_udc *udc) 167862306a36Sopenharmony_ci{ 167962306a36Sopenharmony_ci struct at91_ep *ep; 168062306a36Sopenharmony_ci int i; 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_ci for (i = 0; i < NUM_ENDPOINTS; i++) { 168362306a36Sopenharmony_ci ep = &udc->ep[i]; 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci switch (i) { 168662306a36Sopenharmony_ci case 0: 168762306a36Sopenharmony_ci ep->maxpacket = 8; 168862306a36Sopenharmony_ci break; 168962306a36Sopenharmony_ci case 1 ... 3: 169062306a36Sopenharmony_ci ep->maxpacket = 64; 169162306a36Sopenharmony_ci break; 169262306a36Sopenharmony_ci case 4 ... 5: 169362306a36Sopenharmony_ci ep->maxpacket = 256; 169462306a36Sopenharmony_ci break; 169562306a36Sopenharmony_ci } 169662306a36Sopenharmony_ci } 169762306a36Sopenharmony_ci 169862306a36Sopenharmony_ci udc->matrix = syscon_regmap_lookup_by_phandle(udc->pdev->dev.of_node, 169962306a36Sopenharmony_ci "atmel,matrix"); 170062306a36Sopenharmony_ci return PTR_ERR_OR_ZERO(udc->matrix); 170162306a36Sopenharmony_ci} 170262306a36Sopenharmony_ci 170362306a36Sopenharmony_cistatic void at91sam9261_udc_pullup(struct at91_udc *udc, int is_on) 170462306a36Sopenharmony_ci{ 170562306a36Sopenharmony_ci u32 usbpucr = 0; 170662306a36Sopenharmony_ci 170762306a36Sopenharmony_ci if (is_on) 170862306a36Sopenharmony_ci usbpucr = AT91_MATRIX_USBPUCR_PUON; 170962306a36Sopenharmony_ci 171062306a36Sopenharmony_ci regmap_update_bits(udc->matrix, AT91SAM9261_MATRIX_USBPUCR, 171162306a36Sopenharmony_ci AT91_MATRIX_USBPUCR_PUON, usbpucr); 171262306a36Sopenharmony_ci} 171362306a36Sopenharmony_ci 171462306a36Sopenharmony_cistatic const struct at91_udc_caps at91sam9261_udc_caps = { 171562306a36Sopenharmony_ci .init = at91sam9261_udc_init, 171662306a36Sopenharmony_ci .pullup = at91sam9261_udc_pullup, 171762306a36Sopenharmony_ci}; 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_cistatic int at91sam9263_udc_init(struct at91_udc *udc) 172062306a36Sopenharmony_ci{ 172162306a36Sopenharmony_ci struct at91_ep *ep; 172262306a36Sopenharmony_ci int i; 172362306a36Sopenharmony_ci 172462306a36Sopenharmony_ci for (i = 0; i < NUM_ENDPOINTS; i++) { 172562306a36Sopenharmony_ci ep = &udc->ep[i]; 172662306a36Sopenharmony_ci 172762306a36Sopenharmony_ci switch (i) { 172862306a36Sopenharmony_ci case 0: 172962306a36Sopenharmony_ci case 1: 173062306a36Sopenharmony_ci case 2: 173162306a36Sopenharmony_ci case 3: 173262306a36Sopenharmony_ci ep->maxpacket = 64; 173362306a36Sopenharmony_ci break; 173462306a36Sopenharmony_ci case 4: 173562306a36Sopenharmony_ci case 5: 173662306a36Sopenharmony_ci ep->maxpacket = 256; 173762306a36Sopenharmony_ci break; 173862306a36Sopenharmony_ci } 173962306a36Sopenharmony_ci } 174062306a36Sopenharmony_ci 174162306a36Sopenharmony_ci return 0; 174262306a36Sopenharmony_ci} 174362306a36Sopenharmony_ci 174462306a36Sopenharmony_cistatic const struct at91_udc_caps at91sam9263_udc_caps = { 174562306a36Sopenharmony_ci .init = at91sam9263_udc_init, 174662306a36Sopenharmony_ci .pullup = at91sam9260_udc_pullup, 174762306a36Sopenharmony_ci}; 174862306a36Sopenharmony_ci 174962306a36Sopenharmony_cistatic const struct of_device_id at91_udc_dt_ids[] = { 175062306a36Sopenharmony_ci { 175162306a36Sopenharmony_ci .compatible = "atmel,at91rm9200-udc", 175262306a36Sopenharmony_ci .data = &at91rm9200_udc_caps, 175362306a36Sopenharmony_ci }, 175462306a36Sopenharmony_ci { 175562306a36Sopenharmony_ci .compatible = "atmel,at91sam9260-udc", 175662306a36Sopenharmony_ci .data = &at91sam9260_udc_caps, 175762306a36Sopenharmony_ci }, 175862306a36Sopenharmony_ci { 175962306a36Sopenharmony_ci .compatible = "atmel,at91sam9261-udc", 176062306a36Sopenharmony_ci .data = &at91sam9261_udc_caps, 176162306a36Sopenharmony_ci }, 176262306a36Sopenharmony_ci { 176362306a36Sopenharmony_ci .compatible = "atmel,at91sam9263-udc", 176462306a36Sopenharmony_ci .data = &at91sam9263_udc_caps, 176562306a36Sopenharmony_ci }, 176662306a36Sopenharmony_ci { /* sentinel */ } 176762306a36Sopenharmony_ci}; 176862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, at91_udc_dt_ids); 176962306a36Sopenharmony_ci 177062306a36Sopenharmony_cistatic void at91udc_of_init(struct at91_udc *udc, struct device_node *np) 177162306a36Sopenharmony_ci{ 177262306a36Sopenharmony_ci struct at91_udc_data *board = &udc->board; 177362306a36Sopenharmony_ci const struct of_device_id *match; 177462306a36Sopenharmony_ci u32 val; 177562306a36Sopenharmony_ci 177662306a36Sopenharmony_ci if (of_property_read_u32(np, "atmel,vbus-polled", &val) == 0) 177762306a36Sopenharmony_ci board->vbus_polled = 1; 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci board->vbus_pin = fwnode_gpiod_get_index(of_fwnode_handle(np), 178062306a36Sopenharmony_ci "atmel,vbus", 0, GPIOD_IN, 178162306a36Sopenharmony_ci "udc_vbus"); 178262306a36Sopenharmony_ci if (IS_ERR(board->vbus_pin)) 178362306a36Sopenharmony_ci board->vbus_pin = NULL; 178462306a36Sopenharmony_ci 178562306a36Sopenharmony_ci board->pullup_pin = fwnode_gpiod_get_index(of_fwnode_handle(np), 178662306a36Sopenharmony_ci "atmel,pullup", 0, 178762306a36Sopenharmony_ci GPIOD_ASIS, "udc_pullup"); 178862306a36Sopenharmony_ci if (IS_ERR(board->pullup_pin)) 178962306a36Sopenharmony_ci board->pullup_pin = NULL; 179062306a36Sopenharmony_ci 179162306a36Sopenharmony_ci match = of_match_node(at91_udc_dt_ids, np); 179262306a36Sopenharmony_ci if (match) 179362306a36Sopenharmony_ci udc->caps = match->data; 179462306a36Sopenharmony_ci} 179562306a36Sopenharmony_ci 179662306a36Sopenharmony_cistatic int at91udc_probe(struct platform_device *pdev) 179762306a36Sopenharmony_ci{ 179862306a36Sopenharmony_ci struct device *dev = &pdev->dev; 179962306a36Sopenharmony_ci struct at91_udc *udc; 180062306a36Sopenharmony_ci int retval; 180162306a36Sopenharmony_ci struct at91_ep *ep; 180262306a36Sopenharmony_ci int i; 180362306a36Sopenharmony_ci 180462306a36Sopenharmony_ci udc = devm_kzalloc(dev, sizeof(*udc), GFP_KERNEL); 180562306a36Sopenharmony_ci if (!udc) 180662306a36Sopenharmony_ci return -ENOMEM; 180762306a36Sopenharmony_ci 180862306a36Sopenharmony_ci /* init software state */ 180962306a36Sopenharmony_ci udc->gadget.dev.parent = dev; 181062306a36Sopenharmony_ci at91udc_of_init(udc, pdev->dev.of_node); 181162306a36Sopenharmony_ci udc->pdev = pdev; 181262306a36Sopenharmony_ci udc->enabled = 0; 181362306a36Sopenharmony_ci spin_lock_init(&udc->lock); 181462306a36Sopenharmony_ci 181562306a36Sopenharmony_ci udc->gadget.ops = &at91_udc_ops; 181662306a36Sopenharmony_ci udc->gadget.ep0 = &udc->ep[0].ep; 181762306a36Sopenharmony_ci udc->gadget.name = driver_name; 181862306a36Sopenharmony_ci udc->gadget.dev.init_name = "gadget"; 181962306a36Sopenharmony_ci 182062306a36Sopenharmony_ci for (i = 0; i < NUM_ENDPOINTS; i++) { 182162306a36Sopenharmony_ci ep = &udc->ep[i]; 182262306a36Sopenharmony_ci ep->ep.name = ep_info[i].name; 182362306a36Sopenharmony_ci ep->ep.caps = ep_info[i].caps; 182462306a36Sopenharmony_ci ep->ep.ops = &at91_ep_ops; 182562306a36Sopenharmony_ci ep->udc = udc; 182662306a36Sopenharmony_ci ep->int_mask = BIT(i); 182762306a36Sopenharmony_ci if (i != 0 && i != 3) 182862306a36Sopenharmony_ci ep->is_pingpong = 1; 182962306a36Sopenharmony_ci } 183062306a36Sopenharmony_ci 183162306a36Sopenharmony_ci udc->udp_baseaddr = devm_platform_ioremap_resource(pdev, 0); 183262306a36Sopenharmony_ci if (IS_ERR(udc->udp_baseaddr)) 183362306a36Sopenharmony_ci return PTR_ERR(udc->udp_baseaddr); 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_ci if (udc->caps && udc->caps->init) { 183662306a36Sopenharmony_ci retval = udc->caps->init(udc); 183762306a36Sopenharmony_ci if (retval) 183862306a36Sopenharmony_ci return retval; 183962306a36Sopenharmony_ci } 184062306a36Sopenharmony_ci 184162306a36Sopenharmony_ci udc_reinit(udc); 184262306a36Sopenharmony_ci 184362306a36Sopenharmony_ci /* get interface and function clocks */ 184462306a36Sopenharmony_ci udc->iclk = devm_clk_get(dev, "pclk"); 184562306a36Sopenharmony_ci if (IS_ERR(udc->iclk)) 184662306a36Sopenharmony_ci return PTR_ERR(udc->iclk); 184762306a36Sopenharmony_ci 184862306a36Sopenharmony_ci udc->fclk = devm_clk_get(dev, "hclk"); 184962306a36Sopenharmony_ci if (IS_ERR(udc->fclk)) 185062306a36Sopenharmony_ci return PTR_ERR(udc->fclk); 185162306a36Sopenharmony_ci 185262306a36Sopenharmony_ci /* don't do anything until we have both gadget driver and VBUS */ 185362306a36Sopenharmony_ci clk_set_rate(udc->fclk, 48000000); 185462306a36Sopenharmony_ci retval = clk_prepare(udc->fclk); 185562306a36Sopenharmony_ci if (retval) 185662306a36Sopenharmony_ci return retval; 185762306a36Sopenharmony_ci 185862306a36Sopenharmony_ci retval = clk_prepare_enable(udc->iclk); 185962306a36Sopenharmony_ci if (retval) 186062306a36Sopenharmony_ci goto err_unprepare_fclk; 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); 186362306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff); 186462306a36Sopenharmony_ci /* Clear all pending interrupts - UDP may be used by bootloader. */ 186562306a36Sopenharmony_ci at91_udp_write(udc, AT91_UDP_ICR, 0xffffffff); 186662306a36Sopenharmony_ci clk_disable(udc->iclk); 186762306a36Sopenharmony_ci 186862306a36Sopenharmony_ci /* request UDC and maybe VBUS irqs */ 186962306a36Sopenharmony_ci udc->udp_irq = retval = platform_get_irq(pdev, 0); 187062306a36Sopenharmony_ci if (retval < 0) 187162306a36Sopenharmony_ci goto err_unprepare_iclk; 187262306a36Sopenharmony_ci retval = devm_request_irq(dev, udc->udp_irq, at91_udc_irq, 0, 187362306a36Sopenharmony_ci driver_name, udc); 187462306a36Sopenharmony_ci if (retval) { 187562306a36Sopenharmony_ci DBG("request irq %d failed\n", udc->udp_irq); 187662306a36Sopenharmony_ci goto err_unprepare_iclk; 187762306a36Sopenharmony_ci } 187862306a36Sopenharmony_ci 187962306a36Sopenharmony_ci if (udc->board.vbus_pin) { 188062306a36Sopenharmony_ci gpiod_direction_input(udc->board.vbus_pin); 188162306a36Sopenharmony_ci 188262306a36Sopenharmony_ci /* 188362306a36Sopenharmony_ci * Get the initial state of VBUS - we cannot expect 188462306a36Sopenharmony_ci * a pending interrupt. 188562306a36Sopenharmony_ci */ 188662306a36Sopenharmony_ci udc->vbus = gpiod_get_value_cansleep(udc->board.vbus_pin); 188762306a36Sopenharmony_ci 188862306a36Sopenharmony_ci if (udc->board.vbus_polled) { 188962306a36Sopenharmony_ci INIT_WORK(&udc->vbus_timer_work, at91_vbus_timer_work); 189062306a36Sopenharmony_ci timer_setup(&udc->vbus_timer, at91_vbus_timer, 0); 189162306a36Sopenharmony_ci mod_timer(&udc->vbus_timer, 189262306a36Sopenharmony_ci jiffies + VBUS_POLL_TIMEOUT); 189362306a36Sopenharmony_ci } else { 189462306a36Sopenharmony_ci retval = devm_request_irq(dev, 189562306a36Sopenharmony_ci gpiod_to_irq(udc->board.vbus_pin), 189662306a36Sopenharmony_ci at91_vbus_irq, 0, driver_name, udc); 189762306a36Sopenharmony_ci if (retval) { 189862306a36Sopenharmony_ci DBG("request vbus irq %d failed\n", 189962306a36Sopenharmony_ci desc_to_gpio(udc->board.vbus_pin)); 190062306a36Sopenharmony_ci goto err_unprepare_iclk; 190162306a36Sopenharmony_ci } 190262306a36Sopenharmony_ci } 190362306a36Sopenharmony_ci } else { 190462306a36Sopenharmony_ci DBG("no VBUS detection, assuming always-on\n"); 190562306a36Sopenharmony_ci udc->vbus = 1; 190662306a36Sopenharmony_ci } 190762306a36Sopenharmony_ci retval = usb_add_gadget_udc(dev, &udc->gadget); 190862306a36Sopenharmony_ci if (retval) 190962306a36Sopenharmony_ci goto err_unprepare_iclk; 191062306a36Sopenharmony_ci dev_set_drvdata(dev, udc); 191162306a36Sopenharmony_ci device_init_wakeup(dev, 1); 191262306a36Sopenharmony_ci create_debug_file(udc); 191362306a36Sopenharmony_ci 191462306a36Sopenharmony_ci INFO("%s version %s\n", driver_name, DRIVER_VERSION); 191562306a36Sopenharmony_ci return 0; 191662306a36Sopenharmony_ci 191762306a36Sopenharmony_cierr_unprepare_iclk: 191862306a36Sopenharmony_ci clk_unprepare(udc->iclk); 191962306a36Sopenharmony_cierr_unprepare_fclk: 192062306a36Sopenharmony_ci clk_unprepare(udc->fclk); 192162306a36Sopenharmony_ci 192262306a36Sopenharmony_ci DBG("%s probe failed, %d\n", driver_name, retval); 192362306a36Sopenharmony_ci 192462306a36Sopenharmony_ci return retval; 192562306a36Sopenharmony_ci} 192662306a36Sopenharmony_ci 192762306a36Sopenharmony_cistatic int at91udc_remove(struct platform_device *pdev) 192862306a36Sopenharmony_ci{ 192962306a36Sopenharmony_ci struct at91_udc *udc = platform_get_drvdata(pdev); 193062306a36Sopenharmony_ci unsigned long flags; 193162306a36Sopenharmony_ci 193262306a36Sopenharmony_ci DBG("remove\n"); 193362306a36Sopenharmony_ci 193462306a36Sopenharmony_ci usb_del_gadget_udc(&udc->gadget); 193562306a36Sopenharmony_ci if (udc->driver) 193662306a36Sopenharmony_ci return -EBUSY; 193762306a36Sopenharmony_ci 193862306a36Sopenharmony_ci spin_lock_irqsave(&udc->lock, flags); 193962306a36Sopenharmony_ci pullup(udc, 0); 194062306a36Sopenharmony_ci spin_unlock_irqrestore(&udc->lock, flags); 194162306a36Sopenharmony_ci 194262306a36Sopenharmony_ci device_init_wakeup(&pdev->dev, 0); 194362306a36Sopenharmony_ci remove_debug_file(udc); 194462306a36Sopenharmony_ci clk_unprepare(udc->fclk); 194562306a36Sopenharmony_ci clk_unprepare(udc->iclk); 194662306a36Sopenharmony_ci 194762306a36Sopenharmony_ci return 0; 194862306a36Sopenharmony_ci} 194962306a36Sopenharmony_ci 195062306a36Sopenharmony_ci#ifdef CONFIG_PM 195162306a36Sopenharmony_cistatic int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg) 195262306a36Sopenharmony_ci{ 195362306a36Sopenharmony_ci struct at91_udc *udc = platform_get_drvdata(pdev); 195462306a36Sopenharmony_ci int wake = udc->driver && device_may_wakeup(&pdev->dev); 195562306a36Sopenharmony_ci unsigned long flags; 195662306a36Sopenharmony_ci 195762306a36Sopenharmony_ci /* Unless we can act normally to the host (letting it wake us up 195862306a36Sopenharmony_ci * whenever it has work for us) force disconnect. Wakeup requires 195962306a36Sopenharmony_ci * PLLB for USB events (signaling for reset, wakeup, or incoming 196062306a36Sopenharmony_ci * tokens) and VBUS irqs (on systems which support them). 196162306a36Sopenharmony_ci */ 196262306a36Sopenharmony_ci if ((!udc->suspended && udc->addr) 196362306a36Sopenharmony_ci || !wake 196462306a36Sopenharmony_ci || at91_suspend_entering_slow_clock()) { 196562306a36Sopenharmony_ci spin_lock_irqsave(&udc->lock, flags); 196662306a36Sopenharmony_ci pullup(udc, 0); 196762306a36Sopenharmony_ci wake = 0; 196862306a36Sopenharmony_ci spin_unlock_irqrestore(&udc->lock, flags); 196962306a36Sopenharmony_ci } else 197062306a36Sopenharmony_ci enable_irq_wake(udc->udp_irq); 197162306a36Sopenharmony_ci 197262306a36Sopenharmony_ci udc->active_suspend = wake; 197362306a36Sopenharmony_ci if (udc->board.vbus_pin && !udc->board.vbus_polled && wake) 197462306a36Sopenharmony_ci enable_irq_wake(gpiod_to_irq(udc->board.vbus_pin)); 197562306a36Sopenharmony_ci return 0; 197662306a36Sopenharmony_ci} 197762306a36Sopenharmony_ci 197862306a36Sopenharmony_cistatic int at91udc_resume(struct platform_device *pdev) 197962306a36Sopenharmony_ci{ 198062306a36Sopenharmony_ci struct at91_udc *udc = platform_get_drvdata(pdev); 198162306a36Sopenharmony_ci unsigned long flags; 198262306a36Sopenharmony_ci 198362306a36Sopenharmony_ci if (udc->board.vbus_pin && !udc->board.vbus_polled && 198462306a36Sopenharmony_ci udc->active_suspend) 198562306a36Sopenharmony_ci disable_irq_wake(gpiod_to_irq(udc->board.vbus_pin)); 198662306a36Sopenharmony_ci 198762306a36Sopenharmony_ci /* maybe reconnect to host; if so, clocks on */ 198862306a36Sopenharmony_ci if (udc->active_suspend) 198962306a36Sopenharmony_ci disable_irq_wake(udc->udp_irq); 199062306a36Sopenharmony_ci else { 199162306a36Sopenharmony_ci spin_lock_irqsave(&udc->lock, flags); 199262306a36Sopenharmony_ci pullup(udc, 1); 199362306a36Sopenharmony_ci spin_unlock_irqrestore(&udc->lock, flags); 199462306a36Sopenharmony_ci } 199562306a36Sopenharmony_ci return 0; 199662306a36Sopenharmony_ci} 199762306a36Sopenharmony_ci#else 199862306a36Sopenharmony_ci#define at91udc_suspend NULL 199962306a36Sopenharmony_ci#define at91udc_resume NULL 200062306a36Sopenharmony_ci#endif 200162306a36Sopenharmony_ci 200262306a36Sopenharmony_cistatic struct platform_driver at91_udc_driver = { 200362306a36Sopenharmony_ci .remove = at91udc_remove, 200462306a36Sopenharmony_ci .shutdown = at91udc_shutdown, 200562306a36Sopenharmony_ci .suspend = at91udc_suspend, 200662306a36Sopenharmony_ci .resume = at91udc_resume, 200762306a36Sopenharmony_ci .driver = { 200862306a36Sopenharmony_ci .name = driver_name, 200962306a36Sopenharmony_ci .of_match_table = at91_udc_dt_ids, 201062306a36Sopenharmony_ci }, 201162306a36Sopenharmony_ci}; 201262306a36Sopenharmony_ci 201362306a36Sopenharmony_cimodule_platform_driver_probe(at91_udc_driver, at91udc_probe); 201462306a36Sopenharmony_ci 201562306a36Sopenharmony_ciMODULE_DESCRIPTION("AT91 udc driver"); 201662306a36Sopenharmony_ciMODULE_AUTHOR("Thomas Rathbone, David Brownell"); 201762306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 201862306a36Sopenharmony_ciMODULE_ALIAS("platform:at91_udc"); 2019