xref: /rk3399_rockchip-uboot/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c (revision 30bf5086c36f426f898d1763e3bd3fd557aab79f)
1be5e4bdcSMarek Vasut /*
2be5e4bdcSMarek Vasut  * drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c
3e179ceddSMarek Vasut  * Designware DWC2 on-chip full/high speed USB OTG 2.0 device controllers
4be5e4bdcSMarek Vasut  *
5be5e4bdcSMarek Vasut  * Copyright (C) 2009 for Samsung Electronics
6be5e4bdcSMarek Vasut  *
7be5e4bdcSMarek Vasut  * BSP Support for Samsung's UDC driver
8be5e4bdcSMarek Vasut  * available at:
9be5e4bdcSMarek Vasut  * git://git.kernel.org/pub/scm/linux/kernel/git/kki_ap/linux-2.6-samsung.git
10be5e4bdcSMarek Vasut  *
11be5e4bdcSMarek Vasut  * State machine bugfixes:
12be5e4bdcSMarek Vasut  * Marek Szyprowski <m.szyprowski@samsung.com>
13be5e4bdcSMarek Vasut  *
14be5e4bdcSMarek Vasut  * Ported to u-boot:
15be5e4bdcSMarek Vasut  * Marek Szyprowski <m.szyprowski@samsung.com>
16be5e4bdcSMarek Vasut  * Lukasz Majewski <l.majewski@samsumg.com>
17be5e4bdcSMarek Vasut  *
18be5e4bdcSMarek Vasut  * SPDX-License-Identifier:	GPL-2.0+
19be5e4bdcSMarek Vasut  */
20be5e4bdcSMarek Vasut 
21be5e4bdcSMarek Vasut static u8 clear_feature_num;
22be5e4bdcSMarek Vasut int clear_feature_flag;
23be5e4bdcSMarek Vasut 
24be5e4bdcSMarek Vasut /* Bulk-Only Mass Storage Reset (class-specific request) */
25be5e4bdcSMarek Vasut #define GET_MAX_LUN_REQUEST	0xFE
26be5e4bdcSMarek Vasut #define BOT_RESET_REQUEST	0xFF
27be5e4bdcSMarek Vasut 
dwc2_udc_ep0_zlp(struct dwc2_udc * dev)28be5e4bdcSMarek Vasut static inline void dwc2_udc_ep0_zlp(struct dwc2_udc *dev)
29be5e4bdcSMarek Vasut {
30be5e4bdcSMarek Vasut 	u32 ep_ctrl;
31be5e4bdcSMarek Vasut 
32be5e4bdcSMarek Vasut 	writel(usb_ctrl_dma_addr, &reg->in_endp[EP0_CON].diepdma);
33be5e4bdcSMarek Vasut 	writel(DIEPT_SIZ_PKT_CNT(1), &reg->in_endp[EP0_CON].dieptsiz);
34be5e4bdcSMarek Vasut 
35be5e4bdcSMarek Vasut 	ep_ctrl = readl(&reg->in_endp[EP0_CON].diepctl);
36be5e4bdcSMarek Vasut 	writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK,
37be5e4bdcSMarek Vasut 	       &reg->in_endp[EP0_CON].diepctl);
38be5e4bdcSMarek Vasut 
39be5e4bdcSMarek Vasut 	debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DIEPCTL0 = 0x%x\n",
40be5e4bdcSMarek Vasut 		__func__, readl(&reg->in_endp[EP0_CON].diepctl));
41be5e4bdcSMarek Vasut 	dev->ep0state = WAIT_FOR_IN_COMPLETE;
42be5e4bdcSMarek Vasut }
43be5e4bdcSMarek Vasut 
dwc2_udc_pre_setup(void)44be5e4bdcSMarek Vasut static void dwc2_udc_pre_setup(void)
45be5e4bdcSMarek Vasut {
46be5e4bdcSMarek Vasut 	u32 ep_ctrl;
47be5e4bdcSMarek Vasut 
48be5e4bdcSMarek Vasut 	debug_cond(DEBUG_IN_EP,
49be5e4bdcSMarek Vasut 		   "%s : Prepare Setup packets.\n", __func__);
50be5e4bdcSMarek Vasut 
51be5e4bdcSMarek Vasut 	writel(DOEPT_SIZ_PKT_CNT(1) | sizeof(struct usb_ctrlrequest),
52be5e4bdcSMarek Vasut 	       &reg->out_endp[EP0_CON].doeptsiz);
53be5e4bdcSMarek Vasut 	writel(usb_ctrl_dma_addr, &reg->out_endp[EP0_CON].doepdma);
54be5e4bdcSMarek Vasut 
55be5e4bdcSMarek Vasut 	ep_ctrl = readl(&reg->out_endp[EP0_CON].doepctl);
56be5e4bdcSMarek Vasut 	writel(ep_ctrl|DEPCTL_EPENA, &reg->out_endp[EP0_CON].doepctl);
57be5e4bdcSMarek Vasut 
58be5e4bdcSMarek Vasut 	debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DIEPCTL0 = 0x%x\n",
59be5e4bdcSMarek Vasut 		__func__, readl(&reg->in_endp[EP0_CON].diepctl));
60be5e4bdcSMarek Vasut 	debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DOEPCTL0 = 0x%x\n",
61be5e4bdcSMarek Vasut 		__func__, readl(&reg->out_endp[EP0_CON].doepctl));
62be5e4bdcSMarek Vasut 
63be5e4bdcSMarek Vasut }
64be5e4bdcSMarek Vasut 
dwc2_ep0_complete_out(void)65be5e4bdcSMarek Vasut static inline void dwc2_ep0_complete_out(void)
66be5e4bdcSMarek Vasut {
67be5e4bdcSMarek Vasut 	u32 ep_ctrl;
68be5e4bdcSMarek Vasut 
69be5e4bdcSMarek Vasut 	debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DIEPCTL0 = 0x%x\n",
70be5e4bdcSMarek Vasut 		__func__, readl(&reg->in_endp[EP0_CON].diepctl));
71be5e4bdcSMarek Vasut 	debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DOEPCTL0 = 0x%x\n",
72be5e4bdcSMarek Vasut 		__func__, readl(&reg->out_endp[EP0_CON].doepctl));
73be5e4bdcSMarek Vasut 
74be5e4bdcSMarek Vasut 	debug_cond(DEBUG_IN_EP,
75be5e4bdcSMarek Vasut 		"%s : Prepare Complete Out packet.\n", __func__);
76be5e4bdcSMarek Vasut 
77be5e4bdcSMarek Vasut 	writel(DOEPT_SIZ_PKT_CNT(1) | sizeof(struct usb_ctrlrequest),
78be5e4bdcSMarek Vasut 	       &reg->out_endp[EP0_CON].doeptsiz);
79be5e4bdcSMarek Vasut 	writel(usb_ctrl_dma_addr, &reg->out_endp[EP0_CON].doepdma);
80be5e4bdcSMarek Vasut 
81be5e4bdcSMarek Vasut 	ep_ctrl = readl(&reg->out_endp[EP0_CON].doepctl);
82be5e4bdcSMarek Vasut 	writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK,
83be5e4bdcSMarek Vasut 	       &reg->out_endp[EP0_CON].doepctl);
84be5e4bdcSMarek Vasut 
85be5e4bdcSMarek Vasut 	debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DIEPCTL0 = 0x%x\n",
86be5e4bdcSMarek Vasut 		__func__, readl(&reg->in_endp[EP0_CON].diepctl));
87be5e4bdcSMarek Vasut 	debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DOEPCTL0 = 0x%x\n",
88be5e4bdcSMarek Vasut 		__func__, readl(&reg->out_endp[EP0_CON].doepctl));
89be5e4bdcSMarek Vasut 
90be5e4bdcSMarek Vasut }
91be5e4bdcSMarek Vasut 
92be5e4bdcSMarek Vasut 
setdma_rx(struct dwc2_ep * ep,struct dwc2_request * req)93be5e4bdcSMarek Vasut static int setdma_rx(struct dwc2_ep *ep, struct dwc2_request *req)
94be5e4bdcSMarek Vasut {
95be5e4bdcSMarek Vasut 	u32 *buf, ctrl;
96be5e4bdcSMarek Vasut 	u32 length, pktcnt;
97be5e4bdcSMarek Vasut 	u32 ep_num = ep_index(ep);
98be5e4bdcSMarek Vasut 
99be5e4bdcSMarek Vasut 	buf = req->req.buf + req->req.actual;
100be5e4bdcSMarek Vasut 	length = min_t(u32, req->req.length - req->req.actual,
1018659d08dSFrank Wang 		       ep_num ? DOEPT_SIZ_XFER_SIZE_MAX_EP : ep->ep.maxpacket);
102be5e4bdcSMarek Vasut 
103be5e4bdcSMarek Vasut 	ep->len = length;
104be5e4bdcSMarek Vasut 	ep->dma_buf = buf;
105be5e4bdcSMarek Vasut 
106be5e4bdcSMarek Vasut 	if (ep_num == EP0_CON || length == 0)
107be5e4bdcSMarek Vasut 		pktcnt = 1;
108be5e4bdcSMarek Vasut 	else
109be5e4bdcSMarek Vasut 		pktcnt = (length - 1)/(ep->ep.maxpacket) + 1;
110be5e4bdcSMarek Vasut 
111be5e4bdcSMarek Vasut 	ctrl =  readl(&reg->out_endp[ep_num].doepctl);
112be5e4bdcSMarek Vasut 
1139424f141SXu Ziyuan 	invalidate_dcache_range((unsigned long) ep->dma_buf,
11480553dd1SSeung-Woo Kim 				(unsigned long) ep->dma_buf +
11580553dd1SSeung-Woo Kim 				ROUND(ep->len, CONFIG_SYS_CACHELINE_SIZE));
1169424f141SXu Ziyuan 
117b3c55b56STom Rini 	writel((unsigned long) ep->dma_buf, &reg->out_endp[ep_num].doepdma);
118be5e4bdcSMarek Vasut 	writel(DOEPT_SIZ_PKT_CNT(pktcnt) | DOEPT_SIZ_XFER_SIZE(length),
119be5e4bdcSMarek Vasut 	       &reg->out_endp[ep_num].doeptsiz);
120be5e4bdcSMarek Vasut 	writel(DEPCTL_EPENA|DEPCTL_CNAK|ctrl, &reg->out_endp[ep_num].doepctl);
121be5e4bdcSMarek Vasut 
122be5e4bdcSMarek Vasut 	debug_cond(DEBUG_OUT_EP != 0,
123be5e4bdcSMarek Vasut 		   "%s: EP%d RX DMA start : DOEPDMA = 0x%x,"
124be5e4bdcSMarek Vasut 		   "DOEPTSIZ = 0x%x, DOEPCTL = 0x%x\n"
125be5e4bdcSMarek Vasut 		   "\tbuf = 0x%p, pktcnt = %d, xfersize = %d\n",
126be5e4bdcSMarek Vasut 		   __func__, ep_num,
127be5e4bdcSMarek Vasut 		   readl(&reg->out_endp[ep_num].doepdma),
128be5e4bdcSMarek Vasut 		   readl(&reg->out_endp[ep_num].doeptsiz),
129be5e4bdcSMarek Vasut 		   readl(&reg->out_endp[ep_num].doepctl),
130be5e4bdcSMarek Vasut 		   buf, pktcnt, length);
131be5e4bdcSMarek Vasut 	return 0;
132be5e4bdcSMarek Vasut 
133be5e4bdcSMarek Vasut }
134be5e4bdcSMarek Vasut 
setdma_tx(struct dwc2_ep * ep,struct dwc2_request * req)135be5e4bdcSMarek Vasut static int setdma_tx(struct dwc2_ep *ep, struct dwc2_request *req)
136be5e4bdcSMarek Vasut {
137be5e4bdcSMarek Vasut 	u32 *buf, ctrl = 0;
138be5e4bdcSMarek Vasut 	u32 length, pktcnt;
139be5e4bdcSMarek Vasut 	u32 ep_num = ep_index(ep);
140be5e4bdcSMarek Vasut 
141be5e4bdcSMarek Vasut 	buf = req->req.buf + req->req.actual;
142be5e4bdcSMarek Vasut 	length = req->req.length - req->req.actual;
143be5e4bdcSMarek Vasut 
144be5e4bdcSMarek Vasut 	if (ep_num == EP0_CON)
145be5e4bdcSMarek Vasut 		length = min(length, (u32)ep_maxpacket(ep));
146be5e4bdcSMarek Vasut 
147be5e4bdcSMarek Vasut 	ep->len = length;
148be5e4bdcSMarek Vasut 	ep->dma_buf = buf;
149be5e4bdcSMarek Vasut 
150be5e4bdcSMarek Vasut 	flush_dcache_range((unsigned long) ep->dma_buf,
151be5e4bdcSMarek Vasut 			   (unsigned long) ep->dma_buf +
152be5e4bdcSMarek Vasut 			   ROUND(ep->len, CONFIG_SYS_CACHELINE_SIZE));
153be5e4bdcSMarek Vasut 
154be5e4bdcSMarek Vasut 	if (length == 0)
155be5e4bdcSMarek Vasut 		pktcnt = 1;
156be5e4bdcSMarek Vasut 	else
157be5e4bdcSMarek Vasut 		pktcnt = (length - 1)/(ep->ep.maxpacket) + 1;
158be5e4bdcSMarek Vasut 
159be5e4bdcSMarek Vasut 	/* Flush the endpoint's Tx FIFO */
160be5e4bdcSMarek Vasut 	writel(TX_FIFO_NUMBER(ep->fifo_num), &reg->grstctl);
161be5e4bdcSMarek Vasut 	writel(TX_FIFO_NUMBER(ep->fifo_num) | TX_FIFO_FLUSH, &reg->grstctl);
162be5e4bdcSMarek Vasut 	while (readl(&reg->grstctl) & TX_FIFO_FLUSH)
163be5e4bdcSMarek Vasut 		;
164be5e4bdcSMarek Vasut 
165be5e4bdcSMarek Vasut 	writel((unsigned long) ep->dma_buf, &reg->in_endp[ep_num].diepdma);
166be5e4bdcSMarek Vasut 	writel(DIEPT_SIZ_PKT_CNT(pktcnt) | DIEPT_SIZ_XFER_SIZE(length),
167be5e4bdcSMarek Vasut 	       &reg->in_endp[ep_num].dieptsiz);
168be5e4bdcSMarek Vasut 
169be5e4bdcSMarek Vasut 	ctrl = readl(&reg->in_endp[ep_num].diepctl);
170be5e4bdcSMarek Vasut 
171be5e4bdcSMarek Vasut 	/* Write the FIFO number to be used for this endpoint */
172be5e4bdcSMarek Vasut 	ctrl &= DIEPCTL_TX_FIFO_NUM_MASK;
173be5e4bdcSMarek Vasut 	ctrl |= DIEPCTL_TX_FIFO_NUM(ep->fifo_num);
174be5e4bdcSMarek Vasut 
175be5e4bdcSMarek Vasut 	/* Clear reserved (Next EP) bits */
176be5e4bdcSMarek Vasut 	ctrl = (ctrl&~(EP_MASK<<DEPCTL_NEXT_EP_BIT));
177be5e4bdcSMarek Vasut 
178be5e4bdcSMarek Vasut 	writel(DEPCTL_EPENA|DEPCTL_CNAK|ctrl, &reg->in_endp[ep_num].diepctl);
179be5e4bdcSMarek Vasut 
180be5e4bdcSMarek Vasut 	debug_cond(DEBUG_IN_EP,
181be5e4bdcSMarek Vasut 		"%s:EP%d TX DMA start : DIEPDMA0 = 0x%x,"
182be5e4bdcSMarek Vasut 		"DIEPTSIZ0 = 0x%x, DIEPCTL0 = 0x%x\n"
183be5e4bdcSMarek Vasut 		"\tbuf = 0x%p, pktcnt = %d, xfersize = %d\n",
184be5e4bdcSMarek Vasut 		__func__, ep_num,
185be5e4bdcSMarek Vasut 		readl(&reg->in_endp[ep_num].diepdma),
186be5e4bdcSMarek Vasut 		readl(&reg->in_endp[ep_num].dieptsiz),
187be5e4bdcSMarek Vasut 		readl(&reg->in_endp[ep_num].diepctl),
188be5e4bdcSMarek Vasut 		buf, pktcnt, length);
189be5e4bdcSMarek Vasut 
190be5e4bdcSMarek Vasut 	return length;
191be5e4bdcSMarek Vasut }
192be5e4bdcSMarek Vasut 
complete_rx(struct dwc2_udc * dev,u8 ep_num)193be5e4bdcSMarek Vasut static void complete_rx(struct dwc2_udc *dev, u8 ep_num)
194be5e4bdcSMarek Vasut {
195be5e4bdcSMarek Vasut 	struct dwc2_ep *ep = &dev->ep[ep_num];
196be5e4bdcSMarek Vasut 	struct dwc2_request *req = NULL;
197be5e4bdcSMarek Vasut 	u32 ep_tsr = 0, xfer_size = 0, is_short = 0;
198be5e4bdcSMarek Vasut 
199be5e4bdcSMarek Vasut 	if (list_empty(&ep->queue)) {
200be5e4bdcSMarek Vasut 		debug_cond(DEBUG_OUT_EP != 0,
201be5e4bdcSMarek Vasut 			   "%s: RX DMA done : NULL REQ on OUT EP-%d\n",
202be5e4bdcSMarek Vasut 			   __func__, ep_num);
203be5e4bdcSMarek Vasut 		return;
204be5e4bdcSMarek Vasut 
205be5e4bdcSMarek Vasut 	}
206be5e4bdcSMarek Vasut 
207be5e4bdcSMarek Vasut 	req = list_entry(ep->queue.next, struct dwc2_request, queue);
208be5e4bdcSMarek Vasut 	ep_tsr = readl(&reg->out_endp[ep_num].doeptsiz);
209be5e4bdcSMarek Vasut 
210be5e4bdcSMarek Vasut 	if (ep_num == EP0_CON)
211be5e4bdcSMarek Vasut 		xfer_size = (ep_tsr & DOEPT_SIZ_XFER_SIZE_MAX_EP0);
212be5e4bdcSMarek Vasut 	else
213be5e4bdcSMarek Vasut 		xfer_size = (ep_tsr & DOEPT_SIZ_XFER_SIZE_MAX_EP);
214be5e4bdcSMarek Vasut 
215be5e4bdcSMarek Vasut 	xfer_size = ep->len - xfer_size;
216be5e4bdcSMarek Vasut 
217be5e4bdcSMarek Vasut 	/*
218be5e4bdcSMarek Vasut 	 * NOTE:
219be5e4bdcSMarek Vasut 	 *
220be5e4bdcSMarek Vasut 	 * Please be careful with proper buffer allocation for USB request,
221be5e4bdcSMarek Vasut 	 * which needs to be aligned to CONFIG_SYS_CACHELINE_SIZE, not only
222be5e4bdcSMarek Vasut 	 * with starting address, but also its size shall be a cache line
223be5e4bdcSMarek Vasut 	 * multiplication.
224be5e4bdcSMarek Vasut 	 *
225be5e4bdcSMarek Vasut 	 * This will prevent from corruption of data allocated immediatelly
226be5e4bdcSMarek Vasut 	 * before or after the buffer.
227be5e4bdcSMarek Vasut 	 *
228be5e4bdcSMarek Vasut 	 * For armv7, the cache_v7.c provides proper code to emit "ERROR"
229be5e4bdcSMarek Vasut 	 * message to warn users.
230be5e4bdcSMarek Vasut 	 */
231be5e4bdcSMarek Vasut 	invalidate_dcache_range((unsigned long) ep->dma_buf,
232be5e4bdcSMarek Vasut 				(unsigned long) ep->dma_buf +
233be5e4bdcSMarek Vasut 				ROUND(xfer_size, CONFIG_SYS_CACHELINE_SIZE));
234be5e4bdcSMarek Vasut 
235be5e4bdcSMarek Vasut 	req->req.actual += min(xfer_size, req->req.length - req->req.actual);
236842769eaSRoger Quadros 	is_short = !!(xfer_size % ep->ep.maxpacket);
237be5e4bdcSMarek Vasut 
238be5e4bdcSMarek Vasut 	debug_cond(DEBUG_OUT_EP != 0,
239be5e4bdcSMarek Vasut 		   "%s: RX DMA done : ep = %d, rx bytes = %d/%d, "
240be5e4bdcSMarek Vasut 		   "is_short = %d, DOEPTSIZ = 0x%x, remained bytes = %d\n",
241be5e4bdcSMarek Vasut 		   __func__, ep_num, req->req.actual, req->req.length,
2424d5b6378SRoger Quadros 		   is_short, ep_tsr, req->req.length - req->req.actual);
243be5e4bdcSMarek Vasut 
244be5e4bdcSMarek Vasut 	if (is_short || req->req.actual == req->req.length) {
245be5e4bdcSMarek Vasut 		if (ep_num == EP0_CON && dev->ep0state == DATA_STATE_RECV) {
246be5e4bdcSMarek Vasut 			debug_cond(DEBUG_OUT_EP != 0, "	=> Send ZLP\n");
247be5e4bdcSMarek Vasut 			dwc2_udc_ep0_zlp(dev);
248be5e4bdcSMarek Vasut 			/* packet will be completed in complete_tx() */
249be5e4bdcSMarek Vasut 			dev->ep0state = WAIT_FOR_IN_COMPLETE;
250be5e4bdcSMarek Vasut 		} else {
251be5e4bdcSMarek Vasut 			done(ep, req, 0);
252be5e4bdcSMarek Vasut 
253be5e4bdcSMarek Vasut 			if (!list_empty(&ep->queue)) {
254be5e4bdcSMarek Vasut 				req = list_entry(ep->queue.next,
255be5e4bdcSMarek Vasut 					struct dwc2_request, queue);
256be5e4bdcSMarek Vasut 				debug_cond(DEBUG_OUT_EP != 0,
257be5e4bdcSMarek Vasut 					   "%s: Next Rx request start...\n",
258be5e4bdcSMarek Vasut 					   __func__);
259be5e4bdcSMarek Vasut 				setdma_rx(ep, req);
260be5e4bdcSMarek Vasut 			}
261be5e4bdcSMarek Vasut 		}
262be5e4bdcSMarek Vasut 	} else
263be5e4bdcSMarek Vasut 		setdma_rx(ep, req);
264be5e4bdcSMarek Vasut }
265be5e4bdcSMarek Vasut 
complete_tx(struct dwc2_udc * dev,u8 ep_num)266be5e4bdcSMarek Vasut static void complete_tx(struct dwc2_udc *dev, u8 ep_num)
267be5e4bdcSMarek Vasut {
268be5e4bdcSMarek Vasut 	struct dwc2_ep *ep = &dev->ep[ep_num];
269be5e4bdcSMarek Vasut 	struct dwc2_request *req;
270be5e4bdcSMarek Vasut 	u32 ep_tsr = 0, xfer_size = 0, is_short = 0;
271be5e4bdcSMarek Vasut 	u32 last;
272be5e4bdcSMarek Vasut 
273be5e4bdcSMarek Vasut 	if (dev->ep0state == WAIT_FOR_NULL_COMPLETE) {
274be5e4bdcSMarek Vasut 		dev->ep0state = WAIT_FOR_OUT_COMPLETE;
275be5e4bdcSMarek Vasut 		dwc2_ep0_complete_out();
276be5e4bdcSMarek Vasut 		return;
277be5e4bdcSMarek Vasut 	}
278be5e4bdcSMarek Vasut 
279be5e4bdcSMarek Vasut 	if (list_empty(&ep->queue)) {
280be5e4bdcSMarek Vasut 		debug_cond(DEBUG_IN_EP,
281be5e4bdcSMarek Vasut 			"%s: TX DMA done : NULL REQ on IN EP-%d\n",
282be5e4bdcSMarek Vasut 			__func__, ep_num);
283be5e4bdcSMarek Vasut 		return;
284be5e4bdcSMarek Vasut 
285be5e4bdcSMarek Vasut 	}
286be5e4bdcSMarek Vasut 
287be5e4bdcSMarek Vasut 	req = list_entry(ep->queue.next, struct dwc2_request, queue);
288be5e4bdcSMarek Vasut 
289be5e4bdcSMarek Vasut 	ep_tsr = readl(&reg->in_endp[ep_num].dieptsiz);
290be5e4bdcSMarek Vasut 
291be5e4bdcSMarek Vasut 	xfer_size = ep->len;
292be5e4bdcSMarek Vasut 	is_short = (xfer_size < ep->ep.maxpacket);
293be5e4bdcSMarek Vasut 	req->req.actual += min(xfer_size, req->req.length - req->req.actual);
294be5e4bdcSMarek Vasut 
295be5e4bdcSMarek Vasut 	debug_cond(DEBUG_IN_EP,
296be5e4bdcSMarek Vasut 		"%s: TX DMA done : ep = %d, tx bytes = %d/%d, "
297be5e4bdcSMarek Vasut 		"is_short = %d, DIEPTSIZ = 0x%x, remained bytes = %d\n",
298be5e4bdcSMarek Vasut 		__func__, ep_num, req->req.actual, req->req.length,
2994d5b6378SRoger Quadros 		is_short, ep_tsr, req->req.length - req->req.actual);
300be5e4bdcSMarek Vasut 
301be5e4bdcSMarek Vasut 	if (ep_num == 0) {
302be5e4bdcSMarek Vasut 		if (dev->ep0state == DATA_STATE_XMIT) {
303be5e4bdcSMarek Vasut 			debug_cond(DEBUG_IN_EP,
304be5e4bdcSMarek Vasut 				"%s: ep_num = %d, ep0stat =="
305be5e4bdcSMarek Vasut 				"DATA_STATE_XMIT\n",
306be5e4bdcSMarek Vasut 				__func__, ep_num);
307be5e4bdcSMarek Vasut 			last = write_fifo_ep0(ep, req);
308be5e4bdcSMarek Vasut 			if (last)
309be5e4bdcSMarek Vasut 				dev->ep0state = WAIT_FOR_COMPLETE;
310be5e4bdcSMarek Vasut 		} else if (dev->ep0state == WAIT_FOR_IN_COMPLETE) {
311be5e4bdcSMarek Vasut 			debug_cond(DEBUG_IN_EP,
312be5e4bdcSMarek Vasut 				"%s: ep_num = %d, completing request\n",
313be5e4bdcSMarek Vasut 				__func__, ep_num);
314be5e4bdcSMarek Vasut 			done(ep, req, 0);
315be5e4bdcSMarek Vasut 			dev->ep0state = WAIT_FOR_SETUP;
316be5e4bdcSMarek Vasut 		} else if (dev->ep0state == WAIT_FOR_COMPLETE) {
317be5e4bdcSMarek Vasut 			debug_cond(DEBUG_IN_EP,
318be5e4bdcSMarek Vasut 				"%s: ep_num = %d, completing request\n",
319be5e4bdcSMarek Vasut 				__func__, ep_num);
320be5e4bdcSMarek Vasut 			done(ep, req, 0);
321be5e4bdcSMarek Vasut 			dev->ep0state = WAIT_FOR_OUT_COMPLETE;
322be5e4bdcSMarek Vasut 			dwc2_ep0_complete_out();
323be5e4bdcSMarek Vasut 		} else {
324be5e4bdcSMarek Vasut 			debug_cond(DEBUG_IN_EP,
325be5e4bdcSMarek Vasut 				"%s: ep_num = %d, invalid ep state\n",
326be5e4bdcSMarek Vasut 				__func__, ep_num);
327be5e4bdcSMarek Vasut 		}
328be5e4bdcSMarek Vasut 		return;
329be5e4bdcSMarek Vasut 	}
330be5e4bdcSMarek Vasut 
331be5e4bdcSMarek Vasut 	if (req->req.actual == req->req.length)
332be5e4bdcSMarek Vasut 		done(ep, req, 0);
333be5e4bdcSMarek Vasut 
334be5e4bdcSMarek Vasut 	if (!list_empty(&ep->queue)) {
335be5e4bdcSMarek Vasut 		req = list_entry(ep->queue.next, struct dwc2_request, queue);
336be5e4bdcSMarek Vasut 		debug_cond(DEBUG_IN_EP,
337be5e4bdcSMarek Vasut 			"%s: Next Tx request start...\n", __func__);
338be5e4bdcSMarek Vasut 		setdma_tx(ep, req);
339be5e4bdcSMarek Vasut 	}
340be5e4bdcSMarek Vasut }
341be5e4bdcSMarek Vasut 
dwc2_udc_check_tx_queue(struct dwc2_udc * dev,u8 ep_num)342be5e4bdcSMarek Vasut static inline void dwc2_udc_check_tx_queue(struct dwc2_udc *dev, u8 ep_num)
343be5e4bdcSMarek Vasut {
344be5e4bdcSMarek Vasut 	struct dwc2_ep *ep = &dev->ep[ep_num];
345be5e4bdcSMarek Vasut 	struct dwc2_request *req;
346be5e4bdcSMarek Vasut 
347be5e4bdcSMarek Vasut 	debug_cond(DEBUG_IN_EP,
348be5e4bdcSMarek Vasut 		"%s: Check queue, ep_num = %d\n", __func__, ep_num);
349be5e4bdcSMarek Vasut 
350be5e4bdcSMarek Vasut 	if (!list_empty(&ep->queue)) {
351be5e4bdcSMarek Vasut 		req = list_entry(ep->queue.next, struct dwc2_request, queue);
352be5e4bdcSMarek Vasut 		debug_cond(DEBUG_IN_EP,
353be5e4bdcSMarek Vasut 			"%s: Next Tx request(0x%p) start...\n",
354be5e4bdcSMarek Vasut 			__func__, req);
355be5e4bdcSMarek Vasut 
356be5e4bdcSMarek Vasut 		if (ep_is_in(ep))
357be5e4bdcSMarek Vasut 			setdma_tx(ep, req);
358be5e4bdcSMarek Vasut 		else
359be5e4bdcSMarek Vasut 			setdma_rx(ep, req);
360be5e4bdcSMarek Vasut 	} else {
361be5e4bdcSMarek Vasut 		debug_cond(DEBUG_IN_EP,
362be5e4bdcSMarek Vasut 			"%s: NULL REQ on IN EP-%d\n", __func__, ep_num);
363be5e4bdcSMarek Vasut 
364be5e4bdcSMarek Vasut 		return;
365be5e4bdcSMarek Vasut 	}
366be5e4bdcSMarek Vasut 
367be5e4bdcSMarek Vasut }
368be5e4bdcSMarek Vasut 
process_ep_in_intr(struct dwc2_udc * dev)369be5e4bdcSMarek Vasut static void process_ep_in_intr(struct dwc2_udc *dev)
370be5e4bdcSMarek Vasut {
371be5e4bdcSMarek Vasut 	u32 ep_intr, ep_intr_status;
372be5e4bdcSMarek Vasut 	u8 ep_num = 0;
373be5e4bdcSMarek Vasut 
374be5e4bdcSMarek Vasut 	ep_intr = readl(&reg->daint);
375be5e4bdcSMarek Vasut 	debug_cond(DEBUG_IN_EP,
376be5e4bdcSMarek Vasut 		"*** %s: EP In interrupt : DAINT = 0x%x\n", __func__, ep_intr);
377be5e4bdcSMarek Vasut 
378be5e4bdcSMarek Vasut 	ep_intr &= DAINT_MASK;
379be5e4bdcSMarek Vasut 
380be5e4bdcSMarek Vasut 	while (ep_intr) {
381be5e4bdcSMarek Vasut 		if (ep_intr & DAINT_IN_EP_INT(1)) {
382be5e4bdcSMarek Vasut 			ep_intr_status = readl(&reg->in_endp[ep_num].diepint);
383be5e4bdcSMarek Vasut 			debug_cond(DEBUG_IN_EP,
384be5e4bdcSMarek Vasut 				   "\tEP%d-IN : DIEPINT = 0x%x\n",
385be5e4bdcSMarek Vasut 				   ep_num, ep_intr_status);
386be5e4bdcSMarek Vasut 
387be5e4bdcSMarek Vasut 			/* Interrupt Clear */
388be5e4bdcSMarek Vasut 			writel(ep_intr_status, &reg->in_endp[ep_num].diepint);
389be5e4bdcSMarek Vasut 
390be5e4bdcSMarek Vasut 			if (ep_intr_status & TRANSFER_DONE) {
391be5e4bdcSMarek Vasut 				complete_tx(dev, ep_num);
392be5e4bdcSMarek Vasut 
393be5e4bdcSMarek Vasut 				if (ep_num == 0) {
394be5e4bdcSMarek Vasut 					if (dev->ep0state ==
395be5e4bdcSMarek Vasut 					    WAIT_FOR_IN_COMPLETE)
396be5e4bdcSMarek Vasut 						dev->ep0state = WAIT_FOR_SETUP;
397be5e4bdcSMarek Vasut 
398be5e4bdcSMarek Vasut 					if (dev->ep0state == WAIT_FOR_SETUP)
399be5e4bdcSMarek Vasut 						dwc2_udc_pre_setup();
400be5e4bdcSMarek Vasut 
401be5e4bdcSMarek Vasut 					/* continue transfer after
402be5e4bdcSMarek Vasut 					   set_clear_halt for DMA mode */
403be5e4bdcSMarek Vasut 					if (clear_feature_flag == 1) {
404be5e4bdcSMarek Vasut 						dwc2_udc_check_tx_queue(dev,
405be5e4bdcSMarek Vasut 							clear_feature_num);
406be5e4bdcSMarek Vasut 						clear_feature_flag = 0;
407be5e4bdcSMarek Vasut 					}
408be5e4bdcSMarek Vasut 				}
409be5e4bdcSMarek Vasut 			}
410be5e4bdcSMarek Vasut 		}
411be5e4bdcSMarek Vasut 		ep_num++;
412be5e4bdcSMarek Vasut 		ep_intr >>= 1;
413be5e4bdcSMarek Vasut 	}
414be5e4bdcSMarek Vasut }
415be5e4bdcSMarek Vasut 
process_ep_out_intr(struct dwc2_udc * dev)416be5e4bdcSMarek Vasut static void process_ep_out_intr(struct dwc2_udc *dev)
417be5e4bdcSMarek Vasut {
418be5e4bdcSMarek Vasut 	u32 ep_intr, ep_intr_status;
419be5e4bdcSMarek Vasut 	u8 ep_num = 0;
420be5e4bdcSMarek Vasut 
421be5e4bdcSMarek Vasut 	ep_intr = readl(&reg->daint);
422be5e4bdcSMarek Vasut 	debug_cond(DEBUG_OUT_EP != 0,
423be5e4bdcSMarek Vasut 		   "*** %s: EP OUT interrupt : DAINT = 0x%x\n",
424be5e4bdcSMarek Vasut 		   __func__, ep_intr);
425be5e4bdcSMarek Vasut 
426be5e4bdcSMarek Vasut 	ep_intr = (ep_intr >> DAINT_OUT_BIT) & DAINT_MASK;
427be5e4bdcSMarek Vasut 
428be5e4bdcSMarek Vasut 	while (ep_intr) {
429be5e4bdcSMarek Vasut 		if (ep_intr & 0x1) {
430be5e4bdcSMarek Vasut 			ep_intr_status = readl(&reg->out_endp[ep_num].doepint);
431be5e4bdcSMarek Vasut 			debug_cond(DEBUG_OUT_EP != 0,
432be5e4bdcSMarek Vasut 				   "\tEP%d-OUT : DOEPINT = 0x%x\n",
433be5e4bdcSMarek Vasut 				   ep_num, ep_intr_status);
434be5e4bdcSMarek Vasut 
435be5e4bdcSMarek Vasut 			/* Interrupt Clear */
436be5e4bdcSMarek Vasut 			writel(ep_intr_status, &reg->out_endp[ep_num].doepint);
437be5e4bdcSMarek Vasut 
438be5e4bdcSMarek Vasut 			if (ep_num == 0) {
439be5e4bdcSMarek Vasut 				if (ep_intr_status & TRANSFER_DONE) {
440be5e4bdcSMarek Vasut 					if (dev->ep0state !=
441be5e4bdcSMarek Vasut 					    WAIT_FOR_OUT_COMPLETE)
442be5e4bdcSMarek Vasut 						complete_rx(dev, ep_num);
443be5e4bdcSMarek Vasut 					else {
444be5e4bdcSMarek Vasut 						dev->ep0state = WAIT_FOR_SETUP;
445be5e4bdcSMarek Vasut 						dwc2_udc_pre_setup();
446be5e4bdcSMarek Vasut 					}
447be5e4bdcSMarek Vasut 				}
448be5e4bdcSMarek Vasut 
449be5e4bdcSMarek Vasut 				if (ep_intr_status &
450be5e4bdcSMarek Vasut 				    CTRL_OUT_EP_SETUP_PHASE_DONE) {
451be5e4bdcSMarek Vasut 					debug_cond(DEBUG_OUT_EP != 0,
452be5e4bdcSMarek Vasut 						   "SETUP packet arrived\n");
453be5e4bdcSMarek Vasut 					dwc2_handle_ep0(dev);
454be5e4bdcSMarek Vasut 				}
455be5e4bdcSMarek Vasut 			} else {
456be5e4bdcSMarek Vasut 				if (ep_intr_status & TRANSFER_DONE)
457be5e4bdcSMarek Vasut 					complete_rx(dev, ep_num);
458be5e4bdcSMarek Vasut 			}
459be5e4bdcSMarek Vasut 		}
460be5e4bdcSMarek Vasut 		ep_num++;
461be5e4bdcSMarek Vasut 		ep_intr >>= 1;
462be5e4bdcSMarek Vasut 	}
463be5e4bdcSMarek Vasut }
464be5e4bdcSMarek Vasut 
465be5e4bdcSMarek Vasut /*
466be5e4bdcSMarek Vasut  *	usb client interrupt handler.
467be5e4bdcSMarek Vasut  */
dwc2_udc_irq(int irq,void * _dev)468be5e4bdcSMarek Vasut static int dwc2_udc_irq(int irq, void *_dev)
469be5e4bdcSMarek Vasut {
470be5e4bdcSMarek Vasut 	struct dwc2_udc *dev = _dev;
47124b360daSFabrice Gasnier 	u32 intr_status, gotgint;
472be5e4bdcSMarek Vasut 	u32 usb_status, gintmsk;
473be5e4bdcSMarek Vasut 	unsigned long flags = 0;
474be5e4bdcSMarek Vasut 
475be5e4bdcSMarek Vasut 	spin_lock_irqsave(&dev->lock, flags);
476be5e4bdcSMarek Vasut 
477be5e4bdcSMarek Vasut 	intr_status = readl(&reg->gintsts);
478be5e4bdcSMarek Vasut 	gintmsk = readl(&reg->gintmsk);
479be5e4bdcSMarek Vasut 
480be5e4bdcSMarek Vasut 	debug_cond(DEBUG_ISR,
481be5e4bdcSMarek Vasut 		  "\n*** %s : GINTSTS=0x%x(on state %s), GINTMSK : 0x%x,"
482be5e4bdcSMarek Vasut 		  "DAINT : 0x%x, DAINTMSK : 0x%x\n",
483be5e4bdcSMarek Vasut 		  __func__, intr_status, state_names[dev->ep0state], gintmsk,
484be5e4bdcSMarek Vasut 		  readl(&reg->daint), readl(&reg->daintmsk));
485be5e4bdcSMarek Vasut 
486be5e4bdcSMarek Vasut 	if (!intr_status) {
487be5e4bdcSMarek Vasut 		spin_unlock_irqrestore(&dev->lock, flags);
488be5e4bdcSMarek Vasut 		return IRQ_HANDLED;
489be5e4bdcSMarek Vasut 	}
490be5e4bdcSMarek Vasut 
491be5e4bdcSMarek Vasut 	if (intr_status & INT_ENUMDONE) {
492be5e4bdcSMarek Vasut 		debug_cond(DEBUG_ISR, "\tSpeed Detection interrupt\n");
493be5e4bdcSMarek Vasut 
494be5e4bdcSMarek Vasut 		writel(INT_ENUMDONE, &reg->gintsts);
495be5e4bdcSMarek Vasut 		usb_status = (readl(&reg->dsts) & 0x6);
496be5e4bdcSMarek Vasut 
497be5e4bdcSMarek Vasut 		if (usb_status & (USB_FULL_30_60MHZ | USB_FULL_48MHZ)) {
498be5e4bdcSMarek Vasut 			debug_cond(DEBUG_ISR,
499be5e4bdcSMarek Vasut 				   "\t\tFull Speed Detection\n");
500be5e4bdcSMarek Vasut 			set_max_pktsize(dev, USB_SPEED_FULL);
501be5e4bdcSMarek Vasut 
502be5e4bdcSMarek Vasut 		} else {
503be5e4bdcSMarek Vasut 			debug_cond(DEBUG_ISR,
504be5e4bdcSMarek Vasut 				"\t\tHigh Speed Detection : 0x%x\n",
505be5e4bdcSMarek Vasut 				usb_status);
506be5e4bdcSMarek Vasut 			set_max_pktsize(dev, USB_SPEED_HIGH);
507be5e4bdcSMarek Vasut 		}
508be5e4bdcSMarek Vasut 	}
509be5e4bdcSMarek Vasut 
510be5e4bdcSMarek Vasut 	if (intr_status & INT_EARLY_SUSPEND) {
511be5e4bdcSMarek Vasut 		debug_cond(DEBUG_ISR, "\tEarly suspend interrupt\n");
512be5e4bdcSMarek Vasut 		writel(INT_EARLY_SUSPEND, &reg->gintsts);
513be5e4bdcSMarek Vasut 	}
514be5e4bdcSMarek Vasut 
515be5e4bdcSMarek Vasut 	if (intr_status & INT_SUSPEND) {
516be5e4bdcSMarek Vasut 		usb_status = readl(&reg->dsts);
517be5e4bdcSMarek Vasut 		debug_cond(DEBUG_ISR,
518be5e4bdcSMarek Vasut 			"\tSuspend interrupt :(DSTS):0x%x\n", usb_status);
519be5e4bdcSMarek Vasut 		writel(INT_SUSPEND, &reg->gintsts);
520be5e4bdcSMarek Vasut 
521be5e4bdcSMarek Vasut 		if (dev->gadget.speed != USB_SPEED_UNKNOWN
522be5e4bdcSMarek Vasut 		    && dev->driver) {
523be5e4bdcSMarek Vasut 			if (dev->driver->suspend)
524be5e4bdcSMarek Vasut 				dev->driver->suspend(&dev->gadget);
52524b360daSFabrice Gasnier 		}
52624b360daSFabrice Gasnier 	}
527be5e4bdcSMarek Vasut 
52824b360daSFabrice Gasnier 	if (intr_status & INT_OTG) {
52924b360daSFabrice Gasnier 		gotgint = readl(&reg->gotgint);
53024b360daSFabrice Gasnier 		debug_cond(DEBUG_ISR,
53124b360daSFabrice Gasnier 			   "\tOTG interrupt: (GOTGINT):0x%x\n", gotgint);
53224b360daSFabrice Gasnier 
53324b360daSFabrice Gasnier 		if (gotgint & GOTGINT_SES_END_DET) {
53424b360daSFabrice Gasnier 			debug_cond(DEBUG_ISR, "\t\tSession End Detected\n");
53524b360daSFabrice Gasnier 			/* Let gadget detect disconnected state */
536be5e4bdcSMarek Vasut 			if (dev->driver->disconnect) {
537be5e4bdcSMarek Vasut 				spin_unlock_irqrestore(&dev->lock, flags);
538be5e4bdcSMarek Vasut 				dev->driver->disconnect(&dev->gadget);
539be5e4bdcSMarek Vasut 				spin_lock_irqsave(&dev->lock, flags);
540be5e4bdcSMarek Vasut 			}
541be5e4bdcSMarek Vasut 		}
54224b360daSFabrice Gasnier 		writel(gotgint, &reg->gotgint);
543be5e4bdcSMarek Vasut 	}
544be5e4bdcSMarek Vasut 
545be5e4bdcSMarek Vasut 	if (intr_status & INT_RESUME) {
546be5e4bdcSMarek Vasut 		debug_cond(DEBUG_ISR, "\tResume interrupt\n");
547be5e4bdcSMarek Vasut 		writel(INT_RESUME, &reg->gintsts);
548be5e4bdcSMarek Vasut 
549be5e4bdcSMarek Vasut 		if (dev->gadget.speed != USB_SPEED_UNKNOWN
550be5e4bdcSMarek Vasut 		    && dev->driver
551be5e4bdcSMarek Vasut 		    && dev->driver->resume) {
552be5e4bdcSMarek Vasut 
553be5e4bdcSMarek Vasut 			dev->driver->resume(&dev->gadget);
554be5e4bdcSMarek Vasut 		}
555be5e4bdcSMarek Vasut 	}
556be5e4bdcSMarek Vasut 
557be5e4bdcSMarek Vasut 	if (intr_status & INT_RESET) {
558a52e8dd4SFrank Wang 		u32 temp;
559a52e8dd4SFrank Wang 		u32 connected = dev->connected;
560a52e8dd4SFrank Wang 
561be5e4bdcSMarek Vasut 		usb_status = readl(&reg->gotgctl);
562be5e4bdcSMarek Vasut 		debug_cond(DEBUG_ISR,
563be5e4bdcSMarek Vasut 			"\tReset interrupt - (GOTGCTL):0x%x\n", usb_status);
564be5e4bdcSMarek Vasut 		writel(INT_RESET, &reg->gintsts);
565be5e4bdcSMarek Vasut 
566*30bf5086SWilliam Wu 		if (((usb_status & 0xc0000) == (0x3 << 18)) ||
567*30bf5086SWilliam Wu 		    dev->pdata->force_b_session_valid) {
568be5e4bdcSMarek Vasut 			if (reset_available) {
569be5e4bdcSMarek Vasut 				debug_cond(DEBUG_ISR,
570be5e4bdcSMarek Vasut 					"\t\tOTG core got reset (%d)!!\n",
571be5e4bdcSMarek Vasut 					reset_available);
572a52e8dd4SFrank Wang 				/* Reset device address to zero */
573a52e8dd4SFrank Wang 				temp = readl(&reg->dcfg);
574a52e8dd4SFrank Wang 				temp &= ~DCFG_DEVADDR_MASK;
575a52e8dd4SFrank Wang 				writel(temp, &reg->dcfg);
576a52e8dd4SFrank Wang 
577a52e8dd4SFrank Wang 				/* Soft reset the core if connected */
578a52e8dd4SFrank Wang 				if (connected)
579be5e4bdcSMarek Vasut 					reconfig_usbd(dev);
580a52e8dd4SFrank Wang 
581be5e4bdcSMarek Vasut 				dev->ep0state = WAIT_FOR_SETUP;
582be5e4bdcSMarek Vasut 				reset_available = 0;
583be5e4bdcSMarek Vasut 				dwc2_udc_pre_setup();
584be5e4bdcSMarek Vasut 			} else
585be5e4bdcSMarek Vasut 				reset_available = 1;
586be5e4bdcSMarek Vasut 
587be5e4bdcSMarek Vasut 		} else {
588be5e4bdcSMarek Vasut 			reset_available = 1;
589be5e4bdcSMarek Vasut 			debug_cond(DEBUG_ISR,
590be5e4bdcSMarek Vasut 				   "\t\tRESET handling skipped\n");
591be5e4bdcSMarek Vasut 		}
592be5e4bdcSMarek Vasut 	}
593be5e4bdcSMarek Vasut 
594be5e4bdcSMarek Vasut 	if (intr_status & INT_IN_EP)
595be5e4bdcSMarek Vasut 		process_ep_in_intr(dev);
596be5e4bdcSMarek Vasut 
597be5e4bdcSMarek Vasut 	if (intr_status & INT_OUT_EP)
598be5e4bdcSMarek Vasut 		process_ep_out_intr(dev);
599be5e4bdcSMarek Vasut 
600be5e4bdcSMarek Vasut 	spin_unlock_irqrestore(&dev->lock, flags);
601be5e4bdcSMarek Vasut 
602be5e4bdcSMarek Vasut 	return IRQ_HANDLED;
603be5e4bdcSMarek Vasut }
604be5e4bdcSMarek Vasut 
605be5e4bdcSMarek Vasut /** Queue one request
606be5e4bdcSMarek Vasut  *  Kickstart transfer if needed
607be5e4bdcSMarek Vasut  */
dwc2_queue(struct usb_ep * _ep,struct usb_request * _req,gfp_t gfp_flags)608be5e4bdcSMarek Vasut static int dwc2_queue(struct usb_ep *_ep, struct usb_request *_req,
609be5e4bdcSMarek Vasut 			 gfp_t gfp_flags)
610be5e4bdcSMarek Vasut {
611be5e4bdcSMarek Vasut 	struct dwc2_request *req;
612be5e4bdcSMarek Vasut 	struct dwc2_ep *ep;
613be5e4bdcSMarek Vasut 	struct dwc2_udc *dev;
614be5e4bdcSMarek Vasut 	unsigned long flags = 0;
615be5e4bdcSMarek Vasut 	u32 ep_num, gintsts;
616be5e4bdcSMarek Vasut 
617be5e4bdcSMarek Vasut 	req = container_of(_req, struct dwc2_request, req);
618be5e4bdcSMarek Vasut 	if (unlikely(!_req || !_req->complete || !_req->buf
619be5e4bdcSMarek Vasut 		     || !list_empty(&req->queue))) {
620be5e4bdcSMarek Vasut 
621be5e4bdcSMarek Vasut 		debug("%s: bad params\n", __func__);
622be5e4bdcSMarek Vasut 		return -EINVAL;
623be5e4bdcSMarek Vasut 	}
624be5e4bdcSMarek Vasut 
625be5e4bdcSMarek Vasut 	ep = container_of(_ep, struct dwc2_ep, ep);
626be5e4bdcSMarek Vasut 
627be5e4bdcSMarek Vasut 	if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
628be5e4bdcSMarek Vasut 
629be5e4bdcSMarek Vasut 		debug("%s: bad ep: %s, %d, %p\n", __func__,
630be5e4bdcSMarek Vasut 		      ep->ep.name, !ep->desc, _ep);
631be5e4bdcSMarek Vasut 		return -EINVAL;
632be5e4bdcSMarek Vasut 	}
633be5e4bdcSMarek Vasut 
634be5e4bdcSMarek Vasut 	ep_num = ep_index(ep);
635be5e4bdcSMarek Vasut 	dev = ep->dev;
636be5e4bdcSMarek Vasut 	if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
637be5e4bdcSMarek Vasut 
638be5e4bdcSMarek Vasut 		debug("%s: bogus device state %p\n", __func__, dev->driver);
639be5e4bdcSMarek Vasut 		return -ESHUTDOWN;
640be5e4bdcSMarek Vasut 	}
641be5e4bdcSMarek Vasut 
642be5e4bdcSMarek Vasut 	spin_lock_irqsave(&dev->lock, flags);
643be5e4bdcSMarek Vasut 
644be5e4bdcSMarek Vasut 	_req->status = -EINPROGRESS;
645be5e4bdcSMarek Vasut 	_req->actual = 0;
646be5e4bdcSMarek Vasut 
647be5e4bdcSMarek Vasut 	/* kickstart this i/o queue? */
648be5e4bdcSMarek Vasut 	debug("\n*** %s: %s-%s req = %p, len = %d, buf = %p"
649be5e4bdcSMarek Vasut 		"Q empty = %d, stopped = %d\n",
650be5e4bdcSMarek Vasut 		__func__, _ep->name, ep_is_in(ep) ? "in" : "out",
651be5e4bdcSMarek Vasut 		_req, _req->length, _req->buf,
652be5e4bdcSMarek Vasut 		list_empty(&ep->queue), ep->stopped);
653be5e4bdcSMarek Vasut 
654be5e4bdcSMarek Vasut #ifdef DEBUG
655be5e4bdcSMarek Vasut 	{
656be5e4bdcSMarek Vasut 		int i, len = _req->length;
657be5e4bdcSMarek Vasut 
658be5e4bdcSMarek Vasut 		printf("pkt = ");
659be5e4bdcSMarek Vasut 		if (len > 64)
660be5e4bdcSMarek Vasut 			len = 64;
661be5e4bdcSMarek Vasut 		for (i = 0; i < len; i++) {
662be5e4bdcSMarek Vasut 			printf("%02x", ((u8 *)_req->buf)[i]);
663be5e4bdcSMarek Vasut 			if ((i & 7) == 7)
664be5e4bdcSMarek Vasut 				printf(" ");
665be5e4bdcSMarek Vasut 		}
666be5e4bdcSMarek Vasut 		printf("\n");
667be5e4bdcSMarek Vasut 	}
668be5e4bdcSMarek Vasut #endif
669be5e4bdcSMarek Vasut 
670be5e4bdcSMarek Vasut 	if (list_empty(&ep->queue) && !ep->stopped) {
671be5e4bdcSMarek Vasut 
672be5e4bdcSMarek Vasut 		if (ep_num == 0) {
673be5e4bdcSMarek Vasut 			/* EP0 */
674be5e4bdcSMarek Vasut 			list_add_tail(&req->queue, &ep->queue);
675be5e4bdcSMarek Vasut 			dwc2_ep0_kick(dev, ep);
676be5e4bdcSMarek Vasut 			req = 0;
677be5e4bdcSMarek Vasut 
678be5e4bdcSMarek Vasut 		} else if (ep_is_in(ep)) {
679be5e4bdcSMarek Vasut 			gintsts = readl(&reg->gintsts);
680be5e4bdcSMarek Vasut 			debug_cond(DEBUG_IN_EP,
681507e677bSMarek Vasut 				   "%s: ep_is_in, DWC2_UDC_OTG_GINTSTS=0x%x\n",
682be5e4bdcSMarek Vasut 				   __func__, gintsts);
683be5e4bdcSMarek Vasut 
684be5e4bdcSMarek Vasut 			setdma_tx(ep, req);
685be5e4bdcSMarek Vasut 		} else {
686be5e4bdcSMarek Vasut 			gintsts = readl(&reg->gintsts);
687be5e4bdcSMarek Vasut 			debug_cond(DEBUG_OUT_EP != 0,
688507e677bSMarek Vasut 				   "%s:ep_is_out, DWC2_UDC_OTG_GINTSTS=0x%x\n",
689be5e4bdcSMarek Vasut 				   __func__, gintsts);
690be5e4bdcSMarek Vasut 
691be5e4bdcSMarek Vasut 			setdma_rx(ep, req);
692be5e4bdcSMarek Vasut 		}
693be5e4bdcSMarek Vasut 	}
694be5e4bdcSMarek Vasut 
695be5e4bdcSMarek Vasut 	/* pio or dma irq handler advances the queue. */
696be5e4bdcSMarek Vasut 	if (likely(req != 0))
697be5e4bdcSMarek Vasut 		list_add_tail(&req->queue, &ep->queue);
698be5e4bdcSMarek Vasut 
699be5e4bdcSMarek Vasut 	spin_unlock_irqrestore(&dev->lock, flags);
700be5e4bdcSMarek Vasut 
701be5e4bdcSMarek Vasut 	return 0;
702be5e4bdcSMarek Vasut }
703be5e4bdcSMarek Vasut 
704be5e4bdcSMarek Vasut /****************************************************************/
705be5e4bdcSMarek Vasut /* End Point 0 related functions                                */
706be5e4bdcSMarek Vasut /****************************************************************/
707be5e4bdcSMarek Vasut 
708be5e4bdcSMarek Vasut /* return:  0 = still running, 1 = completed, negative = errno */
write_fifo_ep0(struct dwc2_ep * ep,struct dwc2_request * req)709be5e4bdcSMarek Vasut static int write_fifo_ep0(struct dwc2_ep *ep, struct dwc2_request *req)
710be5e4bdcSMarek Vasut {
711be5e4bdcSMarek Vasut 	u32 max;
712be5e4bdcSMarek Vasut 	unsigned count;
713be5e4bdcSMarek Vasut 	int is_last;
714be5e4bdcSMarek Vasut 
715be5e4bdcSMarek Vasut 	max = ep_maxpacket(ep);
716be5e4bdcSMarek Vasut 
717be5e4bdcSMarek Vasut 	debug_cond(DEBUG_EP0 != 0, "%s: max = %d\n", __func__, max);
718be5e4bdcSMarek Vasut 
719be5e4bdcSMarek Vasut 	count = setdma_tx(ep, req);
720be5e4bdcSMarek Vasut 
721be5e4bdcSMarek Vasut 	/* last packet is usually short (or a zlp) */
722be5e4bdcSMarek Vasut 	if (likely(count != max))
723be5e4bdcSMarek Vasut 		is_last = 1;
724be5e4bdcSMarek Vasut 	else {
725be5e4bdcSMarek Vasut 		if (likely(req->req.length != req->req.actual + count)
726be5e4bdcSMarek Vasut 		    || req->req.zero)
727be5e4bdcSMarek Vasut 			is_last = 0;
728be5e4bdcSMarek Vasut 		else
729be5e4bdcSMarek Vasut 			is_last = 1;
730be5e4bdcSMarek Vasut 	}
731be5e4bdcSMarek Vasut 
732be5e4bdcSMarek Vasut 	debug_cond(DEBUG_EP0 != 0,
733be5e4bdcSMarek Vasut 		   "%s: wrote %s %d bytes%s %d left %p\n", __func__,
734be5e4bdcSMarek Vasut 		   ep->ep.name, count,
735be5e4bdcSMarek Vasut 		   is_last ? "/L" : "",
736be5e4bdcSMarek Vasut 		   req->req.length - req->req.actual - count, req);
737be5e4bdcSMarek Vasut 
738be5e4bdcSMarek Vasut 	/* requests complete when all IN data is in the FIFO */
739be5e4bdcSMarek Vasut 	if (is_last) {
740be5e4bdcSMarek Vasut 		ep->dev->ep0state = WAIT_FOR_SETUP;
741be5e4bdcSMarek Vasut 		return 1;
742be5e4bdcSMarek Vasut 	}
743be5e4bdcSMarek Vasut 
744be5e4bdcSMarek Vasut 	return 0;
745be5e4bdcSMarek Vasut }
746be5e4bdcSMarek Vasut 
dwc2_fifo_read(struct dwc2_ep * ep,void * cp,int max)7477808becdSSimon Goldschmidt static int dwc2_fifo_read(struct dwc2_ep *ep, void *cp, int max)
748be5e4bdcSMarek Vasut {
749be5e4bdcSMarek Vasut 	invalidate_dcache_range((unsigned long)cp, (unsigned long)cp +
750be5e4bdcSMarek Vasut 				ROUND(max, CONFIG_SYS_CACHELINE_SIZE));
751be5e4bdcSMarek Vasut 
752be5e4bdcSMarek Vasut 	debug_cond(DEBUG_EP0 != 0,
753be5e4bdcSMarek Vasut 		   "%s: bytes=%d, ep_index=%d 0x%p\n", __func__,
754be5e4bdcSMarek Vasut 		   max, ep_index(ep), cp);
755be5e4bdcSMarek Vasut 
756be5e4bdcSMarek Vasut 	return max;
757be5e4bdcSMarek Vasut }
758be5e4bdcSMarek Vasut 
759be5e4bdcSMarek Vasut /**
760be5e4bdcSMarek Vasut  * udc_set_address - set the USB address for this device
761be5e4bdcSMarek Vasut  * @address:
762be5e4bdcSMarek Vasut  *
763be5e4bdcSMarek Vasut  * Called from control endpoint function
764be5e4bdcSMarek Vasut  * after it decodes a set address setup packet.
765be5e4bdcSMarek Vasut  */
udc_set_address(struct dwc2_udc * dev,unsigned char address)766be5e4bdcSMarek Vasut static void udc_set_address(struct dwc2_udc *dev, unsigned char address)
767be5e4bdcSMarek Vasut {
768be5e4bdcSMarek Vasut 	u32 ctrl = readl(&reg->dcfg);
769be5e4bdcSMarek Vasut 	writel(DEVICE_ADDRESS(address) | ctrl, &reg->dcfg);
770be5e4bdcSMarek Vasut 
771be5e4bdcSMarek Vasut 	dwc2_udc_ep0_zlp(dev);
772be5e4bdcSMarek Vasut 
773be5e4bdcSMarek Vasut 	debug_cond(DEBUG_EP0 != 0,
774be5e4bdcSMarek Vasut 		   "%s: USB OTG 2.0 Device address=%d, DCFG=0x%x\n",
775be5e4bdcSMarek Vasut 		   __func__, address, readl(&reg->dcfg));
776be5e4bdcSMarek Vasut 
777be5e4bdcSMarek Vasut 	dev->usb_address = address;
778be5e4bdcSMarek Vasut }
779be5e4bdcSMarek Vasut 
dwc2_udc_ep0_set_stall(struct dwc2_ep * ep)780be5e4bdcSMarek Vasut static inline void dwc2_udc_ep0_set_stall(struct dwc2_ep *ep)
781be5e4bdcSMarek Vasut {
782be5e4bdcSMarek Vasut 	struct dwc2_udc *dev;
783be5e4bdcSMarek Vasut 	u32		ep_ctrl = 0;
784be5e4bdcSMarek Vasut 
785be5e4bdcSMarek Vasut 	dev = ep->dev;
786be5e4bdcSMarek Vasut 	ep_ctrl = readl(&reg->in_endp[EP0_CON].diepctl);
787be5e4bdcSMarek Vasut 
788be5e4bdcSMarek Vasut 	/* set the disable and stall bits */
789be5e4bdcSMarek Vasut 	if (ep_ctrl & DEPCTL_EPENA)
790be5e4bdcSMarek Vasut 		ep_ctrl |= DEPCTL_EPDIS;
791be5e4bdcSMarek Vasut 
792be5e4bdcSMarek Vasut 	ep_ctrl |= DEPCTL_STALL;
793be5e4bdcSMarek Vasut 
794be5e4bdcSMarek Vasut 	writel(ep_ctrl, &reg->in_endp[EP0_CON].diepctl);
795be5e4bdcSMarek Vasut 
796be5e4bdcSMarek Vasut 	debug_cond(DEBUG_EP0 != 0,
797be5e4bdcSMarek Vasut 		   "%s: set ep%d stall, DIEPCTL0 = 0x%p\n",
798be5e4bdcSMarek Vasut 		   __func__, ep_index(ep), &reg->in_endp[EP0_CON].diepctl);
799be5e4bdcSMarek Vasut 	/*
800be5e4bdcSMarek Vasut 	 * The application can only set this bit, and the core clears it,
801be5e4bdcSMarek Vasut 	 * when a SETUP token is received for this endpoint
802be5e4bdcSMarek Vasut 	 */
803be5e4bdcSMarek Vasut 	dev->ep0state = WAIT_FOR_SETUP;
804be5e4bdcSMarek Vasut 
805be5e4bdcSMarek Vasut 	dwc2_udc_pre_setup();
806be5e4bdcSMarek Vasut }
807be5e4bdcSMarek Vasut 
dwc2_ep0_read(struct dwc2_udc * dev)808be5e4bdcSMarek Vasut static void dwc2_ep0_read(struct dwc2_udc *dev)
809be5e4bdcSMarek Vasut {
810be5e4bdcSMarek Vasut 	struct dwc2_request *req;
811be5e4bdcSMarek Vasut 	struct dwc2_ep *ep = &dev->ep[0];
812be5e4bdcSMarek Vasut 
813be5e4bdcSMarek Vasut 	if (!list_empty(&ep->queue)) {
814be5e4bdcSMarek Vasut 		req = list_entry(ep->queue.next, struct dwc2_request, queue);
815be5e4bdcSMarek Vasut 
816be5e4bdcSMarek Vasut 	} else {
817be5e4bdcSMarek Vasut 		debug("%s: ---> BUG\n", __func__);
818be5e4bdcSMarek Vasut 		BUG();
819be5e4bdcSMarek Vasut 		return;
820be5e4bdcSMarek Vasut 	}
821be5e4bdcSMarek Vasut 
822be5e4bdcSMarek Vasut 	debug_cond(DEBUG_EP0 != 0,
823be5e4bdcSMarek Vasut 		   "%s: req = %p, req.length = 0x%x, req.actual = 0x%x\n",
824be5e4bdcSMarek Vasut 		   __func__, req, req->req.length, req->req.actual);
825be5e4bdcSMarek Vasut 
826be5e4bdcSMarek Vasut 	if (req->req.length == 0) {
827be5e4bdcSMarek Vasut 		/* zlp for Set_configuration, Set_interface,
828be5e4bdcSMarek Vasut 		 * or Bulk-Only mass storge reset */
829be5e4bdcSMarek Vasut 
830be5e4bdcSMarek Vasut 		ep->len = 0;
831be5e4bdcSMarek Vasut 		dwc2_udc_ep0_zlp(dev);
832be5e4bdcSMarek Vasut 
833be5e4bdcSMarek Vasut 		debug_cond(DEBUG_EP0 != 0,
834be5e4bdcSMarek Vasut 			   "%s: req.length = 0, bRequest = %d\n",
835be5e4bdcSMarek Vasut 			   __func__, usb_ctrl->bRequest);
836be5e4bdcSMarek Vasut 		return;
837be5e4bdcSMarek Vasut 	}
838be5e4bdcSMarek Vasut 
839be5e4bdcSMarek Vasut 	setdma_rx(ep, req);
840be5e4bdcSMarek Vasut }
841be5e4bdcSMarek Vasut 
842be5e4bdcSMarek Vasut /*
843be5e4bdcSMarek Vasut  * DATA_STATE_XMIT
844be5e4bdcSMarek Vasut  */
dwc2_ep0_write(struct dwc2_udc * dev)845be5e4bdcSMarek Vasut static int dwc2_ep0_write(struct dwc2_udc *dev)
846be5e4bdcSMarek Vasut {
847be5e4bdcSMarek Vasut 	struct dwc2_request *req;
848be5e4bdcSMarek Vasut 	struct dwc2_ep *ep = &dev->ep[0];
849be5e4bdcSMarek Vasut 	int ret, need_zlp = 0;
850be5e4bdcSMarek Vasut 
851be5e4bdcSMarek Vasut 	if (list_empty(&ep->queue))
852be5e4bdcSMarek Vasut 		req = 0;
853be5e4bdcSMarek Vasut 	else
854be5e4bdcSMarek Vasut 		req = list_entry(ep->queue.next, struct dwc2_request, queue);
855be5e4bdcSMarek Vasut 
856be5e4bdcSMarek Vasut 	if (!req) {
857be5e4bdcSMarek Vasut 		debug_cond(DEBUG_EP0 != 0, "%s: NULL REQ\n", __func__);
858be5e4bdcSMarek Vasut 		return 0;
859be5e4bdcSMarek Vasut 	}
860be5e4bdcSMarek Vasut 
861be5e4bdcSMarek Vasut 	debug_cond(DEBUG_EP0 != 0,
862be5e4bdcSMarek Vasut 		   "%s: req = %p, req.length = 0x%x, req.actual = 0x%x\n",
863be5e4bdcSMarek Vasut 		   __func__, req, req->req.length, req->req.actual);
864be5e4bdcSMarek Vasut 
865be5e4bdcSMarek Vasut 	if (req->req.length - req->req.actual == ep0_fifo_size) {
866be5e4bdcSMarek Vasut 		/* Next write will end with the packet size, */
867be5e4bdcSMarek Vasut 		/* so we need Zero-length-packet */
868be5e4bdcSMarek Vasut 		need_zlp = 1;
869be5e4bdcSMarek Vasut 	}
870be5e4bdcSMarek Vasut 
871be5e4bdcSMarek Vasut 	ret = write_fifo_ep0(ep, req);
872be5e4bdcSMarek Vasut 
873be5e4bdcSMarek Vasut 	if ((ret == 1) && !need_zlp) {
874be5e4bdcSMarek Vasut 		/* Last packet */
875be5e4bdcSMarek Vasut 		dev->ep0state = WAIT_FOR_COMPLETE;
876be5e4bdcSMarek Vasut 		debug_cond(DEBUG_EP0 != 0,
877be5e4bdcSMarek Vasut 			   "%s: finished, waiting for status\n", __func__);
878be5e4bdcSMarek Vasut 
879be5e4bdcSMarek Vasut 	} else {
880be5e4bdcSMarek Vasut 		dev->ep0state = DATA_STATE_XMIT;
881be5e4bdcSMarek Vasut 		debug_cond(DEBUG_EP0 != 0,
882be5e4bdcSMarek Vasut 			   "%s: not finished\n", __func__);
883be5e4bdcSMarek Vasut 	}
884be5e4bdcSMarek Vasut 
885be5e4bdcSMarek Vasut 	return 1;
886be5e4bdcSMarek Vasut }
887be5e4bdcSMarek Vasut 
dwc2_udc_get_status(struct dwc2_udc * dev,struct usb_ctrlrequest * crq)888be5e4bdcSMarek Vasut static int dwc2_udc_get_status(struct dwc2_udc *dev,
889be5e4bdcSMarek Vasut 		struct usb_ctrlrequest *crq)
890be5e4bdcSMarek Vasut {
891be5e4bdcSMarek Vasut 	u8 ep_num = crq->wIndex & 0x7F;
892be5e4bdcSMarek Vasut 	u16 g_status = 0;
893be5e4bdcSMarek Vasut 	u32 ep_ctrl;
894be5e4bdcSMarek Vasut 
895be5e4bdcSMarek Vasut 	debug_cond(DEBUG_SETUP != 0,
896be5e4bdcSMarek Vasut 		   "%s: *** USB_REQ_GET_STATUS\n", __func__);
897be5e4bdcSMarek Vasut 	printf("crq->brequest:0x%x\n", crq->bRequestType & USB_RECIP_MASK);
898be5e4bdcSMarek Vasut 	switch (crq->bRequestType & USB_RECIP_MASK) {
899be5e4bdcSMarek Vasut 	case USB_RECIP_INTERFACE:
900be5e4bdcSMarek Vasut 		g_status = 0;
901be5e4bdcSMarek Vasut 		debug_cond(DEBUG_SETUP != 0,
902be5e4bdcSMarek Vasut 			   "\tGET_STATUS:USB_RECIP_INTERFACE, g_stauts = %d\n",
903be5e4bdcSMarek Vasut 			   g_status);
904be5e4bdcSMarek Vasut 		break;
905be5e4bdcSMarek Vasut 
906be5e4bdcSMarek Vasut 	case USB_RECIP_DEVICE:
907be5e4bdcSMarek Vasut 		g_status = 0x1; /* Self powered */
908be5e4bdcSMarek Vasut 		debug_cond(DEBUG_SETUP != 0,
909be5e4bdcSMarek Vasut 			   "\tGET_STATUS: USB_RECIP_DEVICE, g_stauts = %d\n",
910be5e4bdcSMarek Vasut 			   g_status);
911be5e4bdcSMarek Vasut 		break;
912be5e4bdcSMarek Vasut 
913be5e4bdcSMarek Vasut 	case USB_RECIP_ENDPOINT:
914be5e4bdcSMarek Vasut 		if (crq->wLength > 2) {
915be5e4bdcSMarek Vasut 			debug_cond(DEBUG_SETUP != 0,
916be5e4bdcSMarek Vasut 				   "\tGET_STATUS:Not support EP or wLength\n");
917be5e4bdcSMarek Vasut 			return 1;
918be5e4bdcSMarek Vasut 		}
919be5e4bdcSMarek Vasut 
920be5e4bdcSMarek Vasut 		g_status = dev->ep[ep_num].stopped;
921be5e4bdcSMarek Vasut 		debug_cond(DEBUG_SETUP != 0,
922be5e4bdcSMarek Vasut 			   "\tGET_STATUS: USB_RECIP_ENDPOINT, g_stauts = %d\n",
923be5e4bdcSMarek Vasut 			   g_status);
924be5e4bdcSMarek Vasut 
925be5e4bdcSMarek Vasut 		break;
926be5e4bdcSMarek Vasut 
927be5e4bdcSMarek Vasut 	default:
928be5e4bdcSMarek Vasut 		return 1;
929be5e4bdcSMarek Vasut 	}
930be5e4bdcSMarek Vasut 
931be5e4bdcSMarek Vasut 	memcpy(usb_ctrl, &g_status, sizeof(g_status));
932be5e4bdcSMarek Vasut 
933be5e4bdcSMarek Vasut 	flush_dcache_range((unsigned long) usb_ctrl,
934be5e4bdcSMarek Vasut 			   (unsigned long) usb_ctrl +
935be5e4bdcSMarek Vasut 			   ROUND(sizeof(g_status), CONFIG_SYS_CACHELINE_SIZE));
936be5e4bdcSMarek Vasut 
937be5e4bdcSMarek Vasut 	writel(usb_ctrl_dma_addr, &reg->in_endp[EP0_CON].diepdma);
938be5e4bdcSMarek Vasut 	writel(DIEPT_SIZ_PKT_CNT(1) | DIEPT_SIZ_XFER_SIZE(2),
939be5e4bdcSMarek Vasut 	       &reg->in_endp[EP0_CON].dieptsiz);
940be5e4bdcSMarek Vasut 
941be5e4bdcSMarek Vasut 	ep_ctrl = readl(&reg->in_endp[EP0_CON].diepctl);
942be5e4bdcSMarek Vasut 	writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK,
943be5e4bdcSMarek Vasut 	       &reg->in_endp[EP0_CON].diepctl);
944be5e4bdcSMarek Vasut 	dev->ep0state = WAIT_FOR_NULL_COMPLETE;
945be5e4bdcSMarek Vasut 
946be5e4bdcSMarek Vasut 	return 0;
947be5e4bdcSMarek Vasut }
948be5e4bdcSMarek Vasut 
dwc2_udc_set_nak(struct dwc2_ep * ep)949be5e4bdcSMarek Vasut static void dwc2_udc_set_nak(struct dwc2_ep *ep)
950be5e4bdcSMarek Vasut {
951be5e4bdcSMarek Vasut 	u8		ep_num;
952be5e4bdcSMarek Vasut 	u32		ep_ctrl = 0;
953be5e4bdcSMarek Vasut 
954be5e4bdcSMarek Vasut 	ep_num = ep_index(ep);
955be5e4bdcSMarek Vasut 	debug("%s: ep_num = %d, ep_type = %d\n", __func__, ep_num, ep->ep_type);
956be5e4bdcSMarek Vasut 
957be5e4bdcSMarek Vasut 	if (ep_is_in(ep)) {
958be5e4bdcSMarek Vasut 		ep_ctrl = readl(&reg->in_endp[ep_num].diepctl);
959be5e4bdcSMarek Vasut 		ep_ctrl |= DEPCTL_SNAK;
960be5e4bdcSMarek Vasut 		writel(ep_ctrl, &reg->in_endp[ep_num].diepctl);
961be5e4bdcSMarek Vasut 		debug("%s: set NAK, DIEPCTL%d = 0x%x\n",
962be5e4bdcSMarek Vasut 			__func__, ep_num, readl(&reg->in_endp[ep_num].diepctl));
963be5e4bdcSMarek Vasut 	} else {
964be5e4bdcSMarek Vasut 		ep_ctrl = readl(&reg->out_endp[ep_num].doepctl);
965be5e4bdcSMarek Vasut 		ep_ctrl |= DEPCTL_SNAK;
966be5e4bdcSMarek Vasut 		writel(ep_ctrl, &reg->out_endp[ep_num].doepctl);
967be5e4bdcSMarek Vasut 		debug("%s: set NAK, DOEPCTL%d = 0x%x\n",
968be5e4bdcSMarek Vasut 		      __func__, ep_num, readl(&reg->out_endp[ep_num].doepctl));
969be5e4bdcSMarek Vasut 	}
970be5e4bdcSMarek Vasut 
971be5e4bdcSMarek Vasut 	return;
972be5e4bdcSMarek Vasut }
973be5e4bdcSMarek Vasut 
974be5e4bdcSMarek Vasut 
dwc2_udc_ep_set_stall(struct dwc2_ep * ep)975be5e4bdcSMarek Vasut static void dwc2_udc_ep_set_stall(struct dwc2_ep *ep)
976be5e4bdcSMarek Vasut {
977be5e4bdcSMarek Vasut 	u8		ep_num;
978be5e4bdcSMarek Vasut 	u32		ep_ctrl = 0;
979be5e4bdcSMarek Vasut 
980be5e4bdcSMarek Vasut 	ep_num = ep_index(ep);
981be5e4bdcSMarek Vasut 	debug("%s: ep_num = %d, ep_type = %d\n", __func__, ep_num, ep->ep_type);
982be5e4bdcSMarek Vasut 
983be5e4bdcSMarek Vasut 	if (ep_is_in(ep)) {
984be5e4bdcSMarek Vasut 		ep_ctrl = readl(&reg->in_endp[ep_num].diepctl);
985be5e4bdcSMarek Vasut 
986be5e4bdcSMarek Vasut 		/* set the disable and stall bits */
987be5e4bdcSMarek Vasut 		if (ep_ctrl & DEPCTL_EPENA)
988be5e4bdcSMarek Vasut 			ep_ctrl |= DEPCTL_EPDIS;
989be5e4bdcSMarek Vasut 
990be5e4bdcSMarek Vasut 		ep_ctrl |= DEPCTL_STALL;
991be5e4bdcSMarek Vasut 
992be5e4bdcSMarek Vasut 		writel(ep_ctrl, &reg->in_endp[ep_num].diepctl);
993be5e4bdcSMarek Vasut 		debug("%s: set stall, DIEPCTL%d = 0x%x\n",
994be5e4bdcSMarek Vasut 		      __func__, ep_num, readl(&reg->in_endp[ep_num].diepctl));
995be5e4bdcSMarek Vasut 
996be5e4bdcSMarek Vasut 	} else {
997be5e4bdcSMarek Vasut 		ep_ctrl = readl(&reg->out_endp[ep_num].doepctl);
998be5e4bdcSMarek Vasut 
999be5e4bdcSMarek Vasut 		/* set the stall bit */
1000be5e4bdcSMarek Vasut 		ep_ctrl |= DEPCTL_STALL;
1001be5e4bdcSMarek Vasut 
1002be5e4bdcSMarek Vasut 		writel(ep_ctrl, &reg->out_endp[ep_num].doepctl);
1003be5e4bdcSMarek Vasut 		debug("%s: set stall, DOEPCTL%d = 0x%x\n",
1004be5e4bdcSMarek Vasut 		      __func__, ep_num, readl(&reg->out_endp[ep_num].doepctl));
1005be5e4bdcSMarek Vasut 	}
1006be5e4bdcSMarek Vasut 
1007be5e4bdcSMarek Vasut 	return;
1008be5e4bdcSMarek Vasut }
1009be5e4bdcSMarek Vasut 
dwc2_udc_ep_clear_stall(struct dwc2_ep * ep)1010be5e4bdcSMarek Vasut static void dwc2_udc_ep_clear_stall(struct dwc2_ep *ep)
1011be5e4bdcSMarek Vasut {
1012be5e4bdcSMarek Vasut 	u8		ep_num;
1013be5e4bdcSMarek Vasut 	u32		ep_ctrl = 0;
1014be5e4bdcSMarek Vasut 
1015be5e4bdcSMarek Vasut 	ep_num = ep_index(ep);
1016be5e4bdcSMarek Vasut 	debug("%s: ep_num = %d, ep_type = %d\n", __func__, ep_num, ep->ep_type);
1017be5e4bdcSMarek Vasut 
1018be5e4bdcSMarek Vasut 	if (ep_is_in(ep)) {
1019be5e4bdcSMarek Vasut 		ep_ctrl = readl(&reg->in_endp[ep_num].diepctl);
1020be5e4bdcSMarek Vasut 
1021be5e4bdcSMarek Vasut 		/* clear stall bit */
1022be5e4bdcSMarek Vasut 		ep_ctrl &= ~DEPCTL_STALL;
1023be5e4bdcSMarek Vasut 
1024be5e4bdcSMarek Vasut 		/*
1025be5e4bdcSMarek Vasut 		 * USB Spec 9.4.5: For endpoints using data toggle, regardless
1026be5e4bdcSMarek Vasut 		 * of whether an endpoint has the Halt feature set, a
1027be5e4bdcSMarek Vasut 		 * ClearFeature(ENDPOINT_HALT) request always results in the
1028be5e4bdcSMarek Vasut 		 * data toggle being reinitialized to DATA0.
1029be5e4bdcSMarek Vasut 		 */
1030be5e4bdcSMarek Vasut 		if (ep->bmAttributes == USB_ENDPOINT_XFER_INT
1031be5e4bdcSMarek Vasut 		    || ep->bmAttributes == USB_ENDPOINT_XFER_BULK) {
1032be5e4bdcSMarek Vasut 			ep_ctrl |= DEPCTL_SETD0PID; /* DATA0 */
1033be5e4bdcSMarek Vasut 		}
1034be5e4bdcSMarek Vasut 
1035be5e4bdcSMarek Vasut 		writel(ep_ctrl, &reg->in_endp[ep_num].diepctl);
1036be5e4bdcSMarek Vasut 		debug("%s: cleared stall, DIEPCTL%d = 0x%x\n",
1037be5e4bdcSMarek Vasut 			__func__, ep_num, readl(&reg->in_endp[ep_num].diepctl));
1038be5e4bdcSMarek Vasut 
1039be5e4bdcSMarek Vasut 	} else {
1040be5e4bdcSMarek Vasut 		ep_ctrl = readl(&reg->out_endp[ep_num].doepctl);
1041be5e4bdcSMarek Vasut 
1042be5e4bdcSMarek Vasut 		/* clear stall bit */
1043be5e4bdcSMarek Vasut 		ep_ctrl &= ~DEPCTL_STALL;
1044be5e4bdcSMarek Vasut 
1045be5e4bdcSMarek Vasut 		if (ep->bmAttributes == USB_ENDPOINT_XFER_INT
1046be5e4bdcSMarek Vasut 		    || ep->bmAttributes == USB_ENDPOINT_XFER_BULK) {
1047be5e4bdcSMarek Vasut 			ep_ctrl |= DEPCTL_SETD0PID; /* DATA0 */
1048be5e4bdcSMarek Vasut 		}
1049be5e4bdcSMarek Vasut 
1050be5e4bdcSMarek Vasut 		writel(ep_ctrl, &reg->out_endp[ep_num].doepctl);
1051be5e4bdcSMarek Vasut 		debug("%s: cleared stall, DOEPCTL%d = 0x%x\n",
1052be5e4bdcSMarek Vasut 		      __func__, ep_num, readl(&reg->out_endp[ep_num].doepctl));
1053be5e4bdcSMarek Vasut 	}
1054be5e4bdcSMarek Vasut 
1055be5e4bdcSMarek Vasut 	return;
1056be5e4bdcSMarek Vasut }
1057be5e4bdcSMarek Vasut 
dwc2_udc_set_halt(struct usb_ep * _ep,int value)1058be5e4bdcSMarek Vasut static int dwc2_udc_set_halt(struct usb_ep *_ep, int value)
1059be5e4bdcSMarek Vasut {
1060be5e4bdcSMarek Vasut 	struct dwc2_ep	*ep;
1061be5e4bdcSMarek Vasut 	struct dwc2_udc	*dev;
1062be5e4bdcSMarek Vasut 	unsigned long	flags = 0;
1063be5e4bdcSMarek Vasut 	u8		ep_num;
1064be5e4bdcSMarek Vasut 
1065be5e4bdcSMarek Vasut 	ep = container_of(_ep, struct dwc2_ep, ep);
1066be5e4bdcSMarek Vasut 	ep_num = ep_index(ep);
1067be5e4bdcSMarek Vasut 
1068be5e4bdcSMarek Vasut 	if (unlikely(!_ep || !ep->desc || ep_num == EP0_CON ||
1069be5e4bdcSMarek Vasut 		     ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC)) {
1070be5e4bdcSMarek Vasut 		debug("%s: %s bad ep or descriptor\n", __func__, ep->ep.name);
1071be5e4bdcSMarek Vasut 		return -EINVAL;
1072be5e4bdcSMarek Vasut 	}
1073be5e4bdcSMarek Vasut 
1074be5e4bdcSMarek Vasut 	/* Attempt to halt IN ep will fail if any transfer requests
1075be5e4bdcSMarek Vasut 	 * are still queue */
1076be5e4bdcSMarek Vasut 	if (value && ep_is_in(ep) && !list_empty(&ep->queue)) {
1077be5e4bdcSMarek Vasut 		debug("%s: %s queue not empty, req = %p\n",
1078be5e4bdcSMarek Vasut 			__func__, ep->ep.name,
1079be5e4bdcSMarek Vasut 			list_entry(ep->queue.next, struct dwc2_request, queue));
1080be5e4bdcSMarek Vasut 
1081be5e4bdcSMarek Vasut 		return -EAGAIN;
1082be5e4bdcSMarek Vasut 	}
1083be5e4bdcSMarek Vasut 
1084be5e4bdcSMarek Vasut 	dev = ep->dev;
1085be5e4bdcSMarek Vasut 	debug("%s: ep_num = %d, value = %d\n", __func__, ep_num, value);
1086be5e4bdcSMarek Vasut 
1087be5e4bdcSMarek Vasut 	spin_lock_irqsave(&dev->lock, flags);
1088be5e4bdcSMarek Vasut 
1089be5e4bdcSMarek Vasut 	if (value == 0) {
1090be5e4bdcSMarek Vasut 		ep->stopped = 0;
1091be5e4bdcSMarek Vasut 		dwc2_udc_ep_clear_stall(ep);
1092be5e4bdcSMarek Vasut 	} else {
1093be5e4bdcSMarek Vasut 		if (ep_num == 0)
1094be5e4bdcSMarek Vasut 			dev->ep0state = WAIT_FOR_SETUP;
1095be5e4bdcSMarek Vasut 
1096be5e4bdcSMarek Vasut 		ep->stopped = 1;
1097be5e4bdcSMarek Vasut 		dwc2_udc_ep_set_stall(ep);
1098be5e4bdcSMarek Vasut 	}
1099be5e4bdcSMarek Vasut 
1100be5e4bdcSMarek Vasut 	spin_unlock_irqrestore(&dev->lock, flags);
1101be5e4bdcSMarek Vasut 
1102be5e4bdcSMarek Vasut 	return 0;
1103be5e4bdcSMarek Vasut }
1104be5e4bdcSMarek Vasut 
dwc2_udc_ep_activate(struct dwc2_ep * ep)1105be5e4bdcSMarek Vasut static void dwc2_udc_ep_activate(struct dwc2_ep *ep)
1106be5e4bdcSMarek Vasut {
1107be5e4bdcSMarek Vasut 	u8 ep_num;
1108be5e4bdcSMarek Vasut 	u32 ep_ctrl = 0, daintmsk = 0;
1109be5e4bdcSMarek Vasut 
1110be5e4bdcSMarek Vasut 	ep_num = ep_index(ep);
1111be5e4bdcSMarek Vasut 
1112be5e4bdcSMarek Vasut 	/* Read DEPCTLn register */
1113be5e4bdcSMarek Vasut 	if (ep_is_in(ep)) {
1114be5e4bdcSMarek Vasut 		ep_ctrl = readl(&reg->in_endp[ep_num].diepctl);
1115be5e4bdcSMarek Vasut 		daintmsk = 1 << ep_num;
1116be5e4bdcSMarek Vasut 	} else {
1117be5e4bdcSMarek Vasut 		ep_ctrl = readl(&reg->out_endp[ep_num].doepctl);
1118be5e4bdcSMarek Vasut 		daintmsk = (1 << ep_num) << DAINT_OUT_BIT;
1119be5e4bdcSMarek Vasut 	}
1120be5e4bdcSMarek Vasut 
1121be5e4bdcSMarek Vasut 	debug("%s: EPCTRL%d = 0x%x, ep_is_in = %d\n",
1122be5e4bdcSMarek Vasut 		__func__, ep_num, ep_ctrl, ep_is_in(ep));
1123be5e4bdcSMarek Vasut 
1124be5e4bdcSMarek Vasut 	/* If the EP is already active don't change the EP Control
1125be5e4bdcSMarek Vasut 	 * register. */
1126be5e4bdcSMarek Vasut 	if (!(ep_ctrl & DEPCTL_USBACTEP)) {
1127be5e4bdcSMarek Vasut 		ep_ctrl = (ep_ctrl & ~DEPCTL_TYPE_MASK) |
1128be5e4bdcSMarek Vasut 			(ep->bmAttributes << DEPCTL_TYPE_BIT);
1129be5e4bdcSMarek Vasut 		ep_ctrl = (ep_ctrl & ~DEPCTL_MPS_MASK) |
1130be5e4bdcSMarek Vasut 			(ep->ep.maxpacket << DEPCTL_MPS_BIT);
1131be5e4bdcSMarek Vasut 		ep_ctrl |= (DEPCTL_SETD0PID | DEPCTL_USBACTEP | DEPCTL_SNAK);
1132be5e4bdcSMarek Vasut 
1133be5e4bdcSMarek Vasut 		if (ep_is_in(ep)) {
1134be5e4bdcSMarek Vasut 			writel(ep_ctrl, &reg->in_endp[ep_num].diepctl);
1135be5e4bdcSMarek Vasut 			debug("%s: USB Ative EP%d, DIEPCTRL%d = 0x%x\n",
1136be5e4bdcSMarek Vasut 			      __func__, ep_num, ep_num,
1137be5e4bdcSMarek Vasut 			      readl(&reg->in_endp[ep_num].diepctl));
1138be5e4bdcSMarek Vasut 		} else {
1139be5e4bdcSMarek Vasut 			writel(ep_ctrl, &reg->out_endp[ep_num].doepctl);
1140be5e4bdcSMarek Vasut 			debug("%s: USB Ative EP%d, DOEPCTRL%d = 0x%x\n",
1141be5e4bdcSMarek Vasut 			      __func__, ep_num, ep_num,
1142be5e4bdcSMarek Vasut 			      readl(&reg->out_endp[ep_num].doepctl));
1143be5e4bdcSMarek Vasut 		}
1144be5e4bdcSMarek Vasut 	}
1145be5e4bdcSMarek Vasut 
1146be5e4bdcSMarek Vasut 	/* Unmask EP Interrtupt */
1147be5e4bdcSMarek Vasut 	writel(readl(&reg->daintmsk)|daintmsk, &reg->daintmsk);
1148be5e4bdcSMarek Vasut 	debug("%s: DAINTMSK = 0x%x\n", __func__, readl(&reg->daintmsk));
1149be5e4bdcSMarek Vasut 
1150be5e4bdcSMarek Vasut }
1151be5e4bdcSMarek Vasut 
dwc2_udc_clear_feature(struct usb_ep * _ep)1152be5e4bdcSMarek Vasut static int dwc2_udc_clear_feature(struct usb_ep *_ep)
1153be5e4bdcSMarek Vasut {
1154be5e4bdcSMarek Vasut 	struct dwc2_udc	*dev;
1155be5e4bdcSMarek Vasut 	struct dwc2_ep	*ep;
1156be5e4bdcSMarek Vasut 	u8		ep_num;
1157be5e4bdcSMarek Vasut 
1158be5e4bdcSMarek Vasut 	ep = container_of(_ep, struct dwc2_ep, ep);
1159be5e4bdcSMarek Vasut 	ep_num = ep_index(ep);
1160be5e4bdcSMarek Vasut 
1161be5e4bdcSMarek Vasut 	dev = ep->dev;
1162be5e4bdcSMarek Vasut 	debug_cond(DEBUG_SETUP != 0,
1163be5e4bdcSMarek Vasut 		   "%s: ep_num = %d, is_in = %d, clear_feature_flag = %d\n",
1164be5e4bdcSMarek Vasut 		   __func__, ep_num, ep_is_in(ep), clear_feature_flag);
1165be5e4bdcSMarek Vasut 
1166be5e4bdcSMarek Vasut 	if (usb_ctrl->wLength != 0) {
1167be5e4bdcSMarek Vasut 		debug_cond(DEBUG_SETUP != 0,
1168be5e4bdcSMarek Vasut 			   "\tCLEAR_FEATURE: wLength is not zero.....\n");
1169be5e4bdcSMarek Vasut 		return 1;
1170be5e4bdcSMarek Vasut 	}
1171be5e4bdcSMarek Vasut 
1172be5e4bdcSMarek Vasut 	switch (usb_ctrl->bRequestType & USB_RECIP_MASK) {
1173be5e4bdcSMarek Vasut 	case USB_RECIP_DEVICE:
1174be5e4bdcSMarek Vasut 		switch (usb_ctrl->wValue) {
1175be5e4bdcSMarek Vasut 		case USB_DEVICE_REMOTE_WAKEUP:
1176be5e4bdcSMarek Vasut 			debug_cond(DEBUG_SETUP != 0,
1177be5e4bdcSMarek Vasut 				   "\tOFF:USB_DEVICE_REMOTE_WAKEUP\n");
1178be5e4bdcSMarek Vasut 			break;
1179be5e4bdcSMarek Vasut 
1180be5e4bdcSMarek Vasut 		case USB_DEVICE_TEST_MODE:
1181be5e4bdcSMarek Vasut 			debug_cond(DEBUG_SETUP != 0,
1182be5e4bdcSMarek Vasut 				   "\tCLEAR_FEATURE: USB_DEVICE_TEST_MODE\n");
1183be5e4bdcSMarek Vasut 			/** @todo Add CLEAR_FEATURE for TEST modes. */
1184be5e4bdcSMarek Vasut 			break;
1185be5e4bdcSMarek Vasut 		}
1186be5e4bdcSMarek Vasut 
1187be5e4bdcSMarek Vasut 		dwc2_udc_ep0_zlp(dev);
1188be5e4bdcSMarek Vasut 		break;
1189be5e4bdcSMarek Vasut 
1190be5e4bdcSMarek Vasut 	case USB_RECIP_ENDPOINT:
1191be5e4bdcSMarek Vasut 		debug_cond(DEBUG_SETUP != 0,
1192be5e4bdcSMarek Vasut 			   "\tCLEAR_FEATURE:USB_RECIP_ENDPOINT, wValue = %d\n",
1193be5e4bdcSMarek Vasut 			   usb_ctrl->wValue);
1194be5e4bdcSMarek Vasut 
1195be5e4bdcSMarek Vasut 		if (usb_ctrl->wValue == USB_ENDPOINT_HALT) {
1196be5e4bdcSMarek Vasut 			if (ep_num == 0) {
1197be5e4bdcSMarek Vasut 				dwc2_udc_ep0_set_stall(ep);
1198be5e4bdcSMarek Vasut 				return 0;
1199be5e4bdcSMarek Vasut 			}
1200be5e4bdcSMarek Vasut 
1201be5e4bdcSMarek Vasut 			dwc2_udc_ep0_zlp(dev);
1202be5e4bdcSMarek Vasut 
1203be5e4bdcSMarek Vasut 			dwc2_udc_ep_clear_stall(ep);
1204be5e4bdcSMarek Vasut 			dwc2_udc_ep_activate(ep);
1205be5e4bdcSMarek Vasut 			ep->stopped = 0;
1206be5e4bdcSMarek Vasut 
1207be5e4bdcSMarek Vasut 			clear_feature_num = ep_num;
1208be5e4bdcSMarek Vasut 			clear_feature_flag = 1;
1209be5e4bdcSMarek Vasut 		}
1210be5e4bdcSMarek Vasut 		break;
1211be5e4bdcSMarek Vasut 	}
1212be5e4bdcSMarek Vasut 
1213be5e4bdcSMarek Vasut 	return 0;
1214be5e4bdcSMarek Vasut }
1215be5e4bdcSMarek Vasut 
dwc2_udc_set_feature(struct usb_ep * _ep)1216be5e4bdcSMarek Vasut static int dwc2_udc_set_feature(struct usb_ep *_ep)
1217be5e4bdcSMarek Vasut {
1218be5e4bdcSMarek Vasut 	struct dwc2_udc	*dev;
1219be5e4bdcSMarek Vasut 	struct dwc2_ep	*ep;
1220be5e4bdcSMarek Vasut 	u8		ep_num;
1221be5e4bdcSMarek Vasut 
1222be5e4bdcSMarek Vasut 	ep = container_of(_ep, struct dwc2_ep, ep);
1223be5e4bdcSMarek Vasut 	ep_num = ep_index(ep);
1224be5e4bdcSMarek Vasut 	dev = ep->dev;
1225be5e4bdcSMarek Vasut 
1226be5e4bdcSMarek Vasut 	debug_cond(DEBUG_SETUP != 0,
1227be5e4bdcSMarek Vasut 		   "%s: *** USB_REQ_SET_FEATURE , ep_num = %d\n",
1228be5e4bdcSMarek Vasut 		    __func__, ep_num);
1229be5e4bdcSMarek Vasut 
1230be5e4bdcSMarek Vasut 	if (usb_ctrl->wLength != 0) {
1231be5e4bdcSMarek Vasut 		debug_cond(DEBUG_SETUP != 0,
1232be5e4bdcSMarek Vasut 			   "\tSET_FEATURE: wLength is not zero.....\n");
1233be5e4bdcSMarek Vasut 		return 1;
1234be5e4bdcSMarek Vasut 	}
1235be5e4bdcSMarek Vasut 
1236be5e4bdcSMarek Vasut 	switch (usb_ctrl->bRequestType & USB_RECIP_MASK) {
1237be5e4bdcSMarek Vasut 	case USB_RECIP_DEVICE:
1238be5e4bdcSMarek Vasut 		switch (usb_ctrl->wValue) {
1239be5e4bdcSMarek Vasut 		case USB_DEVICE_REMOTE_WAKEUP:
1240be5e4bdcSMarek Vasut 			debug_cond(DEBUG_SETUP != 0,
1241be5e4bdcSMarek Vasut 				   "\tSET_FEATURE:USB_DEVICE_REMOTE_WAKEUP\n");
1242be5e4bdcSMarek Vasut 			break;
1243be5e4bdcSMarek Vasut 		case USB_DEVICE_B_HNP_ENABLE:
1244be5e4bdcSMarek Vasut 			debug_cond(DEBUG_SETUP != 0,
1245be5e4bdcSMarek Vasut 				   "\tSET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n");
1246be5e4bdcSMarek Vasut 			break;
1247be5e4bdcSMarek Vasut 
1248be5e4bdcSMarek Vasut 		case USB_DEVICE_A_HNP_SUPPORT:
1249be5e4bdcSMarek Vasut 			/* RH port supports HNP */
1250be5e4bdcSMarek Vasut 			debug_cond(DEBUG_SETUP != 0,
1251be5e4bdcSMarek Vasut 				   "\tSET_FEATURE:USB_DEVICE_A_HNP_SUPPORT\n");
1252be5e4bdcSMarek Vasut 			break;
1253be5e4bdcSMarek Vasut 
1254be5e4bdcSMarek Vasut 		case USB_DEVICE_A_ALT_HNP_SUPPORT:
1255be5e4bdcSMarek Vasut 			/* other RH port does */
1256be5e4bdcSMarek Vasut 			debug_cond(DEBUG_SETUP != 0,
1257be5e4bdcSMarek Vasut 				   "\tSET: USB_DEVICE_A_ALT_HNP_SUPPORT\n");
1258be5e4bdcSMarek Vasut 			break;
1259be5e4bdcSMarek Vasut 		}
1260be5e4bdcSMarek Vasut 
1261be5e4bdcSMarek Vasut 		dwc2_udc_ep0_zlp(dev);
1262be5e4bdcSMarek Vasut 		return 0;
1263be5e4bdcSMarek Vasut 
1264be5e4bdcSMarek Vasut 	case USB_RECIP_INTERFACE:
1265be5e4bdcSMarek Vasut 		debug_cond(DEBUG_SETUP != 0,
1266be5e4bdcSMarek Vasut 			   "\tSET_FEATURE: USB_RECIP_INTERFACE\n");
1267be5e4bdcSMarek Vasut 		break;
1268be5e4bdcSMarek Vasut 
1269be5e4bdcSMarek Vasut 	case USB_RECIP_ENDPOINT:
1270be5e4bdcSMarek Vasut 		debug_cond(DEBUG_SETUP != 0,
1271be5e4bdcSMarek Vasut 			   "\tSET_FEATURE: USB_RECIP_ENDPOINT\n");
1272be5e4bdcSMarek Vasut 		if (usb_ctrl->wValue == USB_ENDPOINT_HALT) {
1273be5e4bdcSMarek Vasut 			if (ep_num == 0) {
1274be5e4bdcSMarek Vasut 				dwc2_udc_ep0_set_stall(ep);
1275be5e4bdcSMarek Vasut 				return 0;
1276be5e4bdcSMarek Vasut 			}
1277be5e4bdcSMarek Vasut 			ep->stopped = 1;
1278be5e4bdcSMarek Vasut 			dwc2_udc_ep_set_stall(ep);
1279be5e4bdcSMarek Vasut 		}
1280be5e4bdcSMarek Vasut 
1281be5e4bdcSMarek Vasut 		dwc2_udc_ep0_zlp(dev);
1282be5e4bdcSMarek Vasut 		return 0;
1283be5e4bdcSMarek Vasut 	}
1284be5e4bdcSMarek Vasut 
1285be5e4bdcSMarek Vasut 	return 1;
1286be5e4bdcSMarek Vasut }
1287be5e4bdcSMarek Vasut 
1288be5e4bdcSMarek Vasut /*
1289be5e4bdcSMarek Vasut  * WAIT_FOR_SETUP (OUT_PKT_RDY)
1290be5e4bdcSMarek Vasut  */
dwc2_ep0_setup(struct dwc2_udc * dev)1291be5e4bdcSMarek Vasut static void dwc2_ep0_setup(struct dwc2_udc *dev)
1292be5e4bdcSMarek Vasut {
1293be5e4bdcSMarek Vasut 	struct dwc2_ep *ep = &dev->ep[0];
1294be5e4bdcSMarek Vasut 	int i;
1295be5e4bdcSMarek Vasut 	u8 ep_num;
1296be5e4bdcSMarek Vasut 
1297be5e4bdcSMarek Vasut 	/* Nuke all previous transfers */
1298be5e4bdcSMarek Vasut 	nuke(ep, -EPROTO);
1299be5e4bdcSMarek Vasut 
1300be5e4bdcSMarek Vasut 	/* read control req from fifo (8 bytes) */
13017808becdSSimon Goldschmidt 	dwc2_fifo_read(ep, usb_ctrl, 8);
1302be5e4bdcSMarek Vasut 
1303be5e4bdcSMarek Vasut 	debug_cond(DEBUG_SETUP != 0,
1304be5e4bdcSMarek Vasut 		   "%s: bRequestType = 0x%x(%s), bRequest = 0x%x"
1305be5e4bdcSMarek Vasut 		   "\twLength = 0x%x, wValue = 0x%x, wIndex= 0x%x\n",
1306be5e4bdcSMarek Vasut 		   __func__, usb_ctrl->bRequestType,
1307be5e4bdcSMarek Vasut 		   (usb_ctrl->bRequestType & USB_DIR_IN) ? "IN" : "OUT",
1308be5e4bdcSMarek Vasut 		   usb_ctrl->bRequest,
1309be5e4bdcSMarek Vasut 		   usb_ctrl->wLength, usb_ctrl->wValue, usb_ctrl->wIndex);
1310be5e4bdcSMarek Vasut 
1311be5e4bdcSMarek Vasut #ifdef DEBUG
1312be5e4bdcSMarek Vasut 	{
1313be5e4bdcSMarek Vasut 		int i, len = sizeof(*usb_ctrl);
1314be5e4bdcSMarek Vasut 		char *p = (char *)usb_ctrl;
1315be5e4bdcSMarek Vasut 
1316be5e4bdcSMarek Vasut 		printf("pkt = ");
1317be5e4bdcSMarek Vasut 		for (i = 0; i < len; i++) {
1318be5e4bdcSMarek Vasut 			printf("%02x", ((u8 *)p)[i]);
1319be5e4bdcSMarek Vasut 			if ((i & 7) == 7)
1320be5e4bdcSMarek Vasut 				printf(" ");
1321be5e4bdcSMarek Vasut 		}
1322be5e4bdcSMarek Vasut 		printf("\n");
1323be5e4bdcSMarek Vasut 	}
1324be5e4bdcSMarek Vasut #endif
1325be5e4bdcSMarek Vasut 
1326be5e4bdcSMarek Vasut 	if (usb_ctrl->bRequest == GET_MAX_LUN_REQUEST &&
1327be5e4bdcSMarek Vasut 	    usb_ctrl->wLength != 1) {
1328be5e4bdcSMarek Vasut 		debug_cond(DEBUG_SETUP != 0,
1329be5e4bdcSMarek Vasut 			   "\t%s:GET_MAX_LUN_REQUEST:invalid",
1330be5e4bdcSMarek Vasut 			   __func__);
1331be5e4bdcSMarek Vasut 		debug_cond(DEBUG_SETUP != 0,
1332be5e4bdcSMarek Vasut 			   "wLength = %d, setup returned\n",
1333be5e4bdcSMarek Vasut 			   usb_ctrl->wLength);
1334be5e4bdcSMarek Vasut 
1335be5e4bdcSMarek Vasut 		dwc2_udc_ep0_set_stall(ep);
1336be5e4bdcSMarek Vasut 		dev->ep0state = WAIT_FOR_SETUP;
1337be5e4bdcSMarek Vasut 
1338be5e4bdcSMarek Vasut 		return;
1339be5e4bdcSMarek Vasut 	} else if (usb_ctrl->bRequest == BOT_RESET_REQUEST &&
1340be5e4bdcSMarek Vasut 		 usb_ctrl->wLength != 0) {
1341be5e4bdcSMarek Vasut 		/* Bulk-Only *mass storge reset of class-specific request */
1342be5e4bdcSMarek Vasut 		debug_cond(DEBUG_SETUP != 0,
1343be5e4bdcSMarek Vasut 			   "%s:BOT Rest:invalid wLength =%d, setup returned\n",
1344be5e4bdcSMarek Vasut 			   __func__, usb_ctrl->wLength);
1345be5e4bdcSMarek Vasut 
1346be5e4bdcSMarek Vasut 		dwc2_udc_ep0_set_stall(ep);
1347be5e4bdcSMarek Vasut 		dev->ep0state = WAIT_FOR_SETUP;
1348be5e4bdcSMarek Vasut 
1349be5e4bdcSMarek Vasut 		return;
1350be5e4bdcSMarek Vasut 	}
1351be5e4bdcSMarek Vasut 
1352be5e4bdcSMarek Vasut 	/* Set direction of EP0 */
1353be5e4bdcSMarek Vasut 	if (likely(usb_ctrl->bRequestType & USB_DIR_IN)) {
1354be5e4bdcSMarek Vasut 		ep->bEndpointAddress |= USB_DIR_IN;
1355be5e4bdcSMarek Vasut 	} else {
1356be5e4bdcSMarek Vasut 		ep->bEndpointAddress &= ~USB_DIR_IN;
1357be5e4bdcSMarek Vasut 	}
1358be5e4bdcSMarek Vasut 	/* cope with automagic for some standard requests. */
1359be5e4bdcSMarek Vasut 	dev->req_std = (usb_ctrl->bRequestType & USB_TYPE_MASK)
1360be5e4bdcSMarek Vasut 		== USB_TYPE_STANDARD;
1361be5e4bdcSMarek Vasut 
1362be5e4bdcSMarek Vasut 	dev->req_pending = 1;
1363be5e4bdcSMarek Vasut 
1364be5e4bdcSMarek Vasut 	/* Handle some SETUP packets ourselves */
1365be5e4bdcSMarek Vasut 	if (dev->req_std) {
1366be5e4bdcSMarek Vasut 		switch (usb_ctrl->bRequest) {
1367be5e4bdcSMarek Vasut 		case USB_REQ_SET_ADDRESS:
1368be5e4bdcSMarek Vasut 		debug_cond(DEBUG_SETUP != 0,
1369be5e4bdcSMarek Vasut 			   "%s: *** USB_REQ_SET_ADDRESS (%d)\n",
1370be5e4bdcSMarek Vasut 			   __func__, usb_ctrl->wValue);
1371be5e4bdcSMarek Vasut 			if (usb_ctrl->bRequestType
1372be5e4bdcSMarek Vasut 				!= (USB_TYPE_STANDARD | USB_RECIP_DEVICE))
1373be5e4bdcSMarek Vasut 				break;
1374a52e8dd4SFrank Wang 			dev->connected = 1;
1375be5e4bdcSMarek Vasut 			udc_set_address(dev, usb_ctrl->wValue);
1376be5e4bdcSMarek Vasut 			return;
1377be5e4bdcSMarek Vasut 
1378be5e4bdcSMarek Vasut 		case USB_REQ_SET_CONFIGURATION:
1379be5e4bdcSMarek Vasut 			debug_cond(DEBUG_SETUP != 0,
1380be5e4bdcSMarek Vasut 				   "=====================================\n");
1381be5e4bdcSMarek Vasut 			debug_cond(DEBUG_SETUP != 0,
1382be5e4bdcSMarek Vasut 				   "%s: USB_REQ_SET_CONFIGURATION (%d)\n",
1383be5e4bdcSMarek Vasut 				   __func__, usb_ctrl->wValue);
1384be5e4bdcSMarek Vasut 
1385be5e4bdcSMarek Vasut 			if (usb_ctrl->bRequestType == USB_RECIP_DEVICE)
1386be5e4bdcSMarek Vasut 				reset_available = 1;
1387be5e4bdcSMarek Vasut 
1388be5e4bdcSMarek Vasut 			break;
1389be5e4bdcSMarek Vasut 
1390be5e4bdcSMarek Vasut 		case USB_REQ_GET_DESCRIPTOR:
1391be5e4bdcSMarek Vasut 			debug_cond(DEBUG_SETUP != 0,
1392be5e4bdcSMarek Vasut 				   "%s: *** USB_REQ_GET_DESCRIPTOR\n",
1393be5e4bdcSMarek Vasut 				   __func__);
1394be5e4bdcSMarek Vasut 			break;
1395be5e4bdcSMarek Vasut 
1396be5e4bdcSMarek Vasut 		case USB_REQ_SET_INTERFACE:
1397be5e4bdcSMarek Vasut 			debug_cond(DEBUG_SETUP != 0,
1398be5e4bdcSMarek Vasut 				   "%s: *** USB_REQ_SET_INTERFACE (%d)\n",
1399be5e4bdcSMarek Vasut 				   __func__, usb_ctrl->wValue);
1400be5e4bdcSMarek Vasut 
1401be5e4bdcSMarek Vasut 			if (usb_ctrl->bRequestType == USB_RECIP_INTERFACE)
1402be5e4bdcSMarek Vasut 				reset_available = 1;
1403be5e4bdcSMarek Vasut 
1404be5e4bdcSMarek Vasut 			break;
1405be5e4bdcSMarek Vasut 
1406be5e4bdcSMarek Vasut 		case USB_REQ_GET_CONFIGURATION:
1407be5e4bdcSMarek Vasut 			debug_cond(DEBUG_SETUP != 0,
1408be5e4bdcSMarek Vasut 				   "%s: *** USB_REQ_GET_CONFIGURATION\n",
1409be5e4bdcSMarek Vasut 				   __func__);
1410be5e4bdcSMarek Vasut 			break;
1411be5e4bdcSMarek Vasut 
1412be5e4bdcSMarek Vasut 		case USB_REQ_GET_STATUS:
1413be5e4bdcSMarek Vasut 			if (!dwc2_udc_get_status(dev, usb_ctrl))
1414be5e4bdcSMarek Vasut 				return;
1415be5e4bdcSMarek Vasut 
1416be5e4bdcSMarek Vasut 			break;
1417be5e4bdcSMarek Vasut 
1418be5e4bdcSMarek Vasut 		case USB_REQ_CLEAR_FEATURE:
1419be5e4bdcSMarek Vasut 			ep_num = usb_ctrl->wIndex & 0x7f;
1420be5e4bdcSMarek Vasut 
1421be5e4bdcSMarek Vasut 			if (!dwc2_udc_clear_feature(&dev->ep[ep_num].ep))
1422be5e4bdcSMarek Vasut 				return;
1423be5e4bdcSMarek Vasut 
1424be5e4bdcSMarek Vasut 			break;
1425be5e4bdcSMarek Vasut 
1426be5e4bdcSMarek Vasut 		case USB_REQ_SET_FEATURE:
1427be5e4bdcSMarek Vasut 			ep_num = usb_ctrl->wIndex & 0x7f;
1428be5e4bdcSMarek Vasut 
1429be5e4bdcSMarek Vasut 			if (!dwc2_udc_set_feature(&dev->ep[ep_num].ep))
1430be5e4bdcSMarek Vasut 				return;
1431be5e4bdcSMarek Vasut 
1432be5e4bdcSMarek Vasut 			break;
1433be5e4bdcSMarek Vasut 
1434be5e4bdcSMarek Vasut 		default:
1435be5e4bdcSMarek Vasut 			debug_cond(DEBUG_SETUP != 0,
1436be5e4bdcSMarek Vasut 				   "%s: *** Default of usb_ctrl->bRequest=0x%x"
1437be5e4bdcSMarek Vasut 				   "happened.\n", __func__, usb_ctrl->bRequest);
1438be5e4bdcSMarek Vasut 			break;
1439be5e4bdcSMarek Vasut 		}
1440be5e4bdcSMarek Vasut 	}
1441be5e4bdcSMarek Vasut 
1442be5e4bdcSMarek Vasut 
1443be5e4bdcSMarek Vasut 	if (likely(dev->driver)) {
1444be5e4bdcSMarek Vasut 		/* device-2-host (IN) or no data setup command,
1445be5e4bdcSMarek Vasut 		 * process immediately */
1446be5e4bdcSMarek Vasut 		debug_cond(DEBUG_SETUP != 0,
1447be5e4bdcSMarek Vasut 			   "%s:usb_ctrlreq will be passed to fsg_setup()\n",
1448be5e4bdcSMarek Vasut 			    __func__);
1449be5e4bdcSMarek Vasut 
1450be5e4bdcSMarek Vasut 		spin_unlock(&dev->lock);
1451be5e4bdcSMarek Vasut 		i = dev->driver->setup(&dev->gadget, usb_ctrl);
1452be5e4bdcSMarek Vasut 		spin_lock(&dev->lock);
1453be5e4bdcSMarek Vasut 
1454be5e4bdcSMarek Vasut 		if (i < 0) {
1455be5e4bdcSMarek Vasut 			/* setup processing failed, force stall */
1456be5e4bdcSMarek Vasut 			dwc2_udc_ep0_set_stall(ep);
1457be5e4bdcSMarek Vasut 			dev->ep0state = WAIT_FOR_SETUP;
1458be5e4bdcSMarek Vasut 
1459be5e4bdcSMarek Vasut 			debug_cond(DEBUG_SETUP != 0,
1460be5e4bdcSMarek Vasut 				   "\tdev->driver->setup failed (%d),"
1461be5e4bdcSMarek Vasut 				    " bRequest = %d\n",
1462be5e4bdcSMarek Vasut 				i, usb_ctrl->bRequest);
1463be5e4bdcSMarek Vasut 
1464be5e4bdcSMarek Vasut 
1465be5e4bdcSMarek Vasut 		} else if (dev->req_pending) {
1466be5e4bdcSMarek Vasut 			dev->req_pending = 0;
1467be5e4bdcSMarek Vasut 			debug_cond(DEBUG_SETUP != 0,
1468be5e4bdcSMarek Vasut 				   "\tdev->req_pending...\n");
1469be5e4bdcSMarek Vasut 		}
1470be5e4bdcSMarek Vasut 
1471be5e4bdcSMarek Vasut 		debug_cond(DEBUG_SETUP != 0,
1472be5e4bdcSMarek Vasut 			   "\tep0state = %s\n", state_names[dev->ep0state]);
1473be5e4bdcSMarek Vasut 
1474be5e4bdcSMarek Vasut 	}
1475be5e4bdcSMarek Vasut }
1476be5e4bdcSMarek Vasut 
1477be5e4bdcSMarek Vasut /*
1478be5e4bdcSMarek Vasut  * handle ep0 interrupt
1479be5e4bdcSMarek Vasut  */
dwc2_handle_ep0(struct dwc2_udc * dev)1480be5e4bdcSMarek Vasut static void dwc2_handle_ep0(struct dwc2_udc *dev)
1481be5e4bdcSMarek Vasut {
1482be5e4bdcSMarek Vasut 	if (dev->ep0state == WAIT_FOR_SETUP) {
1483be5e4bdcSMarek Vasut 		debug_cond(DEBUG_OUT_EP != 0,
1484be5e4bdcSMarek Vasut 			   "%s: WAIT_FOR_SETUP\n", __func__);
1485be5e4bdcSMarek Vasut 		dwc2_ep0_setup(dev);
1486be5e4bdcSMarek Vasut 
1487be5e4bdcSMarek Vasut 	} else {
1488be5e4bdcSMarek Vasut 		debug_cond(DEBUG_OUT_EP != 0,
1489be5e4bdcSMarek Vasut 			   "%s: strange state!!(state = %s)\n",
1490be5e4bdcSMarek Vasut 			__func__, state_names[dev->ep0state]);
1491be5e4bdcSMarek Vasut 	}
1492be5e4bdcSMarek Vasut }
1493be5e4bdcSMarek Vasut 
dwc2_ep0_kick(struct dwc2_udc * dev,struct dwc2_ep * ep)1494be5e4bdcSMarek Vasut static void dwc2_ep0_kick(struct dwc2_udc *dev, struct dwc2_ep *ep)
1495be5e4bdcSMarek Vasut {
1496be5e4bdcSMarek Vasut 	debug_cond(DEBUG_EP0 != 0,
1497be5e4bdcSMarek Vasut 		   "%s: ep_is_in = %d\n", __func__, ep_is_in(ep));
1498be5e4bdcSMarek Vasut 	if (ep_is_in(ep)) {
1499be5e4bdcSMarek Vasut 		dev->ep0state = DATA_STATE_XMIT;
1500be5e4bdcSMarek Vasut 		dwc2_ep0_write(dev);
1501be5e4bdcSMarek Vasut 
1502be5e4bdcSMarek Vasut 	} else {
1503be5e4bdcSMarek Vasut 		dev->ep0state = DATA_STATE_RECV;
1504be5e4bdcSMarek Vasut 		dwc2_ep0_read(dev);
1505be5e4bdcSMarek Vasut 	}
1506be5e4bdcSMarek Vasut }
1507