xref: /openbmc/linux/drivers/usb/gadget/udc/gr_udc.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0+
290fccb52SAndrzej Pietrasiewicz /*
390fccb52SAndrzej Pietrasiewicz  * USB Peripheral Controller driver for Aeroflex Gaisler GRUSBDC.
490fccb52SAndrzej Pietrasiewicz  *
590fccb52SAndrzej Pietrasiewicz  * 2013 (c) Aeroflex Gaisler AB
690fccb52SAndrzej Pietrasiewicz  *
790fccb52SAndrzej Pietrasiewicz  * This driver supports GRUSBDC USB Device Controller cores available in the
890fccb52SAndrzej Pietrasiewicz  * GRLIB VHDL IP core library.
990fccb52SAndrzej Pietrasiewicz  *
1090fccb52SAndrzej Pietrasiewicz  * Full documentation of the GRUSBDC core can be found here:
1110fadd5eSAlexander A. Klimov  * https://www.gaisler.com/products/grlib/grip.pdf
1290fccb52SAndrzej Pietrasiewicz  *
1390fccb52SAndrzej Pietrasiewicz  * Contributors:
1490fccb52SAndrzej Pietrasiewicz  * - Andreas Larsson <andreas@gaisler.com>
1590fccb52SAndrzej Pietrasiewicz  * - Marko Isomaki
1690fccb52SAndrzej Pietrasiewicz  */
1790fccb52SAndrzej Pietrasiewicz 
1890fccb52SAndrzej Pietrasiewicz /*
1990fccb52SAndrzej Pietrasiewicz  * A GRUSBDC core can have up to 16 IN endpoints and 16 OUT endpoints each
2090fccb52SAndrzej Pietrasiewicz  * individually configurable to any of the four USB transfer types. This driver
2190fccb52SAndrzej Pietrasiewicz  * only supports cores in DMA mode.
2290fccb52SAndrzej Pietrasiewicz  */
2390fccb52SAndrzej Pietrasiewicz 
2490fccb52SAndrzej Pietrasiewicz #include <linux/kernel.h>
2590fccb52SAndrzej Pietrasiewicz #include <linux/module.h>
26484468fbSRob Herring #include <linux/platform_device.h>
2790fccb52SAndrzej Pietrasiewicz #include <linux/slab.h>
2890fccb52SAndrzej Pietrasiewicz #include <linux/spinlock.h>
2990fccb52SAndrzej Pietrasiewicz #include <linux/errno.h>
3090fccb52SAndrzej Pietrasiewicz #include <linux/list.h>
3190fccb52SAndrzej Pietrasiewicz #include <linux/interrupt.h>
3290fccb52SAndrzej Pietrasiewicz #include <linux/device.h>
3391a9f2d3SChunfeng Yun #include <linux/usb.h>
3490fccb52SAndrzej Pietrasiewicz #include <linux/usb/ch9.h>
3590fccb52SAndrzej Pietrasiewicz #include <linux/usb/gadget.h>
3690fccb52SAndrzej Pietrasiewicz #include <linux/dma-mapping.h>
3790fccb52SAndrzej Pietrasiewicz #include <linux/dmapool.h>
3890fccb52SAndrzej Pietrasiewicz #include <linux/debugfs.h>
3990fccb52SAndrzej Pietrasiewicz #include <linux/seq_file.h>
40484468fbSRob Herring #include <linux/of.h>
4190fccb52SAndrzej Pietrasiewicz 
4290fccb52SAndrzej Pietrasiewicz #include <asm/byteorder.h>
4390fccb52SAndrzej Pietrasiewicz 
4490fccb52SAndrzej Pietrasiewicz #include "gr_udc.h"
4590fccb52SAndrzej Pietrasiewicz 
4690fccb52SAndrzej Pietrasiewicz #define	DRIVER_NAME	"gr_udc"
4790fccb52SAndrzej Pietrasiewicz #define	DRIVER_DESC	"Aeroflex Gaisler GRUSBDC USB Peripheral Controller"
4890fccb52SAndrzej Pietrasiewicz 
4990fccb52SAndrzej Pietrasiewicz static const char driver_name[] = DRIVER_NAME;
5090fccb52SAndrzej Pietrasiewicz 
5190fccb52SAndrzej Pietrasiewicz #define gr_read32(x) (ioread32be((x)))
5290fccb52SAndrzej Pietrasiewicz #define gr_write32(x, v) (iowrite32be((v), (x)))
5390fccb52SAndrzej Pietrasiewicz 
5490fccb52SAndrzej Pietrasiewicz /* USB speed and corresponding string calculated from status register value */
5590fccb52SAndrzej Pietrasiewicz #define GR_SPEED(status) \
5690fccb52SAndrzej Pietrasiewicz 	((status & GR_STATUS_SP) ? USB_SPEED_FULL : USB_SPEED_HIGH)
5790fccb52SAndrzej Pietrasiewicz #define GR_SPEED_STR(status) usb_speed_string(GR_SPEED(status))
5890fccb52SAndrzej Pietrasiewicz 
5990fccb52SAndrzej Pietrasiewicz /* Size of hardware buffer calculated from epctrl register value */
6090fccb52SAndrzej Pietrasiewicz #define GR_BUFFER_SIZE(epctrl)					      \
6190fccb52SAndrzej Pietrasiewicz 	((((epctrl) & GR_EPCTRL_BUFSZ_MASK) >> GR_EPCTRL_BUFSZ_POS) * \
6290fccb52SAndrzej Pietrasiewicz 	 GR_EPCTRL_BUFSZ_SCALER)
6390fccb52SAndrzej Pietrasiewicz 
6490fccb52SAndrzej Pietrasiewicz /* ---------------------------------------------------------------------- */
6590fccb52SAndrzej Pietrasiewicz /* Debug printout functionality */
6690fccb52SAndrzej Pietrasiewicz 
6790fccb52SAndrzej Pietrasiewicz static const char * const gr_modestring[] = {"control", "iso", "bulk", "int"};
6890fccb52SAndrzej Pietrasiewicz 
gr_ep0state_string(enum gr_ep0state state)6990fccb52SAndrzej Pietrasiewicz static const char *gr_ep0state_string(enum gr_ep0state state)
7090fccb52SAndrzej Pietrasiewicz {
7190fccb52SAndrzej Pietrasiewicz 	static const char *const names[] = {
7290fccb52SAndrzej Pietrasiewicz 		[GR_EP0_DISCONNECT] = "disconnect",
7390fccb52SAndrzej Pietrasiewicz 		[GR_EP0_SETUP] = "setup",
7490fccb52SAndrzej Pietrasiewicz 		[GR_EP0_IDATA] = "idata",
7590fccb52SAndrzej Pietrasiewicz 		[GR_EP0_ODATA] = "odata",
7690fccb52SAndrzej Pietrasiewicz 		[GR_EP0_ISTATUS] = "istatus",
7790fccb52SAndrzej Pietrasiewicz 		[GR_EP0_OSTATUS] = "ostatus",
7890fccb52SAndrzej Pietrasiewicz 		[GR_EP0_STALL] = "stall",
7990fccb52SAndrzej Pietrasiewicz 		[GR_EP0_SUSPEND] = "suspend",
8090fccb52SAndrzej Pietrasiewicz 	};
8190fccb52SAndrzej Pietrasiewicz 
8290fccb52SAndrzej Pietrasiewicz 	if (state < 0 || state >= ARRAY_SIZE(names))
8390fccb52SAndrzej Pietrasiewicz 		return "UNKNOWN";
8490fccb52SAndrzej Pietrasiewicz 
8590fccb52SAndrzej Pietrasiewicz 	return names[state];
8690fccb52SAndrzej Pietrasiewicz }
8790fccb52SAndrzej Pietrasiewicz 
8890fccb52SAndrzej Pietrasiewicz #ifdef VERBOSE_DEBUG
8990fccb52SAndrzej Pietrasiewicz 
gr_dbgprint_request(const char * str,struct gr_ep * ep,struct gr_request * req)9090fccb52SAndrzej Pietrasiewicz static void gr_dbgprint_request(const char *str, struct gr_ep *ep,
9190fccb52SAndrzej Pietrasiewicz 				struct gr_request *req)
9290fccb52SAndrzej Pietrasiewicz {
9390fccb52SAndrzej Pietrasiewicz 	int buflen = ep->is_in ? req->req.length : req->req.actual;
9490fccb52SAndrzej Pietrasiewicz 	int rowlen = 32;
9590fccb52SAndrzej Pietrasiewicz 	int plen = min(rowlen, buflen);
9690fccb52SAndrzej Pietrasiewicz 
9790fccb52SAndrzej Pietrasiewicz 	dev_dbg(ep->dev->dev, "%s: 0x%p, %d bytes data%s:\n", str, req, buflen,
9890fccb52SAndrzej Pietrasiewicz 		(buflen > plen ? " (truncated)" : ""));
9990fccb52SAndrzej Pietrasiewicz 	print_hex_dump_debug("   ", DUMP_PREFIX_NONE,
10090fccb52SAndrzej Pietrasiewicz 			     rowlen, 4, req->req.buf, plen, false);
10190fccb52SAndrzej Pietrasiewicz }
10290fccb52SAndrzej Pietrasiewicz 
gr_dbgprint_devreq(struct gr_udc * dev,u8 type,u8 request,u16 value,u16 index,u16 length)10390fccb52SAndrzej Pietrasiewicz static void gr_dbgprint_devreq(struct gr_udc *dev, u8 type, u8 request,
10490fccb52SAndrzej Pietrasiewicz 			       u16 value, u16 index, u16 length)
10590fccb52SAndrzej Pietrasiewicz {
10690fccb52SAndrzej Pietrasiewicz 	dev_vdbg(dev->dev, "REQ: %02x.%02x v%04x i%04x l%04x\n",
10790fccb52SAndrzej Pietrasiewicz 		 type, request, value, index, length);
10890fccb52SAndrzej Pietrasiewicz }
10990fccb52SAndrzej Pietrasiewicz #else /* !VERBOSE_DEBUG */
11090fccb52SAndrzej Pietrasiewicz 
gr_dbgprint_request(const char * str,struct gr_ep * ep,struct gr_request * req)11190fccb52SAndrzej Pietrasiewicz static void gr_dbgprint_request(const char *str, struct gr_ep *ep,
11290fccb52SAndrzej Pietrasiewicz 				struct gr_request *req) {}
11390fccb52SAndrzej Pietrasiewicz 
gr_dbgprint_devreq(struct gr_udc * dev,u8 type,u8 request,u16 value,u16 index,u16 length)11490fccb52SAndrzej Pietrasiewicz static void gr_dbgprint_devreq(struct gr_udc *dev, u8 type, u8 request,
11590fccb52SAndrzej Pietrasiewicz 			       u16 value, u16 index, u16 length) {}
11690fccb52SAndrzej Pietrasiewicz 
11790fccb52SAndrzej Pietrasiewicz #endif /* VERBOSE_DEBUG */
11890fccb52SAndrzej Pietrasiewicz 
11990fccb52SAndrzej Pietrasiewicz /* ---------------------------------------------------------------------- */
12090fccb52SAndrzej Pietrasiewicz /* Debugfs functionality */
12190fccb52SAndrzej Pietrasiewicz 
12290fccb52SAndrzej Pietrasiewicz #ifdef CONFIG_USB_GADGET_DEBUG_FS
12390fccb52SAndrzej Pietrasiewicz 
gr_seq_ep_show(struct seq_file * seq,struct gr_ep * ep)12490fccb52SAndrzej Pietrasiewicz static void gr_seq_ep_show(struct seq_file *seq, struct gr_ep *ep)
12590fccb52SAndrzej Pietrasiewicz {
12690fccb52SAndrzej Pietrasiewicz 	u32 epctrl = gr_read32(&ep->regs->epctrl);
12790fccb52SAndrzej Pietrasiewicz 	u32 epstat = gr_read32(&ep->regs->epstat);
12890fccb52SAndrzej Pietrasiewicz 	int mode = (epctrl & GR_EPCTRL_TT_MASK) >> GR_EPCTRL_TT_POS;
12990fccb52SAndrzej Pietrasiewicz 	struct gr_request *req;
13090fccb52SAndrzej Pietrasiewicz 
13190fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "%s:\n", ep->ep.name);
13290fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "  mode = %s\n", gr_modestring[mode]);
13390fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "  halted: %d\n", !!(epctrl & GR_EPCTRL_EH));
13490fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "  disabled: %d\n", !!(epctrl & GR_EPCTRL_ED));
13590fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "  valid: %d\n", !!(epctrl & GR_EPCTRL_EV));
13690fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "  dma_start = %d\n", ep->dma_start);
13790fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "  stopped = %d\n", ep->stopped);
13890fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "  wedged = %d\n", ep->wedged);
13990fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "  callback = %d\n", ep->callback);
14090fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "  maxpacket = %d\n", ep->ep.maxpacket);
14190fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "  maxpacket_limit = %d\n", ep->ep.maxpacket_limit);
14290fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "  bytes_per_buffer = %d\n", ep->bytes_per_buffer);
14390fccb52SAndrzej Pietrasiewicz 	if (mode == 1 || mode == 3)
14490fccb52SAndrzej Pietrasiewicz 		seq_printf(seq, "  nt = %d\n",
14590fccb52SAndrzej Pietrasiewicz 			   (epctrl & GR_EPCTRL_NT_MASK) >> GR_EPCTRL_NT_POS);
14690fccb52SAndrzej Pietrasiewicz 
14790fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "  Buffer 0: %s %s%d\n",
14890fccb52SAndrzej Pietrasiewicz 		   epstat & GR_EPSTAT_B0 ? "valid" : "invalid",
14990fccb52SAndrzej Pietrasiewicz 		   epstat & GR_EPSTAT_BS ? " " : "selected ",
15090fccb52SAndrzej Pietrasiewicz 		   (epstat & GR_EPSTAT_B0CNT_MASK) >> GR_EPSTAT_B0CNT_POS);
15190fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "  Buffer 1: %s %s%d\n",
15290fccb52SAndrzej Pietrasiewicz 		   epstat & GR_EPSTAT_B1 ? "valid" : "invalid",
15390fccb52SAndrzej Pietrasiewicz 		   epstat & GR_EPSTAT_BS ? "selected " : " ",
15490fccb52SAndrzej Pietrasiewicz 		   (epstat & GR_EPSTAT_B1CNT_MASK) >> GR_EPSTAT_B1CNT_POS);
15590fccb52SAndrzej Pietrasiewicz 
15690fccb52SAndrzej Pietrasiewicz 	if (list_empty(&ep->queue)) {
15790fccb52SAndrzej Pietrasiewicz 		seq_puts(seq, "  Queue: empty\n\n");
15890fccb52SAndrzej Pietrasiewicz 		return;
15990fccb52SAndrzej Pietrasiewicz 	}
16090fccb52SAndrzej Pietrasiewicz 
16190fccb52SAndrzej Pietrasiewicz 	seq_puts(seq, "  Queue:\n");
16290fccb52SAndrzej Pietrasiewicz 	list_for_each_entry(req, &ep->queue, queue) {
16390fccb52SAndrzej Pietrasiewicz 		struct gr_dma_desc *desc;
16490fccb52SAndrzej Pietrasiewicz 		struct gr_dma_desc *next;
16590fccb52SAndrzej Pietrasiewicz 
16690fccb52SAndrzej Pietrasiewicz 		seq_printf(seq, "    0x%p: 0x%p %d %d\n", req,
16790fccb52SAndrzej Pietrasiewicz 			   &req->req.buf, req->req.actual, req->req.length);
16890fccb52SAndrzej Pietrasiewicz 
16990fccb52SAndrzej Pietrasiewicz 		next = req->first_desc;
17090fccb52SAndrzej Pietrasiewicz 		do {
17190fccb52SAndrzej Pietrasiewicz 			desc = next;
17290fccb52SAndrzej Pietrasiewicz 			next = desc->next_desc;
17390fccb52SAndrzej Pietrasiewicz 			seq_printf(seq, "    %c 0x%p (0x%08x): 0x%05x 0x%08x\n",
17490fccb52SAndrzej Pietrasiewicz 				   desc == req->curr_desc ? 'c' : ' ',
17590fccb52SAndrzej Pietrasiewicz 				   desc, desc->paddr, desc->ctrl, desc->data);
17690fccb52SAndrzej Pietrasiewicz 		} while (desc != req->last_desc);
17790fccb52SAndrzej Pietrasiewicz 	}
17890fccb52SAndrzej Pietrasiewicz 	seq_puts(seq, "\n");
17990fccb52SAndrzej Pietrasiewicz }
18090fccb52SAndrzej Pietrasiewicz 
gr_dfs_show(struct seq_file * seq,void * v)18140d2589aSAndy Shevchenko static int gr_dfs_show(struct seq_file *seq, void *v)
18290fccb52SAndrzej Pietrasiewicz {
18390fccb52SAndrzej Pietrasiewicz 	struct gr_udc *dev = seq->private;
18490fccb52SAndrzej Pietrasiewicz 	u32 control = gr_read32(&dev->regs->control);
18590fccb52SAndrzej Pietrasiewicz 	u32 status = gr_read32(&dev->regs->status);
18690fccb52SAndrzej Pietrasiewicz 	struct gr_ep *ep;
18790fccb52SAndrzej Pietrasiewicz 
18890fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "usb state = %s\n",
18990fccb52SAndrzej Pietrasiewicz 		   usb_state_string(dev->gadget.state));
19090fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "address = %d\n",
19190fccb52SAndrzej Pietrasiewicz 		   (control & GR_CONTROL_UA_MASK) >> GR_CONTROL_UA_POS);
19290fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "speed = %s\n", GR_SPEED_STR(status));
19390fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "ep0state = %s\n", gr_ep0state_string(dev->ep0state));
19490fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "irq_enabled = %d\n", dev->irq_enabled);
19590fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "remote_wakeup = %d\n", dev->remote_wakeup);
19690fccb52SAndrzej Pietrasiewicz 	seq_printf(seq, "test_mode = %d\n", dev->test_mode);
19790fccb52SAndrzej Pietrasiewicz 	seq_puts(seq, "\n");
19890fccb52SAndrzej Pietrasiewicz 
19990fccb52SAndrzej Pietrasiewicz 	list_for_each_entry(ep, &dev->ep_list, ep_list)
20090fccb52SAndrzej Pietrasiewicz 		gr_seq_ep_show(seq, ep);
20190fccb52SAndrzej Pietrasiewicz 
20290fccb52SAndrzej Pietrasiewicz 	return 0;
20390fccb52SAndrzej Pietrasiewicz }
20440d2589aSAndy Shevchenko DEFINE_SHOW_ATTRIBUTE(gr_dfs);
20590fccb52SAndrzej Pietrasiewicz 
gr_dfs_create(struct gr_udc * dev)20690fccb52SAndrzej Pietrasiewicz static void gr_dfs_create(struct gr_udc *dev)
20790fccb52SAndrzej Pietrasiewicz {
20890fccb52SAndrzej Pietrasiewicz 	const char *name = "gr_udc_state";
209425de318SGreg Kroah-Hartman 	struct dentry *root;
21090fccb52SAndrzej Pietrasiewicz 
211425de318SGreg Kroah-Hartman 	root = debugfs_create_dir(dev_name(dev->dev), usb_debug_root);
212425de318SGreg Kroah-Hartman 	debugfs_create_file(name, 0444, root, dev, &gr_dfs_fops);
21390fccb52SAndrzej Pietrasiewicz }
21490fccb52SAndrzej Pietrasiewicz 
gr_dfs_delete(struct gr_udc * dev)21590fccb52SAndrzej Pietrasiewicz static void gr_dfs_delete(struct gr_udc *dev)
21690fccb52SAndrzej Pietrasiewicz {
21773f44513SGreg Kroah-Hartman 	debugfs_lookup_and_remove(dev_name(dev->dev), usb_debug_root);
21890fccb52SAndrzej Pietrasiewicz }
21990fccb52SAndrzej Pietrasiewicz 
22090fccb52SAndrzej Pietrasiewicz #else /* !CONFIG_USB_GADGET_DEBUG_FS */
22190fccb52SAndrzej Pietrasiewicz 
gr_dfs_create(struct gr_udc * dev)22290fccb52SAndrzej Pietrasiewicz static void gr_dfs_create(struct gr_udc *dev) {}
gr_dfs_delete(struct gr_udc * dev)22390fccb52SAndrzej Pietrasiewicz static void gr_dfs_delete(struct gr_udc *dev) {}
22490fccb52SAndrzej Pietrasiewicz 
22590fccb52SAndrzej Pietrasiewicz #endif /* CONFIG_USB_GADGET_DEBUG_FS */
22690fccb52SAndrzej Pietrasiewicz 
22790fccb52SAndrzej Pietrasiewicz /* ---------------------------------------------------------------------- */
22890fccb52SAndrzej Pietrasiewicz /* DMA and request handling */
22990fccb52SAndrzej Pietrasiewicz 
23090fccb52SAndrzej Pietrasiewicz /* Allocates a new struct gr_dma_desc, sets paddr and zeroes the rest */
gr_alloc_dma_desc(struct gr_ep * ep,gfp_t gfp_flags)23190fccb52SAndrzej Pietrasiewicz static struct gr_dma_desc *gr_alloc_dma_desc(struct gr_ep *ep, gfp_t gfp_flags)
23290fccb52SAndrzej Pietrasiewicz {
23390fccb52SAndrzej Pietrasiewicz 	dma_addr_t paddr;
23490fccb52SAndrzej Pietrasiewicz 	struct gr_dma_desc *dma_desc;
23590fccb52SAndrzej Pietrasiewicz 
23684c1eeb0SSaurabh Sengar 	dma_desc = dma_pool_zalloc(ep->dev->desc_pool, gfp_flags, &paddr);
23790fccb52SAndrzej Pietrasiewicz 	if (!dma_desc) {
23890fccb52SAndrzej Pietrasiewicz 		dev_err(ep->dev->dev, "Could not allocate from DMA pool\n");
23990fccb52SAndrzej Pietrasiewicz 		return NULL;
24090fccb52SAndrzej Pietrasiewicz 	}
24190fccb52SAndrzej Pietrasiewicz 
24290fccb52SAndrzej Pietrasiewicz 	dma_desc->paddr = paddr;
24390fccb52SAndrzej Pietrasiewicz 
24490fccb52SAndrzej Pietrasiewicz 	return dma_desc;
24590fccb52SAndrzej Pietrasiewicz }
24690fccb52SAndrzej Pietrasiewicz 
gr_free_dma_desc(struct gr_udc * dev,struct gr_dma_desc * desc)24790fccb52SAndrzej Pietrasiewicz static inline void gr_free_dma_desc(struct gr_udc *dev,
24890fccb52SAndrzej Pietrasiewicz 				    struct gr_dma_desc *desc)
24990fccb52SAndrzej Pietrasiewicz {
25090fccb52SAndrzej Pietrasiewicz 	dma_pool_free(dev->desc_pool, desc, (dma_addr_t)desc->paddr);
25190fccb52SAndrzej Pietrasiewicz }
25290fccb52SAndrzej Pietrasiewicz 
25390fccb52SAndrzej Pietrasiewicz /* Frees the chain of struct gr_dma_desc for the given request */
gr_free_dma_desc_chain(struct gr_udc * dev,struct gr_request * req)25490fccb52SAndrzej Pietrasiewicz static void gr_free_dma_desc_chain(struct gr_udc *dev, struct gr_request *req)
25590fccb52SAndrzej Pietrasiewicz {
25690fccb52SAndrzej Pietrasiewicz 	struct gr_dma_desc *desc;
25790fccb52SAndrzej Pietrasiewicz 	struct gr_dma_desc *next;
25890fccb52SAndrzej Pietrasiewicz 
25990fccb52SAndrzej Pietrasiewicz 	next = req->first_desc;
26090fccb52SAndrzej Pietrasiewicz 	if (!next)
26190fccb52SAndrzej Pietrasiewicz 		return;
26290fccb52SAndrzej Pietrasiewicz 
26390fccb52SAndrzej Pietrasiewicz 	do {
26490fccb52SAndrzej Pietrasiewicz 		desc = next;
26590fccb52SAndrzej Pietrasiewicz 		next = desc->next_desc;
26690fccb52SAndrzej Pietrasiewicz 		gr_free_dma_desc(dev, desc);
26790fccb52SAndrzej Pietrasiewicz 	} while (desc != req->last_desc);
26890fccb52SAndrzej Pietrasiewicz 
26990fccb52SAndrzej Pietrasiewicz 	req->first_desc = NULL;
27090fccb52SAndrzej Pietrasiewicz 	req->curr_desc = NULL;
27190fccb52SAndrzej Pietrasiewicz 	req->last_desc = NULL;
27290fccb52SAndrzej Pietrasiewicz }
27390fccb52SAndrzej Pietrasiewicz 
27490fccb52SAndrzej Pietrasiewicz static void gr_ep0_setup(struct gr_udc *dev, struct gr_request *req);
27590fccb52SAndrzej Pietrasiewicz 
27690fccb52SAndrzej Pietrasiewicz /*
27790fccb52SAndrzej Pietrasiewicz  * Frees allocated resources and calls the appropriate completion function/setup
27890fccb52SAndrzej Pietrasiewicz  * package handler for a finished request.
27990fccb52SAndrzej Pietrasiewicz  *
28090fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held and irqs disabled.
28190fccb52SAndrzej Pietrasiewicz  */
gr_finish_request(struct gr_ep * ep,struct gr_request * req,int status)28290fccb52SAndrzej Pietrasiewicz static void gr_finish_request(struct gr_ep *ep, struct gr_request *req,
28390fccb52SAndrzej Pietrasiewicz 			      int status)
28490fccb52SAndrzej Pietrasiewicz 	__releases(&dev->lock)
28590fccb52SAndrzej Pietrasiewicz 	__acquires(&dev->lock)
28690fccb52SAndrzej Pietrasiewicz {
28790fccb52SAndrzej Pietrasiewicz 	struct gr_udc *dev;
28890fccb52SAndrzej Pietrasiewicz 
28990fccb52SAndrzej Pietrasiewicz 	list_del_init(&req->queue);
29090fccb52SAndrzej Pietrasiewicz 
29190fccb52SAndrzej Pietrasiewicz 	if (likely(req->req.status == -EINPROGRESS))
29290fccb52SAndrzej Pietrasiewicz 		req->req.status = status;
29390fccb52SAndrzej Pietrasiewicz 	else
29490fccb52SAndrzej Pietrasiewicz 		status = req->req.status;
29590fccb52SAndrzej Pietrasiewicz 
29690fccb52SAndrzej Pietrasiewicz 	dev = ep->dev;
29790fccb52SAndrzej Pietrasiewicz 	usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in);
29890fccb52SAndrzej Pietrasiewicz 	gr_free_dma_desc_chain(dev, req);
29990fccb52SAndrzej Pietrasiewicz 
3005b484989SAndreas Larsson 	if (ep->is_in) { /* For OUT, req->req.actual gets updated bit by bit */
30190fccb52SAndrzej Pietrasiewicz 		req->req.actual = req->req.length;
3025b484989SAndreas Larsson 	} else if (req->oddlen && req->req.actual > req->evenlen) {
3035b484989SAndreas Larsson 		/*
3045b484989SAndreas Larsson 		 * Copy to user buffer in this case where length was not evenly
3055b484989SAndreas Larsson 		 * divisible by ep->ep.maxpacket and the last descriptor was
3065b484989SAndreas Larsson 		 * actually used.
3075b484989SAndreas Larsson 		 */
3085b484989SAndreas Larsson 		char *buftail = ((char *)req->req.buf + req->evenlen);
3095b484989SAndreas Larsson 
3105b484989SAndreas Larsson 		memcpy(buftail, ep->tailbuf, req->oddlen);
3115b484989SAndreas Larsson 
3125b484989SAndreas Larsson 		if (req->req.actual > req->req.length) {
3135b484989SAndreas Larsson 			/* We got more data than was requested */
3145b484989SAndreas Larsson 			dev_dbg(ep->dev->dev, "Overflow for ep %s\n",
3155b484989SAndreas Larsson 				ep->ep.name);
3165b484989SAndreas Larsson 			gr_dbgprint_request("OVFL", ep, req);
3175b484989SAndreas Larsson 			req->req.status = -EOVERFLOW;
3185b484989SAndreas Larsson 		}
3195b484989SAndreas Larsson 	}
32090fccb52SAndrzej Pietrasiewicz 
32190fccb52SAndrzej Pietrasiewicz 	if (!status) {
32290fccb52SAndrzej Pietrasiewicz 		if (ep->is_in)
32390fccb52SAndrzej Pietrasiewicz 			gr_dbgprint_request("SENT", ep, req);
32490fccb52SAndrzej Pietrasiewicz 		else
32590fccb52SAndrzej Pietrasiewicz 			gr_dbgprint_request("RECV", ep, req);
32690fccb52SAndrzej Pietrasiewicz 	}
32790fccb52SAndrzej Pietrasiewicz 
32890fccb52SAndrzej Pietrasiewicz 	/* Prevent changes to ep->queue during callback */
32990fccb52SAndrzej Pietrasiewicz 	ep->callback = 1;
33090fccb52SAndrzej Pietrasiewicz 	if (req == dev->ep0reqo && !status) {
33190fccb52SAndrzej Pietrasiewicz 		if (req->setup)
33290fccb52SAndrzej Pietrasiewicz 			gr_ep0_setup(dev, req);
33390fccb52SAndrzej Pietrasiewicz 		else
33490fccb52SAndrzej Pietrasiewicz 			dev_err(dev->dev,
33590fccb52SAndrzej Pietrasiewicz 				"Unexpected non setup packet on ep0in\n");
33690fccb52SAndrzej Pietrasiewicz 	} else if (req->req.complete) {
33790fccb52SAndrzej Pietrasiewicz 		spin_unlock(&dev->lock);
33890fccb52SAndrzej Pietrasiewicz 
339304f7e5eSMichal Sojka 		usb_gadget_giveback_request(&ep->ep, &req->req);
34090fccb52SAndrzej Pietrasiewicz 
34190fccb52SAndrzej Pietrasiewicz 		spin_lock(&dev->lock);
34290fccb52SAndrzej Pietrasiewicz 	}
34390fccb52SAndrzej Pietrasiewicz 	ep->callback = 0;
34490fccb52SAndrzej Pietrasiewicz }
34590fccb52SAndrzej Pietrasiewicz 
gr_alloc_request(struct usb_ep * _ep,gfp_t gfp_flags)34690fccb52SAndrzej Pietrasiewicz static struct usb_request *gr_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
34790fccb52SAndrzej Pietrasiewicz {
34890fccb52SAndrzej Pietrasiewicz 	struct gr_request *req;
34990fccb52SAndrzej Pietrasiewicz 
35090fccb52SAndrzej Pietrasiewicz 	req = kzalloc(sizeof(*req), gfp_flags);
35190fccb52SAndrzej Pietrasiewicz 	if (!req)
35290fccb52SAndrzej Pietrasiewicz 		return NULL;
35390fccb52SAndrzej Pietrasiewicz 
35490fccb52SAndrzej Pietrasiewicz 	INIT_LIST_HEAD(&req->queue);
35590fccb52SAndrzej Pietrasiewicz 
35690fccb52SAndrzej Pietrasiewicz 	return &req->req;
35790fccb52SAndrzej Pietrasiewicz }
35890fccb52SAndrzej Pietrasiewicz 
35990fccb52SAndrzej Pietrasiewicz /*
36090fccb52SAndrzej Pietrasiewicz  * Starts DMA for endpoint ep if there are requests in the queue.
36190fccb52SAndrzej Pietrasiewicz  *
36290fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held and with !ep->stopped.
36390fccb52SAndrzej Pietrasiewicz  */
gr_start_dma(struct gr_ep * ep)36490fccb52SAndrzej Pietrasiewicz static void gr_start_dma(struct gr_ep *ep)
36590fccb52SAndrzej Pietrasiewicz {
36690fccb52SAndrzej Pietrasiewicz 	struct gr_request *req;
36790fccb52SAndrzej Pietrasiewicz 	u32 dmactrl;
36890fccb52SAndrzej Pietrasiewicz 
36990fccb52SAndrzej Pietrasiewicz 	if (list_empty(&ep->queue)) {
37090fccb52SAndrzej Pietrasiewicz 		ep->dma_start = 0;
37190fccb52SAndrzej Pietrasiewicz 		return;
37290fccb52SAndrzej Pietrasiewicz 	}
37390fccb52SAndrzej Pietrasiewicz 
37490fccb52SAndrzej Pietrasiewicz 	req = list_first_entry(&ep->queue, struct gr_request, queue);
37590fccb52SAndrzej Pietrasiewicz 
37690fccb52SAndrzej Pietrasiewicz 	/* A descriptor should already have been allocated */
37790fccb52SAndrzej Pietrasiewicz 	BUG_ON(!req->curr_desc);
37890fccb52SAndrzej Pietrasiewicz 
3795b484989SAndreas Larsson 	/*
3805b484989SAndreas Larsson 	 * The DMA controller can not handle smaller OUT buffers than
3815b484989SAndreas Larsson 	 * ep->ep.maxpacket. It could lead to buffer overruns if an unexpectedly
3825b484989SAndreas Larsson 	 * long packet are received. Therefore an internal bounce buffer gets
3835b484989SAndreas Larsson 	 * used when such a request gets enabled.
3845b484989SAndreas Larsson 	 */
3855b484989SAndreas Larsson 	if (!ep->is_in && req->oddlen)
3865b484989SAndreas Larsson 		req->last_desc->data = ep->tailbuf_paddr;
3875b484989SAndreas Larsson 
38890fccb52SAndrzej Pietrasiewicz 	wmb(); /* Make sure all is settled before handing it over to DMA */
38990fccb52SAndrzej Pietrasiewicz 
39090fccb52SAndrzej Pietrasiewicz 	/* Set the descriptor pointer in the hardware */
39190fccb52SAndrzej Pietrasiewicz 	gr_write32(&ep->regs->dmaaddr, req->curr_desc->paddr);
39290fccb52SAndrzej Pietrasiewicz 
39390fccb52SAndrzej Pietrasiewicz 	/* Announce available descriptors */
39490fccb52SAndrzej Pietrasiewicz 	dmactrl = gr_read32(&ep->regs->dmactrl);
39590fccb52SAndrzej Pietrasiewicz 	gr_write32(&ep->regs->dmactrl, dmactrl | GR_DMACTRL_DA);
39690fccb52SAndrzej Pietrasiewicz 
39790fccb52SAndrzej Pietrasiewicz 	ep->dma_start = 1;
39890fccb52SAndrzej Pietrasiewicz }
39990fccb52SAndrzej Pietrasiewicz 
40090fccb52SAndrzej Pietrasiewicz /*
40190fccb52SAndrzej Pietrasiewicz  * Finishes the first request in the ep's queue and, if available, starts the
40290fccb52SAndrzej Pietrasiewicz  * next request in queue.
40390fccb52SAndrzej Pietrasiewicz  *
40490fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held, irqs disabled and with !ep->stopped.
40590fccb52SAndrzej Pietrasiewicz  */
gr_dma_advance(struct gr_ep * ep,int status)40690fccb52SAndrzej Pietrasiewicz static void gr_dma_advance(struct gr_ep *ep, int status)
40790fccb52SAndrzej Pietrasiewicz {
40890fccb52SAndrzej Pietrasiewicz 	struct gr_request *req;
40990fccb52SAndrzej Pietrasiewicz 
41090fccb52SAndrzej Pietrasiewicz 	req = list_first_entry(&ep->queue, struct gr_request, queue);
41190fccb52SAndrzej Pietrasiewicz 	gr_finish_request(ep, req, status);
41290fccb52SAndrzej Pietrasiewicz 	gr_start_dma(ep); /* Regardless of ep->dma_start */
41390fccb52SAndrzej Pietrasiewicz }
41490fccb52SAndrzej Pietrasiewicz 
41590fccb52SAndrzej Pietrasiewicz /*
41690fccb52SAndrzej Pietrasiewicz  * Abort DMA for an endpoint. Sets the abort DMA bit which causes an ongoing DMA
41790fccb52SAndrzej Pietrasiewicz  * transfer to be canceled and clears GR_DMACTRL_DA.
41890fccb52SAndrzej Pietrasiewicz  *
41990fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held.
42090fccb52SAndrzej Pietrasiewicz  */
gr_abort_dma(struct gr_ep * ep)42190fccb52SAndrzej Pietrasiewicz static void gr_abort_dma(struct gr_ep *ep)
42290fccb52SAndrzej Pietrasiewicz {
42390fccb52SAndrzej Pietrasiewicz 	u32 dmactrl;
42490fccb52SAndrzej Pietrasiewicz 
42590fccb52SAndrzej Pietrasiewicz 	dmactrl = gr_read32(&ep->regs->dmactrl);
42690fccb52SAndrzej Pietrasiewicz 	gr_write32(&ep->regs->dmactrl, dmactrl | GR_DMACTRL_AD);
42790fccb52SAndrzej Pietrasiewicz }
42890fccb52SAndrzej Pietrasiewicz 
42990fccb52SAndrzej Pietrasiewicz /*
43090fccb52SAndrzej Pietrasiewicz  * Allocates and sets up a struct gr_dma_desc and putting it on the descriptor
43190fccb52SAndrzej Pietrasiewicz  * chain.
43290fccb52SAndrzej Pietrasiewicz  *
43390fccb52SAndrzej Pietrasiewicz  * Size is not used for OUT endpoints. Hardware can not be instructed to handle
43490fccb52SAndrzej Pietrasiewicz  * smaller buffer than MAXPL in the OUT direction.
43590fccb52SAndrzej Pietrasiewicz  */
gr_add_dma_desc(struct gr_ep * ep,struct gr_request * req,dma_addr_t data,unsigned size,gfp_t gfp_flags)43690fccb52SAndrzej Pietrasiewicz static int gr_add_dma_desc(struct gr_ep *ep, struct gr_request *req,
43790fccb52SAndrzej Pietrasiewicz 			   dma_addr_t data, unsigned size, gfp_t gfp_flags)
43890fccb52SAndrzej Pietrasiewicz {
43990fccb52SAndrzej Pietrasiewicz 	struct gr_dma_desc *desc;
44090fccb52SAndrzej Pietrasiewicz 
44190fccb52SAndrzej Pietrasiewicz 	desc = gr_alloc_dma_desc(ep, gfp_flags);
44290fccb52SAndrzej Pietrasiewicz 	if (!desc)
44390fccb52SAndrzej Pietrasiewicz 		return -ENOMEM;
44490fccb52SAndrzej Pietrasiewicz 
44590fccb52SAndrzej Pietrasiewicz 	desc->data = data;
44690fccb52SAndrzej Pietrasiewicz 	if (ep->is_in)
44790fccb52SAndrzej Pietrasiewicz 		desc->ctrl =
44890fccb52SAndrzej Pietrasiewicz 			(GR_DESC_IN_CTRL_LEN_MASK & size) | GR_DESC_IN_CTRL_EN;
44990fccb52SAndrzej Pietrasiewicz 	else
45090fccb52SAndrzej Pietrasiewicz 		desc->ctrl = GR_DESC_OUT_CTRL_IE;
45190fccb52SAndrzej Pietrasiewicz 
45290fccb52SAndrzej Pietrasiewicz 	if (!req->first_desc) {
45390fccb52SAndrzej Pietrasiewicz 		req->first_desc = desc;
45490fccb52SAndrzej Pietrasiewicz 		req->curr_desc = desc;
45590fccb52SAndrzej Pietrasiewicz 	} else {
45690fccb52SAndrzej Pietrasiewicz 		req->last_desc->next_desc = desc;
45790fccb52SAndrzej Pietrasiewicz 		req->last_desc->next = desc->paddr;
45890fccb52SAndrzej Pietrasiewicz 		req->last_desc->ctrl |= GR_DESC_OUT_CTRL_NX;
45990fccb52SAndrzej Pietrasiewicz 	}
46090fccb52SAndrzej Pietrasiewicz 	req->last_desc = desc;
46190fccb52SAndrzej Pietrasiewicz 
46290fccb52SAndrzej Pietrasiewicz 	return 0;
46390fccb52SAndrzej Pietrasiewicz }
46490fccb52SAndrzej Pietrasiewicz 
46590fccb52SAndrzej Pietrasiewicz /*
46690fccb52SAndrzej Pietrasiewicz  * Sets up a chain of struct gr_dma_descriptors pointing to buffers that
46790fccb52SAndrzej Pietrasiewicz  * together covers req->req.length bytes of the buffer at DMA address
46890fccb52SAndrzej Pietrasiewicz  * req->req.dma for the OUT direction.
46990fccb52SAndrzej Pietrasiewicz  *
47090fccb52SAndrzej Pietrasiewicz  * The first descriptor in the chain is enabled, the rest disabled. The
47190fccb52SAndrzej Pietrasiewicz  * interrupt handler will later enable them one by one when needed so we can
47290fccb52SAndrzej Pietrasiewicz  * find out when the transfer is finished. For OUT endpoints, all descriptors
47390fccb52SAndrzej Pietrasiewicz  * therefore generate interrutps.
47490fccb52SAndrzej Pietrasiewicz  */
gr_setup_out_desc_list(struct gr_ep * ep,struct gr_request * req,gfp_t gfp_flags)47590fccb52SAndrzej Pietrasiewicz static int gr_setup_out_desc_list(struct gr_ep *ep, struct gr_request *req,
47690fccb52SAndrzej Pietrasiewicz 				  gfp_t gfp_flags)
47790fccb52SAndrzej Pietrasiewicz {
47890fccb52SAndrzej Pietrasiewicz 	u16 bytes_left; /* Bytes left to provide descriptors for */
47990fccb52SAndrzej Pietrasiewicz 	u16 bytes_used; /* Bytes accommodated for */
48090fccb52SAndrzej Pietrasiewicz 	int ret = 0;
48190fccb52SAndrzej Pietrasiewicz 
48290fccb52SAndrzej Pietrasiewicz 	req->first_desc = NULL; /* Signals that no allocation is done yet */
48390fccb52SAndrzej Pietrasiewicz 	bytes_left = req->req.length;
48490fccb52SAndrzej Pietrasiewicz 	bytes_used = 0;
48590fccb52SAndrzej Pietrasiewicz 	while (bytes_left > 0) {
48690fccb52SAndrzej Pietrasiewicz 		dma_addr_t start = req->req.dma + bytes_used;
48790fccb52SAndrzej Pietrasiewicz 		u16 size = min(bytes_left, ep->bytes_per_buffer);
48890fccb52SAndrzej Pietrasiewicz 
4895b484989SAndreas Larsson 		if (size < ep->bytes_per_buffer) {
4905b484989SAndreas Larsson 			/* Prepare using bounce buffer */
4915b484989SAndreas Larsson 			req->evenlen = req->req.length - bytes_left;
4925b484989SAndreas Larsson 			req->oddlen = size;
4935b484989SAndreas Larsson 		}
49490fccb52SAndrzej Pietrasiewicz 
49590fccb52SAndrzej Pietrasiewicz 		ret = gr_add_dma_desc(ep, req, start, size, gfp_flags);
49690fccb52SAndrzej Pietrasiewicz 		if (ret)
49790fccb52SAndrzej Pietrasiewicz 			goto alloc_err;
49890fccb52SAndrzej Pietrasiewicz 
49990fccb52SAndrzej Pietrasiewicz 		bytes_left -= size;
50090fccb52SAndrzej Pietrasiewicz 		bytes_used += size;
50190fccb52SAndrzej Pietrasiewicz 	}
50290fccb52SAndrzej Pietrasiewicz 
50390fccb52SAndrzej Pietrasiewicz 	req->first_desc->ctrl |= GR_DESC_OUT_CTRL_EN;
50490fccb52SAndrzej Pietrasiewicz 
50590fccb52SAndrzej Pietrasiewicz 	return 0;
50690fccb52SAndrzej Pietrasiewicz 
50790fccb52SAndrzej Pietrasiewicz alloc_err:
50890fccb52SAndrzej Pietrasiewicz 	gr_free_dma_desc_chain(ep->dev, req);
50990fccb52SAndrzej Pietrasiewicz 
51090fccb52SAndrzej Pietrasiewicz 	return ret;
51190fccb52SAndrzej Pietrasiewicz }
51290fccb52SAndrzej Pietrasiewicz 
51390fccb52SAndrzej Pietrasiewicz /*
51490fccb52SAndrzej Pietrasiewicz  * Sets up a chain of struct gr_dma_descriptors pointing to buffers that
51590fccb52SAndrzej Pietrasiewicz  * together covers req->req.length bytes of the buffer at DMA address
51690fccb52SAndrzej Pietrasiewicz  * req->req.dma for the IN direction.
51790fccb52SAndrzej Pietrasiewicz  *
51890fccb52SAndrzej Pietrasiewicz  * When more data is provided than the maximum payload size, the hardware splits
51990fccb52SAndrzej Pietrasiewicz  * this up into several payloads automatically. Moreover, ep->bytes_per_buffer
52090fccb52SAndrzej Pietrasiewicz  * is always set to a multiple of the maximum payload (restricted to the valid
52190fccb52SAndrzej Pietrasiewicz  * number of maximum payloads during high bandwidth isochronous or interrupt
52290fccb52SAndrzej Pietrasiewicz  * transfers)
52390fccb52SAndrzej Pietrasiewicz  *
52490fccb52SAndrzej Pietrasiewicz  * All descriptors are enabled from the beginning and we only generate an
52590fccb52SAndrzej Pietrasiewicz  * interrupt for the last one indicating that the entire request has been pushed
52690fccb52SAndrzej Pietrasiewicz  * to hardware.
52790fccb52SAndrzej Pietrasiewicz  */
gr_setup_in_desc_list(struct gr_ep * ep,struct gr_request * req,gfp_t gfp_flags)52890fccb52SAndrzej Pietrasiewicz static int gr_setup_in_desc_list(struct gr_ep *ep, struct gr_request *req,
52990fccb52SAndrzej Pietrasiewicz 				 gfp_t gfp_flags)
53090fccb52SAndrzej Pietrasiewicz {
53190fccb52SAndrzej Pietrasiewicz 	u16 bytes_left; /* Bytes left in req to provide descriptors for */
53290fccb52SAndrzej Pietrasiewicz 	u16 bytes_used; /* Bytes in req accommodated for */
53390fccb52SAndrzej Pietrasiewicz 	int ret = 0;
53490fccb52SAndrzej Pietrasiewicz 
53590fccb52SAndrzej Pietrasiewicz 	req->first_desc = NULL; /* Signals that no allocation is done yet */
53690fccb52SAndrzej Pietrasiewicz 	bytes_left = req->req.length;
53790fccb52SAndrzej Pietrasiewicz 	bytes_used = 0;
53890fccb52SAndrzej Pietrasiewicz 	do { /* Allow for zero length packets */
53990fccb52SAndrzej Pietrasiewicz 		dma_addr_t start = req->req.dma + bytes_used;
54090fccb52SAndrzej Pietrasiewicz 		u16 size = min(bytes_left, ep->bytes_per_buffer);
54190fccb52SAndrzej Pietrasiewicz 
54290fccb52SAndrzej Pietrasiewicz 		ret = gr_add_dma_desc(ep, req, start, size, gfp_flags);
54390fccb52SAndrzej Pietrasiewicz 		if (ret)
54490fccb52SAndrzej Pietrasiewicz 			goto alloc_err;
54590fccb52SAndrzej Pietrasiewicz 
54690fccb52SAndrzej Pietrasiewicz 		bytes_left -= size;
54790fccb52SAndrzej Pietrasiewicz 		bytes_used += size;
54890fccb52SAndrzej Pietrasiewicz 	} while (bytes_left > 0);
54990fccb52SAndrzej Pietrasiewicz 
55090fccb52SAndrzej Pietrasiewicz 	/*
55190fccb52SAndrzej Pietrasiewicz 	 * Send an extra zero length packet to indicate that no more data is
55290fccb52SAndrzej Pietrasiewicz 	 * available when req->req.zero is set and the data length is even
55390fccb52SAndrzej Pietrasiewicz 	 * multiples of ep->ep.maxpacket.
55490fccb52SAndrzej Pietrasiewicz 	 */
55590fccb52SAndrzej Pietrasiewicz 	if (req->req.zero && (req->req.length % ep->ep.maxpacket == 0)) {
55690fccb52SAndrzej Pietrasiewicz 		ret = gr_add_dma_desc(ep, req, 0, 0, gfp_flags);
55790fccb52SAndrzej Pietrasiewicz 		if (ret)
55890fccb52SAndrzej Pietrasiewicz 			goto alloc_err;
55990fccb52SAndrzej Pietrasiewicz 	}
56090fccb52SAndrzej Pietrasiewicz 
56190fccb52SAndrzej Pietrasiewicz 	/*
56290fccb52SAndrzej Pietrasiewicz 	 * For IN packets we only want to know when the last packet has been
56390fccb52SAndrzej Pietrasiewicz 	 * transmitted (not just put into internal buffers).
56490fccb52SAndrzej Pietrasiewicz 	 */
56590fccb52SAndrzej Pietrasiewicz 	req->last_desc->ctrl |= GR_DESC_IN_CTRL_PI;
56690fccb52SAndrzej Pietrasiewicz 
56790fccb52SAndrzej Pietrasiewicz 	return 0;
56890fccb52SAndrzej Pietrasiewicz 
56990fccb52SAndrzej Pietrasiewicz alloc_err:
57090fccb52SAndrzej Pietrasiewicz 	gr_free_dma_desc_chain(ep->dev, req);
57190fccb52SAndrzej Pietrasiewicz 
57290fccb52SAndrzej Pietrasiewicz 	return ret;
57390fccb52SAndrzej Pietrasiewicz }
57490fccb52SAndrzej Pietrasiewicz 
57590fccb52SAndrzej Pietrasiewicz /* Must be called with dev->lock held */
gr_queue(struct gr_ep * ep,struct gr_request * req,gfp_t gfp_flags)57690fccb52SAndrzej Pietrasiewicz static int gr_queue(struct gr_ep *ep, struct gr_request *req, gfp_t gfp_flags)
57790fccb52SAndrzej Pietrasiewicz {
57890fccb52SAndrzej Pietrasiewicz 	struct gr_udc *dev = ep->dev;
57990fccb52SAndrzej Pietrasiewicz 	int ret;
58090fccb52SAndrzej Pietrasiewicz 
58190fccb52SAndrzej Pietrasiewicz 	if (unlikely(!ep->ep.desc && ep->num != 0)) {
58290fccb52SAndrzej Pietrasiewicz 		dev_err(dev->dev, "No ep descriptor for %s\n", ep->ep.name);
58390fccb52SAndrzej Pietrasiewicz 		return -EINVAL;
58490fccb52SAndrzej Pietrasiewicz 	}
58590fccb52SAndrzej Pietrasiewicz 
58690fccb52SAndrzej Pietrasiewicz 	if (unlikely(!req->req.buf || !list_empty(&req->queue))) {
58790fccb52SAndrzej Pietrasiewicz 		dev_err(dev->dev,
58890fccb52SAndrzej Pietrasiewicz 			"Invalid request for %s: buf=%p list_empty=%d\n",
58990fccb52SAndrzej Pietrasiewicz 			ep->ep.name, req->req.buf, list_empty(&req->queue));
59090fccb52SAndrzej Pietrasiewicz 		return -EINVAL;
59190fccb52SAndrzej Pietrasiewicz 	}
59290fccb52SAndrzej Pietrasiewicz 
59390fccb52SAndrzej Pietrasiewicz 	if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
59490fccb52SAndrzej Pietrasiewicz 		dev_err(dev->dev, "-ESHUTDOWN");
59590fccb52SAndrzej Pietrasiewicz 		return -ESHUTDOWN;
59690fccb52SAndrzej Pietrasiewicz 	}
59790fccb52SAndrzej Pietrasiewicz 
59890fccb52SAndrzej Pietrasiewicz 	/* Can't touch registers when suspended */
59990fccb52SAndrzej Pietrasiewicz 	if (dev->ep0state == GR_EP0_SUSPEND) {
60090fccb52SAndrzej Pietrasiewicz 		dev_err(dev->dev, "-EBUSY");
60190fccb52SAndrzej Pietrasiewicz 		return -EBUSY;
60290fccb52SAndrzej Pietrasiewicz 	}
60390fccb52SAndrzej Pietrasiewicz 
60490fccb52SAndrzej Pietrasiewicz 	/* Set up DMA mapping in case the caller didn't */
60590fccb52SAndrzej Pietrasiewicz 	ret = usb_gadget_map_request(&dev->gadget, &req->req, ep->is_in);
60690fccb52SAndrzej Pietrasiewicz 	if (ret) {
60790fccb52SAndrzej Pietrasiewicz 		dev_err(dev->dev, "usb_gadget_map_request");
60890fccb52SAndrzej Pietrasiewicz 		return ret;
60990fccb52SAndrzej Pietrasiewicz 	}
61090fccb52SAndrzej Pietrasiewicz 
61190fccb52SAndrzej Pietrasiewicz 	if (ep->is_in)
61290fccb52SAndrzej Pietrasiewicz 		ret = gr_setup_in_desc_list(ep, req, gfp_flags);
61390fccb52SAndrzej Pietrasiewicz 	else
61490fccb52SAndrzej Pietrasiewicz 		ret = gr_setup_out_desc_list(ep, req, gfp_flags);
61590fccb52SAndrzej Pietrasiewicz 	if (ret)
61690fccb52SAndrzej Pietrasiewicz 		return ret;
61790fccb52SAndrzej Pietrasiewicz 
61890fccb52SAndrzej Pietrasiewicz 	req->req.status = -EINPROGRESS;
61990fccb52SAndrzej Pietrasiewicz 	req->req.actual = 0;
62090fccb52SAndrzej Pietrasiewicz 	list_add_tail(&req->queue, &ep->queue);
62190fccb52SAndrzej Pietrasiewicz 
62290fccb52SAndrzej Pietrasiewicz 	/* Start DMA if not started, otherwise interrupt handler handles it */
62390fccb52SAndrzej Pietrasiewicz 	if (!ep->dma_start && likely(!ep->stopped))
62490fccb52SAndrzej Pietrasiewicz 		gr_start_dma(ep);
62590fccb52SAndrzej Pietrasiewicz 
62690fccb52SAndrzej Pietrasiewicz 	return 0;
62790fccb52SAndrzej Pietrasiewicz }
62890fccb52SAndrzej Pietrasiewicz 
62990fccb52SAndrzej Pietrasiewicz /*
63090fccb52SAndrzej Pietrasiewicz  * Queue a request from within the driver.
63190fccb52SAndrzej Pietrasiewicz  *
63290fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held.
63390fccb52SAndrzej Pietrasiewicz  */
gr_queue_int(struct gr_ep * ep,struct gr_request * req,gfp_t gfp_flags)63490fccb52SAndrzej Pietrasiewicz static inline int gr_queue_int(struct gr_ep *ep, struct gr_request *req,
63590fccb52SAndrzej Pietrasiewicz 			       gfp_t gfp_flags)
63690fccb52SAndrzej Pietrasiewicz {
63790fccb52SAndrzej Pietrasiewicz 	if (ep->is_in)
63890fccb52SAndrzej Pietrasiewicz 		gr_dbgprint_request("RESP", ep, req);
63990fccb52SAndrzej Pietrasiewicz 
64090fccb52SAndrzej Pietrasiewicz 	return gr_queue(ep, req, gfp_flags);
64190fccb52SAndrzej Pietrasiewicz }
64290fccb52SAndrzej Pietrasiewicz 
64390fccb52SAndrzej Pietrasiewicz /* ---------------------------------------------------------------------- */
64490fccb52SAndrzej Pietrasiewicz /* General helper functions */
64590fccb52SAndrzej Pietrasiewicz 
64690fccb52SAndrzej Pietrasiewicz /*
64790fccb52SAndrzej Pietrasiewicz  * Dequeue ALL requests.
64890fccb52SAndrzej Pietrasiewicz  *
64990fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held and irqs disabled.
65090fccb52SAndrzej Pietrasiewicz  */
gr_ep_nuke(struct gr_ep * ep)65190fccb52SAndrzej Pietrasiewicz static void gr_ep_nuke(struct gr_ep *ep)
65290fccb52SAndrzej Pietrasiewicz {
65390fccb52SAndrzej Pietrasiewicz 	struct gr_request *req;
65490fccb52SAndrzej Pietrasiewicz 
65590fccb52SAndrzej Pietrasiewicz 	ep->stopped = 1;
65690fccb52SAndrzej Pietrasiewicz 	ep->dma_start = 0;
65790fccb52SAndrzej Pietrasiewicz 	gr_abort_dma(ep);
65890fccb52SAndrzej Pietrasiewicz 
65990fccb52SAndrzej Pietrasiewicz 	while (!list_empty(&ep->queue)) {
66090fccb52SAndrzej Pietrasiewicz 		req = list_first_entry(&ep->queue, struct gr_request, queue);
66190fccb52SAndrzej Pietrasiewicz 		gr_finish_request(ep, req, -ESHUTDOWN);
66290fccb52SAndrzej Pietrasiewicz 	}
66390fccb52SAndrzej Pietrasiewicz }
66490fccb52SAndrzej Pietrasiewicz 
66590fccb52SAndrzej Pietrasiewicz /*
66690fccb52SAndrzej Pietrasiewicz  * Reset the hardware state of this endpoint.
66790fccb52SAndrzej Pietrasiewicz  *
66890fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held.
66990fccb52SAndrzej Pietrasiewicz  */
gr_ep_reset(struct gr_ep * ep)67090fccb52SAndrzej Pietrasiewicz static void gr_ep_reset(struct gr_ep *ep)
67190fccb52SAndrzej Pietrasiewicz {
67290fccb52SAndrzej Pietrasiewicz 	gr_write32(&ep->regs->epctrl, 0);
67390fccb52SAndrzej Pietrasiewicz 	gr_write32(&ep->regs->dmactrl, 0);
67490fccb52SAndrzej Pietrasiewicz 
67590fccb52SAndrzej Pietrasiewicz 	ep->ep.maxpacket = MAX_CTRL_PL_SIZE;
67690fccb52SAndrzej Pietrasiewicz 	ep->ep.desc = NULL;
67790fccb52SAndrzej Pietrasiewicz 	ep->stopped = 1;
67890fccb52SAndrzej Pietrasiewicz 	ep->dma_start = 0;
67990fccb52SAndrzej Pietrasiewicz }
68090fccb52SAndrzej Pietrasiewicz 
68190fccb52SAndrzej Pietrasiewicz /*
68290fccb52SAndrzej Pietrasiewicz  * Generate STALL on ep0in/out.
68390fccb52SAndrzej Pietrasiewicz  *
68490fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held.
68590fccb52SAndrzej Pietrasiewicz  */
gr_control_stall(struct gr_udc * dev)68690fccb52SAndrzej Pietrasiewicz static void gr_control_stall(struct gr_udc *dev)
68790fccb52SAndrzej Pietrasiewicz {
68890fccb52SAndrzej Pietrasiewicz 	u32 epctrl;
68990fccb52SAndrzej Pietrasiewicz 
69090fccb52SAndrzej Pietrasiewicz 	epctrl = gr_read32(&dev->epo[0].regs->epctrl);
69190fccb52SAndrzej Pietrasiewicz 	gr_write32(&dev->epo[0].regs->epctrl, epctrl | GR_EPCTRL_CS);
69290fccb52SAndrzej Pietrasiewicz 	epctrl = gr_read32(&dev->epi[0].regs->epctrl);
69390fccb52SAndrzej Pietrasiewicz 	gr_write32(&dev->epi[0].regs->epctrl, epctrl | GR_EPCTRL_CS);
69490fccb52SAndrzej Pietrasiewicz 
69590fccb52SAndrzej Pietrasiewicz 	dev->ep0state = GR_EP0_STALL;
69690fccb52SAndrzej Pietrasiewicz }
69790fccb52SAndrzej Pietrasiewicz 
69890fccb52SAndrzej Pietrasiewicz /*
69990fccb52SAndrzej Pietrasiewicz  * Halts, halts and wedges, or clears halt for an endpoint.
70090fccb52SAndrzej Pietrasiewicz  *
70190fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held.
70290fccb52SAndrzej Pietrasiewicz  */
gr_ep_halt_wedge(struct gr_ep * ep,int halt,int wedge,int fromhost)70390fccb52SAndrzej Pietrasiewicz static int gr_ep_halt_wedge(struct gr_ep *ep, int halt, int wedge, int fromhost)
70490fccb52SAndrzej Pietrasiewicz {
70590fccb52SAndrzej Pietrasiewicz 	u32 epctrl;
70690fccb52SAndrzej Pietrasiewicz 	int retval = 0;
70790fccb52SAndrzej Pietrasiewicz 
70890fccb52SAndrzej Pietrasiewicz 	if (ep->num && !ep->ep.desc)
70990fccb52SAndrzej Pietrasiewicz 		return -EINVAL;
71090fccb52SAndrzej Pietrasiewicz 
71190fccb52SAndrzej Pietrasiewicz 	if (ep->num && ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC)
71290fccb52SAndrzej Pietrasiewicz 		return -EOPNOTSUPP;
71390fccb52SAndrzej Pietrasiewicz 
71490fccb52SAndrzej Pietrasiewicz 	/* Never actually halt ep0, and therefore never clear halt for ep0 */
71590fccb52SAndrzej Pietrasiewicz 	if (!ep->num) {
71690fccb52SAndrzej Pietrasiewicz 		if (halt && !fromhost) {
71790fccb52SAndrzej Pietrasiewicz 			/* ep0 halt from gadget - generate protocol stall */
71890fccb52SAndrzej Pietrasiewicz 			gr_control_stall(ep->dev);
71990fccb52SAndrzej Pietrasiewicz 			dev_dbg(ep->dev->dev, "EP: stall ep0\n");
72090fccb52SAndrzej Pietrasiewicz 			return 0;
72190fccb52SAndrzej Pietrasiewicz 		}
72290fccb52SAndrzej Pietrasiewicz 		return -EINVAL;
72390fccb52SAndrzej Pietrasiewicz 	}
72490fccb52SAndrzej Pietrasiewicz 
72590fccb52SAndrzej Pietrasiewicz 	dev_dbg(ep->dev->dev, "EP: %s halt %s\n",
72690fccb52SAndrzej Pietrasiewicz 		(halt ? (wedge ? "wedge" : "set") : "clear"), ep->ep.name);
72790fccb52SAndrzej Pietrasiewicz 
72890fccb52SAndrzej Pietrasiewicz 	epctrl = gr_read32(&ep->regs->epctrl);
72990fccb52SAndrzej Pietrasiewicz 	if (halt) {
73090fccb52SAndrzej Pietrasiewicz 		/* Set HALT */
73190fccb52SAndrzej Pietrasiewicz 		gr_write32(&ep->regs->epctrl, epctrl | GR_EPCTRL_EH);
73290fccb52SAndrzej Pietrasiewicz 		ep->stopped = 1;
73390fccb52SAndrzej Pietrasiewicz 		if (wedge)
73490fccb52SAndrzej Pietrasiewicz 			ep->wedged = 1;
73590fccb52SAndrzej Pietrasiewicz 	} else {
73690fccb52SAndrzej Pietrasiewicz 		gr_write32(&ep->regs->epctrl, epctrl & ~GR_EPCTRL_EH);
73790fccb52SAndrzej Pietrasiewicz 		ep->stopped = 0;
73890fccb52SAndrzej Pietrasiewicz 		ep->wedged = 0;
73990fccb52SAndrzej Pietrasiewicz 
74090fccb52SAndrzej Pietrasiewicz 		/* Things might have been queued up in the meantime */
74190fccb52SAndrzej Pietrasiewicz 		if (!ep->dma_start)
74290fccb52SAndrzej Pietrasiewicz 			gr_start_dma(ep);
74390fccb52SAndrzej Pietrasiewicz 	}
74490fccb52SAndrzej Pietrasiewicz 
74590fccb52SAndrzej Pietrasiewicz 	return retval;
74690fccb52SAndrzej Pietrasiewicz }
74790fccb52SAndrzej Pietrasiewicz 
74890fccb52SAndrzej Pietrasiewicz /* Must be called with dev->lock held */
gr_set_ep0state(struct gr_udc * dev,enum gr_ep0state value)74990fccb52SAndrzej Pietrasiewicz static inline void gr_set_ep0state(struct gr_udc *dev, enum gr_ep0state value)
75090fccb52SAndrzej Pietrasiewicz {
75190fccb52SAndrzej Pietrasiewicz 	if (dev->ep0state != value)
75290fccb52SAndrzej Pietrasiewicz 		dev_vdbg(dev->dev, "STATE:  ep0state=%s\n",
75390fccb52SAndrzej Pietrasiewicz 			 gr_ep0state_string(value));
75490fccb52SAndrzej Pietrasiewicz 	dev->ep0state = value;
75590fccb52SAndrzej Pietrasiewicz }
75690fccb52SAndrzej Pietrasiewicz 
75790fccb52SAndrzej Pietrasiewicz /*
75890fccb52SAndrzej Pietrasiewicz  * Should only be called when endpoints can not generate interrupts.
75990fccb52SAndrzej Pietrasiewicz  *
76090fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held.
76190fccb52SAndrzej Pietrasiewicz  */
gr_disable_interrupts_and_pullup(struct gr_udc * dev)76290fccb52SAndrzej Pietrasiewicz static void gr_disable_interrupts_and_pullup(struct gr_udc *dev)
76390fccb52SAndrzej Pietrasiewicz {
76490fccb52SAndrzej Pietrasiewicz 	gr_write32(&dev->regs->control, 0);
76590fccb52SAndrzej Pietrasiewicz 	wmb(); /* Make sure that we do not deny one of our interrupts */
76690fccb52SAndrzej Pietrasiewicz 	dev->irq_enabled = 0;
76790fccb52SAndrzej Pietrasiewicz }
76890fccb52SAndrzej Pietrasiewicz 
76990fccb52SAndrzej Pietrasiewicz /*
77090fccb52SAndrzej Pietrasiewicz  * Stop all device activity and disable data line pullup.
77190fccb52SAndrzej Pietrasiewicz  *
77290fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held and irqs disabled.
77390fccb52SAndrzej Pietrasiewicz  */
gr_stop_activity(struct gr_udc * dev)77490fccb52SAndrzej Pietrasiewicz static void gr_stop_activity(struct gr_udc *dev)
77590fccb52SAndrzej Pietrasiewicz {
77690fccb52SAndrzej Pietrasiewicz 	struct gr_ep *ep;
77790fccb52SAndrzej Pietrasiewicz 
77890fccb52SAndrzej Pietrasiewicz 	list_for_each_entry(ep, &dev->ep_list, ep_list)
77990fccb52SAndrzej Pietrasiewicz 		gr_ep_nuke(ep);
78090fccb52SAndrzej Pietrasiewicz 
78190fccb52SAndrzej Pietrasiewicz 	gr_disable_interrupts_and_pullup(dev);
78290fccb52SAndrzej Pietrasiewicz 
78390fccb52SAndrzej Pietrasiewicz 	gr_set_ep0state(dev, GR_EP0_DISCONNECT);
78490fccb52SAndrzej Pietrasiewicz 	usb_gadget_set_state(&dev->gadget, USB_STATE_NOTATTACHED);
78590fccb52SAndrzej Pietrasiewicz }
78690fccb52SAndrzej Pietrasiewicz 
78790fccb52SAndrzej Pietrasiewicz /* ---------------------------------------------------------------------- */
78890fccb52SAndrzej Pietrasiewicz /* ep0 setup packet handling */
78990fccb52SAndrzej Pietrasiewicz 
gr_ep0_testmode_complete(struct usb_ep * _ep,struct usb_request * _req)79090fccb52SAndrzej Pietrasiewicz static void gr_ep0_testmode_complete(struct usb_ep *_ep,
79190fccb52SAndrzej Pietrasiewicz 				     struct usb_request *_req)
79290fccb52SAndrzej Pietrasiewicz {
79390fccb52SAndrzej Pietrasiewicz 	struct gr_ep *ep;
79490fccb52SAndrzej Pietrasiewicz 	struct gr_udc *dev;
79590fccb52SAndrzej Pietrasiewicz 	u32 control;
79690fccb52SAndrzej Pietrasiewicz 
79790fccb52SAndrzej Pietrasiewicz 	ep = container_of(_ep, struct gr_ep, ep);
79890fccb52SAndrzej Pietrasiewicz 	dev = ep->dev;
79990fccb52SAndrzej Pietrasiewicz 
80090fccb52SAndrzej Pietrasiewicz 	spin_lock(&dev->lock);
80190fccb52SAndrzej Pietrasiewicz 
80290fccb52SAndrzej Pietrasiewicz 	control = gr_read32(&dev->regs->control);
80390fccb52SAndrzej Pietrasiewicz 	control |= GR_CONTROL_TM | (dev->test_mode << GR_CONTROL_TS_POS);
80490fccb52SAndrzej Pietrasiewicz 	gr_write32(&dev->regs->control, control);
80590fccb52SAndrzej Pietrasiewicz 
80690fccb52SAndrzej Pietrasiewicz 	spin_unlock(&dev->lock);
80790fccb52SAndrzej Pietrasiewicz }
80890fccb52SAndrzej Pietrasiewicz 
gr_ep0_dummy_complete(struct usb_ep * _ep,struct usb_request * _req)80990fccb52SAndrzej Pietrasiewicz static void gr_ep0_dummy_complete(struct usb_ep *_ep, struct usb_request *_req)
81090fccb52SAndrzej Pietrasiewicz {
81190fccb52SAndrzej Pietrasiewicz 	/* Nothing needs to be done here */
81290fccb52SAndrzej Pietrasiewicz }
81390fccb52SAndrzej Pietrasiewicz 
81490fccb52SAndrzej Pietrasiewicz /*
81590fccb52SAndrzej Pietrasiewicz  * Queue a response on ep0in.
81690fccb52SAndrzej Pietrasiewicz  *
81790fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held.
81890fccb52SAndrzej Pietrasiewicz  */
gr_ep0_respond(struct gr_udc * dev,u8 * buf,int length,void (* complete)(struct usb_ep * ep,struct usb_request * req))81990fccb52SAndrzej Pietrasiewicz static int gr_ep0_respond(struct gr_udc *dev, u8 *buf, int length,
82090fccb52SAndrzej Pietrasiewicz 			  void (*complete)(struct usb_ep *ep,
82190fccb52SAndrzej Pietrasiewicz 					   struct usb_request *req))
82290fccb52SAndrzej Pietrasiewicz {
82390fccb52SAndrzej Pietrasiewicz 	u8 *reqbuf = dev->ep0reqi->req.buf;
82490fccb52SAndrzej Pietrasiewicz 	int status;
82590fccb52SAndrzej Pietrasiewicz 	int i;
82690fccb52SAndrzej Pietrasiewicz 
82790fccb52SAndrzej Pietrasiewicz 	for (i = 0; i < length; i++)
82890fccb52SAndrzej Pietrasiewicz 		reqbuf[i] = buf[i];
82990fccb52SAndrzej Pietrasiewicz 	dev->ep0reqi->req.length = length;
83090fccb52SAndrzej Pietrasiewicz 	dev->ep0reqi->req.complete = complete;
83190fccb52SAndrzej Pietrasiewicz 
83290fccb52SAndrzej Pietrasiewicz 	status = gr_queue_int(&dev->epi[0], dev->ep0reqi, GFP_ATOMIC);
83390fccb52SAndrzej Pietrasiewicz 	if (status < 0)
83490fccb52SAndrzej Pietrasiewicz 		dev_err(dev->dev,
83590fccb52SAndrzej Pietrasiewicz 			"Could not queue ep0in setup response: %d\n", status);
83690fccb52SAndrzej Pietrasiewicz 
83790fccb52SAndrzej Pietrasiewicz 	return status;
83890fccb52SAndrzej Pietrasiewicz }
83990fccb52SAndrzej Pietrasiewicz 
84090fccb52SAndrzej Pietrasiewicz /*
84190fccb52SAndrzej Pietrasiewicz  * Queue a 2 byte response on ep0in.
84290fccb52SAndrzej Pietrasiewicz  *
84390fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held.
84490fccb52SAndrzej Pietrasiewicz  */
gr_ep0_respond_u16(struct gr_udc * dev,u16 response)84590fccb52SAndrzej Pietrasiewicz static inline int gr_ep0_respond_u16(struct gr_udc *dev, u16 response)
84690fccb52SAndrzej Pietrasiewicz {
84790fccb52SAndrzej Pietrasiewicz 	__le16 le_response = cpu_to_le16(response);
84890fccb52SAndrzej Pietrasiewicz 
84990fccb52SAndrzej Pietrasiewicz 	return gr_ep0_respond(dev, (u8 *)&le_response, 2,
85090fccb52SAndrzej Pietrasiewicz 			      gr_ep0_dummy_complete);
85190fccb52SAndrzej Pietrasiewicz }
85290fccb52SAndrzej Pietrasiewicz 
85390fccb52SAndrzej Pietrasiewicz /*
85490fccb52SAndrzej Pietrasiewicz  * Queue a ZLP response on ep0in.
85590fccb52SAndrzej Pietrasiewicz  *
85690fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held.
85790fccb52SAndrzej Pietrasiewicz  */
gr_ep0_respond_empty(struct gr_udc * dev)85890fccb52SAndrzej Pietrasiewicz static inline int gr_ep0_respond_empty(struct gr_udc *dev)
85990fccb52SAndrzej Pietrasiewicz {
86090fccb52SAndrzej Pietrasiewicz 	return gr_ep0_respond(dev, NULL, 0, gr_ep0_dummy_complete);
86190fccb52SAndrzej Pietrasiewicz }
86290fccb52SAndrzej Pietrasiewicz 
86390fccb52SAndrzej Pietrasiewicz /*
86490fccb52SAndrzej Pietrasiewicz  * This is run when a SET_ADDRESS request is received. First writes
86590fccb52SAndrzej Pietrasiewicz  * the new address to the control register which is updated internally
86690fccb52SAndrzej Pietrasiewicz  * when the next IN packet is ACKED.
86790fccb52SAndrzej Pietrasiewicz  *
86890fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held.
86990fccb52SAndrzej Pietrasiewicz  */
gr_set_address(struct gr_udc * dev,u8 address)87090fccb52SAndrzej Pietrasiewicz static void gr_set_address(struct gr_udc *dev, u8 address)
87190fccb52SAndrzej Pietrasiewicz {
87290fccb52SAndrzej Pietrasiewicz 	u32 control;
87390fccb52SAndrzej Pietrasiewicz 
87490fccb52SAndrzej Pietrasiewicz 	control = gr_read32(&dev->regs->control) & ~GR_CONTROL_UA_MASK;
87590fccb52SAndrzej Pietrasiewicz 	control |= (address << GR_CONTROL_UA_POS) & GR_CONTROL_UA_MASK;
87690fccb52SAndrzej Pietrasiewicz 	control |= GR_CONTROL_SU;
87790fccb52SAndrzej Pietrasiewicz 	gr_write32(&dev->regs->control, control);
87890fccb52SAndrzej Pietrasiewicz }
87990fccb52SAndrzej Pietrasiewicz 
88090fccb52SAndrzej Pietrasiewicz /*
88190fccb52SAndrzej Pietrasiewicz  * Returns negative for STALL, 0 for successful handling and positive for
88290fccb52SAndrzej Pietrasiewicz  * delegation.
88390fccb52SAndrzej Pietrasiewicz  *
88490fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held.
88590fccb52SAndrzej Pietrasiewicz  */
gr_device_request(struct gr_udc * dev,u8 type,u8 request,u16 value,u16 index)88690fccb52SAndrzej Pietrasiewicz static int gr_device_request(struct gr_udc *dev, u8 type, u8 request,
88790fccb52SAndrzej Pietrasiewicz 			     u16 value, u16 index)
88890fccb52SAndrzej Pietrasiewicz {
88990fccb52SAndrzej Pietrasiewicz 	u16 response;
89090fccb52SAndrzej Pietrasiewicz 	u8 test;
89190fccb52SAndrzej Pietrasiewicz 
89290fccb52SAndrzej Pietrasiewicz 	switch (request) {
89390fccb52SAndrzej Pietrasiewicz 	case USB_REQ_SET_ADDRESS:
89490fccb52SAndrzej Pietrasiewicz 		dev_dbg(dev->dev, "STATUS: address %d\n", value & 0xff);
89590fccb52SAndrzej Pietrasiewicz 		gr_set_address(dev, value & 0xff);
89690fccb52SAndrzej Pietrasiewicz 		if (value)
89790fccb52SAndrzej Pietrasiewicz 			usb_gadget_set_state(&dev->gadget, USB_STATE_ADDRESS);
89890fccb52SAndrzej Pietrasiewicz 		else
89990fccb52SAndrzej Pietrasiewicz 			usb_gadget_set_state(&dev->gadget, USB_STATE_DEFAULT);
90090fccb52SAndrzej Pietrasiewicz 		return gr_ep0_respond_empty(dev);
90190fccb52SAndrzej Pietrasiewicz 
90290fccb52SAndrzej Pietrasiewicz 	case USB_REQ_GET_STATUS:
90390fccb52SAndrzej Pietrasiewicz 		/* Self powered | remote wakeup */
90490fccb52SAndrzej Pietrasiewicz 		response = 0x0001 | (dev->remote_wakeup ? 0x0002 : 0);
90590fccb52SAndrzej Pietrasiewicz 		return gr_ep0_respond_u16(dev, response);
90690fccb52SAndrzej Pietrasiewicz 
90790fccb52SAndrzej Pietrasiewicz 	case USB_REQ_SET_FEATURE:
90890fccb52SAndrzej Pietrasiewicz 		switch (value) {
90990fccb52SAndrzej Pietrasiewicz 		case USB_DEVICE_REMOTE_WAKEUP:
91090fccb52SAndrzej Pietrasiewicz 			/* Allow remote wakeup */
91190fccb52SAndrzej Pietrasiewicz 			dev->remote_wakeup = 1;
91290fccb52SAndrzej Pietrasiewicz 			return gr_ep0_respond_empty(dev);
91390fccb52SAndrzej Pietrasiewicz 
91490fccb52SAndrzej Pietrasiewicz 		case USB_DEVICE_TEST_MODE:
91562fb45d3SGreg Kroah-Hartman 			/* The hardware does not support USB_TEST_FORCE_ENABLE */
91690fccb52SAndrzej Pietrasiewicz 			test = index >> 8;
91762fb45d3SGreg Kroah-Hartman 			if (test >= USB_TEST_J && test <= USB_TEST_PACKET) {
91890fccb52SAndrzej Pietrasiewicz 				dev->test_mode = test;
91990fccb52SAndrzej Pietrasiewicz 				return gr_ep0_respond(dev, NULL, 0,
92090fccb52SAndrzej Pietrasiewicz 						      gr_ep0_testmode_complete);
92190fccb52SAndrzej Pietrasiewicz 			}
92290fccb52SAndrzej Pietrasiewicz 		}
92390fccb52SAndrzej Pietrasiewicz 		break;
92490fccb52SAndrzej Pietrasiewicz 
92590fccb52SAndrzej Pietrasiewicz 	case USB_REQ_CLEAR_FEATURE:
92690fccb52SAndrzej Pietrasiewicz 		switch (value) {
92790fccb52SAndrzej Pietrasiewicz 		case USB_DEVICE_REMOTE_WAKEUP:
92890fccb52SAndrzej Pietrasiewicz 			/* Disallow remote wakeup */
92990fccb52SAndrzej Pietrasiewicz 			dev->remote_wakeup = 0;
93090fccb52SAndrzej Pietrasiewicz 			return gr_ep0_respond_empty(dev);
93190fccb52SAndrzej Pietrasiewicz 		}
93290fccb52SAndrzej Pietrasiewicz 		break;
93390fccb52SAndrzej Pietrasiewicz 	}
93490fccb52SAndrzej Pietrasiewicz 
93590fccb52SAndrzej Pietrasiewicz 	return 1; /* Delegate the rest */
93690fccb52SAndrzej Pietrasiewicz }
93790fccb52SAndrzej Pietrasiewicz 
93890fccb52SAndrzej Pietrasiewicz /*
93990fccb52SAndrzej Pietrasiewicz  * Returns negative for STALL, 0 for successful handling and positive for
94090fccb52SAndrzej Pietrasiewicz  * delegation.
94190fccb52SAndrzej Pietrasiewicz  *
94290fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held.
94390fccb52SAndrzej Pietrasiewicz  */
gr_interface_request(struct gr_udc * dev,u8 type,u8 request,u16 value,u16 index)94490fccb52SAndrzej Pietrasiewicz static int gr_interface_request(struct gr_udc *dev, u8 type, u8 request,
94590fccb52SAndrzej Pietrasiewicz 				u16 value, u16 index)
94690fccb52SAndrzej Pietrasiewicz {
94790fccb52SAndrzej Pietrasiewicz 	if (dev->gadget.state != USB_STATE_CONFIGURED)
94890fccb52SAndrzej Pietrasiewicz 		return -1;
94990fccb52SAndrzej Pietrasiewicz 
95090fccb52SAndrzej Pietrasiewicz 	/*
95190fccb52SAndrzej Pietrasiewicz 	 * Should return STALL for invalid interfaces, but udc driver does not
95290fccb52SAndrzej Pietrasiewicz 	 * know anything about that. However, many gadget drivers do not handle
95390fccb52SAndrzej Pietrasiewicz 	 * GET_STATUS so we need to take care of that.
95490fccb52SAndrzej Pietrasiewicz 	 */
95590fccb52SAndrzej Pietrasiewicz 
95690fccb52SAndrzej Pietrasiewicz 	switch (request) {
95790fccb52SAndrzej Pietrasiewicz 	case USB_REQ_GET_STATUS:
95890fccb52SAndrzej Pietrasiewicz 		return gr_ep0_respond_u16(dev, 0x0000);
95990fccb52SAndrzej Pietrasiewicz 
96090fccb52SAndrzej Pietrasiewicz 	case USB_REQ_SET_FEATURE:
96190fccb52SAndrzej Pietrasiewicz 	case USB_REQ_CLEAR_FEATURE:
96290fccb52SAndrzej Pietrasiewicz 		/*
96390fccb52SAndrzej Pietrasiewicz 		 * No possible valid standard requests. Still let gadget drivers
96490fccb52SAndrzej Pietrasiewicz 		 * have a go at it.
96590fccb52SAndrzej Pietrasiewicz 		 */
96690fccb52SAndrzej Pietrasiewicz 		break;
96790fccb52SAndrzej Pietrasiewicz 	}
96890fccb52SAndrzej Pietrasiewicz 
96990fccb52SAndrzej Pietrasiewicz 	return 1; /* Delegate the rest */
97090fccb52SAndrzej Pietrasiewicz }
97190fccb52SAndrzej Pietrasiewicz 
97290fccb52SAndrzej Pietrasiewicz /*
97390fccb52SAndrzej Pietrasiewicz  * Returns negative for STALL, 0 for successful handling and positive for
97490fccb52SAndrzej Pietrasiewicz  * delegation.
97590fccb52SAndrzej Pietrasiewicz  *
97690fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held.
97790fccb52SAndrzej Pietrasiewicz  */
gr_endpoint_request(struct gr_udc * dev,u8 type,u8 request,u16 value,u16 index)97890fccb52SAndrzej Pietrasiewicz static int gr_endpoint_request(struct gr_udc *dev, u8 type, u8 request,
97990fccb52SAndrzej Pietrasiewicz 			       u16 value, u16 index)
98090fccb52SAndrzej Pietrasiewicz {
98190fccb52SAndrzej Pietrasiewicz 	struct gr_ep *ep;
98290fccb52SAndrzej Pietrasiewicz 	int status;
98390fccb52SAndrzej Pietrasiewicz 	int halted;
98490fccb52SAndrzej Pietrasiewicz 	u8 epnum = index & USB_ENDPOINT_NUMBER_MASK;
98590fccb52SAndrzej Pietrasiewicz 	u8 is_in = index & USB_ENDPOINT_DIR_MASK;
98690fccb52SAndrzej Pietrasiewicz 
98790fccb52SAndrzej Pietrasiewicz 	if ((is_in && epnum >= dev->nepi) || (!is_in && epnum >= dev->nepo))
98890fccb52SAndrzej Pietrasiewicz 		return -1;
98990fccb52SAndrzej Pietrasiewicz 
99090fccb52SAndrzej Pietrasiewicz 	if (dev->gadget.state != USB_STATE_CONFIGURED && epnum != 0)
99190fccb52SAndrzej Pietrasiewicz 		return -1;
99290fccb52SAndrzej Pietrasiewicz 
99390fccb52SAndrzej Pietrasiewicz 	ep = (is_in ? &dev->epi[epnum] : &dev->epo[epnum]);
99490fccb52SAndrzej Pietrasiewicz 
99590fccb52SAndrzej Pietrasiewicz 	switch (request) {
99690fccb52SAndrzej Pietrasiewicz 	case USB_REQ_GET_STATUS:
99790fccb52SAndrzej Pietrasiewicz 		halted = gr_read32(&ep->regs->epctrl) & GR_EPCTRL_EH;
99890fccb52SAndrzej Pietrasiewicz 		return gr_ep0_respond_u16(dev, halted ? 0x0001 : 0);
99990fccb52SAndrzej Pietrasiewicz 
100090fccb52SAndrzej Pietrasiewicz 	case USB_REQ_SET_FEATURE:
100190fccb52SAndrzej Pietrasiewicz 		switch (value) {
100290fccb52SAndrzej Pietrasiewicz 		case USB_ENDPOINT_HALT:
100390fccb52SAndrzej Pietrasiewicz 			status = gr_ep_halt_wedge(ep, 1, 0, 1);
100490fccb52SAndrzej Pietrasiewicz 			if (status >= 0)
100590fccb52SAndrzej Pietrasiewicz 				status = gr_ep0_respond_empty(dev);
100690fccb52SAndrzej Pietrasiewicz 			return status;
100790fccb52SAndrzej Pietrasiewicz 		}
100890fccb52SAndrzej Pietrasiewicz 		break;
100990fccb52SAndrzej Pietrasiewicz 
101090fccb52SAndrzej Pietrasiewicz 	case USB_REQ_CLEAR_FEATURE:
101190fccb52SAndrzej Pietrasiewicz 		switch (value) {
101290fccb52SAndrzej Pietrasiewicz 		case USB_ENDPOINT_HALT:
101390fccb52SAndrzej Pietrasiewicz 			if (ep->wedged)
101490fccb52SAndrzej Pietrasiewicz 				return -1;
101590fccb52SAndrzej Pietrasiewicz 			status = gr_ep_halt_wedge(ep, 0, 0, 1);
101690fccb52SAndrzej Pietrasiewicz 			if (status >= 0)
101790fccb52SAndrzej Pietrasiewicz 				status = gr_ep0_respond_empty(dev);
101890fccb52SAndrzej Pietrasiewicz 			return status;
101990fccb52SAndrzej Pietrasiewicz 		}
102090fccb52SAndrzej Pietrasiewicz 		break;
102190fccb52SAndrzej Pietrasiewicz 	}
102290fccb52SAndrzej Pietrasiewicz 
102390fccb52SAndrzej Pietrasiewicz 	return 1; /* Delegate the rest */
102490fccb52SAndrzej Pietrasiewicz }
102590fccb52SAndrzej Pietrasiewicz 
102690fccb52SAndrzej Pietrasiewicz /* Must be called with dev->lock held */
gr_ep0out_requeue(struct gr_udc * dev)102790fccb52SAndrzej Pietrasiewicz static void gr_ep0out_requeue(struct gr_udc *dev)
102890fccb52SAndrzej Pietrasiewicz {
102990fccb52SAndrzej Pietrasiewicz 	int ret = gr_queue_int(&dev->epo[0], dev->ep0reqo, GFP_ATOMIC);
103090fccb52SAndrzej Pietrasiewicz 
103190fccb52SAndrzej Pietrasiewicz 	if (ret)
103290fccb52SAndrzej Pietrasiewicz 		dev_err(dev->dev, "Could not queue ep0out setup request: %d\n",
103390fccb52SAndrzej Pietrasiewicz 			ret);
103490fccb52SAndrzej Pietrasiewicz }
103590fccb52SAndrzej Pietrasiewicz 
103690fccb52SAndrzej Pietrasiewicz /*
103790fccb52SAndrzej Pietrasiewicz  * The main function dealing with setup requests on ep0.
103890fccb52SAndrzej Pietrasiewicz  *
103990fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held and irqs disabled
104090fccb52SAndrzej Pietrasiewicz  */
gr_ep0_setup(struct gr_udc * dev,struct gr_request * req)104190fccb52SAndrzej Pietrasiewicz static void gr_ep0_setup(struct gr_udc *dev, struct gr_request *req)
104290fccb52SAndrzej Pietrasiewicz 	__releases(&dev->lock)
104390fccb52SAndrzej Pietrasiewicz 	__acquires(&dev->lock)
104490fccb52SAndrzej Pietrasiewicz {
104590fccb52SAndrzej Pietrasiewicz 	union {
104690fccb52SAndrzej Pietrasiewicz 		struct usb_ctrlrequest ctrl;
104790fccb52SAndrzej Pietrasiewicz 		u8 raw[8];
104890fccb52SAndrzej Pietrasiewicz 		u32 word[2];
104990fccb52SAndrzej Pietrasiewicz 	} u;
105090fccb52SAndrzej Pietrasiewicz 	u8 type;
105190fccb52SAndrzej Pietrasiewicz 	u8 request;
105290fccb52SAndrzej Pietrasiewicz 	u16 value;
105390fccb52SAndrzej Pietrasiewicz 	u16 index;
105490fccb52SAndrzej Pietrasiewicz 	u16 length;
105590fccb52SAndrzej Pietrasiewicz 	int i;
105690fccb52SAndrzej Pietrasiewicz 	int status;
105790fccb52SAndrzej Pietrasiewicz 
105890fccb52SAndrzej Pietrasiewicz 	/* Restore from ep0 halt */
105990fccb52SAndrzej Pietrasiewicz 	if (dev->ep0state == GR_EP0_STALL) {
106090fccb52SAndrzej Pietrasiewicz 		gr_set_ep0state(dev, GR_EP0_SETUP);
106190fccb52SAndrzej Pietrasiewicz 		if (!req->req.actual)
106290fccb52SAndrzej Pietrasiewicz 			goto out;
106390fccb52SAndrzej Pietrasiewicz 	}
106490fccb52SAndrzej Pietrasiewicz 
106590fccb52SAndrzej Pietrasiewicz 	if (dev->ep0state == GR_EP0_ISTATUS) {
106690fccb52SAndrzej Pietrasiewicz 		gr_set_ep0state(dev, GR_EP0_SETUP);
106790fccb52SAndrzej Pietrasiewicz 		if (req->req.actual > 0)
106890fccb52SAndrzej Pietrasiewicz 			dev_dbg(dev->dev,
106990fccb52SAndrzej Pietrasiewicz 				"Unexpected setup packet at state %s\n",
107090fccb52SAndrzej Pietrasiewicz 				gr_ep0state_string(GR_EP0_ISTATUS));
107190fccb52SAndrzej Pietrasiewicz 		else
107290fccb52SAndrzej Pietrasiewicz 			goto out; /* Got expected ZLP */
107390fccb52SAndrzej Pietrasiewicz 	} else if (dev->ep0state != GR_EP0_SETUP) {
107490fccb52SAndrzej Pietrasiewicz 		dev_info(dev->dev,
107590fccb52SAndrzej Pietrasiewicz 			 "Unexpected ep0out request at state %s - stalling\n",
107690fccb52SAndrzej Pietrasiewicz 			 gr_ep0state_string(dev->ep0state));
107790fccb52SAndrzej Pietrasiewicz 		gr_control_stall(dev);
107890fccb52SAndrzej Pietrasiewicz 		gr_set_ep0state(dev, GR_EP0_SETUP);
107990fccb52SAndrzej Pietrasiewicz 		goto out;
108090fccb52SAndrzej Pietrasiewicz 	} else if (!req->req.actual) {
108190fccb52SAndrzej Pietrasiewicz 		dev_dbg(dev->dev, "Unexpected ZLP at state %s\n",
108290fccb52SAndrzej Pietrasiewicz 			gr_ep0state_string(dev->ep0state));
108390fccb52SAndrzej Pietrasiewicz 		goto out;
108490fccb52SAndrzej Pietrasiewicz 	}
108590fccb52SAndrzej Pietrasiewicz 
108690fccb52SAndrzej Pietrasiewicz 	/* Handle SETUP packet */
108790fccb52SAndrzej Pietrasiewicz 	for (i = 0; i < req->req.actual; i++)
108890fccb52SAndrzej Pietrasiewicz 		u.raw[i] = ((u8 *)req->req.buf)[i];
108990fccb52SAndrzej Pietrasiewicz 
109090fccb52SAndrzej Pietrasiewicz 	type = u.ctrl.bRequestType;
109190fccb52SAndrzej Pietrasiewicz 	request = u.ctrl.bRequest;
109290fccb52SAndrzej Pietrasiewicz 	value = le16_to_cpu(u.ctrl.wValue);
109390fccb52SAndrzej Pietrasiewicz 	index = le16_to_cpu(u.ctrl.wIndex);
109490fccb52SAndrzej Pietrasiewicz 	length = le16_to_cpu(u.ctrl.wLength);
109590fccb52SAndrzej Pietrasiewicz 
109690fccb52SAndrzej Pietrasiewicz 	gr_dbgprint_devreq(dev, type, request, value, index, length);
109790fccb52SAndrzej Pietrasiewicz 
109890fccb52SAndrzej Pietrasiewicz 	/* Check for data stage */
109990fccb52SAndrzej Pietrasiewicz 	if (length) {
110090fccb52SAndrzej Pietrasiewicz 		if (type & USB_DIR_IN)
110190fccb52SAndrzej Pietrasiewicz 			gr_set_ep0state(dev, GR_EP0_IDATA);
110290fccb52SAndrzej Pietrasiewicz 		else
110390fccb52SAndrzej Pietrasiewicz 			gr_set_ep0state(dev, GR_EP0_ODATA);
110490fccb52SAndrzej Pietrasiewicz 	}
110590fccb52SAndrzej Pietrasiewicz 
110690fccb52SAndrzej Pietrasiewicz 	status = 1; /* Positive status flags delegation */
110790fccb52SAndrzej Pietrasiewicz 	if ((type & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
110890fccb52SAndrzej Pietrasiewicz 		switch (type & USB_RECIP_MASK) {
110990fccb52SAndrzej Pietrasiewicz 		case USB_RECIP_DEVICE:
111090fccb52SAndrzej Pietrasiewicz 			status = gr_device_request(dev, type, request,
111190fccb52SAndrzej Pietrasiewicz 						   value, index);
111290fccb52SAndrzej Pietrasiewicz 			break;
111390fccb52SAndrzej Pietrasiewicz 		case USB_RECIP_ENDPOINT:
111490fccb52SAndrzej Pietrasiewicz 			status =  gr_endpoint_request(dev, type, request,
111590fccb52SAndrzej Pietrasiewicz 						      value, index);
111690fccb52SAndrzej Pietrasiewicz 			break;
111790fccb52SAndrzej Pietrasiewicz 		case USB_RECIP_INTERFACE:
111890fccb52SAndrzej Pietrasiewicz 			status = gr_interface_request(dev, type, request,
111990fccb52SAndrzej Pietrasiewicz 						      value, index);
112090fccb52SAndrzej Pietrasiewicz 			break;
112190fccb52SAndrzej Pietrasiewicz 		}
112290fccb52SAndrzej Pietrasiewicz 	}
112390fccb52SAndrzej Pietrasiewicz 
112490fccb52SAndrzej Pietrasiewicz 	if (status > 0) {
112590fccb52SAndrzej Pietrasiewicz 		spin_unlock(&dev->lock);
112690fccb52SAndrzej Pietrasiewicz 
112790fccb52SAndrzej Pietrasiewicz 		dev_vdbg(dev->dev, "DELEGATE\n");
112890fccb52SAndrzej Pietrasiewicz 		status = dev->driver->setup(&dev->gadget, &u.ctrl);
112990fccb52SAndrzej Pietrasiewicz 
113090fccb52SAndrzej Pietrasiewicz 		spin_lock(&dev->lock);
113190fccb52SAndrzej Pietrasiewicz 	}
113290fccb52SAndrzej Pietrasiewicz 
113390fccb52SAndrzej Pietrasiewicz 	/* Generate STALL on both ep0out and ep0in if requested */
113490fccb52SAndrzej Pietrasiewicz 	if (unlikely(status < 0)) {
113590fccb52SAndrzej Pietrasiewicz 		dev_vdbg(dev->dev, "STALL\n");
113690fccb52SAndrzej Pietrasiewicz 		gr_control_stall(dev);
113790fccb52SAndrzej Pietrasiewicz 	}
113890fccb52SAndrzej Pietrasiewicz 
113990fccb52SAndrzej Pietrasiewicz 	if ((type & USB_TYPE_MASK) == USB_TYPE_STANDARD &&
114090fccb52SAndrzej Pietrasiewicz 	    request == USB_REQ_SET_CONFIGURATION) {
114190fccb52SAndrzej Pietrasiewicz 		if (!value) {
114290fccb52SAndrzej Pietrasiewicz 			dev_dbg(dev->dev, "STATUS: deconfigured\n");
114390fccb52SAndrzej Pietrasiewicz 			usb_gadget_set_state(&dev->gadget, USB_STATE_ADDRESS);
114490fccb52SAndrzej Pietrasiewicz 		} else if (status >= 0) {
114590fccb52SAndrzej Pietrasiewicz 			/* Not configured unless gadget OK:s it */
114690fccb52SAndrzej Pietrasiewicz 			dev_dbg(dev->dev, "STATUS: configured: %d\n", value);
114790fccb52SAndrzej Pietrasiewicz 			usb_gadget_set_state(&dev->gadget,
114890fccb52SAndrzej Pietrasiewicz 					     USB_STATE_CONFIGURED);
114990fccb52SAndrzej Pietrasiewicz 		}
115090fccb52SAndrzej Pietrasiewicz 	}
115190fccb52SAndrzej Pietrasiewicz 
115290fccb52SAndrzej Pietrasiewicz 	/* Get ready for next stage */
115390fccb52SAndrzej Pietrasiewicz 	if (dev->ep0state == GR_EP0_ODATA)
115490fccb52SAndrzej Pietrasiewicz 		gr_set_ep0state(dev, GR_EP0_OSTATUS);
115590fccb52SAndrzej Pietrasiewicz 	else if (dev->ep0state == GR_EP0_IDATA)
115690fccb52SAndrzej Pietrasiewicz 		gr_set_ep0state(dev, GR_EP0_ISTATUS);
115790fccb52SAndrzej Pietrasiewicz 	else
115890fccb52SAndrzej Pietrasiewicz 		gr_set_ep0state(dev, GR_EP0_SETUP);
115990fccb52SAndrzej Pietrasiewicz 
116090fccb52SAndrzej Pietrasiewicz out:
116190fccb52SAndrzej Pietrasiewicz 	gr_ep0out_requeue(dev);
116290fccb52SAndrzej Pietrasiewicz }
116390fccb52SAndrzej Pietrasiewicz 
116490fccb52SAndrzej Pietrasiewicz /* ---------------------------------------------------------------------- */
116590fccb52SAndrzej Pietrasiewicz /* VBUS and USB reset handling */
116690fccb52SAndrzej Pietrasiewicz 
116790fccb52SAndrzej Pietrasiewicz /* Must be called with dev->lock held and irqs disabled  */
gr_vbus_connected(struct gr_udc * dev,u32 status)116890fccb52SAndrzej Pietrasiewicz static void gr_vbus_connected(struct gr_udc *dev, u32 status)
116990fccb52SAndrzej Pietrasiewicz {
117090fccb52SAndrzej Pietrasiewicz 	u32 control;
117190fccb52SAndrzej Pietrasiewicz 
117290fccb52SAndrzej Pietrasiewicz 	dev->gadget.speed = GR_SPEED(status);
117390fccb52SAndrzej Pietrasiewicz 	usb_gadget_set_state(&dev->gadget, USB_STATE_POWERED);
117490fccb52SAndrzej Pietrasiewicz 
117590fccb52SAndrzej Pietrasiewicz 	/* Turn on full interrupts and pullup */
117690fccb52SAndrzej Pietrasiewicz 	control = (GR_CONTROL_SI | GR_CONTROL_UI | GR_CONTROL_VI |
117790fccb52SAndrzej Pietrasiewicz 		   GR_CONTROL_SP | GR_CONTROL_EP);
117890fccb52SAndrzej Pietrasiewicz 	gr_write32(&dev->regs->control, control);
117990fccb52SAndrzej Pietrasiewicz }
118090fccb52SAndrzej Pietrasiewicz 
118190fccb52SAndrzej Pietrasiewicz /* Must be called with dev->lock held */
gr_enable_vbus_detect(struct gr_udc * dev)118290fccb52SAndrzej Pietrasiewicz static void gr_enable_vbus_detect(struct gr_udc *dev)
118390fccb52SAndrzej Pietrasiewicz {
118490fccb52SAndrzej Pietrasiewicz 	u32 status;
118590fccb52SAndrzej Pietrasiewicz 
118690fccb52SAndrzej Pietrasiewicz 	dev->irq_enabled = 1;
118790fccb52SAndrzej Pietrasiewicz 	wmb(); /* Make sure we do not ignore an interrupt */
118890fccb52SAndrzej Pietrasiewicz 	gr_write32(&dev->regs->control, GR_CONTROL_VI);
118990fccb52SAndrzej Pietrasiewicz 
119090fccb52SAndrzej Pietrasiewicz 	/* Take care of the case we are already plugged in at this point */
119190fccb52SAndrzej Pietrasiewicz 	status = gr_read32(&dev->regs->status);
119290fccb52SAndrzej Pietrasiewicz 	if (status & GR_STATUS_VB)
119390fccb52SAndrzej Pietrasiewicz 		gr_vbus_connected(dev, status);
119490fccb52SAndrzej Pietrasiewicz }
119590fccb52SAndrzej Pietrasiewicz 
119690fccb52SAndrzej Pietrasiewicz /* Must be called with dev->lock held and irqs disabled */
gr_vbus_disconnected(struct gr_udc * dev)119790fccb52SAndrzej Pietrasiewicz static void gr_vbus_disconnected(struct gr_udc *dev)
119890fccb52SAndrzej Pietrasiewicz {
119990fccb52SAndrzej Pietrasiewicz 	gr_stop_activity(dev);
120090fccb52SAndrzej Pietrasiewicz 
120190fccb52SAndrzej Pietrasiewicz 	/* Report disconnect */
120290fccb52SAndrzej Pietrasiewicz 	if (dev->driver && dev->driver->disconnect) {
120390fccb52SAndrzej Pietrasiewicz 		spin_unlock(&dev->lock);
120490fccb52SAndrzej Pietrasiewicz 
120590fccb52SAndrzej Pietrasiewicz 		dev->driver->disconnect(&dev->gadget);
120690fccb52SAndrzej Pietrasiewicz 
120790fccb52SAndrzej Pietrasiewicz 		spin_lock(&dev->lock);
120890fccb52SAndrzej Pietrasiewicz 	}
120990fccb52SAndrzej Pietrasiewicz 
121090fccb52SAndrzej Pietrasiewicz 	gr_enable_vbus_detect(dev);
121190fccb52SAndrzej Pietrasiewicz }
121290fccb52SAndrzej Pietrasiewicz 
121390fccb52SAndrzej Pietrasiewicz /* Must be called with dev->lock held and irqs disabled */
gr_udc_usbreset(struct gr_udc * dev,u32 status)121490fccb52SAndrzej Pietrasiewicz static void gr_udc_usbreset(struct gr_udc *dev, u32 status)
121590fccb52SAndrzej Pietrasiewicz {
121690fccb52SAndrzej Pietrasiewicz 	gr_set_address(dev, 0);
121790fccb52SAndrzej Pietrasiewicz 	gr_set_ep0state(dev, GR_EP0_SETUP);
121890fccb52SAndrzej Pietrasiewicz 	usb_gadget_set_state(&dev->gadget, USB_STATE_DEFAULT);
121990fccb52SAndrzej Pietrasiewicz 	dev->gadget.speed = GR_SPEED(status);
122090fccb52SAndrzej Pietrasiewicz 
122190fccb52SAndrzej Pietrasiewicz 	gr_ep_nuke(&dev->epo[0]);
122290fccb52SAndrzej Pietrasiewicz 	gr_ep_nuke(&dev->epi[0]);
122390fccb52SAndrzej Pietrasiewicz 	dev->epo[0].stopped = 0;
122490fccb52SAndrzej Pietrasiewicz 	dev->epi[0].stopped = 0;
122590fccb52SAndrzej Pietrasiewicz 	gr_ep0out_requeue(dev);
122690fccb52SAndrzej Pietrasiewicz }
122790fccb52SAndrzej Pietrasiewicz 
122890fccb52SAndrzej Pietrasiewicz /* ---------------------------------------------------------------------- */
122990fccb52SAndrzej Pietrasiewicz /* Irq handling */
123090fccb52SAndrzej Pietrasiewicz 
123190fccb52SAndrzej Pietrasiewicz /*
123290fccb52SAndrzej Pietrasiewicz  * Handles interrupts from in endpoints. Returns whether something was handled.
123390fccb52SAndrzej Pietrasiewicz  *
123490fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held, irqs disabled and with !ep->stopped.
123590fccb52SAndrzej Pietrasiewicz  */
gr_handle_in_ep(struct gr_ep * ep)123690fccb52SAndrzej Pietrasiewicz static int gr_handle_in_ep(struct gr_ep *ep)
123790fccb52SAndrzej Pietrasiewicz {
123890fccb52SAndrzej Pietrasiewicz 	struct gr_request *req;
123990fccb52SAndrzej Pietrasiewicz 
124090fccb52SAndrzej Pietrasiewicz 	req = list_first_entry(&ep->queue, struct gr_request, queue);
124190fccb52SAndrzej Pietrasiewicz 	if (!req->last_desc)
124290fccb52SAndrzej Pietrasiewicz 		return 0;
124390fccb52SAndrzej Pietrasiewicz 
12446aa7de05SMark Rutland 	if (READ_ONCE(req->last_desc->ctrl) & GR_DESC_IN_CTRL_EN)
124590fccb52SAndrzej Pietrasiewicz 		return 0; /* Not put in hardware buffers yet */
124690fccb52SAndrzej Pietrasiewicz 
124790fccb52SAndrzej Pietrasiewicz 	if (gr_read32(&ep->regs->epstat) & (GR_EPSTAT_B1 | GR_EPSTAT_B0))
124890fccb52SAndrzej Pietrasiewicz 		return 0; /* Not transmitted yet, still in hardware buffers */
124990fccb52SAndrzej Pietrasiewicz 
125090fccb52SAndrzej Pietrasiewicz 	/* Write complete */
125190fccb52SAndrzej Pietrasiewicz 	gr_dma_advance(ep, 0);
125290fccb52SAndrzej Pietrasiewicz 
125390fccb52SAndrzej Pietrasiewicz 	return 1;
125490fccb52SAndrzej Pietrasiewicz }
125590fccb52SAndrzej Pietrasiewicz 
125690fccb52SAndrzej Pietrasiewicz /*
125790fccb52SAndrzej Pietrasiewicz  * Handles interrupts from out endpoints. Returns whether something was handled.
125890fccb52SAndrzej Pietrasiewicz  *
125990fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held, irqs disabled and with !ep->stopped.
126090fccb52SAndrzej Pietrasiewicz  */
gr_handle_out_ep(struct gr_ep * ep)126190fccb52SAndrzej Pietrasiewicz static int gr_handle_out_ep(struct gr_ep *ep)
126290fccb52SAndrzej Pietrasiewicz {
126390fccb52SAndrzej Pietrasiewicz 	u32 ep_dmactrl;
126490fccb52SAndrzej Pietrasiewicz 	u32 ctrl;
126590fccb52SAndrzej Pietrasiewicz 	u16 len;
126690fccb52SAndrzej Pietrasiewicz 	struct gr_request *req;
126790fccb52SAndrzej Pietrasiewicz 	struct gr_udc *dev = ep->dev;
126890fccb52SAndrzej Pietrasiewicz 
126990fccb52SAndrzej Pietrasiewicz 	req = list_first_entry(&ep->queue, struct gr_request, queue);
127090fccb52SAndrzej Pietrasiewicz 	if (!req->curr_desc)
127190fccb52SAndrzej Pietrasiewicz 		return 0;
127290fccb52SAndrzej Pietrasiewicz 
12736aa7de05SMark Rutland 	ctrl = READ_ONCE(req->curr_desc->ctrl);
127490fccb52SAndrzej Pietrasiewicz 	if (ctrl & GR_DESC_OUT_CTRL_EN)
127590fccb52SAndrzej Pietrasiewicz 		return 0; /* Not received yet */
127690fccb52SAndrzej Pietrasiewicz 
127790fccb52SAndrzej Pietrasiewicz 	/* Read complete */
127890fccb52SAndrzej Pietrasiewicz 	len = ctrl & GR_DESC_OUT_CTRL_LEN_MASK;
127990fccb52SAndrzej Pietrasiewicz 	req->req.actual += len;
128090fccb52SAndrzej Pietrasiewicz 	if (ctrl & GR_DESC_OUT_CTRL_SE)
128190fccb52SAndrzej Pietrasiewicz 		req->setup = 1;
128290fccb52SAndrzej Pietrasiewicz 
12835b484989SAndreas Larsson 	if (len < ep->ep.maxpacket || req->req.actual >= req->req.length) {
12845b484989SAndreas Larsson 		/* Short packet or >= expected size - we are done */
128590fccb52SAndrzej Pietrasiewicz 
128690fccb52SAndrzej Pietrasiewicz 		if ((ep == &dev->epo[0]) && (dev->ep0state == GR_EP0_OSTATUS)) {
128790fccb52SAndrzej Pietrasiewicz 			/*
128890fccb52SAndrzej Pietrasiewicz 			 * Send a status stage ZLP to ack the DATA stage in the
128990fccb52SAndrzej Pietrasiewicz 			 * OUT direction. This needs to be done before
129090fccb52SAndrzej Pietrasiewicz 			 * gr_dma_advance as that can lead to a call to
129190fccb52SAndrzej Pietrasiewicz 			 * ep0_setup that can change dev->ep0state.
129290fccb52SAndrzej Pietrasiewicz 			 */
129390fccb52SAndrzej Pietrasiewicz 			gr_ep0_respond_empty(dev);
129490fccb52SAndrzej Pietrasiewicz 			gr_set_ep0state(dev, GR_EP0_SETUP);
129590fccb52SAndrzej Pietrasiewicz 		}
129690fccb52SAndrzej Pietrasiewicz 
129790fccb52SAndrzej Pietrasiewicz 		gr_dma_advance(ep, 0);
129890fccb52SAndrzej Pietrasiewicz 	} else {
129990fccb52SAndrzej Pietrasiewicz 		/* Not done yet. Enable the next descriptor to receive more. */
130090fccb52SAndrzej Pietrasiewicz 		req->curr_desc = req->curr_desc->next_desc;
130190fccb52SAndrzej Pietrasiewicz 		req->curr_desc->ctrl |= GR_DESC_OUT_CTRL_EN;
130290fccb52SAndrzej Pietrasiewicz 
130390fccb52SAndrzej Pietrasiewicz 		ep_dmactrl = gr_read32(&ep->regs->dmactrl);
130490fccb52SAndrzej Pietrasiewicz 		gr_write32(&ep->regs->dmactrl, ep_dmactrl | GR_DMACTRL_DA);
130590fccb52SAndrzej Pietrasiewicz 	}
130690fccb52SAndrzej Pietrasiewicz 
130790fccb52SAndrzej Pietrasiewicz 	return 1;
130890fccb52SAndrzej Pietrasiewicz }
130990fccb52SAndrzej Pietrasiewicz 
131090fccb52SAndrzej Pietrasiewicz /*
131190fccb52SAndrzej Pietrasiewicz  * Handle state changes. Returns whether something was handled.
131290fccb52SAndrzej Pietrasiewicz  *
131390fccb52SAndrzej Pietrasiewicz  * Must be called with dev->lock held and irqs disabled.
131490fccb52SAndrzej Pietrasiewicz  */
gr_handle_state_changes(struct gr_udc * dev)131590fccb52SAndrzej Pietrasiewicz static int gr_handle_state_changes(struct gr_udc *dev)
131690fccb52SAndrzej Pietrasiewicz {
131790fccb52SAndrzej Pietrasiewicz 	u32 status = gr_read32(&dev->regs->status);
131890fccb52SAndrzej Pietrasiewicz 	int handled = 0;
131990fccb52SAndrzej Pietrasiewicz 	int powstate = !(dev->gadget.state == USB_STATE_NOTATTACHED ||
132090fccb52SAndrzej Pietrasiewicz 			 dev->gadget.state == USB_STATE_ATTACHED);
132190fccb52SAndrzej Pietrasiewicz 
132290fccb52SAndrzej Pietrasiewicz 	/* VBUS valid detected */
132390fccb52SAndrzej Pietrasiewicz 	if (!powstate && (status & GR_STATUS_VB)) {
132490fccb52SAndrzej Pietrasiewicz 		dev_dbg(dev->dev, "STATUS: vbus valid detected\n");
132590fccb52SAndrzej Pietrasiewicz 		gr_vbus_connected(dev, status);
132690fccb52SAndrzej Pietrasiewicz 		handled = 1;
132790fccb52SAndrzej Pietrasiewicz 	}
132890fccb52SAndrzej Pietrasiewicz 
132990fccb52SAndrzej Pietrasiewicz 	/* Disconnect */
133090fccb52SAndrzej Pietrasiewicz 	if (powstate && !(status & GR_STATUS_VB)) {
133190fccb52SAndrzej Pietrasiewicz 		dev_dbg(dev->dev, "STATUS: vbus invalid detected\n");
133290fccb52SAndrzej Pietrasiewicz 		gr_vbus_disconnected(dev);
133390fccb52SAndrzej Pietrasiewicz 		handled = 1;
133490fccb52SAndrzej Pietrasiewicz 	}
133590fccb52SAndrzej Pietrasiewicz 
133690fccb52SAndrzej Pietrasiewicz 	/* USB reset detected */
133790fccb52SAndrzej Pietrasiewicz 	if (status & GR_STATUS_UR) {
133890fccb52SAndrzej Pietrasiewicz 		dev_dbg(dev->dev, "STATUS: USB reset - speed is %s\n",
133990fccb52SAndrzej Pietrasiewicz 			GR_SPEED_STR(status));
134090fccb52SAndrzej Pietrasiewicz 		gr_write32(&dev->regs->status, GR_STATUS_UR);
134190fccb52SAndrzej Pietrasiewicz 		gr_udc_usbreset(dev, status);
134290fccb52SAndrzej Pietrasiewicz 		handled = 1;
134390fccb52SAndrzej Pietrasiewicz 	}
134490fccb52SAndrzej Pietrasiewicz 
134590fccb52SAndrzej Pietrasiewicz 	/* Speed change */
134690fccb52SAndrzej Pietrasiewicz 	if (dev->gadget.speed != GR_SPEED(status)) {
134790fccb52SAndrzej Pietrasiewicz 		dev_dbg(dev->dev, "STATUS: USB Speed change to %s\n",
134890fccb52SAndrzej Pietrasiewicz 			GR_SPEED_STR(status));
134990fccb52SAndrzej Pietrasiewicz 		dev->gadget.speed = GR_SPEED(status);
135090fccb52SAndrzej Pietrasiewicz 		handled = 1;
135190fccb52SAndrzej Pietrasiewicz 	}
135290fccb52SAndrzej Pietrasiewicz 
135390fccb52SAndrzej Pietrasiewicz 	/* Going into suspend */
135490fccb52SAndrzej Pietrasiewicz 	if ((dev->ep0state != GR_EP0_SUSPEND) && !(status & GR_STATUS_SU)) {
135590fccb52SAndrzej Pietrasiewicz 		dev_dbg(dev->dev, "STATUS: USB suspend\n");
135690fccb52SAndrzej Pietrasiewicz 		gr_set_ep0state(dev, GR_EP0_SUSPEND);
135790fccb52SAndrzej Pietrasiewicz 		dev->suspended_from = dev->gadget.state;
135890fccb52SAndrzej Pietrasiewicz 		usb_gadget_set_state(&dev->gadget, USB_STATE_SUSPENDED);
135990fccb52SAndrzej Pietrasiewicz 
136090fccb52SAndrzej Pietrasiewicz 		if ((dev->gadget.speed != USB_SPEED_UNKNOWN) &&
136190fccb52SAndrzej Pietrasiewicz 		    dev->driver && dev->driver->suspend) {
136290fccb52SAndrzej Pietrasiewicz 			spin_unlock(&dev->lock);
136390fccb52SAndrzej Pietrasiewicz 
136490fccb52SAndrzej Pietrasiewicz 			dev->driver->suspend(&dev->gadget);
136590fccb52SAndrzej Pietrasiewicz 
136690fccb52SAndrzej Pietrasiewicz 			spin_lock(&dev->lock);
136790fccb52SAndrzej Pietrasiewicz 		}
136890fccb52SAndrzej Pietrasiewicz 		handled = 1;
136990fccb52SAndrzej Pietrasiewicz 	}
137090fccb52SAndrzej Pietrasiewicz 
137190fccb52SAndrzej Pietrasiewicz 	/* Coming out of suspend */
137290fccb52SAndrzej Pietrasiewicz 	if ((dev->ep0state == GR_EP0_SUSPEND) && (status & GR_STATUS_SU)) {
137390fccb52SAndrzej Pietrasiewicz 		dev_dbg(dev->dev, "STATUS: USB resume\n");
137490fccb52SAndrzej Pietrasiewicz 		if (dev->suspended_from == USB_STATE_POWERED)
137590fccb52SAndrzej Pietrasiewicz 			gr_set_ep0state(dev, GR_EP0_DISCONNECT);
137690fccb52SAndrzej Pietrasiewicz 		else
137790fccb52SAndrzej Pietrasiewicz 			gr_set_ep0state(dev, GR_EP0_SETUP);
137890fccb52SAndrzej Pietrasiewicz 		usb_gadget_set_state(&dev->gadget, dev->suspended_from);
137990fccb52SAndrzej Pietrasiewicz 
138090fccb52SAndrzej Pietrasiewicz 		if ((dev->gadget.speed != USB_SPEED_UNKNOWN) &&
138190fccb52SAndrzej Pietrasiewicz 		    dev->driver && dev->driver->resume) {
138290fccb52SAndrzej Pietrasiewicz 			spin_unlock(&dev->lock);
138390fccb52SAndrzej Pietrasiewicz 
138490fccb52SAndrzej Pietrasiewicz 			dev->driver->resume(&dev->gadget);
138590fccb52SAndrzej Pietrasiewicz 
138690fccb52SAndrzej Pietrasiewicz 			spin_lock(&dev->lock);
138790fccb52SAndrzej Pietrasiewicz 		}
138890fccb52SAndrzej Pietrasiewicz 		handled = 1;
138990fccb52SAndrzej Pietrasiewicz 	}
139090fccb52SAndrzej Pietrasiewicz 
139190fccb52SAndrzej Pietrasiewicz 	return handled;
139290fccb52SAndrzej Pietrasiewicz }
139390fccb52SAndrzej Pietrasiewicz 
139490fccb52SAndrzej Pietrasiewicz /* Non-interrupt context irq handler */
gr_irq_handler(int irq,void * _dev)139590fccb52SAndrzej Pietrasiewicz static irqreturn_t gr_irq_handler(int irq, void *_dev)
139690fccb52SAndrzej Pietrasiewicz {
139790fccb52SAndrzej Pietrasiewicz 	struct gr_udc *dev = _dev;
139890fccb52SAndrzej Pietrasiewicz 	struct gr_ep *ep;
139990fccb52SAndrzej Pietrasiewicz 	int handled = 0;
140090fccb52SAndrzej Pietrasiewicz 	int i;
140190fccb52SAndrzej Pietrasiewicz 	unsigned long flags;
140290fccb52SAndrzej Pietrasiewicz 
140390fccb52SAndrzej Pietrasiewicz 	spin_lock_irqsave(&dev->lock, flags);
140490fccb52SAndrzej Pietrasiewicz 
140590fccb52SAndrzej Pietrasiewicz 	if (!dev->irq_enabled)
140690fccb52SAndrzej Pietrasiewicz 		goto out;
140790fccb52SAndrzej Pietrasiewicz 
140890fccb52SAndrzej Pietrasiewicz 	/*
140990fccb52SAndrzej Pietrasiewicz 	 * Check IN ep interrupts. We check these before the OUT eps because
141090fccb52SAndrzej Pietrasiewicz 	 * some gadgets reuse the request that might already be currently
141190fccb52SAndrzej Pietrasiewicz 	 * outstanding and needs to be completed (mainly setup requests).
141290fccb52SAndrzej Pietrasiewicz 	 */
141390fccb52SAndrzej Pietrasiewicz 	for (i = 0; i < dev->nepi; i++) {
141490fccb52SAndrzej Pietrasiewicz 		ep = &dev->epi[i];
141590fccb52SAndrzej Pietrasiewicz 		if (!ep->stopped && !ep->callback && !list_empty(&ep->queue))
141690fccb52SAndrzej Pietrasiewicz 			handled = gr_handle_in_ep(ep) || handled;
141790fccb52SAndrzej Pietrasiewicz 	}
141890fccb52SAndrzej Pietrasiewicz 
141990fccb52SAndrzej Pietrasiewicz 	/* Check OUT ep interrupts */
142090fccb52SAndrzej Pietrasiewicz 	for (i = 0; i < dev->nepo; i++) {
142190fccb52SAndrzej Pietrasiewicz 		ep = &dev->epo[i];
142290fccb52SAndrzej Pietrasiewicz 		if (!ep->stopped && !ep->callback && !list_empty(&ep->queue))
142390fccb52SAndrzej Pietrasiewicz 			handled = gr_handle_out_ep(ep) || handled;
142490fccb52SAndrzej Pietrasiewicz 	}
142590fccb52SAndrzej Pietrasiewicz 
142690fccb52SAndrzej Pietrasiewicz 	/* Check status interrupts */
142790fccb52SAndrzej Pietrasiewicz 	handled = gr_handle_state_changes(dev) || handled;
142890fccb52SAndrzej Pietrasiewicz 
142990fccb52SAndrzej Pietrasiewicz 	/*
143090fccb52SAndrzej Pietrasiewicz 	 * Check AMBA DMA errors. Only check if we didn't find anything else to
143190fccb52SAndrzej Pietrasiewicz 	 * handle because this shouldn't happen if we did everything right.
143290fccb52SAndrzej Pietrasiewicz 	 */
143390fccb52SAndrzej Pietrasiewicz 	if (!handled) {
143490fccb52SAndrzej Pietrasiewicz 		list_for_each_entry(ep, &dev->ep_list, ep_list) {
143590fccb52SAndrzej Pietrasiewicz 			if (gr_read32(&ep->regs->dmactrl) & GR_DMACTRL_AE) {
143690fccb52SAndrzej Pietrasiewicz 				dev_err(dev->dev,
143790fccb52SAndrzej Pietrasiewicz 					"AMBA Error occurred for %s\n",
143890fccb52SAndrzej Pietrasiewicz 					ep->ep.name);
143990fccb52SAndrzej Pietrasiewicz 				handled = 1;
144090fccb52SAndrzej Pietrasiewicz 			}
144190fccb52SAndrzej Pietrasiewicz 		}
144290fccb52SAndrzej Pietrasiewicz 	}
144390fccb52SAndrzej Pietrasiewicz 
144490fccb52SAndrzej Pietrasiewicz out:
144590fccb52SAndrzej Pietrasiewicz 	spin_unlock_irqrestore(&dev->lock, flags);
144690fccb52SAndrzej Pietrasiewicz 
144790fccb52SAndrzej Pietrasiewicz 	return handled ? IRQ_HANDLED : IRQ_NONE;
144890fccb52SAndrzej Pietrasiewicz }
144990fccb52SAndrzej Pietrasiewicz 
145090fccb52SAndrzej Pietrasiewicz /* Interrupt context irq handler */
gr_irq(int irq,void * _dev)145190fccb52SAndrzej Pietrasiewicz static irqreturn_t gr_irq(int irq, void *_dev)
145290fccb52SAndrzej Pietrasiewicz {
145390fccb52SAndrzej Pietrasiewicz 	struct gr_udc *dev = _dev;
145490fccb52SAndrzej Pietrasiewicz 
145590fccb52SAndrzej Pietrasiewicz 	if (!dev->irq_enabled)
145690fccb52SAndrzej Pietrasiewicz 		return IRQ_NONE;
145790fccb52SAndrzej Pietrasiewicz 
145890fccb52SAndrzej Pietrasiewicz 	return IRQ_WAKE_THREAD;
145990fccb52SAndrzej Pietrasiewicz }
146090fccb52SAndrzej Pietrasiewicz 
146190fccb52SAndrzej Pietrasiewicz /* ---------------------------------------------------------------------- */
146290fccb52SAndrzej Pietrasiewicz /* USB ep ops */
146390fccb52SAndrzej Pietrasiewicz 
146490fccb52SAndrzej Pietrasiewicz /* Enable endpoint. Not for ep0in and ep0out that are handled separately. */
gr_ep_enable(struct usb_ep * _ep,const struct usb_endpoint_descriptor * desc)146590fccb52SAndrzej Pietrasiewicz static int gr_ep_enable(struct usb_ep *_ep,
146690fccb52SAndrzej Pietrasiewicz 			const struct usb_endpoint_descriptor *desc)
146790fccb52SAndrzej Pietrasiewicz {
146890fccb52SAndrzej Pietrasiewicz 	struct gr_udc *dev;
146990fccb52SAndrzej Pietrasiewicz 	struct gr_ep *ep;
147090fccb52SAndrzej Pietrasiewicz 	u8 mode;
147190fccb52SAndrzej Pietrasiewicz 	u8 nt;
147290fccb52SAndrzej Pietrasiewicz 	u16 max;
147390fccb52SAndrzej Pietrasiewicz 	u16 buffer_size = 0;
147490fccb52SAndrzej Pietrasiewicz 	u32 epctrl;
147590fccb52SAndrzej Pietrasiewicz 
147690fccb52SAndrzej Pietrasiewicz 	ep = container_of(_ep, struct gr_ep, ep);
147790fccb52SAndrzej Pietrasiewicz 	if (!_ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT)
147890fccb52SAndrzej Pietrasiewicz 		return -EINVAL;
147990fccb52SAndrzej Pietrasiewicz 
148090fccb52SAndrzej Pietrasiewicz 	dev = ep->dev;
148190fccb52SAndrzej Pietrasiewicz 
148290fccb52SAndrzej Pietrasiewicz 	/* 'ep0' IN and OUT are reserved */
148390fccb52SAndrzej Pietrasiewicz 	if (ep == &dev->epo[0] || ep == &dev->epi[0])
148490fccb52SAndrzej Pietrasiewicz 		return -EINVAL;
148590fccb52SAndrzej Pietrasiewicz 
148690fccb52SAndrzej Pietrasiewicz 	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
148790fccb52SAndrzej Pietrasiewicz 		return -ESHUTDOWN;
148890fccb52SAndrzej Pietrasiewicz 
148990fccb52SAndrzej Pietrasiewicz 	/* Make sure we are clear for enabling */
149090fccb52SAndrzej Pietrasiewicz 	epctrl = gr_read32(&ep->regs->epctrl);
149190fccb52SAndrzej Pietrasiewicz 	if (epctrl & GR_EPCTRL_EV)
149290fccb52SAndrzej Pietrasiewicz 		return -EBUSY;
149390fccb52SAndrzej Pietrasiewicz 
149490fccb52SAndrzej Pietrasiewicz 	/* Check that directions match */
149590fccb52SAndrzej Pietrasiewicz 	if (!ep->is_in != !usb_endpoint_dir_in(desc))
149690fccb52SAndrzej Pietrasiewicz 		return -EINVAL;
149790fccb52SAndrzej Pietrasiewicz 
149890fccb52SAndrzej Pietrasiewicz 	/* Check ep num */
149990fccb52SAndrzej Pietrasiewicz 	if ((!ep->is_in && ep->num >= dev->nepo) ||
150090fccb52SAndrzej Pietrasiewicz 	    (ep->is_in && ep->num >= dev->nepi))
150190fccb52SAndrzej Pietrasiewicz 		return -EINVAL;
150290fccb52SAndrzej Pietrasiewicz 
150390fccb52SAndrzej Pietrasiewicz 	if (usb_endpoint_xfer_control(desc)) {
150490fccb52SAndrzej Pietrasiewicz 		mode = 0;
150590fccb52SAndrzej Pietrasiewicz 	} else if (usb_endpoint_xfer_isoc(desc)) {
150690fccb52SAndrzej Pietrasiewicz 		mode = 1;
150790fccb52SAndrzej Pietrasiewicz 	} else if (usb_endpoint_xfer_bulk(desc)) {
150890fccb52SAndrzej Pietrasiewicz 		mode = 2;
150990fccb52SAndrzej Pietrasiewicz 	} else if (usb_endpoint_xfer_int(desc)) {
151090fccb52SAndrzej Pietrasiewicz 		mode = 3;
151190fccb52SAndrzej Pietrasiewicz 	} else {
151290fccb52SAndrzej Pietrasiewicz 		dev_err(dev->dev, "Unknown transfer type for %s\n",
151390fccb52SAndrzej Pietrasiewicz 			ep->ep.name);
151490fccb52SAndrzej Pietrasiewicz 		return -EINVAL;
151590fccb52SAndrzej Pietrasiewicz 	}
151690fccb52SAndrzej Pietrasiewicz 
151790fccb52SAndrzej Pietrasiewicz 	/*
151890fccb52SAndrzej Pietrasiewicz 	 * Bits 10-0 set the max payload. 12-11 set the number of
151990fccb52SAndrzej Pietrasiewicz 	 * additional transactions.
152090fccb52SAndrzej Pietrasiewicz 	 */
15217521d479SJaejoong Kim 	max = usb_endpoint_maxp(desc);
1522a0fefbdeSFelipe Balbi 	nt = usb_endpoint_maxp_mult(desc) - 1;
152390fccb52SAndrzej Pietrasiewicz 	buffer_size = GR_BUFFER_SIZE(epctrl);
152490fccb52SAndrzej Pietrasiewicz 	if (nt && (mode == 0 || mode == 2)) {
152590fccb52SAndrzej Pietrasiewicz 		dev_err(dev->dev,
152690fccb52SAndrzej Pietrasiewicz 			"%s mode: multiple trans./microframe not valid\n",
152790fccb52SAndrzej Pietrasiewicz 			(mode == 2 ? "Bulk" : "Control"));
152890fccb52SAndrzej Pietrasiewicz 		return -EINVAL;
152961fe2d75SGreg Kroah-Hartman 	} else if (nt == 0x3) {
153061fe2d75SGreg Kroah-Hartman 		dev_err(dev->dev,
153161fe2d75SGreg Kroah-Hartman 			"Invalid value 0x3 for additional trans./microframe\n");
153290fccb52SAndrzej Pietrasiewicz 		return -EINVAL;
153390fccb52SAndrzej Pietrasiewicz 	} else if ((nt + 1) * max > buffer_size) {
153490fccb52SAndrzej Pietrasiewicz 		dev_err(dev->dev, "Hw buffer size %d < max payload %d * %d\n",
153590fccb52SAndrzej Pietrasiewicz 			buffer_size, (nt + 1), max);
153690fccb52SAndrzej Pietrasiewicz 		return -EINVAL;
153790fccb52SAndrzej Pietrasiewicz 	} else if (max == 0) {
153890fccb52SAndrzej Pietrasiewicz 		dev_err(dev->dev, "Max payload cannot be set to 0\n");
153990fccb52SAndrzej Pietrasiewicz 		return -EINVAL;
154090fccb52SAndrzej Pietrasiewicz 	} else if (max > ep->ep.maxpacket_limit) {
154190fccb52SAndrzej Pietrasiewicz 		dev_err(dev->dev, "Requested max payload %d > limit %d\n",
154290fccb52SAndrzej Pietrasiewicz 			max, ep->ep.maxpacket_limit);
154390fccb52SAndrzej Pietrasiewicz 		return -EINVAL;
154490fccb52SAndrzej Pietrasiewicz 	}
154590fccb52SAndrzej Pietrasiewicz 
154690fccb52SAndrzej Pietrasiewicz 	spin_lock(&ep->dev->lock);
154790fccb52SAndrzej Pietrasiewicz 
154890fccb52SAndrzej Pietrasiewicz 	if (!ep->stopped) {
154990fccb52SAndrzej Pietrasiewicz 		spin_unlock(&ep->dev->lock);
155090fccb52SAndrzej Pietrasiewicz 		return -EBUSY;
155190fccb52SAndrzej Pietrasiewicz 	}
155290fccb52SAndrzej Pietrasiewicz 
155390fccb52SAndrzej Pietrasiewicz 	ep->stopped = 0;
155490fccb52SAndrzej Pietrasiewicz 	ep->wedged = 0;
155590fccb52SAndrzej Pietrasiewicz 	ep->ep.desc = desc;
155690fccb52SAndrzej Pietrasiewicz 	ep->ep.maxpacket = max;
155790fccb52SAndrzej Pietrasiewicz 	ep->dma_start = 0;
155890fccb52SAndrzej Pietrasiewicz 
155990fccb52SAndrzej Pietrasiewicz 
156090fccb52SAndrzej Pietrasiewicz 	if (nt) {
156190fccb52SAndrzej Pietrasiewicz 		/*
156290fccb52SAndrzej Pietrasiewicz 		 * Maximum possible size of all payloads in one microframe
156390fccb52SAndrzej Pietrasiewicz 		 * regardless of direction when using high-bandwidth mode.
156490fccb52SAndrzej Pietrasiewicz 		 */
156590fccb52SAndrzej Pietrasiewicz 		ep->bytes_per_buffer = (nt + 1) * max;
156690fccb52SAndrzej Pietrasiewicz 	} else if (ep->is_in) {
156790fccb52SAndrzej Pietrasiewicz 		/*
156890fccb52SAndrzej Pietrasiewicz 		 * The biggest multiple of maximum packet size that fits into
156990fccb52SAndrzej Pietrasiewicz 		 * the buffer. The hardware will split up into many packets in
157090fccb52SAndrzej Pietrasiewicz 		 * the IN direction.
157190fccb52SAndrzej Pietrasiewicz 		 */
157290fccb52SAndrzej Pietrasiewicz 		ep->bytes_per_buffer = (buffer_size / max) * max;
157390fccb52SAndrzej Pietrasiewicz 	} else {
157490fccb52SAndrzej Pietrasiewicz 		/*
157590fccb52SAndrzej Pietrasiewicz 		 * Only single packets will be placed the buffers in the OUT
157690fccb52SAndrzej Pietrasiewicz 		 * direction.
157790fccb52SAndrzej Pietrasiewicz 		 */
157890fccb52SAndrzej Pietrasiewicz 		ep->bytes_per_buffer = max;
157990fccb52SAndrzej Pietrasiewicz 	}
158090fccb52SAndrzej Pietrasiewicz 
158190fccb52SAndrzej Pietrasiewicz 	epctrl = (max << GR_EPCTRL_MAXPL_POS)
158290fccb52SAndrzej Pietrasiewicz 		| (nt << GR_EPCTRL_NT_POS)
158390fccb52SAndrzej Pietrasiewicz 		| (mode << GR_EPCTRL_TT_POS)
158490fccb52SAndrzej Pietrasiewicz 		| GR_EPCTRL_EV;
158590fccb52SAndrzej Pietrasiewicz 	if (ep->is_in)
158690fccb52SAndrzej Pietrasiewicz 		epctrl |= GR_EPCTRL_PI;
158790fccb52SAndrzej Pietrasiewicz 	gr_write32(&ep->regs->epctrl, epctrl);
158890fccb52SAndrzej Pietrasiewicz 
158990fccb52SAndrzej Pietrasiewicz 	gr_write32(&ep->regs->dmactrl, GR_DMACTRL_IE | GR_DMACTRL_AI);
159090fccb52SAndrzej Pietrasiewicz 
159190fccb52SAndrzej Pietrasiewicz 	spin_unlock(&ep->dev->lock);
159290fccb52SAndrzej Pietrasiewicz 
159390fccb52SAndrzej Pietrasiewicz 	dev_dbg(ep->dev->dev, "EP: %s enabled - %s with %d bytes/buffer\n",
159490fccb52SAndrzej Pietrasiewicz 		ep->ep.name, gr_modestring[mode], ep->bytes_per_buffer);
159590fccb52SAndrzej Pietrasiewicz 	return 0;
159690fccb52SAndrzej Pietrasiewicz }
159790fccb52SAndrzej Pietrasiewicz 
159890fccb52SAndrzej Pietrasiewicz /* Disable endpoint. Not for ep0in and ep0out that are handled separately. */
gr_ep_disable(struct usb_ep * _ep)159990fccb52SAndrzej Pietrasiewicz static int gr_ep_disable(struct usb_ep *_ep)
160090fccb52SAndrzej Pietrasiewicz {
160190fccb52SAndrzej Pietrasiewicz 	struct gr_ep *ep;
160290fccb52SAndrzej Pietrasiewicz 	struct gr_udc *dev;
160390fccb52SAndrzej Pietrasiewicz 	unsigned long flags;
160490fccb52SAndrzej Pietrasiewicz 
160590fccb52SAndrzej Pietrasiewicz 	ep = container_of(_ep, struct gr_ep, ep);
160690fccb52SAndrzej Pietrasiewicz 	if (!_ep || !ep->ep.desc)
160790fccb52SAndrzej Pietrasiewicz 		return -ENODEV;
160890fccb52SAndrzej Pietrasiewicz 
160990fccb52SAndrzej Pietrasiewicz 	dev = ep->dev;
161090fccb52SAndrzej Pietrasiewicz 
161190fccb52SAndrzej Pietrasiewicz 	/* 'ep0' IN and OUT are reserved */
161290fccb52SAndrzej Pietrasiewicz 	if (ep == &dev->epo[0] || ep == &dev->epi[0])
161390fccb52SAndrzej Pietrasiewicz 		return -EINVAL;
161490fccb52SAndrzej Pietrasiewicz 
161590fccb52SAndrzej Pietrasiewicz 	if (dev->ep0state == GR_EP0_SUSPEND)
161690fccb52SAndrzej Pietrasiewicz 		return -EBUSY;
161790fccb52SAndrzej Pietrasiewicz 
161890fccb52SAndrzej Pietrasiewicz 	dev_dbg(ep->dev->dev, "EP: disable %s\n", ep->ep.name);
161990fccb52SAndrzej Pietrasiewicz 
162090fccb52SAndrzej Pietrasiewicz 	spin_lock_irqsave(&dev->lock, flags);
162190fccb52SAndrzej Pietrasiewicz 
162290fccb52SAndrzej Pietrasiewicz 	gr_ep_nuke(ep);
162390fccb52SAndrzej Pietrasiewicz 	gr_ep_reset(ep);
162490fccb52SAndrzej Pietrasiewicz 	ep->ep.desc = NULL;
162590fccb52SAndrzej Pietrasiewicz 
162690fccb52SAndrzej Pietrasiewicz 	spin_unlock_irqrestore(&dev->lock, flags);
162790fccb52SAndrzej Pietrasiewicz 
162890fccb52SAndrzej Pietrasiewicz 	return 0;
162990fccb52SAndrzej Pietrasiewicz }
163090fccb52SAndrzej Pietrasiewicz 
163190fccb52SAndrzej Pietrasiewicz /*
163290fccb52SAndrzej Pietrasiewicz  * Frees a request, but not any DMA buffers associated with it
163390fccb52SAndrzej Pietrasiewicz  * (gr_finish_request should already have taken care of that).
163490fccb52SAndrzej Pietrasiewicz  */
gr_free_request(struct usb_ep * _ep,struct usb_request * _req)163590fccb52SAndrzej Pietrasiewicz static void gr_free_request(struct usb_ep *_ep, struct usb_request *_req)
163690fccb52SAndrzej Pietrasiewicz {
163790fccb52SAndrzej Pietrasiewicz 	struct gr_request *req;
163890fccb52SAndrzej Pietrasiewicz 
163990fccb52SAndrzej Pietrasiewicz 	if (!_ep || !_req)
164090fccb52SAndrzej Pietrasiewicz 		return;
164190fccb52SAndrzej Pietrasiewicz 	req = container_of(_req, struct gr_request, req);
164290fccb52SAndrzej Pietrasiewicz 
164390fccb52SAndrzej Pietrasiewicz 	/* Leads to memory leak */
164490fccb52SAndrzej Pietrasiewicz 	WARN(!list_empty(&req->queue),
164590fccb52SAndrzej Pietrasiewicz 	     "request not dequeued properly before freeing\n");
164690fccb52SAndrzej Pietrasiewicz 
164790fccb52SAndrzej Pietrasiewicz 	kfree(req);
164890fccb52SAndrzej Pietrasiewicz }
164990fccb52SAndrzej Pietrasiewicz 
165090fccb52SAndrzej Pietrasiewicz /* Queue a request from the gadget */
gr_queue_ext(struct usb_ep * _ep,struct usb_request * _req,gfp_t gfp_flags)165190fccb52SAndrzej Pietrasiewicz static int gr_queue_ext(struct usb_ep *_ep, struct usb_request *_req,
165290fccb52SAndrzej Pietrasiewicz 			gfp_t gfp_flags)
165390fccb52SAndrzej Pietrasiewicz {
165490fccb52SAndrzej Pietrasiewicz 	struct gr_ep *ep;
165590fccb52SAndrzej Pietrasiewicz 	struct gr_request *req;
165690fccb52SAndrzej Pietrasiewicz 	struct gr_udc *dev;
165790fccb52SAndrzej Pietrasiewicz 	int ret;
165890fccb52SAndrzej Pietrasiewicz 
165990fccb52SAndrzej Pietrasiewicz 	if (unlikely(!_ep || !_req))
166090fccb52SAndrzej Pietrasiewicz 		return -EINVAL;
166190fccb52SAndrzej Pietrasiewicz 
166290fccb52SAndrzej Pietrasiewicz 	ep = container_of(_ep, struct gr_ep, ep);
166390fccb52SAndrzej Pietrasiewicz 	req = container_of(_req, struct gr_request, req);
166490fccb52SAndrzej Pietrasiewicz 	dev = ep->dev;
166590fccb52SAndrzej Pietrasiewicz 
166690fccb52SAndrzej Pietrasiewicz 	spin_lock(&ep->dev->lock);
166790fccb52SAndrzej Pietrasiewicz 
166890fccb52SAndrzej Pietrasiewicz 	/*
166990fccb52SAndrzej Pietrasiewicz 	 * The ep0 pointer in the gadget struct is used both for ep0in and
167090fccb52SAndrzej Pietrasiewicz 	 * ep0out. In a data stage in the out direction ep0out needs to be used
167190fccb52SAndrzej Pietrasiewicz 	 * instead of the default ep0in. Completion functions might use
167290fccb52SAndrzej Pietrasiewicz 	 * driver_data, so that needs to be copied as well.
167390fccb52SAndrzej Pietrasiewicz 	 */
167490fccb52SAndrzej Pietrasiewicz 	if ((ep == &dev->epi[0]) && (dev->ep0state == GR_EP0_ODATA)) {
167590fccb52SAndrzej Pietrasiewicz 		ep = &dev->epo[0];
167690fccb52SAndrzej Pietrasiewicz 		ep->ep.driver_data = dev->epi[0].ep.driver_data;
167790fccb52SAndrzej Pietrasiewicz 	}
167890fccb52SAndrzej Pietrasiewicz 
167990fccb52SAndrzej Pietrasiewicz 	if (ep->is_in)
168090fccb52SAndrzej Pietrasiewicz 		gr_dbgprint_request("EXTERN", ep, req);
168190fccb52SAndrzej Pietrasiewicz 
168290fccb52SAndrzej Pietrasiewicz 	ret = gr_queue(ep, req, GFP_ATOMIC);
168390fccb52SAndrzej Pietrasiewicz 
168490fccb52SAndrzej Pietrasiewicz 	spin_unlock(&ep->dev->lock);
168590fccb52SAndrzej Pietrasiewicz 
168690fccb52SAndrzej Pietrasiewicz 	return ret;
168790fccb52SAndrzej Pietrasiewicz }
168890fccb52SAndrzej Pietrasiewicz 
168990fccb52SAndrzej Pietrasiewicz /* Dequeue JUST ONE request */
gr_dequeue(struct usb_ep * _ep,struct usb_request * _req)169090fccb52SAndrzej Pietrasiewicz static int gr_dequeue(struct usb_ep *_ep, struct usb_request *_req)
169190fccb52SAndrzej Pietrasiewicz {
169272149b81SJakob Koschel 	struct gr_request *req = NULL, *iter;
169390fccb52SAndrzej Pietrasiewicz 	struct gr_ep *ep;
169490fccb52SAndrzej Pietrasiewicz 	struct gr_udc *dev;
169590fccb52SAndrzej Pietrasiewicz 	int ret = 0;
169690fccb52SAndrzej Pietrasiewicz 	unsigned long flags;
169790fccb52SAndrzej Pietrasiewicz 
169890fccb52SAndrzej Pietrasiewicz 	ep = container_of(_ep, struct gr_ep, ep);
169990fccb52SAndrzej Pietrasiewicz 	if (!_ep || !_req || (!ep->ep.desc && ep->num != 0))
170090fccb52SAndrzej Pietrasiewicz 		return -EINVAL;
170190fccb52SAndrzej Pietrasiewicz 	dev = ep->dev;
170290fccb52SAndrzej Pietrasiewicz 	if (!dev->driver)
170390fccb52SAndrzej Pietrasiewicz 		return -ESHUTDOWN;
170490fccb52SAndrzej Pietrasiewicz 
170590fccb52SAndrzej Pietrasiewicz 	/* We can't touch (DMA) registers when suspended */
170690fccb52SAndrzej Pietrasiewicz 	if (dev->ep0state == GR_EP0_SUSPEND)
170790fccb52SAndrzej Pietrasiewicz 		return -EBUSY;
170890fccb52SAndrzej Pietrasiewicz 
170990fccb52SAndrzej Pietrasiewicz 	spin_lock_irqsave(&dev->lock, flags);
171090fccb52SAndrzej Pietrasiewicz 
171190fccb52SAndrzej Pietrasiewicz 	/* Make sure it's actually queued on this endpoint */
171272149b81SJakob Koschel 	list_for_each_entry(iter, &ep->queue, queue) {
171372149b81SJakob Koschel 		if (&iter->req != _req)
171472149b81SJakob Koschel 			continue;
171572149b81SJakob Koschel 		req = iter;
171690fccb52SAndrzej Pietrasiewicz 		break;
171790fccb52SAndrzej Pietrasiewicz 	}
171872149b81SJakob Koschel 	if (!req) {
171990fccb52SAndrzej Pietrasiewicz 		ret = -EINVAL;
172090fccb52SAndrzej Pietrasiewicz 		goto out;
172190fccb52SAndrzej Pietrasiewicz 	}
172290fccb52SAndrzej Pietrasiewicz 
172390fccb52SAndrzej Pietrasiewicz 	if (list_first_entry(&ep->queue, struct gr_request, queue) == req) {
172490fccb52SAndrzej Pietrasiewicz 		/* This request is currently being processed */
172590fccb52SAndrzej Pietrasiewicz 		gr_abort_dma(ep);
172690fccb52SAndrzej Pietrasiewicz 		if (ep->stopped)
172790fccb52SAndrzej Pietrasiewicz 			gr_finish_request(ep, req, -ECONNRESET);
172890fccb52SAndrzej Pietrasiewicz 		else
172990fccb52SAndrzej Pietrasiewicz 			gr_dma_advance(ep, -ECONNRESET);
173090fccb52SAndrzej Pietrasiewicz 	} else if (!list_empty(&req->queue)) {
173190fccb52SAndrzej Pietrasiewicz 		/* Not being processed - gr_finish_request dequeues it */
173290fccb52SAndrzej Pietrasiewicz 		gr_finish_request(ep, req, -ECONNRESET);
173390fccb52SAndrzej Pietrasiewicz 	} else {
173490fccb52SAndrzej Pietrasiewicz 		ret = -EOPNOTSUPP;
173590fccb52SAndrzej Pietrasiewicz 	}
173690fccb52SAndrzej Pietrasiewicz 
173790fccb52SAndrzej Pietrasiewicz out:
173890fccb52SAndrzej Pietrasiewicz 	spin_unlock_irqrestore(&dev->lock, flags);
173990fccb52SAndrzej Pietrasiewicz 
174090fccb52SAndrzej Pietrasiewicz 	return ret;
174190fccb52SAndrzej Pietrasiewicz }
174290fccb52SAndrzej Pietrasiewicz 
174390fccb52SAndrzej Pietrasiewicz /* Helper for gr_set_halt and gr_set_wedge */
gr_set_halt_wedge(struct usb_ep * _ep,int halt,int wedge)174490fccb52SAndrzej Pietrasiewicz static int gr_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge)
174590fccb52SAndrzej Pietrasiewicz {
174690fccb52SAndrzej Pietrasiewicz 	int ret;
174790fccb52SAndrzej Pietrasiewicz 	struct gr_ep *ep;
174890fccb52SAndrzej Pietrasiewicz 
174990fccb52SAndrzej Pietrasiewicz 	if (!_ep)
175090fccb52SAndrzej Pietrasiewicz 		return -ENODEV;
175190fccb52SAndrzej Pietrasiewicz 	ep = container_of(_ep, struct gr_ep, ep);
175290fccb52SAndrzej Pietrasiewicz 
175390fccb52SAndrzej Pietrasiewicz 	spin_lock(&ep->dev->lock);
175490fccb52SAndrzej Pietrasiewicz 
175590fccb52SAndrzej Pietrasiewicz 	/* Halting an IN endpoint should fail if queue is not empty */
175690fccb52SAndrzej Pietrasiewicz 	if (halt && ep->is_in && !list_empty(&ep->queue)) {
175790fccb52SAndrzej Pietrasiewicz 		ret = -EAGAIN;
175890fccb52SAndrzej Pietrasiewicz 		goto out;
175990fccb52SAndrzej Pietrasiewicz 	}
176090fccb52SAndrzej Pietrasiewicz 
176190fccb52SAndrzej Pietrasiewicz 	ret = gr_ep_halt_wedge(ep, halt, wedge, 0);
176290fccb52SAndrzej Pietrasiewicz 
176390fccb52SAndrzej Pietrasiewicz out:
176490fccb52SAndrzej Pietrasiewicz 	spin_unlock(&ep->dev->lock);
176590fccb52SAndrzej Pietrasiewicz 
176690fccb52SAndrzej Pietrasiewicz 	return ret;
176790fccb52SAndrzej Pietrasiewicz }
176890fccb52SAndrzej Pietrasiewicz 
176990fccb52SAndrzej Pietrasiewicz /* Halt endpoint */
gr_set_halt(struct usb_ep * _ep,int halt)177090fccb52SAndrzej Pietrasiewicz static int gr_set_halt(struct usb_ep *_ep, int halt)
177190fccb52SAndrzej Pietrasiewicz {
177290fccb52SAndrzej Pietrasiewicz 	return gr_set_halt_wedge(_ep, halt, 0);
177390fccb52SAndrzej Pietrasiewicz }
177490fccb52SAndrzej Pietrasiewicz 
177590fccb52SAndrzej Pietrasiewicz /* Halt and wedge endpoint */
gr_set_wedge(struct usb_ep * _ep)177690fccb52SAndrzej Pietrasiewicz static int gr_set_wedge(struct usb_ep *_ep)
177790fccb52SAndrzej Pietrasiewicz {
177890fccb52SAndrzej Pietrasiewicz 	return gr_set_halt_wedge(_ep, 1, 1);
177990fccb52SAndrzej Pietrasiewicz }
178090fccb52SAndrzej Pietrasiewicz 
178190fccb52SAndrzej Pietrasiewicz /*
178290fccb52SAndrzej Pietrasiewicz  * Return the total number of bytes currently stored in the internal buffers of
178390fccb52SAndrzej Pietrasiewicz  * the endpoint.
178490fccb52SAndrzej Pietrasiewicz  */
gr_fifo_status(struct usb_ep * _ep)178590fccb52SAndrzej Pietrasiewicz static int gr_fifo_status(struct usb_ep *_ep)
178690fccb52SAndrzej Pietrasiewicz {
178790fccb52SAndrzej Pietrasiewicz 	struct gr_ep *ep;
178890fccb52SAndrzej Pietrasiewicz 	u32 epstat;
178990fccb52SAndrzej Pietrasiewicz 	u32 bytes = 0;
179090fccb52SAndrzej Pietrasiewicz 
179190fccb52SAndrzej Pietrasiewicz 	if (!_ep)
179290fccb52SAndrzej Pietrasiewicz 		return -ENODEV;
179390fccb52SAndrzej Pietrasiewicz 	ep = container_of(_ep, struct gr_ep, ep);
179490fccb52SAndrzej Pietrasiewicz 
179590fccb52SAndrzej Pietrasiewicz 	epstat = gr_read32(&ep->regs->epstat);
179690fccb52SAndrzej Pietrasiewicz 
179790fccb52SAndrzej Pietrasiewicz 	if (epstat & GR_EPSTAT_B0)
179890fccb52SAndrzej Pietrasiewicz 		bytes += (epstat & GR_EPSTAT_B0CNT_MASK) >> GR_EPSTAT_B0CNT_POS;
179990fccb52SAndrzej Pietrasiewicz 	if (epstat & GR_EPSTAT_B1)
180090fccb52SAndrzej Pietrasiewicz 		bytes += (epstat & GR_EPSTAT_B1CNT_MASK) >> GR_EPSTAT_B1CNT_POS;
180190fccb52SAndrzej Pietrasiewicz 
180290fccb52SAndrzej Pietrasiewicz 	return bytes;
180390fccb52SAndrzej Pietrasiewicz }
180490fccb52SAndrzej Pietrasiewicz 
180590fccb52SAndrzej Pietrasiewicz 
180690fccb52SAndrzej Pietrasiewicz /* Empty data from internal buffers of an endpoint. */
gr_fifo_flush(struct usb_ep * _ep)180790fccb52SAndrzej Pietrasiewicz static void gr_fifo_flush(struct usb_ep *_ep)
180890fccb52SAndrzej Pietrasiewicz {
180990fccb52SAndrzej Pietrasiewicz 	struct gr_ep *ep;
181090fccb52SAndrzej Pietrasiewicz 	u32 epctrl;
181190fccb52SAndrzej Pietrasiewicz 
181290fccb52SAndrzej Pietrasiewicz 	if (!_ep)
181390fccb52SAndrzej Pietrasiewicz 		return;
181490fccb52SAndrzej Pietrasiewicz 	ep = container_of(_ep, struct gr_ep, ep);
181590fccb52SAndrzej Pietrasiewicz 	dev_vdbg(ep->dev->dev, "EP: flush fifo %s\n", ep->ep.name);
181690fccb52SAndrzej Pietrasiewicz 
181790fccb52SAndrzej Pietrasiewicz 	spin_lock(&ep->dev->lock);
181890fccb52SAndrzej Pietrasiewicz 
181990fccb52SAndrzej Pietrasiewicz 	epctrl = gr_read32(&ep->regs->epctrl);
182090fccb52SAndrzej Pietrasiewicz 	epctrl |= GR_EPCTRL_CB;
182190fccb52SAndrzej Pietrasiewicz 	gr_write32(&ep->regs->epctrl, epctrl);
182290fccb52SAndrzej Pietrasiewicz 
182390fccb52SAndrzej Pietrasiewicz 	spin_unlock(&ep->dev->lock);
182490fccb52SAndrzej Pietrasiewicz }
182590fccb52SAndrzej Pietrasiewicz 
1826977ac789SBhumika Goyal static const struct usb_ep_ops gr_ep_ops = {
182790fccb52SAndrzej Pietrasiewicz 	.enable		= gr_ep_enable,
182890fccb52SAndrzej Pietrasiewicz 	.disable	= gr_ep_disable,
182990fccb52SAndrzej Pietrasiewicz 
183090fccb52SAndrzej Pietrasiewicz 	.alloc_request	= gr_alloc_request,
183190fccb52SAndrzej Pietrasiewicz 	.free_request	= gr_free_request,
183290fccb52SAndrzej Pietrasiewicz 
183390fccb52SAndrzej Pietrasiewicz 	.queue		= gr_queue_ext,
183490fccb52SAndrzej Pietrasiewicz 	.dequeue	= gr_dequeue,
183590fccb52SAndrzej Pietrasiewicz 
183690fccb52SAndrzej Pietrasiewicz 	.set_halt	= gr_set_halt,
183790fccb52SAndrzej Pietrasiewicz 	.set_wedge	= gr_set_wedge,
183890fccb52SAndrzej Pietrasiewicz 	.fifo_status	= gr_fifo_status,
183990fccb52SAndrzej Pietrasiewicz 	.fifo_flush	= gr_fifo_flush,
184090fccb52SAndrzej Pietrasiewicz };
184190fccb52SAndrzej Pietrasiewicz 
184290fccb52SAndrzej Pietrasiewicz /* ---------------------------------------------------------------------- */
184390fccb52SAndrzej Pietrasiewicz /* USB Gadget ops */
184490fccb52SAndrzej Pietrasiewicz 
gr_get_frame(struct usb_gadget * _gadget)184590fccb52SAndrzej Pietrasiewicz static int gr_get_frame(struct usb_gadget *_gadget)
184690fccb52SAndrzej Pietrasiewicz {
184790fccb52SAndrzej Pietrasiewicz 	struct gr_udc *dev;
184890fccb52SAndrzej Pietrasiewicz 
184990fccb52SAndrzej Pietrasiewicz 	if (!_gadget)
185090fccb52SAndrzej Pietrasiewicz 		return -ENODEV;
185190fccb52SAndrzej Pietrasiewicz 	dev = container_of(_gadget, struct gr_udc, gadget);
185290fccb52SAndrzej Pietrasiewicz 	return gr_read32(&dev->regs->status) & GR_STATUS_FN_MASK;
185390fccb52SAndrzej Pietrasiewicz }
185490fccb52SAndrzej Pietrasiewicz 
gr_wakeup(struct usb_gadget * _gadget)185590fccb52SAndrzej Pietrasiewicz static int gr_wakeup(struct usb_gadget *_gadget)
185690fccb52SAndrzej Pietrasiewicz {
185790fccb52SAndrzej Pietrasiewicz 	struct gr_udc *dev;
185890fccb52SAndrzej Pietrasiewicz 
185990fccb52SAndrzej Pietrasiewicz 	if (!_gadget)
186090fccb52SAndrzej Pietrasiewicz 		return -ENODEV;
186190fccb52SAndrzej Pietrasiewicz 	dev = container_of(_gadget, struct gr_udc, gadget);
186290fccb52SAndrzej Pietrasiewicz 
186390fccb52SAndrzej Pietrasiewicz 	/* Remote wakeup feature not enabled by host*/
186490fccb52SAndrzej Pietrasiewicz 	if (!dev->remote_wakeup)
186590fccb52SAndrzej Pietrasiewicz 		return -EINVAL;
186690fccb52SAndrzej Pietrasiewicz 
186790fccb52SAndrzej Pietrasiewicz 	spin_lock(&dev->lock);
186890fccb52SAndrzej Pietrasiewicz 
186990fccb52SAndrzej Pietrasiewicz 	gr_write32(&dev->regs->control,
187090fccb52SAndrzej Pietrasiewicz 		   gr_read32(&dev->regs->control) | GR_CONTROL_RW);
187190fccb52SAndrzej Pietrasiewicz 
187290fccb52SAndrzej Pietrasiewicz 	spin_unlock(&dev->lock);
187390fccb52SAndrzej Pietrasiewicz 
187490fccb52SAndrzej Pietrasiewicz 	return 0;
187590fccb52SAndrzej Pietrasiewicz }
187690fccb52SAndrzej Pietrasiewicz 
gr_pullup(struct usb_gadget * _gadget,int is_on)187790fccb52SAndrzej Pietrasiewicz static int gr_pullup(struct usb_gadget *_gadget, int is_on)
187890fccb52SAndrzej Pietrasiewicz {
187990fccb52SAndrzej Pietrasiewicz 	struct gr_udc *dev;
188090fccb52SAndrzej Pietrasiewicz 	u32 control;
188190fccb52SAndrzej Pietrasiewicz 
188290fccb52SAndrzej Pietrasiewicz 	if (!_gadget)
188390fccb52SAndrzej Pietrasiewicz 		return -ENODEV;
188490fccb52SAndrzej Pietrasiewicz 	dev = container_of(_gadget, struct gr_udc, gadget);
188590fccb52SAndrzej Pietrasiewicz 
188690fccb52SAndrzej Pietrasiewicz 	spin_lock(&dev->lock);
188790fccb52SAndrzej Pietrasiewicz 
188890fccb52SAndrzej Pietrasiewicz 	control = gr_read32(&dev->regs->control);
188990fccb52SAndrzej Pietrasiewicz 	if (is_on)
189090fccb52SAndrzej Pietrasiewicz 		control |= GR_CONTROL_EP;
189190fccb52SAndrzej Pietrasiewicz 	else
189290fccb52SAndrzej Pietrasiewicz 		control &= ~GR_CONTROL_EP;
189390fccb52SAndrzej Pietrasiewicz 	gr_write32(&dev->regs->control, control);
189490fccb52SAndrzej Pietrasiewicz 
189590fccb52SAndrzej Pietrasiewicz 	spin_unlock(&dev->lock);
189690fccb52SAndrzej Pietrasiewicz 
189790fccb52SAndrzej Pietrasiewicz 	return 0;
189890fccb52SAndrzej Pietrasiewicz }
189990fccb52SAndrzej Pietrasiewicz 
gr_udc_start(struct usb_gadget * gadget,struct usb_gadget_driver * driver)190090fccb52SAndrzej Pietrasiewicz static int gr_udc_start(struct usb_gadget *gadget,
190190fccb52SAndrzej Pietrasiewicz 			struct usb_gadget_driver *driver)
190290fccb52SAndrzej Pietrasiewicz {
190390fccb52SAndrzej Pietrasiewicz 	struct gr_udc *dev = to_gr_udc(gadget);
190490fccb52SAndrzej Pietrasiewicz 
190590fccb52SAndrzej Pietrasiewicz 	spin_lock(&dev->lock);
190690fccb52SAndrzej Pietrasiewicz 
190790fccb52SAndrzej Pietrasiewicz 	/* Hook up the driver */
190890fccb52SAndrzej Pietrasiewicz 	dev->driver = driver;
190990fccb52SAndrzej Pietrasiewicz 
191090fccb52SAndrzej Pietrasiewicz 	/* Get ready for host detection */
191190fccb52SAndrzej Pietrasiewicz 	gr_enable_vbus_detect(dev);
191290fccb52SAndrzej Pietrasiewicz 
191390fccb52SAndrzej Pietrasiewicz 	spin_unlock(&dev->lock);
191490fccb52SAndrzej Pietrasiewicz 
191590fccb52SAndrzej Pietrasiewicz 	return 0;
191690fccb52SAndrzej Pietrasiewicz }
191790fccb52SAndrzej Pietrasiewicz 
gr_udc_stop(struct usb_gadget * gadget)191822835b80SFelipe Balbi static int gr_udc_stop(struct usb_gadget *gadget)
191990fccb52SAndrzej Pietrasiewicz {
192090fccb52SAndrzej Pietrasiewicz 	struct gr_udc *dev = to_gr_udc(gadget);
192190fccb52SAndrzej Pietrasiewicz 	unsigned long flags;
192290fccb52SAndrzej Pietrasiewicz 
192390fccb52SAndrzej Pietrasiewicz 	spin_lock_irqsave(&dev->lock, flags);
192490fccb52SAndrzej Pietrasiewicz 
192590fccb52SAndrzej Pietrasiewicz 	dev->driver = NULL;
192690fccb52SAndrzej Pietrasiewicz 	gr_stop_activity(dev);
192790fccb52SAndrzej Pietrasiewicz 
192890fccb52SAndrzej Pietrasiewicz 	spin_unlock_irqrestore(&dev->lock, flags);
192990fccb52SAndrzej Pietrasiewicz 
193090fccb52SAndrzej Pietrasiewicz 	return 0;
193190fccb52SAndrzej Pietrasiewicz }
193290fccb52SAndrzej Pietrasiewicz 
193390fccb52SAndrzej Pietrasiewicz static const struct usb_gadget_ops gr_ops = {
193490fccb52SAndrzej Pietrasiewicz 	.get_frame	= gr_get_frame,
193590fccb52SAndrzej Pietrasiewicz 	.wakeup         = gr_wakeup,
193690fccb52SAndrzej Pietrasiewicz 	.pullup         = gr_pullup,
193790fccb52SAndrzej Pietrasiewicz 	.udc_start	= gr_udc_start,
193890fccb52SAndrzej Pietrasiewicz 	.udc_stop	= gr_udc_stop,
193990fccb52SAndrzej Pietrasiewicz 	/* Other operations not supported */
194090fccb52SAndrzej Pietrasiewicz };
194190fccb52SAndrzej Pietrasiewicz 
194290fccb52SAndrzej Pietrasiewicz /* ---------------------------------------------------------------------- */
194390fccb52SAndrzej Pietrasiewicz /* Module probe, removal and of-matching */
194490fccb52SAndrzej Pietrasiewicz 
194590fccb52SAndrzej Pietrasiewicz static const char * const onames[] = {
194690fccb52SAndrzej Pietrasiewicz 	"ep0out", "ep1out", "ep2out", "ep3out", "ep4out", "ep5out",
194790fccb52SAndrzej Pietrasiewicz 	"ep6out", "ep7out", "ep8out", "ep9out", "ep10out", "ep11out",
194890fccb52SAndrzej Pietrasiewicz 	"ep12out", "ep13out", "ep14out", "ep15out"
194990fccb52SAndrzej Pietrasiewicz };
195090fccb52SAndrzej Pietrasiewicz 
195190fccb52SAndrzej Pietrasiewicz static const char * const inames[] = {
195290fccb52SAndrzej Pietrasiewicz 	"ep0in", "ep1in", "ep2in", "ep3in", "ep4in", "ep5in",
195390fccb52SAndrzej Pietrasiewicz 	"ep6in", "ep7in", "ep8in", "ep9in", "ep10in", "ep11in",
195490fccb52SAndrzej Pietrasiewicz 	"ep12in", "ep13in", "ep14in", "ep15in"
195590fccb52SAndrzej Pietrasiewicz };
195690fccb52SAndrzej Pietrasiewicz 
195790fccb52SAndrzej Pietrasiewicz /* Must be called with dev->lock held */
gr_ep_init(struct gr_udc * dev,int num,int is_in,u32 maxplimit)195890fccb52SAndrzej Pietrasiewicz static int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit)
195990fccb52SAndrzej Pietrasiewicz {
196090fccb52SAndrzej Pietrasiewicz 	struct gr_ep *ep;
196190fccb52SAndrzej Pietrasiewicz 	struct gr_request *req;
196290fccb52SAndrzej Pietrasiewicz 	struct usb_request *_req;
196390fccb52SAndrzej Pietrasiewicz 	void *buf;
196490fccb52SAndrzej Pietrasiewicz 
196590fccb52SAndrzej Pietrasiewicz 	if (is_in) {
196690fccb52SAndrzej Pietrasiewicz 		ep = &dev->epi[num];
196790fccb52SAndrzej Pietrasiewicz 		ep->ep.name = inames[num];
196890fccb52SAndrzej Pietrasiewicz 		ep->regs = &dev->regs->epi[num];
196990fccb52SAndrzej Pietrasiewicz 	} else {
197090fccb52SAndrzej Pietrasiewicz 		ep = &dev->epo[num];
197190fccb52SAndrzej Pietrasiewicz 		ep->ep.name = onames[num];
197290fccb52SAndrzej Pietrasiewicz 		ep->regs = &dev->regs->epo[num];
197390fccb52SAndrzej Pietrasiewicz 	}
197490fccb52SAndrzej Pietrasiewicz 
197590fccb52SAndrzej Pietrasiewicz 	gr_ep_reset(ep);
197690fccb52SAndrzej Pietrasiewicz 	ep->num = num;
197790fccb52SAndrzej Pietrasiewicz 	ep->is_in = is_in;
197890fccb52SAndrzej Pietrasiewicz 	ep->dev = dev;
197990fccb52SAndrzej Pietrasiewicz 	ep->ep.ops = &gr_ep_ops;
198090fccb52SAndrzej Pietrasiewicz 	INIT_LIST_HEAD(&ep->queue);
198190fccb52SAndrzej Pietrasiewicz 
198290fccb52SAndrzej Pietrasiewicz 	if (num == 0) {
198390fccb52SAndrzej Pietrasiewicz 		_req = gr_alloc_request(&ep->ep, GFP_ATOMIC);
1984c8f8529eSEvgeny Novikov 		if (!_req)
1985c8f8529eSEvgeny Novikov 			return -ENOMEM;
1986c8f8529eSEvgeny Novikov 
198790fccb52SAndrzej Pietrasiewicz 		buf = devm_kzalloc(dev->dev, PAGE_SIZE, GFP_DMA | GFP_ATOMIC);
1988c8f8529eSEvgeny Novikov 		if (!buf) {
1989c8f8529eSEvgeny Novikov 			gr_free_request(&ep->ep, _req);
199090fccb52SAndrzej Pietrasiewicz 			return -ENOMEM;
199190fccb52SAndrzej Pietrasiewicz 		}
199290fccb52SAndrzej Pietrasiewicz 
199390fccb52SAndrzej Pietrasiewicz 		req = container_of(_req, struct gr_request, req);
199490fccb52SAndrzej Pietrasiewicz 		req->req.buf = buf;
199590fccb52SAndrzej Pietrasiewicz 		req->req.length = MAX_CTRL_PL_SIZE;
199690fccb52SAndrzej Pietrasiewicz 
199790fccb52SAndrzej Pietrasiewicz 		if (is_in)
199890fccb52SAndrzej Pietrasiewicz 			dev->ep0reqi = req; /* Complete gets set as used */
199990fccb52SAndrzej Pietrasiewicz 		else
200090fccb52SAndrzej Pietrasiewicz 			dev->ep0reqo = req; /* Completion treated separately */
200190fccb52SAndrzej Pietrasiewicz 
200290fccb52SAndrzej Pietrasiewicz 		usb_ep_set_maxpacket_limit(&ep->ep, MAX_CTRL_PL_SIZE);
200390fccb52SAndrzej Pietrasiewicz 		ep->bytes_per_buffer = MAX_CTRL_PL_SIZE;
200489226992SRobert Baldyga 
200589226992SRobert Baldyga 		ep->ep.caps.type_control = true;
200690fccb52SAndrzej Pietrasiewicz 	} else {
200790fccb52SAndrzej Pietrasiewicz 		usb_ep_set_maxpacket_limit(&ep->ep, (u16)maxplimit);
200890fccb52SAndrzej Pietrasiewicz 		list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
200989226992SRobert Baldyga 
201089226992SRobert Baldyga 		ep->ep.caps.type_iso = true;
201189226992SRobert Baldyga 		ep->ep.caps.type_bulk = true;
201289226992SRobert Baldyga 		ep->ep.caps.type_int = true;
201390fccb52SAndrzej Pietrasiewicz 	}
201490fccb52SAndrzej Pietrasiewicz 	list_add_tail(&ep->ep_list, &dev->ep_list);
201590fccb52SAndrzej Pietrasiewicz 
201689226992SRobert Baldyga 	if (is_in)
201789226992SRobert Baldyga 		ep->ep.caps.dir_in = true;
201889226992SRobert Baldyga 	else
201989226992SRobert Baldyga 		ep->ep.caps.dir_out = true;
202089226992SRobert Baldyga 
20215b484989SAndreas Larsson 	ep->tailbuf = dma_alloc_coherent(dev->dev, ep->ep.maxpacket_limit,
20225b484989SAndreas Larsson 					 &ep->tailbuf_paddr, GFP_ATOMIC);
20235b484989SAndreas Larsson 	if (!ep->tailbuf)
20245b484989SAndreas Larsson 		return -ENOMEM;
20255b484989SAndreas Larsson 
202690fccb52SAndrzej Pietrasiewicz 	return 0;
202790fccb52SAndrzej Pietrasiewicz }
202890fccb52SAndrzej Pietrasiewicz 
202990fccb52SAndrzej Pietrasiewicz /* Must be called with dev->lock held */
gr_udc_init(struct gr_udc * dev)203090fccb52SAndrzej Pietrasiewicz static int gr_udc_init(struct gr_udc *dev)
203190fccb52SAndrzej Pietrasiewicz {
203290fccb52SAndrzej Pietrasiewicz 	struct device_node *np = dev->dev->of_node;
203390fccb52SAndrzej Pietrasiewicz 	u32 epctrl_val;
203490fccb52SAndrzej Pietrasiewicz 	u32 dmactrl_val;
203590fccb52SAndrzej Pietrasiewicz 	int i;
203690fccb52SAndrzej Pietrasiewicz 	int ret = 0;
203790fccb52SAndrzej Pietrasiewicz 	u32 bufsize;
203890fccb52SAndrzej Pietrasiewicz 
203990fccb52SAndrzej Pietrasiewicz 	gr_set_address(dev, 0);
204090fccb52SAndrzej Pietrasiewicz 
204190fccb52SAndrzej Pietrasiewicz 	INIT_LIST_HEAD(&dev->gadget.ep_list);
204290fccb52SAndrzej Pietrasiewicz 	dev->gadget.speed = USB_SPEED_UNKNOWN;
204390fccb52SAndrzej Pietrasiewicz 	dev->gadget.ep0 = &dev->epi[0].ep;
204490fccb52SAndrzej Pietrasiewicz 
204590fccb52SAndrzej Pietrasiewicz 	INIT_LIST_HEAD(&dev->ep_list);
204690fccb52SAndrzej Pietrasiewicz 	gr_set_ep0state(dev, GR_EP0_DISCONNECT);
204790fccb52SAndrzej Pietrasiewicz 
204890fccb52SAndrzej Pietrasiewicz 	for (i = 0; i < dev->nepo; i++) {
204990fccb52SAndrzej Pietrasiewicz 		if (of_property_read_u32_index(np, "epobufsizes", i, &bufsize))
205090fccb52SAndrzej Pietrasiewicz 			bufsize = 1024;
205190fccb52SAndrzej Pietrasiewicz 		ret = gr_ep_init(dev, i, 0, bufsize);
205290fccb52SAndrzej Pietrasiewicz 		if (ret)
205390fccb52SAndrzej Pietrasiewicz 			return ret;
205490fccb52SAndrzej Pietrasiewicz 	}
205590fccb52SAndrzej Pietrasiewicz 
205690fccb52SAndrzej Pietrasiewicz 	for (i = 0; i < dev->nepi; i++) {
205790fccb52SAndrzej Pietrasiewicz 		if (of_property_read_u32_index(np, "epibufsizes", i, &bufsize))
205890fccb52SAndrzej Pietrasiewicz 			bufsize = 1024;
205990fccb52SAndrzej Pietrasiewicz 		ret = gr_ep_init(dev, i, 1, bufsize);
206090fccb52SAndrzej Pietrasiewicz 		if (ret)
206190fccb52SAndrzej Pietrasiewicz 			return ret;
206290fccb52SAndrzej Pietrasiewicz 	}
206390fccb52SAndrzej Pietrasiewicz 
206490fccb52SAndrzej Pietrasiewicz 	/* Must be disabled by default */
206590fccb52SAndrzej Pietrasiewicz 	dev->remote_wakeup = 0;
206690fccb52SAndrzej Pietrasiewicz 
206790fccb52SAndrzej Pietrasiewicz 	/* Enable ep0out and ep0in */
206890fccb52SAndrzej Pietrasiewicz 	epctrl_val = (MAX_CTRL_PL_SIZE << GR_EPCTRL_MAXPL_POS) | GR_EPCTRL_EV;
206990fccb52SAndrzej Pietrasiewicz 	dmactrl_val = GR_DMACTRL_IE | GR_DMACTRL_AI;
207090fccb52SAndrzej Pietrasiewicz 	gr_write32(&dev->epo[0].regs->epctrl, epctrl_val);
207190fccb52SAndrzej Pietrasiewicz 	gr_write32(&dev->epi[0].regs->epctrl, epctrl_val | GR_EPCTRL_PI);
207290fccb52SAndrzej Pietrasiewicz 	gr_write32(&dev->epo[0].regs->dmactrl, dmactrl_val);
207390fccb52SAndrzej Pietrasiewicz 	gr_write32(&dev->epi[0].regs->dmactrl, dmactrl_val);
207490fccb52SAndrzej Pietrasiewicz 
207590fccb52SAndrzej Pietrasiewicz 	return 0;
207690fccb52SAndrzej Pietrasiewicz }
207790fccb52SAndrzej Pietrasiewicz 
gr_ep_remove(struct gr_udc * dev,int num,int is_in)20785b484989SAndreas Larsson static void gr_ep_remove(struct gr_udc *dev, int num, int is_in)
20795b484989SAndreas Larsson {
20805b484989SAndreas Larsson 	struct gr_ep *ep;
20815b484989SAndreas Larsson 
20825b484989SAndreas Larsson 	if (is_in)
20835b484989SAndreas Larsson 		ep = &dev->epi[num];
20845b484989SAndreas Larsson 	else
20855b484989SAndreas Larsson 		ep = &dev->epo[num];
20865b484989SAndreas Larsson 
20875b484989SAndreas Larsson 	if (ep->tailbuf)
20885b484989SAndreas Larsson 		dma_free_coherent(dev->dev, ep->ep.maxpacket_limit,
20895b484989SAndreas Larsson 				  ep->tailbuf, ep->tailbuf_paddr);
20905b484989SAndreas Larsson }
20915b484989SAndreas Larsson 
gr_remove(struct platform_device * pdev)209290fccb52SAndrzej Pietrasiewicz static int gr_remove(struct platform_device *pdev)
209390fccb52SAndrzej Pietrasiewicz {
209490fccb52SAndrzej Pietrasiewicz 	struct gr_udc *dev = platform_get_drvdata(pdev);
20955b484989SAndreas Larsson 	int i;
209690fccb52SAndrzej Pietrasiewicz 
209790fccb52SAndrzej Pietrasiewicz 	if (dev->added)
209890fccb52SAndrzej Pietrasiewicz 		usb_del_gadget_udc(&dev->gadget); /* Shuts everything down */
209990fccb52SAndrzej Pietrasiewicz 	if (dev->driver)
210090fccb52SAndrzej Pietrasiewicz 		return -EBUSY;
210190fccb52SAndrzej Pietrasiewicz 
210290fccb52SAndrzej Pietrasiewicz 	gr_dfs_delete(dev);
210390fccb52SAndrzej Pietrasiewicz 	dma_pool_destroy(dev->desc_pool);
210490fccb52SAndrzej Pietrasiewicz 	platform_set_drvdata(pdev, NULL);
210590fccb52SAndrzej Pietrasiewicz 
210690fccb52SAndrzej Pietrasiewicz 	gr_free_request(&dev->epi[0].ep, &dev->ep0reqi->req);
210790fccb52SAndrzej Pietrasiewicz 	gr_free_request(&dev->epo[0].ep, &dev->ep0reqo->req);
210890fccb52SAndrzej Pietrasiewicz 
21095b484989SAndreas Larsson 	for (i = 0; i < dev->nepo; i++)
21105b484989SAndreas Larsson 		gr_ep_remove(dev, i, 0);
21115b484989SAndreas Larsson 	for (i = 0; i < dev->nepi; i++)
21125b484989SAndreas Larsson 		gr_ep_remove(dev, i, 1);
21135b484989SAndreas Larsson 
211490fccb52SAndrzej Pietrasiewicz 	return 0;
211590fccb52SAndrzej Pietrasiewicz }
gr_request_irq(struct gr_udc * dev,int irq)211690fccb52SAndrzej Pietrasiewicz static int gr_request_irq(struct gr_udc *dev, int irq)
211790fccb52SAndrzej Pietrasiewicz {
211890fccb52SAndrzej Pietrasiewicz 	return devm_request_threaded_irq(dev->dev, irq, gr_irq, gr_irq_handler,
211990fccb52SAndrzej Pietrasiewicz 					 IRQF_SHARED, driver_name, dev);
212090fccb52SAndrzej Pietrasiewicz }
212190fccb52SAndrzej Pietrasiewicz 
gr_probe(struct platform_device * pdev)212290fccb52SAndrzej Pietrasiewicz static int gr_probe(struct platform_device *pdev)
212390fccb52SAndrzej Pietrasiewicz {
212490fccb52SAndrzej Pietrasiewicz 	struct gr_udc *dev;
212590fccb52SAndrzej Pietrasiewicz 	struct gr_regs __iomem *regs;
212690fccb52SAndrzej Pietrasiewicz 	int retval;
212790fccb52SAndrzej Pietrasiewicz 	u32 status;
212890fccb52SAndrzej Pietrasiewicz 
212990fccb52SAndrzej Pietrasiewicz 	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
213090fccb52SAndrzej Pietrasiewicz 	if (!dev)
213190fccb52SAndrzej Pietrasiewicz 		return -ENOMEM;
213290fccb52SAndrzej Pietrasiewicz 	dev->dev = &pdev->dev;
213390fccb52SAndrzej Pietrasiewicz 
2134ec035f91SYueHaibing 	regs = devm_platform_ioremap_resource(pdev, 0);
213590fccb52SAndrzej Pietrasiewicz 	if (IS_ERR(regs))
213690fccb52SAndrzej Pietrasiewicz 		return PTR_ERR(regs);
213790fccb52SAndrzej Pietrasiewicz 
213890fccb52SAndrzej Pietrasiewicz 	dev->irq = platform_get_irq(pdev, 0);
2139*4f4bda58SZhu Wang 	if (dev->irq < 0)
2140*4f4bda58SZhu Wang 		return dev->irq;
214190fccb52SAndrzej Pietrasiewicz 
214290fccb52SAndrzej Pietrasiewicz 	/* Some core configurations has separate irqs for IN and OUT events */
214390fccb52SAndrzej Pietrasiewicz 	dev->irqi = platform_get_irq(pdev, 1);
214490fccb52SAndrzej Pietrasiewicz 	if (dev->irqi > 0) {
214590fccb52SAndrzej Pietrasiewicz 		dev->irqo = platform_get_irq(pdev, 2);
2146*4f4bda58SZhu Wang 		if (dev->irqo < 0)
2147*4f4bda58SZhu Wang 			return dev->irqo;
214890fccb52SAndrzej Pietrasiewicz 	} else {
214990fccb52SAndrzej Pietrasiewicz 		dev->irqi = 0;
215090fccb52SAndrzej Pietrasiewicz 	}
215190fccb52SAndrzej Pietrasiewicz 
215290fccb52SAndrzej Pietrasiewicz 	dev->gadget.name = driver_name;
215390fccb52SAndrzej Pietrasiewicz 	dev->gadget.max_speed = USB_SPEED_HIGH;
215490fccb52SAndrzej Pietrasiewicz 	dev->gadget.ops = &gr_ops;
215590fccb52SAndrzej Pietrasiewicz 
215690fccb52SAndrzej Pietrasiewicz 	spin_lock_init(&dev->lock);
215790fccb52SAndrzej Pietrasiewicz 	dev->regs = regs;
215890fccb52SAndrzej Pietrasiewicz 
215990fccb52SAndrzej Pietrasiewicz 	platform_set_drvdata(pdev, dev);
216090fccb52SAndrzej Pietrasiewicz 
216190fccb52SAndrzej Pietrasiewicz 	/* Determine number of endpoints and data interface mode */
216290fccb52SAndrzej Pietrasiewicz 	status = gr_read32(&dev->regs->status);
216390fccb52SAndrzej Pietrasiewicz 	dev->nepi = ((status & GR_STATUS_NEPI_MASK) >> GR_STATUS_NEPI_POS) + 1;
216490fccb52SAndrzej Pietrasiewicz 	dev->nepo = ((status & GR_STATUS_NEPO_MASK) >> GR_STATUS_NEPO_POS) + 1;
216590fccb52SAndrzej Pietrasiewicz 
216690fccb52SAndrzej Pietrasiewicz 	if (!(status & GR_STATUS_DM)) {
216790fccb52SAndrzej Pietrasiewicz 		dev_err(dev->dev, "Slave mode cores are not supported\n");
216890fccb52SAndrzej Pietrasiewicz 		return -ENODEV;
216990fccb52SAndrzej Pietrasiewicz 	}
217090fccb52SAndrzej Pietrasiewicz 
217190fccb52SAndrzej Pietrasiewicz 	/* --- Effects of the following calls might need explicit cleanup --- */
217290fccb52SAndrzej Pietrasiewicz 
217390fccb52SAndrzej Pietrasiewicz 	/* Create DMA pool for descriptors */
217490fccb52SAndrzej Pietrasiewicz 	dev->desc_pool = dma_pool_create("desc_pool", dev->dev,
217590fccb52SAndrzej Pietrasiewicz 					 sizeof(struct gr_dma_desc), 4, 0);
217690fccb52SAndrzej Pietrasiewicz 	if (!dev->desc_pool) {
217790fccb52SAndrzej Pietrasiewicz 		dev_err(dev->dev, "Could not allocate DMA pool");
217890fccb52SAndrzej Pietrasiewicz 		return -ENOMEM;
217990fccb52SAndrzej Pietrasiewicz 	}
218090fccb52SAndrzej Pietrasiewicz 
218190fccb52SAndrzej Pietrasiewicz 	/* Inside lock so that no gadget can use this udc until probe is done */
218290fccb52SAndrzej Pietrasiewicz 	retval = usb_add_gadget_udc(dev->dev, &dev->gadget);
218390fccb52SAndrzej Pietrasiewicz 	if (retval) {
218490fccb52SAndrzej Pietrasiewicz 		dev_err(dev->dev, "Could not add gadget udc");
218590fccb52SAndrzej Pietrasiewicz 		goto out;
218690fccb52SAndrzej Pietrasiewicz 	}
218790fccb52SAndrzej Pietrasiewicz 	dev->added = 1;
218890fccb52SAndrzej Pietrasiewicz 
21899c1ed62aSJia-Ju Bai 	spin_lock(&dev->lock);
219090fccb52SAndrzej Pietrasiewicz 
21919c1ed62aSJia-Ju Bai 	retval = gr_udc_init(dev);
21929c1ed62aSJia-Ju Bai 	if (retval) {
21939c1ed62aSJia-Ju Bai 		spin_unlock(&dev->lock);
21949c1ed62aSJia-Ju Bai 		goto out;
21959c1ed62aSJia-Ju Bai 	}
219690fccb52SAndrzej Pietrasiewicz 
219790fccb52SAndrzej Pietrasiewicz 	/* Clear all interrupt enables that might be left on since last boot */
219890fccb52SAndrzej Pietrasiewicz 	gr_disable_interrupts_and_pullup(dev);
219990fccb52SAndrzej Pietrasiewicz 
22009c1ed62aSJia-Ju Bai 	spin_unlock(&dev->lock);
22019c1ed62aSJia-Ju Bai 
22029c1ed62aSJia-Ju Bai 	gr_dfs_create(dev);
22039c1ed62aSJia-Ju Bai 
220490fccb52SAndrzej Pietrasiewicz 	retval = gr_request_irq(dev, dev->irq);
220590fccb52SAndrzej Pietrasiewicz 	if (retval) {
220690fccb52SAndrzej Pietrasiewicz 		dev_err(dev->dev, "Failed to request irq %d\n", dev->irq);
220790fccb52SAndrzej Pietrasiewicz 		goto out;
220890fccb52SAndrzej Pietrasiewicz 	}
220990fccb52SAndrzej Pietrasiewicz 
221090fccb52SAndrzej Pietrasiewicz 	if (dev->irqi) {
221190fccb52SAndrzej Pietrasiewicz 		retval = gr_request_irq(dev, dev->irqi);
221290fccb52SAndrzej Pietrasiewicz 		if (retval) {
221390fccb52SAndrzej Pietrasiewicz 			dev_err(dev->dev, "Failed to request irqi %d\n",
221490fccb52SAndrzej Pietrasiewicz 				dev->irqi);
221590fccb52SAndrzej Pietrasiewicz 			goto out;
221690fccb52SAndrzej Pietrasiewicz 		}
221790fccb52SAndrzej Pietrasiewicz 		retval = gr_request_irq(dev, dev->irqo);
221890fccb52SAndrzej Pietrasiewicz 		if (retval) {
221990fccb52SAndrzej Pietrasiewicz 			dev_err(dev->dev, "Failed to request irqo %d\n",
222090fccb52SAndrzej Pietrasiewicz 				dev->irqo);
222190fccb52SAndrzej Pietrasiewicz 			goto out;
222290fccb52SAndrzej Pietrasiewicz 		}
222390fccb52SAndrzej Pietrasiewicz 	}
222490fccb52SAndrzej Pietrasiewicz 
222590fccb52SAndrzej Pietrasiewicz 	if (dev->irqi)
222690fccb52SAndrzej Pietrasiewicz 		dev_info(dev->dev, "regs: %p, irqs %d, %d, %d\n", dev->regs,
222790fccb52SAndrzej Pietrasiewicz 			 dev->irq, dev->irqi, dev->irqo);
222890fccb52SAndrzej Pietrasiewicz 	else
222990fccb52SAndrzej Pietrasiewicz 		dev_info(dev->dev, "regs: %p, irq %d\n", dev->regs, dev->irq);
223090fccb52SAndrzej Pietrasiewicz 
223190fccb52SAndrzej Pietrasiewicz out:
223290fccb52SAndrzej Pietrasiewicz 	if (retval)
223390fccb52SAndrzej Pietrasiewicz 		gr_remove(pdev);
223490fccb52SAndrzej Pietrasiewicz 
223590fccb52SAndrzej Pietrasiewicz 	return retval;
223690fccb52SAndrzej Pietrasiewicz }
223790fccb52SAndrzej Pietrasiewicz 
223890fccb52SAndrzej Pietrasiewicz static const struct of_device_id gr_match[] = {
223990fccb52SAndrzej Pietrasiewicz 	{.name = "GAISLER_USBDC"},
224090fccb52SAndrzej Pietrasiewicz 	{.name = "01_021"},
224190fccb52SAndrzej Pietrasiewicz 	{},
224290fccb52SAndrzej Pietrasiewicz };
224390fccb52SAndrzej Pietrasiewicz MODULE_DEVICE_TABLE(of, gr_match);
224490fccb52SAndrzej Pietrasiewicz 
224590fccb52SAndrzej Pietrasiewicz static struct platform_driver gr_driver = {
224690fccb52SAndrzej Pietrasiewicz 	.driver = {
224790fccb52SAndrzej Pietrasiewicz 		.name = DRIVER_NAME,
224890fccb52SAndrzej Pietrasiewicz 		.of_match_table = gr_match,
224990fccb52SAndrzej Pietrasiewicz 	},
225090fccb52SAndrzej Pietrasiewicz 	.probe = gr_probe,
225190fccb52SAndrzej Pietrasiewicz 	.remove = gr_remove,
225290fccb52SAndrzej Pietrasiewicz };
225390fccb52SAndrzej Pietrasiewicz module_platform_driver(gr_driver);
225490fccb52SAndrzej Pietrasiewicz 
225590fccb52SAndrzej Pietrasiewicz MODULE_AUTHOR("Aeroflex Gaisler AB.");
225690fccb52SAndrzej Pietrasiewicz MODULE_DESCRIPTION(DRIVER_DESC);
225790fccb52SAndrzej Pietrasiewicz MODULE_LICENSE("GPL");
2258