blob: 7fc5d27d436f837c35458ba4384473ce77907676 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Vipin KUMARa4f5ec62010-01-15 19:15:47 +05302/*
3 * Based on drivers/usb/gadget/omap1510_udc.c
4 * TI OMAP1510 USB bus interface driver
5 *
6 * (C) Copyright 2009
7 * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
Vipin KUMARa4f5ec62010-01-15 19:15:47 +05308 */
9
10#include <common.h>
Simon Glassbd7a59a2019-11-14 12:57:23 -070011#include <serial.h>
Vipin KUMARa4f5ec62010-01-15 19:15:47 +053012#include <asm/io.h>
Simon Glassdbd79542020-05-10 11:40:11 -060013#include <linux/delay.h>
Vipin KUMARa4f5ec62010-01-15 19:15:47 +053014
Simon Glass0af6e2d2019-08-01 09:46:52 -060015#include <env.h>
Vipin KUMARa4f5ec62010-01-15 19:15:47 +053016#include <usbdevice.h>
17#include "ep0.h"
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +000018#include <usb/designware_udc.h>
Troy Kiskydf446f52013-10-10 15:28:04 -070019#include <usb/udc.h>
Vipin KUMARa4f5ec62010-01-15 19:15:47 +053020#include <asm/arch/hardware.h>
Vipin KUMARa4f5ec62010-01-15 19:15:47 +053021
22#define UDC_INIT_MDELAY 80 /* Device settle delay */
23
24/* Some kind of debugging output... */
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +000025#ifndef DEBUG_DWUSBTTY
Vipin KUMARa4f5ec62010-01-15 19:15:47 +053026#define UDCDBG(str)
27#define UDCDBGA(fmt, args...)
28#else
29#define UDCDBG(str) serial_printf(str "\n")
30#define UDCDBGA(fmt, args...) serial_printf(fmt "\n", ##args)
31#endif
32
33static struct urb *ep0_urb;
34static struct usb_device_instance *udc_device;
35
36static struct plug_regs *const plug_regs_p =
37 (struct plug_regs * const)CONFIG_SYS_PLUG_BASE;
38static struct udc_regs *const udc_regs_p =
39 (struct udc_regs * const)CONFIG_SYS_USBD_BASE;
40static struct udc_endp_regs *const outep_regs_p =
41 &((struct udc_regs * const)CONFIG_SYS_USBD_BASE)->out_regs[0];
42static struct udc_endp_regs *const inep_regs_p =
43 &((struct udc_regs * const)CONFIG_SYS_USBD_BASE)->in_regs[0];
44
45/*
46 * udc_state_transition - Write the next packet to TxFIFO.
47 * @initial: Initial state.
48 * @final: Final state.
49 *
50 * Helper function to implement device state changes. The device states and
51 * the events that transition between them are:
52 *
53 * STATE_ATTACHED
54 * || /\
55 * \/ ||
56 * DEVICE_HUB_CONFIGURED DEVICE_HUB_RESET
57 * || /\
58 * \/ ||
59 * STATE_POWERED
60 * || /\
61 * \/ ||
62 * DEVICE_RESET DEVICE_POWER_INTERRUPTION
63 * || /\
64 * \/ ||
65 * STATE_DEFAULT
66 * || /\
67 * \/ ||
68 * DEVICE_ADDRESS_ASSIGNED DEVICE_RESET
69 * || /\
70 * \/ ||
71 * STATE_ADDRESSED
72 * || /\
73 * \/ ||
74 * DEVICE_CONFIGURED DEVICE_DE_CONFIGURED
75 * || /\
76 * \/ ||
77 * STATE_CONFIGURED
78 *
79 * udc_state_transition transitions up (in the direction from STATE_ATTACHED
80 * to STATE_CONFIGURED) from the specified initial state to the specified final
81 * state, passing through each intermediate state on the way. If the initial
82 * state is at or above (i.e. nearer to STATE_CONFIGURED) the final state, then
83 * no state transitions will take place.
84 *
85 * udc_state_transition also transitions down (in the direction from
86 * STATE_CONFIGURED to STATE_ATTACHED) from the specified initial state to the
87 * specified final state, passing through each intermediate state on the way.
88 * If the initial state is at or below (i.e. nearer to STATE_ATTACHED) the final
89 * state, then no state transitions will take place.
90 *
91 * This function must only be called with interrupts disabled.
92 */
93static void udc_state_transition(usb_device_state_t initial,
94 usb_device_state_t final)
95{
96 if (initial < final) {
97 switch (initial) {
98 case STATE_ATTACHED:
99 usbd_device_event_irq(udc_device,
100 DEVICE_HUB_CONFIGURED, 0);
101 if (final == STATE_POWERED)
102 break;
103 case STATE_POWERED:
104 usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
105 if (final == STATE_DEFAULT)
106 break;
107 case STATE_DEFAULT:
108 usbd_device_event_irq(udc_device,
109 DEVICE_ADDRESS_ASSIGNED, 0);
110 if (final == STATE_ADDRESSED)
111 break;
112 case STATE_ADDRESSED:
113 usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);
114 case STATE_CONFIGURED:
115 break;
116 default:
117 break;
118 }
119 } else if (initial > final) {
120 switch (initial) {
121 case STATE_CONFIGURED:
122 usbd_device_event_irq(udc_device,
123 DEVICE_DE_CONFIGURED, 0);
124 if (final == STATE_ADDRESSED)
125 break;
126 case STATE_ADDRESSED:
127 usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
128 if (final == STATE_DEFAULT)
129 break;
130 case STATE_DEFAULT:
131 usbd_device_event_irq(udc_device,
132 DEVICE_POWER_INTERRUPTION, 0);
133 if (final == STATE_POWERED)
134 break;
135 case STATE_POWERED:
136 usbd_device_event_irq(udc_device, DEVICE_HUB_RESET, 0);
137 case STATE_ATTACHED:
138 break;
139 default:
140 break;
141 }
142 }
143}
144
145/* Stall endpoint */
146static void udc_stall_ep(u32 ep_num)
147{
148 writel(readl(&inep_regs_p[ep_num].endp_cntl) | ENDP_CNTL_STALL,
149 &inep_regs_p[ep_num].endp_cntl);
150
151 writel(readl(&outep_regs_p[ep_num].endp_cntl) | ENDP_CNTL_STALL,
152 &outep_regs_p[ep_num].endp_cntl);
153}
154
155static void *get_fifo(int ep_num, int in)
156{
157 u32 *fifo_ptr = (u32 *)CONFIG_SYS_FIFO_BASE;
158
159 switch (ep_num) {
160 case UDC_EP3:
161 fifo_ptr += readl(&inep_regs_p[1].endp_bsorfn);
162 /* break intentionally left out */
163
164 case UDC_EP1:
165 fifo_ptr += readl(&inep_regs_p[0].endp_bsorfn);
166 /* break intentionally left out */
167
168 case UDC_EP0:
169 default:
170 if (in) {
171 fifo_ptr +=
172 readl(&outep_regs_p[2].endp_maxpacksize) >> 16;
173 /* break intentionally left out */
174 } else {
175 break;
176 }
177
178 case UDC_EP2:
179 fifo_ptr += readl(&outep_regs_p[0].endp_maxpacksize) >> 16;
180 /* break intentionally left out */
181 }
182
183 return (void *)fifo_ptr;
184}
185
186static int usbgetpckfromfifo(int epNum, u8 *bufp, u32 len)
187{
188 u8 *fifo_ptr = (u8 *)get_fifo(epNum, 0);
189 u32 i, nw, nb;
190 u32 *wrdp;
191 u8 *bytp;
Shiraz Hashim466e3ac2012-03-06 23:39:41 +0000192 u32 tmp[128];
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530193
194 if (readl(&udc_regs_p->dev_stat) & DEV_STAT_RXFIFO_EMPTY)
195 return -1;
196
197 nw = len / sizeof(u32);
198 nb = len % sizeof(u32);
199
Shiraz Hashim466e3ac2012-03-06 23:39:41 +0000200 /* use tmp buf if bufp is not word aligned */
201 if ((int)bufp & 0x3)
202 wrdp = (u32 *)&tmp[0];
203 else
204 wrdp = (u32 *)bufp;
205
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530206 for (i = 0; i < nw; i++) {
207 writel(readl(fifo_ptr), wrdp);
208 wrdp++;
209 }
210
211 bytp = (u8 *)wrdp;
212 for (i = 0; i < nb; i++) {
213 writeb(readb(fifo_ptr), bytp);
214 fifo_ptr++;
215 bytp++;
216 }
217 readl(&outep_regs_p[epNum].write_done);
218
Shiraz Hashim466e3ac2012-03-06 23:39:41 +0000219 /* copy back tmp buffer to bufp if bufp is not word aligned */
220 if ((int)bufp & 0x3)
221 memcpy(bufp, tmp, len);
222
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530223 return 0;
224}
225
226static void usbputpcktofifo(int epNum, u8 *bufp, u32 len)
227{
228 u32 i, nw, nb;
229 u32 *wrdp;
230 u8 *bytp;
231 u8 *fifo_ptr = get_fifo(epNum, 1);
232
233 nw = len / sizeof(int);
234 nb = len % sizeof(int);
235 wrdp = (u32 *)bufp;
236 for (i = 0; i < nw; i++) {
237 writel(*wrdp, fifo_ptr);
238 wrdp++;
239 }
240
241 bytp = (u8 *)wrdp;
242 for (i = 0; i < nb; i++) {
243 writeb(*bytp, fifo_ptr);
244 fifo_ptr++;
245 bytp++;
246 }
247}
248
249/*
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000250 * dw_write_noniso_tx_fifo - Write the next packet to TxFIFO.
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530251 * @endpoint: Endpoint pointer.
252 *
253 * If the endpoint has an active tx_urb, then the next packet of data from the
254 * URB is written to the tx FIFO. The total amount of data in the urb is given
255 * by urb->actual_length. The maximum amount of data that can be sent in any
256 * one packet is given by endpoint->tx_packetSize. The number of data bytes
257 * from this URB that have already been transmitted is given by endpoint->sent.
258 * endpoint->last is updated by this routine with the number of data bytes
259 * transmitted in this packet.
260 *
261 */
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000262static void dw_write_noniso_tx_fifo(struct usb_endpoint_instance
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530263 *endpoint)
264{
265 struct urb *urb = endpoint->tx_urb;
266 int align;
267
268 if (urb) {
269 u32 last;
270
271 UDCDBGA("urb->buffer %p, buffer_length %d, actual_length %d",
272 urb->buffer, urb->buffer_length, urb->actual_length);
273
Masahiro Yamadadb204642014-11-07 03:03:31 +0900274 last = min_t(u32, urb->actual_length - endpoint->sent,
275 endpoint->tx_packetSize);
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530276
277 if (last) {
278 u8 *cp = urb->buffer + endpoint->sent;
279
280 /*
281 * This ensures that USBD packet fifo is accessed
282 * - through word aligned pointer or
283 * - through non word aligned pointer but only
284 * with a max length to make the next packet
285 * word aligned
286 */
287
288 align = ((ulong)cp % sizeof(int));
289 if (align)
Masahiro Yamadab62b39b2014-09-18 13:28:06 +0900290 last = min(last, sizeof(int) - align);
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530291
292 UDCDBGA("endpoint->sent %d, tx_packetSize %d, last %d",
293 endpoint->sent, endpoint->tx_packetSize, last);
294
295 usbputpcktofifo(endpoint->endpoint_address &
296 USB_ENDPOINT_NUMBER_MASK, cp, last);
297 }
298 endpoint->last = last;
299 }
300}
301
302/*
303 * Handle SETUP USB interrupt.
304 * This function implements TRM Figure 14-14.
305 */
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000306static void dw_udc_setup(struct usb_endpoint_instance *endpoint)
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530307{
308 u8 *datap = (u8 *)&ep0_urb->device_request;
309 int ep_addr = endpoint->endpoint_address;
310
311 UDCDBG("-> Entering device setup");
312 usbgetpckfromfifo(ep_addr, datap, 8);
313
314 /* Try to process setup packet */
315 if (ep0_recv_setup(ep0_urb)) {
316 /* Not a setup packet, stall next EP0 transaction */
317 udc_stall_ep(0);
318 UDCDBG("can't parse setup packet, still waiting for setup");
319 return;
320 }
321
322 /* Check direction */
323 if ((ep0_urb->device_request.bmRequestType & USB_REQ_DIRECTION_MASK)
324 == USB_REQ_HOST2DEVICE) {
325 UDCDBG("control write on EP0");
326 if (le16_to_cpu(ep0_urb->device_request.wLength)) {
327 /* Stall this request */
328 UDCDBG("Stalling unsupported EP0 control write data "
329 "stage.");
330 udc_stall_ep(0);
331 }
332 } else {
333
334 UDCDBG("control read on EP0");
335 /*
336 * The ep0_recv_setup function has already placed our response
337 * packet data in ep0_urb->buffer and the packet length in
338 * ep0_urb->actual_length.
339 */
340 endpoint->tx_urb = ep0_urb;
341 endpoint->sent = 0;
342 /*
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000343 * Write packet data to the FIFO. dw_write_noniso_tx_fifo
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530344 * will update endpoint->last with the number of bytes written
345 * to the FIFO.
346 */
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000347 dw_write_noniso_tx_fifo(endpoint);
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530348
349 writel(0x0, &inep_regs_p[ep_addr].write_done);
350 }
351
352 udc_unset_nak(endpoint->endpoint_address);
353
354 UDCDBG("<- Leaving device setup");
355}
356
357/*
358 * Handle endpoint 0 RX interrupt
359 */
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000360static void dw_udc_ep0_rx(struct usb_endpoint_instance *endpoint)
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530361{
362 u8 dummy[64];
363
364 UDCDBG("RX on EP0");
365
366 /* Check direction */
367 if ((ep0_urb->device_request.bmRequestType
368 & USB_REQ_DIRECTION_MASK) == USB_REQ_HOST2DEVICE) {
369 /*
370 * This rx interrupt must be for a control write data
371 * stage packet.
372 *
373 * We don't support control write data stages.
374 * We should never end up here.
375 */
376
377 UDCDBG("Stalling unexpected EP0 control write "
378 "data stage packet");
379 udc_stall_ep(0);
380 } else {
381 /*
382 * This rx interrupt must be for a control read status
383 * stage packet.
384 */
385 UDCDBG("ACK on EP0 control read status stage packet");
386 u32 len = (readl(&outep_regs_p[0].endp_status) >> 11) & 0xfff;
387 usbgetpckfromfifo(0, dummy, len);
388 }
389}
390
391/*
392 * Handle endpoint 0 TX interrupt
393 */
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000394static void dw_udc_ep0_tx(struct usb_endpoint_instance *endpoint)
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530395{
396 struct usb_device_request *request = &ep0_urb->device_request;
397 int ep_addr;
398
399 UDCDBG("TX on EP0");
400
401 /* Check direction */
402 if ((request->bmRequestType & USB_REQ_DIRECTION_MASK) ==
403 USB_REQ_HOST2DEVICE) {
404 /*
405 * This tx interrupt must be for a control write status
406 * stage packet.
407 */
408 UDCDBG("ACK on EP0 control write status stage packet");
409 } else {
410 /*
411 * This tx interrupt must be for a control read data
412 * stage packet.
413 */
414 int wLength = le16_to_cpu(request->wLength);
415
416 /*
417 * Update our count of bytes sent so far in this
418 * transfer.
419 */
420 endpoint->sent += endpoint->last;
421
422 /*
423 * We are finished with this transfer if we have sent
424 * all of the bytes in our tx urb (urb->actual_length)
425 * unless we need a zero-length terminating packet. We
426 * need a zero-length terminating packet if we returned
427 * fewer bytes than were requested (wLength) by the host,
428 * and the number of bytes we returned is an exact
429 * multiple of the packet size endpoint->tx_packetSize.
430 */
431 if ((endpoint->sent == ep0_urb->actual_length) &&
432 ((ep0_urb->actual_length == wLength) ||
433 (endpoint->last != endpoint->tx_packetSize))) {
434 /* Done with control read data stage. */
435 UDCDBG("control read data stage complete");
436 } else {
437 /*
438 * We still have another packet of data to send
439 * in this control read data stage or else we
440 * need a zero-length terminating packet.
441 */
442 UDCDBG("ACK control read data stage packet");
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000443 dw_write_noniso_tx_fifo(endpoint);
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530444
445 ep_addr = endpoint->endpoint_address;
446 writel(0x0, &inep_regs_p[ep_addr].write_done);
447 }
448 }
449}
450
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000451static struct usb_endpoint_instance *dw_find_ep(int ep)
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530452{
453 int i;
454
455 for (i = 0; i < udc_device->bus->max_endpoints; i++) {
456 if ((udc_device->bus->endpoint_array[i].endpoint_address &
457 USB_ENDPOINT_NUMBER_MASK) == ep)
458 return &udc_device->bus->endpoint_array[i];
459 }
460 return NULL;
461}
462
463/*
464 * Handle RX transaction on non-ISO endpoint.
465 * The ep argument is a physical endpoint number for a non-ISO IN endpoint
466 * in the range 1 to 15.
467 */
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000468static void dw_udc_epn_rx(int ep)
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530469{
470 int nbytes = 0;
471 struct urb *urb;
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000472 struct usb_endpoint_instance *endpoint = dw_find_ep(ep);
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530473
474 if (endpoint) {
475 urb = endpoint->rcv_urb;
476
477 if (urb) {
478 u8 *cp = urb->buffer + urb->actual_length;
479
480 nbytes = (readl(&outep_regs_p[ep].endp_status) >> 11) &
481 0xfff;
482 usbgetpckfromfifo(ep, cp, nbytes);
483 usbd_rcv_complete(endpoint, nbytes, 0);
484 }
485 }
486}
487
488/*
489 * Handle TX transaction on non-ISO endpoint.
490 * The ep argument is a physical endpoint number for a non-ISO IN endpoint
491 * in the range 16 to 30.
492 */
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000493static void dw_udc_epn_tx(int ep)
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530494{
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000495 struct usb_endpoint_instance *endpoint = dw_find_ep(ep);
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530496
Vipin KUMARb8af20782012-03-06 23:39:38 +0000497 if (!endpoint)
498 return;
499
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530500 /*
501 * We need to transmit a terminating zero-length packet now if
502 * we have sent all of the data in this URB and the transfer
503 * size was an exact multiple of the packet size.
504 */
Vipin KUMARb8af20782012-03-06 23:39:38 +0000505 if (endpoint->tx_urb &&
506 (endpoint->last == endpoint->tx_packetSize) &&
507 (endpoint->tx_urb->actual_length - endpoint->sent -
508 endpoint->last == 0)) {
509 /* handle zero length packet here */
510 writel(0x0, &inep_regs_p[ep].write_done);
511
512 }
513
514 if (endpoint->tx_urb && endpoint->tx_urb->actual_length) {
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530515 /* retire the data that was just sent */
516 usbd_tx_complete(endpoint);
517 /*
518 * Check to see if we have more data ready to transmit
519 * now.
520 */
521 if (endpoint->tx_urb && endpoint->tx_urb->actual_length) {
522 /* write data to FIFO */
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000523 dw_write_noniso_tx_fifo(endpoint);
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530524 writel(0x0, &inep_regs_p[ep].write_done);
525
526 } else if (endpoint->tx_urb
527 && (endpoint->tx_urb->actual_length == 0)) {
528 /* udc_set_nak(ep); */
529 }
530 }
531}
532
533/*
534 * Start of public functions.
535 */
536
537/* Called to start packet transmission. */
538int udc_endpoint_write(struct usb_endpoint_instance *endpoint)
539{
540 udc_unset_nak(endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK);
541 return 0;
542}
543
544/* Start to initialize h/w stuff */
545int udc_init(void)
546{
547 int i;
548 u32 plug_st;
549
550 udc_device = NULL;
551
552 UDCDBG("starting");
553
554 readl(&plug_regs_p->plug_pending);
555
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530556 for (i = 0; i < UDC_INIT_MDELAY; i++)
557 udelay(1000);
558
559 plug_st = readl(&plug_regs_p->plug_state);
560 writel(plug_st | PLUG_STATUS_EN, &plug_regs_p->plug_state);
561
562 writel(~0x0, &udc_regs_p->endp_int);
563 writel(~0x0, &udc_regs_p->dev_int_mask);
564 writel(~0x0, &udc_regs_p->endp_int_mask);
565
Vipin KUMARf710a112012-03-06 23:39:39 +0000566#ifndef CONFIG_USBD_HS
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530567 writel(DEV_CONF_FS_SPEED | DEV_CONF_REMWAKEUP | DEV_CONF_SELFPOW |
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530568 DEV_CONF_PHYINT_16, &udc_regs_p->dev_conf);
Vipin KUMARf710a112012-03-06 23:39:39 +0000569#else
570 writel(DEV_CONF_HS_SPEED | DEV_CONF_REMWAKEUP | DEV_CONF_SELFPOW |
571 DEV_CONF_PHYINT_16, &udc_regs_p->dev_conf);
572#endif
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530573
Vipin KUMARb8af20782012-03-06 23:39:38 +0000574 writel(DEV_CNTL_SOFTDISCONNECT, &udc_regs_p->dev_cntl);
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530575
576 /* Clear all interrupts pending */
577 writel(DEV_INT_MSK, &udc_regs_p->dev_int);
578
579 return 0;
580}
581
Vipin KUMARf710a112012-03-06 23:39:39 +0000582int is_usbd_high_speed(void)
583{
584 return (readl(&udc_regs_p->dev_stat) & DEV_STAT_ENUM) ? 0 : 1;
585}
586
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530587/*
588 * udc_setup_ep - setup endpoint
589 * Associate a physical endpoint with endpoint_instance
590 */
591void udc_setup_ep(struct usb_device_instance *device,
592 u32 ep, struct usb_endpoint_instance *endpoint)
593{
594 UDCDBGA("setting up endpoint addr %x", endpoint->endpoint_address);
595 int ep_addr;
596 int ep_num, ep_type;
597 int packet_size;
598 int buffer_size;
599 int attributes;
600 char *tt;
601 u32 endp_intmask;
602
Vipin KUMARb8af20782012-03-06 23:39:38 +0000603 if ((ep != 0) && (udc_device->device_state < STATE_ADDRESSED))
604 return;
605
Simon Glass64b723f2017-08-03 12:22:12 -0600606 tt = env_get("usbtty");
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530607 if (!tt)
608 tt = "generic";
609
610 ep_addr = endpoint->endpoint_address;
611 ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK;
612
613 if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
614 /* IN endpoint */
615 packet_size = endpoint->tx_packetSize;
616 buffer_size = packet_size * 2;
617 attributes = endpoint->tx_attributes;
618 } else {
619 /* OUT endpoint */
620 packet_size = endpoint->rcv_packetSize;
621 buffer_size = packet_size * 2;
622 attributes = endpoint->rcv_attributes;
623 }
624
625 switch (attributes & USB_ENDPOINT_XFERTYPE_MASK) {
626 case USB_ENDPOINT_XFER_CONTROL:
627 ep_type = ENDP_EPTYPE_CNTL;
628 break;
629 case USB_ENDPOINT_XFER_BULK:
630 default:
631 ep_type = ENDP_EPTYPE_BULK;
632 break;
633 case USB_ENDPOINT_XFER_INT:
634 ep_type = ENDP_EPTYPE_INT;
635 break;
636 case USB_ENDPOINT_XFER_ISOC:
637 ep_type = ENDP_EPTYPE_ISO;
638 break;
639 }
640
641 struct udc_endp_regs *out_p = &outep_regs_p[ep_num];
642 struct udc_endp_regs *in_p = &inep_regs_p[ep_num];
643
644 if (!ep_addr) {
645 /* Setup endpoint 0 */
646 buffer_size = packet_size;
647
648 writel(readl(&in_p->endp_cntl) | ENDP_CNTL_CNAK,
649 &in_p->endp_cntl);
650
651 writel(readl(&out_p->endp_cntl) | ENDP_CNTL_CNAK,
652 &out_p->endp_cntl);
653
654 writel(ENDP_CNTL_CONTROL | ENDP_CNTL_FLUSH, &in_p->endp_cntl);
655
656 writel(buffer_size / sizeof(int), &in_p->endp_bsorfn);
657
658 writel(packet_size, &in_p->endp_maxpacksize);
659
660 writel(ENDP_CNTL_CONTROL | ENDP_CNTL_RRDY, &out_p->endp_cntl);
661
662 writel(packet_size | ((buffer_size / sizeof(int)) << 16),
663 &out_p->endp_maxpacksize);
664
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530665 } else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
666 /* Setup the IN endpoint */
667 writel(0x0, &in_p->endp_status);
668 writel((ep_type << 4) | ENDP_CNTL_RRDY, &in_p->endp_cntl);
669 writel(buffer_size / sizeof(int), &in_p->endp_bsorfn);
670 writel(packet_size, &in_p->endp_maxpacksize);
671
672 if (!strcmp(tt, "cdc_acm")) {
673 if (ep_type == ENDP_EPTYPE_INT) {
674 /* Conf no. 1 Interface no. 0 */
675 writel((packet_size << 19) |
676 ENDP_EPDIR_IN | (1 << 7) |
677 (0 << 11) | (ep_type << 5) | ep_num,
678 &udc_regs_p->udc_endp_reg[ep_num]);
679 } else {
680 /* Conf no. 1 Interface no. 1 */
681 writel((packet_size << 19) |
682 ENDP_EPDIR_IN | (1 << 7) |
683 (1 << 11) | (ep_type << 5) | ep_num,
684 &udc_regs_p->udc_endp_reg[ep_num]);
685 }
686 } else {
687 /* Conf no. 1 Interface no. 0 */
688 writel((packet_size << 19) |
689 ENDP_EPDIR_IN | (1 << 7) |
690 (0 << 11) | (ep_type << 5) | ep_num,
691 &udc_regs_p->udc_endp_reg[ep_num]);
692 }
693
694 } else {
695 /* Setup the OUT endpoint */
696 writel(0x0, &out_p->endp_status);
697 writel((ep_type << 4) | ENDP_CNTL_RRDY, &out_p->endp_cntl);
698 writel(packet_size | ((buffer_size / sizeof(int)) << 16),
699 &out_p->endp_maxpacksize);
700
701 if (!strcmp(tt, "cdc_acm")) {
702 writel((packet_size << 19) |
703 ENDP_EPDIR_OUT | (1 << 7) |
704 (1 << 11) | (ep_type << 5) | ep_num,
705 &udc_regs_p->udc_endp_reg[ep_num]);
706 } else {
707 writel((packet_size << 19) |
708 ENDP_EPDIR_OUT | (1 << 7) |
709 (0 << 11) | (ep_type << 5) | ep_num,
710 &udc_regs_p->udc_endp_reg[ep_num]);
711 }
712
713 }
714
715 endp_intmask = readl(&udc_regs_p->endp_int_mask);
716 endp_intmask &= ~((1 << ep_num) | 0x10000 << ep_num);
717 writel(endp_intmask, &udc_regs_p->endp_int_mask);
718}
719
720/* Turn on the USB connection by enabling the pullup resistor */
721void udc_connect(void)
722{
Vipin KUMARb8af20782012-03-06 23:39:38 +0000723 u32 plug_st, dev_cntl;
724
725 dev_cntl = readl(&udc_regs_p->dev_cntl);
726 dev_cntl |= DEV_CNTL_SOFTDISCONNECT;
727 writel(dev_cntl, &udc_regs_p->dev_cntl);
728
729 udelay(1000);
730
731 dev_cntl = readl(&udc_regs_p->dev_cntl);
732 dev_cntl &= ~DEV_CNTL_SOFTDISCONNECT;
733 writel(dev_cntl, &udc_regs_p->dev_cntl);
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530734
735 plug_st = readl(&plug_regs_p->plug_state);
736 plug_st &= ~(PLUG_STATUS_PHY_RESET | PLUG_STATUS_PHY_MODE);
737 writel(plug_st, &plug_regs_p->plug_state);
738}
739
740/* Turn off the USB connection by disabling the pullup resistor */
741void udc_disconnect(void)
742{
743 u32 plug_st;
744
Vipin KUMARb8af20782012-03-06 23:39:38 +0000745 writel(DEV_CNTL_SOFTDISCONNECT, &udc_regs_p->dev_cntl);
746
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530747 plug_st = readl(&plug_regs_p->plug_state);
748 plug_st |= (PLUG_STATUS_PHY_RESET | PLUG_STATUS_PHY_MODE);
749 writel(plug_st, &plug_regs_p->plug_state);
750}
751
752/* Switch on the UDC */
753void udc_enable(struct usb_device_instance *device)
754{
755 UDCDBGA("enable device %p, status %d", device, device->status);
756
757 /* Save the device structure pointer */
758 udc_device = device;
759
760 /* Setup ep0 urb */
761 if (!ep0_urb) {
762 ep0_urb =
763 usbd_alloc_urb(udc_device, udc_device->bus->endpoint_array);
764 } else {
765 serial_printf("udc_enable: ep0_urb already allocated %p\n",
766 ep0_urb);
767 }
768
769 writel(DEV_INT_SOF, &udc_regs_p->dev_int_mask);
770}
771
772/**
773 * udc_startup - allow udc code to do any additional startup
774 */
775void udc_startup_events(struct usb_device_instance *device)
776{
777 /* The DEVICE_INIT event puts the USB device in the state STATE_INIT. */
778 usbd_device_event_irq(device, DEVICE_INIT, 0);
779
780 /*
781 * The DEVICE_CREATE event puts the USB device in the state
782 * STATE_ATTACHED.
783 */
784 usbd_device_event_irq(device, DEVICE_CREATE, 0);
785
786 /*
787 * Some USB controller driver implementations signal
788 * DEVICE_HUB_CONFIGURED and DEVICE_RESET events here.
789 * DEVICE_HUB_CONFIGURED causes a transition to the state STATE_POWERED,
790 * and DEVICE_RESET causes a transition to the state STATE_DEFAULT.
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000791 * The DW USB client controller has the capability to detect when the
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530792 * USB cable is connected to a powered USB bus, so we will defer the
793 * DEVICE_HUB_CONFIGURED and DEVICE_RESET events until later.
794 */
795
796 udc_enable(device);
797}
798
799/*
800 * Plug detection interrupt handling
801 */
Amit Virdic1b4f8e2012-03-06 23:39:40 +0000802static void dw_udc_plug_irq(void)
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530803{
804 if (readl(&plug_regs_p->plug_state) & PLUG_STATUS_ATTACHED) {
805 /*
806 * USB cable attached
807 * Turn off PHY reset bit (PLUG detect).
808 * Switch PHY opmode to normal operation (PLUG detect).
809 */
810 udc_connect();
811 writel(DEV_INT_SOF, &udc_regs_p->dev_int_mask);
812
813 UDCDBG("device attached and powered");
814 udc_state_transition(udc_device->device_state, STATE_POWERED);
815 } else {
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530816 writel(~0x0, &udc_regs_p->dev_int_mask);
817
818 UDCDBG("device detached or unpowered");
819 udc_state_transition(udc_device->device_state, STATE_ATTACHED);
820 }
821}
822
823/*
824 * Device interrupt handling
825 */
Amit Virdic1b4f8e2012-03-06 23:39:40 +0000826static void dw_udc_dev_irq(void)
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530827{
828 if (readl(&udc_regs_p->dev_int) & DEV_INT_USBRESET) {
829 writel(~0x0, &udc_regs_p->endp_int_mask);
830
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530831 writel(readl(&inep_regs_p[0].endp_cntl) | ENDP_CNTL_FLUSH,
832 &inep_regs_p[0].endp_cntl);
833
834 writel(DEV_INT_USBRESET, &udc_regs_p->dev_int);
835
Vipin KUMARb8af20782012-03-06 23:39:38 +0000836 /*
837 * This endpoint0 specific register can be programmed only
838 * after the phy clock is initialized
839 */
840 writel((EP0_MAX_PACKET_SIZE << 19) | ENDP_EPTYPE_CNTL,
841 &udc_regs_p->udc_endp_reg[0]);
842
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530843 UDCDBG("device reset in progess");
844 udc_state_transition(udc_device->device_state, STATE_DEFAULT);
845 }
846
847 /* Device Enumeration completed */
848 if (readl(&udc_regs_p->dev_int) & DEV_INT_ENUM) {
849 writel(DEV_INT_ENUM, &udc_regs_p->dev_int);
850
851 /* Endpoint interrupt enabled for Ctrl IN & Ctrl OUT */
852 writel(readl(&udc_regs_p->endp_int_mask) & ~0x10001,
853 &udc_regs_p->endp_int_mask);
854
855 UDCDBG("default -> addressed");
856 udc_state_transition(udc_device->device_state, STATE_ADDRESSED);
857 }
858
859 /* The USB will be in SUSPEND in 3 ms */
860 if (readl(&udc_regs_p->dev_int) & DEV_INT_INACTIVE) {
861 writel(DEV_INT_INACTIVE, &udc_regs_p->dev_int);
862
863 UDCDBG("entering inactive state");
864 /* usbd_device_event_irq(udc_device, DEVICE_BUS_INACTIVE, 0); */
865 }
866
867 /* SetConfiguration command received */
868 if (readl(&udc_regs_p->dev_int) & DEV_INT_SETCFG) {
869 writel(DEV_INT_SETCFG, &udc_regs_p->dev_int);
870
871 UDCDBG("entering configured state");
872 udc_state_transition(udc_device->device_state,
873 STATE_CONFIGURED);
874 }
875
876 /* SetInterface command received */
877 if (readl(&udc_regs_p->dev_int) & DEV_INT_SETINTF)
878 writel(DEV_INT_SETINTF, &udc_regs_p->dev_int);
879
880 /* USB Suspend detected on cable */
881 if (readl(&udc_regs_p->dev_int) & DEV_INT_SUSPUSB) {
882 writel(DEV_INT_SUSPUSB, &udc_regs_p->dev_int);
883
884 UDCDBG("entering suspended state");
885 usbd_device_event_irq(udc_device, DEVICE_BUS_INACTIVE, 0);
886 }
887
888 /* USB Start-Of-Frame detected on cable */
889 if (readl(&udc_regs_p->dev_int) & DEV_INT_SOF)
890 writel(DEV_INT_SOF, &udc_regs_p->dev_int);
891}
892
893/*
894 * Endpoint interrupt handling
895 */
Amit Virdic1b4f8e2012-03-06 23:39:40 +0000896static void dw_udc_endpoint_irq(void)
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530897{
898 while (readl(&udc_regs_p->endp_int) & ENDP0_INT_CTRLOUT) {
899
900 writel(ENDP0_INT_CTRLOUT, &udc_regs_p->endp_int);
901
902 if ((readl(&outep_regs_p[0].endp_status) & ENDP_STATUS_OUTMSK)
903 == ENDP_STATUS_OUT_SETUP) {
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000904 dw_udc_setup(udc_device->bus->endpoint_array + 0);
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530905 writel(ENDP_STATUS_OUT_SETUP,
906 &outep_regs_p[0].endp_status);
907
908 } else if ((readl(&outep_regs_p[0].endp_status) &
909 ENDP_STATUS_OUTMSK) == ENDP_STATUS_OUT_DATA) {
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000910 dw_udc_ep0_rx(udc_device->bus->endpoint_array + 0);
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530911 writel(ENDP_STATUS_OUT_DATA,
912 &outep_regs_p[0].endp_status);
913
914 } else if ((readl(&outep_regs_p[0].endp_status) &
915 ENDP_STATUS_OUTMSK) == ENDP_STATUS_OUT_NONE) {
916 /* NONE received */
917 }
918
919 writel(0x0, &outep_regs_p[0].endp_status);
920 }
921
922 if (readl(&udc_regs_p->endp_int) & ENDP0_INT_CTRLIN) {
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000923 dw_udc_ep0_tx(udc_device->bus->endpoint_array + 0);
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530924
925 writel(ENDP_STATUS_IN, &inep_regs_p[0].endp_status);
926 writel(ENDP0_INT_CTRLIN, &udc_regs_p->endp_int);
927 }
928
Vipin KUMARb8af20782012-03-06 23:39:38 +0000929 if (readl(&udc_regs_p->endp_int) & ENDP_INT_NONISOOUT_MSK) {
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530930 u32 epnum = 0;
931 u32 ep_int = readl(&udc_regs_p->endp_int) &
932 ENDP_INT_NONISOOUT_MSK;
933
934 ep_int >>= 16;
935 while (0x0 == (ep_int & 0x1)) {
936 ep_int >>= 1;
937 epnum++;
938 }
939
940 writel((1 << 16) << epnum, &udc_regs_p->endp_int);
941
942 if ((readl(&outep_regs_p[epnum].endp_status) &
943 ENDP_STATUS_OUTMSK) == ENDP_STATUS_OUT_DATA) {
944
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000945 dw_udc_epn_rx(epnum);
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530946 writel(ENDP_STATUS_OUT_DATA,
947 &outep_regs_p[epnum].endp_status);
948 } else if ((readl(&outep_regs_p[epnum].endp_status) &
949 ENDP_STATUS_OUTMSK) == ENDP_STATUS_OUT_NONE) {
950 writel(0x0, &outep_regs_p[epnum].endp_status);
951 }
952 }
953
954 if (readl(&udc_regs_p->endp_int) & ENDP_INT_NONISOIN_MSK) {
955 u32 epnum = 0;
956 u32 ep_int = readl(&udc_regs_p->endp_int) &
957 ENDP_INT_NONISOIN_MSK;
958
959 while (0x0 == (ep_int & 0x1)) {
960 ep_int >>= 1;
961 epnum++;
962 }
963
964 if (readl(&inep_regs_p[epnum].endp_status) & ENDP_STATUS_IN) {
965 writel(ENDP_STATUS_IN,
966 &outep_regs_p[epnum].endp_status);
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000967 dw_udc_epn_tx(epnum);
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530968
969 writel(ENDP_STATUS_IN,
970 &outep_regs_p[epnum].endp_status);
971 }
972
973 writel((1 << epnum), &udc_regs_p->endp_int);
974 }
975}
976
977/*
978 * UDC interrupts
979 */
980void udc_irq(void)
981{
982 /*
983 * Loop while we have interrupts.
984 * If we don't do this, the input chain
985 * polling delay is likely to miss
986 * host requests.
987 */
988 while (readl(&plug_regs_p->plug_pending))
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000989 dw_udc_plug_irq();
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530990
991 while (readl(&udc_regs_p->dev_int))
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000992 dw_udc_dev_irq();
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530993
994 if (readl(&udc_regs_p->endp_int))
Vipin KUMAR33cf5bd2012-03-06 23:39:37 +0000995 dw_udc_endpoint_irq();
Vipin KUMARa4f5ec62010-01-15 19:15:47 +0530996}
997
998/* Flow control */
999void udc_set_nak(int epid)
1000{
1001 writel(readl(&inep_regs_p[epid].endp_cntl) | ENDP_CNTL_SNAK,
1002 &inep_regs_p[epid].endp_cntl);
1003
1004 writel(readl(&outep_regs_p[epid].endp_cntl) | ENDP_CNTL_SNAK,
1005 &outep_regs_p[epid].endp_cntl);
1006}
1007
1008void udc_unset_nak(int epid)
1009{
1010 u32 val;
1011
1012 val = readl(&inep_regs_p[epid].endp_cntl);
1013 val &= ~ENDP_CNTL_SNAK;
1014 val |= ENDP_CNTL_CNAK;
1015 writel(val, &inep_regs_p[epid].endp_cntl);
1016
1017 val = readl(&outep_regs_p[epid].endp_cntl);
1018 val &= ~ENDP_CNTL_SNAK;
1019 val |= ENDP_CNTL_CNAK;
1020 writel(val, &outep_regs_p[epid].endp_cntl);
1021}