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, ®->in_endp[EP0_CON].diepdma);
33be5e4bdcSMarek Vasut writel(DIEPT_SIZ_PKT_CNT(1), ®->in_endp[EP0_CON].dieptsiz);
34be5e4bdcSMarek Vasut
35be5e4bdcSMarek Vasut ep_ctrl = readl(®->in_endp[EP0_CON].diepctl);
36be5e4bdcSMarek Vasut writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK,
37be5e4bdcSMarek Vasut ®->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(®->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 ®->out_endp[EP0_CON].doeptsiz);
53be5e4bdcSMarek Vasut writel(usb_ctrl_dma_addr, ®->out_endp[EP0_CON].doepdma);
54be5e4bdcSMarek Vasut
55be5e4bdcSMarek Vasut ep_ctrl = readl(®->out_endp[EP0_CON].doepctl);
56be5e4bdcSMarek Vasut writel(ep_ctrl|DEPCTL_EPENA, ®->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(®->in_endp[EP0_CON].diepctl));
60be5e4bdcSMarek Vasut debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DOEPCTL0 = 0x%x\n",
61be5e4bdcSMarek Vasut __func__, readl(®->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(®->in_endp[EP0_CON].diepctl));
71be5e4bdcSMarek Vasut debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DOEPCTL0 = 0x%x\n",
72be5e4bdcSMarek Vasut __func__, readl(®->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 ®->out_endp[EP0_CON].doeptsiz);
79be5e4bdcSMarek Vasut writel(usb_ctrl_dma_addr, ®->out_endp[EP0_CON].doepdma);
80be5e4bdcSMarek Vasut
81be5e4bdcSMarek Vasut ep_ctrl = readl(®->out_endp[EP0_CON].doepctl);
82be5e4bdcSMarek Vasut writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK,
83be5e4bdcSMarek Vasut ®->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(®->in_endp[EP0_CON].diepctl));
87be5e4bdcSMarek Vasut debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DOEPCTL0 = 0x%x\n",
88be5e4bdcSMarek Vasut __func__, readl(®->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(®->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, ®->out_endp[ep_num].doepdma);
118be5e4bdcSMarek Vasut writel(DOEPT_SIZ_PKT_CNT(pktcnt) | DOEPT_SIZ_XFER_SIZE(length),
119be5e4bdcSMarek Vasut ®->out_endp[ep_num].doeptsiz);
120be5e4bdcSMarek Vasut writel(DEPCTL_EPENA|DEPCTL_CNAK|ctrl, ®->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(®->out_endp[ep_num].doepdma),
128be5e4bdcSMarek Vasut readl(®->out_endp[ep_num].doeptsiz),
129be5e4bdcSMarek Vasut readl(®->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), ®->grstctl);
161be5e4bdcSMarek Vasut writel(TX_FIFO_NUMBER(ep->fifo_num) | TX_FIFO_FLUSH, ®->grstctl);
162be5e4bdcSMarek Vasut while (readl(®->grstctl) & TX_FIFO_FLUSH)
163be5e4bdcSMarek Vasut ;
164be5e4bdcSMarek Vasut
165be5e4bdcSMarek Vasut writel((unsigned long) ep->dma_buf, ®->in_endp[ep_num].diepdma);
166be5e4bdcSMarek Vasut writel(DIEPT_SIZ_PKT_CNT(pktcnt) | DIEPT_SIZ_XFER_SIZE(length),
167be5e4bdcSMarek Vasut ®->in_endp[ep_num].dieptsiz);
168be5e4bdcSMarek Vasut
169be5e4bdcSMarek Vasut ctrl = readl(®->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, ®->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(®->in_endp[ep_num].diepdma),
186be5e4bdcSMarek Vasut readl(®->in_endp[ep_num].dieptsiz),
187be5e4bdcSMarek Vasut readl(®->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(®->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(®->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(®->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(®->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, ®->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(®->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(®->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, ®->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(®->gintsts);
478be5e4bdcSMarek Vasut gintmsk = readl(®->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(®->daint), readl(®->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, ®->gintsts);
495be5e4bdcSMarek Vasut usb_status = (readl(®->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, ®->gintsts);
513be5e4bdcSMarek Vasut }
514be5e4bdcSMarek Vasut
515be5e4bdcSMarek Vasut if (intr_status & INT_SUSPEND) {
516be5e4bdcSMarek Vasut usb_status = readl(®->dsts);
517be5e4bdcSMarek Vasut debug_cond(DEBUG_ISR,
518be5e4bdcSMarek Vasut "\tSuspend interrupt :(DSTS):0x%x\n", usb_status);
519be5e4bdcSMarek Vasut writel(INT_SUSPEND, ®->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(®->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, ®->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, ®->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(®->gotgctl);
562be5e4bdcSMarek Vasut debug_cond(DEBUG_ISR,
563be5e4bdcSMarek Vasut "\tReset interrupt - (GOTGCTL):0x%x\n", usb_status);
564be5e4bdcSMarek Vasut writel(INT_RESET, ®->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(®->dcfg);
574a52e8dd4SFrank Wang temp &= ~DCFG_DEVADDR_MASK;
575a52e8dd4SFrank Wang writel(temp, ®->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(®->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(®->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(®->dcfg);
769be5e4bdcSMarek Vasut writel(DEVICE_ADDRESS(address) | ctrl, ®->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(®->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(®->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, ®->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), ®->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, ®->in_endp[EP0_CON].diepdma);
938be5e4bdcSMarek Vasut writel(DIEPT_SIZ_PKT_CNT(1) | DIEPT_SIZ_XFER_SIZE(2),
939be5e4bdcSMarek Vasut ®->in_endp[EP0_CON].dieptsiz);
940be5e4bdcSMarek Vasut
941be5e4bdcSMarek Vasut ep_ctrl = readl(®->in_endp[EP0_CON].diepctl);
942be5e4bdcSMarek Vasut writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK,
943be5e4bdcSMarek Vasut ®->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(®->in_endp[ep_num].diepctl);
959be5e4bdcSMarek Vasut ep_ctrl |= DEPCTL_SNAK;
960be5e4bdcSMarek Vasut writel(ep_ctrl, ®->in_endp[ep_num].diepctl);
961be5e4bdcSMarek Vasut debug("%s: set NAK, DIEPCTL%d = 0x%x\n",
962be5e4bdcSMarek Vasut __func__, ep_num, readl(®->in_endp[ep_num].diepctl));
963be5e4bdcSMarek Vasut } else {
964be5e4bdcSMarek Vasut ep_ctrl = readl(®->out_endp[ep_num].doepctl);
965be5e4bdcSMarek Vasut ep_ctrl |= DEPCTL_SNAK;
966be5e4bdcSMarek Vasut writel(ep_ctrl, ®->out_endp[ep_num].doepctl);
967be5e4bdcSMarek Vasut debug("%s: set NAK, DOEPCTL%d = 0x%x\n",
968be5e4bdcSMarek Vasut __func__, ep_num, readl(®->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(®->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, ®->in_endp[ep_num].diepctl);
993be5e4bdcSMarek Vasut debug("%s: set stall, DIEPCTL%d = 0x%x\n",
994be5e4bdcSMarek Vasut __func__, ep_num, readl(®->in_endp[ep_num].diepctl));
995be5e4bdcSMarek Vasut
996be5e4bdcSMarek Vasut } else {
997be5e4bdcSMarek Vasut ep_ctrl = readl(®->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, ®->out_endp[ep_num].doepctl);
1003be5e4bdcSMarek Vasut debug("%s: set stall, DOEPCTL%d = 0x%x\n",
1004be5e4bdcSMarek Vasut __func__, ep_num, readl(®->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(®->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, ®->in_endp[ep_num].diepctl);
1036be5e4bdcSMarek Vasut debug("%s: cleared stall, DIEPCTL%d = 0x%x\n",
1037be5e4bdcSMarek Vasut __func__, ep_num, readl(®->in_endp[ep_num].diepctl));
1038be5e4bdcSMarek Vasut
1039be5e4bdcSMarek Vasut } else {
1040be5e4bdcSMarek Vasut ep_ctrl = readl(®->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, ®->out_endp[ep_num].doepctl);
1051be5e4bdcSMarek Vasut debug("%s: cleared stall, DOEPCTL%d = 0x%x\n",
1052be5e4bdcSMarek Vasut __func__, ep_num, readl(®->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(®->in_endp[ep_num].diepctl);
1115be5e4bdcSMarek Vasut daintmsk = 1 << ep_num;
1116be5e4bdcSMarek Vasut } else {
1117be5e4bdcSMarek Vasut ep_ctrl = readl(®->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, ®->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(®->in_endp[ep_num].diepctl));
1138be5e4bdcSMarek Vasut } else {
1139be5e4bdcSMarek Vasut writel(ep_ctrl, ®->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(®->out_endp[ep_num].doepctl));
1143be5e4bdcSMarek Vasut }
1144be5e4bdcSMarek Vasut }
1145be5e4bdcSMarek Vasut
1146be5e4bdcSMarek Vasut /* Unmask EP Interrtupt */
1147be5e4bdcSMarek Vasut writel(readl(®->daintmsk)|daintmsk, ®->daintmsk);
1148be5e4bdcSMarek Vasut debug("%s: DAINTMSK = 0x%x\n", __func__, readl(®->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