blob: ffed3b82bed241662d7bd3194a8d82d9745cfa29 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Thomas Abraham38f424f2009-01-04 09:41:03 +05302/*
3 * Mentor USB OTG Core host controller driver.
4 *
5 * Copyright (c) 2008 Texas Instruments
6 *
Thomas Abraham38f424f2009-01-04 09:41:03 +05307 * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
8 */
9
10#include <common.h>
Simon Glass0f2af882020-05-10 11:40:05 -060011#include <log.h>
Ilya Yanoka1cf10f2012-11-06 13:48:20 +000012#include <usb.h>
Simon Glassdbd79542020-05-10 11:40:11 -060013#include <linux/delay.h>
Thomas Abraham38f424f2009-01-04 09:41:03 +053014#include "musb_hcd.h"
15
16/* MSC control transfers */
17#define USB_MSC_BBB_RESET 0xFF
18#define USB_MSC_BBB_GET_MAX_LUN 0xFE
19
20/* Endpoint configuration information */
Mike Frysinger671bc3d2010-10-20 07:15:35 -040021static const struct musb_epinfo epinfo[3] = {
Thomas Abraham38f424f2009-01-04 09:41:03 +053022 {MUSB_BULK_EP, 1, 512}, /* EP1 - Bluk Out - 512 Bytes */
23 {MUSB_BULK_EP, 0, 512}, /* EP1 - Bluk In - 512 Bytes */
24 {MUSB_INTR_EP, 0, 64} /* EP2 - Interrupt IN - 64 Bytes */
25};
26
Bryan Wu73073cc2010-01-09 16:53:54 -050027/* --- Virtual Root Hub ---------------------------------------------------- */
28#ifdef MUSB_NO_MULTIPOINT
29static int rh_devnum;
30static u32 port_status;
31
Stephen Warren39c89682014-02-13 21:15:18 -070032#include <usbroothubdes.h>
Bryan Wu73073cc2010-01-09 16:53:54 -050033
Bryan Wu73073cc2010-01-09 16:53:54 -050034#endif
35
Thomas Abraham38f424f2009-01-04 09:41:03 +053036/*
37 * This function writes the data toggle value.
38 */
39static void write_toggle(struct usb_device *dev, u8 ep, u8 dir_out)
40{
41 u16 toggle = usb_gettoggle(dev, ep, dir_out);
42 u16 csr;
43
44 if (dir_out) {
Bryan Wufe439d22010-08-09 14:58:24 -040045 csr = readw(&musbr->txcsr);
46 if (!toggle) {
47 if (csr & MUSB_TXCSR_MODE)
48 csr = MUSB_TXCSR_CLRDATATOG;
49 else
50 csr = 0;
51 writew(csr, &musbr->txcsr);
52 } else {
Thomas Abraham38f424f2009-01-04 09:41:03 +053053 csr |= MUSB_TXCSR_H_WR_DATATOGGLE;
54 writew(csr, &musbr->txcsr);
55 csr |= (toggle << MUSB_TXCSR_H_DATATOGGLE_SHIFT);
56 writew(csr, &musbr->txcsr);
57 }
58 } else {
Bryan Wufe439d22010-08-09 14:58:24 -040059 if (!toggle) {
60 csr = readw(&musbr->txcsr);
61 if (csr & MUSB_TXCSR_MODE)
62 csr = MUSB_RXCSR_CLRDATATOG;
63 else
64 csr = 0;
65 writew(csr, &musbr->rxcsr);
66 } else {
Thomas Abraham38f424f2009-01-04 09:41:03 +053067 csr = readw(&musbr->rxcsr);
68 csr |= MUSB_RXCSR_H_WR_DATATOGGLE;
69 writew(csr, &musbr->rxcsr);
70 csr |= (toggle << MUSB_S_RXCSR_H_DATATOGGLE);
71 writew(csr, &musbr->rxcsr);
72 }
73 }
74}
75
76/*
Vagrant Cascadianedfdb992016-04-30 19:18:00 -070077 * This function checks if RxStall has occurred on the endpoint. If a RxStall
78 * has occurred, the RxStall is cleared and 1 is returned. If RxStall has
79 * not occurred, 0 is returned.
Thomas Abraham38f424f2009-01-04 09:41:03 +053080 */
81static u8 check_stall(u8 ep, u8 dir_out)
82{
83 u16 csr;
84
85 /* For endpoint 0 */
86 if (!ep) {
87 csr = readw(&musbr->txcsr);
88 if (csr & MUSB_CSR0_H_RXSTALL) {
89 csr &= ~MUSB_CSR0_H_RXSTALL;
90 writew(csr, &musbr->txcsr);
91 return 1;
92 }
93 } else { /* For non-ep0 */
94 if (dir_out) { /* is it tx ep */
95 csr = readw(&musbr->txcsr);
96 if (csr & MUSB_TXCSR_H_RXSTALL) {
97 csr &= ~MUSB_TXCSR_H_RXSTALL;
98 writew(csr, &musbr->txcsr);
99 return 1;
100 }
101 } else { /* is it rx ep */
102 csr = readw(&musbr->rxcsr);
103 if (csr & MUSB_RXCSR_H_RXSTALL) {
104 csr &= ~MUSB_RXCSR_H_RXSTALL;
105 writew(csr, &musbr->rxcsr);
106 return 1;
107 }
108 }
109 }
110 return 0;
111}
112
113/*
114 * waits until ep0 is ready. Returns 0 if ep is ready, -1 for timeout
115 * error and -2 for stall.
116 */
117static int wait_until_ep0_ready(struct usb_device *dev, u32 bit_mask)
118{
119 u16 csr;
120 int result = 1;
Paul Kocialkowskif34dfcb2015-08-04 17:04:06 +0200121 int timeout = CONFIG_USB_MUSB_TIMEOUT;
Thomas Abraham38f424f2009-01-04 09:41:03 +0530122
123 while (result > 0) {
124 csr = readw(&musbr->txcsr);
125 if (csr & MUSB_CSR0_H_ERROR) {
126 csr &= ~MUSB_CSR0_H_ERROR;
127 writew(csr, &musbr->txcsr);
128 dev->status = USB_ST_CRC_ERR;
129 result = -1;
130 break;
131 }
132
133 switch (bit_mask) {
134 case MUSB_CSR0_TXPKTRDY:
135 if (!(csr & MUSB_CSR0_TXPKTRDY)) {
136 if (check_stall(MUSB_CONTROL_EP, 0)) {
137 dev->status = USB_ST_STALLED;
138 result = -2;
139 } else
140 result = 0;
141 }
142 break;
143
144 case MUSB_CSR0_RXPKTRDY:
145 if (check_stall(MUSB_CONTROL_EP, 0)) {
146 dev->status = USB_ST_STALLED;
147 result = -2;
148 } else
149 if (csr & MUSB_CSR0_RXPKTRDY)
150 result = 0;
151 break;
152
153 case MUSB_CSR0_H_REQPKT:
154 if (!(csr & MUSB_CSR0_H_REQPKT)) {
155 if (check_stall(MUSB_CONTROL_EP, 0)) {
156 dev->status = USB_ST_STALLED;
157 result = -2;
158 } else
159 result = 0;
160 }
161 break;
162 }
Bryan Wu3169ce82009-06-16 05:26:27 -0400163
164 /* Check the timeout */
165 if (--timeout)
166 udelay(1);
167 else {
168 dev->status = USB_ST_CRC_ERR;
169 result = -1;
170 break;
171 }
Thomas Abraham38f424f2009-01-04 09:41:03 +0530172 }
Bryan Wu3169ce82009-06-16 05:26:27 -0400173
Thomas Abraham38f424f2009-01-04 09:41:03 +0530174 return result;
175}
176
177/*
178 * waits until tx ep is ready. Returns 1 when ep is ready and 0 on error.
179 */
Andrew Murrayca6dfde2013-10-01 15:58:56 +0100180static int wait_until_txep_ready(struct usb_device *dev, u8 ep)
Thomas Abraham38f424f2009-01-04 09:41:03 +0530181{
182 u16 csr;
Paul Kocialkowskif34dfcb2015-08-04 17:04:06 +0200183 int timeout = CONFIG_USB_MUSB_TIMEOUT;
Thomas Abraham38f424f2009-01-04 09:41:03 +0530184
185 do {
186 if (check_stall(ep, 1)) {
187 dev->status = USB_ST_STALLED;
188 return 0;
189 }
190
191 csr = readw(&musbr->txcsr);
192 if (csr & MUSB_TXCSR_H_ERROR) {
193 dev->status = USB_ST_CRC_ERR;
194 return 0;
195 }
Bryan Wu3169ce82009-06-16 05:26:27 -0400196
197 /* Check the timeout */
198 if (--timeout)
199 udelay(1);
200 else {
201 dev->status = USB_ST_CRC_ERR;
202 return -1;
203 }
204
Thomas Abraham38f424f2009-01-04 09:41:03 +0530205 } while (csr & MUSB_TXCSR_TXPKTRDY);
206 return 1;
207}
208
209/*
210 * waits until rx ep is ready. Returns 1 when ep is ready and 0 on error.
211 */
Andrew Murrayca6dfde2013-10-01 15:58:56 +0100212static int wait_until_rxep_ready(struct usb_device *dev, u8 ep)
Thomas Abraham38f424f2009-01-04 09:41:03 +0530213{
214 u16 csr;
Paul Kocialkowskif34dfcb2015-08-04 17:04:06 +0200215 int timeout = CONFIG_USB_MUSB_TIMEOUT;
Thomas Abraham38f424f2009-01-04 09:41:03 +0530216
217 do {
218 if (check_stall(ep, 0)) {
219 dev->status = USB_ST_STALLED;
220 return 0;
221 }
222
223 csr = readw(&musbr->rxcsr);
224 if (csr & MUSB_RXCSR_H_ERROR) {
225 dev->status = USB_ST_CRC_ERR;
226 return 0;
227 }
Bryan Wu3169ce82009-06-16 05:26:27 -0400228
229 /* Check the timeout */
230 if (--timeout)
231 udelay(1);
232 else {
233 dev->status = USB_ST_CRC_ERR;
234 return -1;
235 }
236
Thomas Abraham38f424f2009-01-04 09:41:03 +0530237 } while (!(csr & MUSB_RXCSR_RXPKTRDY));
238 return 1;
239}
240
241/*
242 * This function performs the setup phase of the control transfer
243 */
244static int ctrlreq_setup_phase(struct usb_device *dev, struct devrequest *setup)
245{
246 int result;
247 u16 csr;
248
249 /* write the control request to ep0 fifo */
250 write_fifo(MUSB_CONTROL_EP, sizeof(struct devrequest), (void *)setup);
251
252 /* enable transfer of setup packet */
253 csr = readw(&musbr->txcsr);
254 csr |= (MUSB_CSR0_TXPKTRDY|MUSB_CSR0_H_SETUPPKT);
255 writew(csr, &musbr->txcsr);
256
257 /* wait until the setup packet is transmitted */
258 result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY);
259 dev->act_len = 0;
260 return result;
261}
262
263/*
264 * This function handles the control transfer in data phase
265 */
266static int ctrlreq_in_data_phase(struct usb_device *dev, u32 len, void *buffer)
267{
268 u16 csr;
269 u32 rxlen = 0;
270 u32 nextlen = 0;
271 u8 maxpktsize = (1 << dev->maxpacketsize) * 8;
272 u8 *rxbuff = (u8 *)buffer;
273 u8 rxedlength;
274 int result;
275
276 while (rxlen < len) {
277 /* Determine the next read length */
278 nextlen = ((len-rxlen) > maxpktsize) ? maxpktsize : (len-rxlen);
279
280 /* Set the ReqPkt bit */
281 csr = readw(&musbr->txcsr);
282 writew(csr | MUSB_CSR0_H_REQPKT, &musbr->txcsr);
283 result = wait_until_ep0_ready(dev, MUSB_CSR0_RXPKTRDY);
284 if (result < 0)
285 return result;
286
287 /* Actual number of bytes received by usb */
288 rxedlength = readb(&musbr->rxcount);
289
290 /* Read the data from the RxFIFO */
291 read_fifo(MUSB_CONTROL_EP, rxedlength, &rxbuff[rxlen]);
292
293 /* Clear the RxPktRdy Bit */
294 csr = readw(&musbr->txcsr);
295 csr &= ~MUSB_CSR0_RXPKTRDY;
296 writew(csr, &musbr->txcsr);
297
298 /* short packet? */
299 if (rxedlength != nextlen) {
300 dev->act_len += rxedlength;
301 break;
302 }
303 rxlen += nextlen;
304 dev->act_len = rxlen;
305 }
306 return 0;
307}
308
309/*
310 * This function handles the control transfer out data phase
311 */
312static int ctrlreq_out_data_phase(struct usb_device *dev, u32 len, void *buffer)
313{
314 u16 csr;
315 u32 txlen = 0;
316 u32 nextlen = 0;
317 u8 maxpktsize = (1 << dev->maxpacketsize) * 8;
318 u8 *txbuff = (u8 *)buffer;
319 int result = 0;
320
321 while (txlen < len) {
322 /* Determine the next write length */
323 nextlen = ((len-txlen) > maxpktsize) ? maxpktsize : (len-txlen);
324
325 /* Load the data to send in FIFO */
326 write_fifo(MUSB_CONTROL_EP, txlen, &txbuff[txlen]);
327
328 /* Set TXPKTRDY bit */
329 csr = readw(&musbr->txcsr);
Wolfgang Denk9d328a62021-09-27 17:42:38 +0200330
Andrew Murray98529262013-09-29 18:02:22 +0100331 csr |= MUSB_CSR0_TXPKTRDY;
Andrew Murray98529262013-09-29 18:02:22 +0100332 csr |= MUSB_CSR0_H_DIS_PING;
Andrew Murray98529262013-09-29 18:02:22 +0100333 writew(csr, &musbr->txcsr);
Thomas Abraham38f424f2009-01-04 09:41:03 +0530334 result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY);
335 if (result < 0)
336 break;
337
338 txlen += nextlen;
339 dev->act_len = txlen;
340 }
341 return result;
342}
343
344/*
345 * This function handles the control transfer out status phase
346 */
347static int ctrlreq_out_status_phase(struct usb_device *dev)
348{
349 u16 csr;
350 int result;
351
352 /* Set the StatusPkt bit */
353 csr = readw(&musbr->txcsr);
Andrew Murray98529262013-09-29 18:02:22 +0100354 csr |= (MUSB_CSR0_TXPKTRDY | MUSB_CSR0_H_STATUSPKT);
Andrew Murray98529262013-09-29 18:02:22 +0100355 csr |= MUSB_CSR0_H_DIS_PING;
Thomas Abraham38f424f2009-01-04 09:41:03 +0530356 writew(csr, &musbr->txcsr);
357
358 /* Wait until TXPKTRDY bit is cleared */
359 result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY);
360 return result;
361}
362
363/*
364 * This function handles the control transfer in status phase
365 */
366static int ctrlreq_in_status_phase(struct usb_device *dev)
367{
368 u16 csr;
369 int result;
370
371 /* Set the StatusPkt bit and ReqPkt bit */
Andrew Murray98529262013-09-29 18:02:22 +0100372 csr = MUSB_CSR0_H_REQPKT | MUSB_CSR0_H_STATUSPKT;
Andrew Murray98529262013-09-29 18:02:22 +0100373 csr |= MUSB_CSR0_H_DIS_PING;
Thomas Abraham38f424f2009-01-04 09:41:03 +0530374 writew(csr, &musbr->txcsr);
375 result = wait_until_ep0_ready(dev, MUSB_CSR0_H_REQPKT);
376
377 /* clear StatusPkt bit and RxPktRdy bit */
378 csr = readw(&musbr->txcsr);
379 csr &= ~(MUSB_CSR0_RXPKTRDY | MUSB_CSR0_H_STATUSPKT);
380 writew(csr, &musbr->txcsr);
381 return result;
382}
383
384/*
385 * determines the speed of the device (High/Full/Slow)
386 */
387static u8 get_dev_speed(struct usb_device *dev)
388{
Ilya Yanoka1cf10f2012-11-06 13:48:20 +0000389 return (dev->speed == USB_SPEED_HIGH) ? MUSB_TYPE_SPEED_HIGH :
390 ((dev->speed == USB_SPEED_LOW) ? MUSB_TYPE_SPEED_LOW :
Thomas Abraham38f424f2009-01-04 09:41:03 +0530391 MUSB_TYPE_SPEED_FULL);
392}
393
394/*
395 * configure the hub address and the port address.
396 */
397static void config_hub_port(struct usb_device *dev, u8 ep)
398{
399 u8 chid;
400 u8 hub;
401
402 /* Find out the nearest parent which is high speed */
403 while (dev->parent->parent != NULL)
404 if (get_dev_speed(dev->parent) != MUSB_TYPE_SPEED_HIGH)
405 dev = dev->parent;
406 else
407 break;
408
409 /* determine the port address at that hub */
410 hub = dev->parent->devnum;
411 for (chid = 0; chid < USB_MAXCHILDREN; chid++)
412 if (dev->parent->children[chid] == dev)
413 break;
414
Bryan Wu784f1382009-12-16 22:04:00 -0500415#ifndef MUSB_NO_MULTIPOINT
Thomas Abraham38f424f2009-01-04 09:41:03 +0530416 /* configure the hub address and the port address */
417 writeb(hub, &musbr->tar[ep].txhubaddr);
418 writeb((chid + 1), &musbr->tar[ep].txhubport);
419 writeb(hub, &musbr->tar[ep].rxhubaddr);
420 writeb((chid + 1), &musbr->tar[ep].rxhubport);
Bryan Wu784f1382009-12-16 22:04:00 -0500421#endif
Thomas Abraham38f424f2009-01-04 09:41:03 +0530422}
423
Bryan Wu73073cc2010-01-09 16:53:54 -0500424#ifdef MUSB_NO_MULTIPOINT
425
426static void musb_port_reset(int do_reset)
427{
428 u8 power = readb(&musbr->power);
429
430 if (do_reset) {
431 power &= 0xf0;
432 writeb(power | MUSB_POWER_RESET, &musbr->power);
433 port_status |= USB_PORT_STAT_RESET;
434 port_status &= ~USB_PORT_STAT_ENABLE;
435 udelay(30000);
436 } else {
437 writeb(power & ~MUSB_POWER_RESET, &musbr->power);
438
439 power = readb(&musbr->power);
440 if (power & MUSB_POWER_HSMODE)
441 port_status |= USB_PORT_STAT_HIGH_SPEED;
442
443 port_status &= ~(USB_PORT_STAT_RESET | (USB_PORT_STAT_C_CONNECTION << 16));
444 port_status |= USB_PORT_STAT_ENABLE
445 | (USB_PORT_STAT_C_RESET << 16)
446 | (USB_PORT_STAT_C_ENABLE << 16);
447 }
448}
449
Thomas Abraham38f424f2009-01-04 09:41:03 +0530450/*
Bryan Wu73073cc2010-01-09 16:53:54 -0500451 * root hub control
452 */
453static int musb_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
454 void *buffer, int transfer_len,
455 struct devrequest *cmd)
456{
457 int leni = transfer_len;
458 int len = 0;
459 int stat = 0;
460 u32 datab[4];
Mike Frysinger671bc3d2010-10-20 07:15:35 -0400461 const u8 *data_buf = (u8 *) datab;
Bryan Wu73073cc2010-01-09 16:53:54 -0500462 u16 bmRType_bReq;
463 u16 wValue;
464 u16 wIndex;
465 u16 wLength;
466 u16 int_usb;
467
468 if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) {
469 debug("Root-Hub submit IRQ: NOT implemented\n");
470 return 0;
471 }
472
473 bmRType_bReq = cmd->requesttype | (cmd->request << 8);
474 wValue = swap_16(cmd->value);
475 wIndex = swap_16(cmd->index);
476 wLength = swap_16(cmd->length);
477
478 debug("--- HUB ----------------------------------------\n");
479 debug("submit rh urb, req=%x val=%#x index=%#x len=%d\n",
480 bmRType_bReq, wValue, wIndex, wLength);
481 debug("------------------------------------------------\n");
482
483 switch (bmRType_bReq) {
484 case RH_GET_STATUS:
485 debug("RH_GET_STATUS\n");
486
487 *(__u16 *) data_buf = swap_16(1);
488 len = 2;
489 break;
490
491 case RH_GET_STATUS | RH_INTERFACE:
492 debug("RH_GET_STATUS | RH_INTERFACE\n");
493
494 *(__u16 *) data_buf = swap_16(0);
495 len = 2;
496 break;
497
498 case RH_GET_STATUS | RH_ENDPOINT:
499 debug("RH_GET_STATUS | RH_ENDPOINT\n");
500
501 *(__u16 *) data_buf = swap_16(0);
502 len = 2;
503 break;
504
505 case RH_GET_STATUS | RH_CLASS:
506 debug("RH_GET_STATUS | RH_CLASS\n");
507
508 *(__u32 *) data_buf = swap_32(0);
509 len = 4;
510 break;
511
512 case RH_GET_STATUS | RH_OTHER | RH_CLASS:
513 debug("RH_GET_STATUS | RH_OTHER | RH_CLASS\n");
514
515 int_usb = readw(&musbr->intrusb);
516 if (int_usb & MUSB_INTR_CONNECT) {
517 port_status |= USB_PORT_STAT_CONNECTION
518 | (USB_PORT_STAT_C_CONNECTION << 16);
519 port_status |= USB_PORT_STAT_HIGH_SPEED
520 | USB_PORT_STAT_ENABLE;
521 }
522
523 if (port_status & USB_PORT_STAT_RESET)
524 musb_port_reset(0);
525
526 *(__u32 *) data_buf = swap_32(port_status);
527 len = 4;
528 break;
529
530 case RH_CLEAR_FEATURE | RH_ENDPOINT:
531 debug("RH_CLEAR_FEATURE | RH_ENDPOINT\n");
532
533 switch (wValue) {
534 case RH_ENDPOINT_STALL:
535 debug("C_HUB_ENDPOINT_STALL\n");
536 len = 0;
537 break;
538 }
539 port_status &= ~(1 << wValue);
540 break;
541
542 case RH_CLEAR_FEATURE | RH_CLASS:
543 debug("RH_CLEAR_FEATURE | RH_CLASS\n");
544
545 switch (wValue) {
546 case RH_C_HUB_LOCAL_POWER:
547 debug("C_HUB_LOCAL_POWER\n");
548 len = 0;
549 break;
550
551 case RH_C_HUB_OVER_CURRENT:
552 debug("C_HUB_OVER_CURRENT\n");
553 len = 0;
554 break;
555 }
556 port_status &= ~(1 << wValue);
557 break;
558
559 case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
560 debug("RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS\n");
561
562 switch (wValue) {
563 case RH_PORT_ENABLE:
564 len = 0;
565 break;
566
567 case RH_PORT_SUSPEND:
568 len = 0;
569 break;
570
571 case RH_PORT_POWER:
572 len = 0;
573 break;
574
575 case RH_C_PORT_CONNECTION:
576 len = 0;
577 break;
578
579 case RH_C_PORT_ENABLE:
580 len = 0;
581 break;
582
583 case RH_C_PORT_SUSPEND:
584 len = 0;
585 break;
586
587 case RH_C_PORT_OVER_CURRENT:
588 len = 0;
589 break;
590
591 case RH_C_PORT_RESET:
592 len = 0;
593 break;
594
595 default:
596 debug("invalid wValue\n");
597 stat = USB_ST_STALLED;
598 }
599
600 port_status &= ~(1 << wValue);
601 break;
602
603 case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
604 debug("RH_SET_FEATURE | RH_OTHER | RH_CLASS\n");
605
606 switch (wValue) {
607 case RH_PORT_SUSPEND:
608 len = 0;
609 break;
610
611 case RH_PORT_RESET:
612 musb_port_reset(1);
613 len = 0;
614 break;
615
616 case RH_PORT_POWER:
617 len = 0;
618 break;
619
620 case RH_PORT_ENABLE:
621 len = 0;
622 break;
623
624 default:
625 debug("invalid wValue\n");
626 stat = USB_ST_STALLED;
627 }
628
629 port_status |= 1 << wValue;
630 break;
631
632 case RH_SET_ADDRESS:
633 debug("RH_SET_ADDRESS\n");
634
635 rh_devnum = wValue;
636 len = 0;
637 break;
638
639 case RH_GET_DESCRIPTOR:
640 debug("RH_GET_DESCRIPTOR: %x, %d\n", wValue, wLength);
641
642 switch (wValue) {
643 case (USB_DT_DEVICE << 8): /* device descriptor */
644 len = min_t(unsigned int,
645 leni, min_t(unsigned int,
646 sizeof(root_hub_dev_des),
647 wLength));
648 data_buf = root_hub_dev_des;
649 break;
650
651 case (USB_DT_CONFIG << 8): /* configuration descriptor */
652 len = min_t(unsigned int,
653 leni, min_t(unsigned int,
654 sizeof(root_hub_config_des),
655 wLength));
656 data_buf = root_hub_config_des;
657 break;
658
659 case ((USB_DT_STRING << 8) | 0x00): /* string 0 descriptors */
660 len = min_t(unsigned int,
661 leni, min_t(unsigned int,
662 sizeof(root_hub_str_index0),
663 wLength));
664 data_buf = root_hub_str_index0;
665 break;
666
667 case ((USB_DT_STRING << 8) | 0x01): /* string 1 descriptors */
668 len = min_t(unsigned int,
669 leni, min_t(unsigned int,
670 sizeof(root_hub_str_index1),
671 wLength));
672 data_buf = root_hub_str_index1;
673 break;
674
675 default:
676 debug("invalid wValue\n");
677 stat = USB_ST_STALLED;
678 }
679
680 break;
681
Mike Frysinger671bc3d2010-10-20 07:15:35 -0400682 case RH_GET_DESCRIPTOR | RH_CLASS: {
683 u8 *_data_buf = (u8 *) datab;
Bryan Wu73073cc2010-01-09 16:53:54 -0500684 debug("RH_GET_DESCRIPTOR | RH_CLASS\n");
685
Mike Frysinger671bc3d2010-10-20 07:15:35 -0400686 _data_buf[0] = 0x09; /* min length; */
687 _data_buf[1] = 0x29;
688 _data_buf[2] = 0x1; /* 1 port */
689 _data_buf[3] = 0x01; /* per-port power switching */
690 _data_buf[3] |= 0x10; /* no overcurrent reporting */
Bryan Wu73073cc2010-01-09 16:53:54 -0500691
692 /* Corresponds to data_buf[4-7] */
Mike Frysinger671bc3d2010-10-20 07:15:35 -0400693 _data_buf[4] = 0;
694 _data_buf[5] = 5;
695 _data_buf[6] = 0;
696 _data_buf[7] = 0x02;
697 _data_buf[8] = 0xff;
Bryan Wu73073cc2010-01-09 16:53:54 -0500698
699 len = min_t(unsigned int, leni,
700 min_t(unsigned int, data_buf[0], wLength));
701 break;
Mike Frysinger671bc3d2010-10-20 07:15:35 -0400702 }
Bryan Wu73073cc2010-01-09 16:53:54 -0500703
704 case RH_GET_CONFIGURATION:
705 debug("RH_GET_CONFIGURATION\n");
706
707 *(__u8 *) data_buf = 0x01;
708 len = 1;
709 break;
710
711 case RH_SET_CONFIGURATION:
712 debug("RH_SET_CONFIGURATION\n");
713
714 len = 0;
715 break;
716
717 default:
718 debug("*** *** *** unsupported root hub command *** *** ***\n");
719 stat = USB_ST_STALLED;
720 }
721
722 len = min_t(int, len, leni);
723 if (buffer != data_buf)
724 memcpy(buffer, data_buf, len);
725
726 dev->act_len = len;
727 dev->status = stat;
Mike Frysinger68896282012-02-03 03:03:04 +0000728 debug("dev act_len %d, status %lu\n", dev->act_len, dev->status);
Bryan Wu73073cc2010-01-09 16:53:54 -0500729
730 return stat;
731}
732
733static void musb_rh_init(void)
734{
735 rh_devnum = 0;
736 port_status = 0;
737}
738
739#else
740
741static void musb_rh_init(void) {}
742
743#endif
744
745/*
Thomas Abraham38f424f2009-01-04 09:41:03 +0530746 * do a control transfer
747 */
748int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
749 int len, struct devrequest *setup)
750{
751 int devnum = usb_pipedevice(pipe);
Thomas Abraham38f424f2009-01-04 09:41:03 +0530752 u8 devspeed;
753
Bryan Wu73073cc2010-01-09 16:53:54 -0500754#ifdef MUSB_NO_MULTIPOINT
755 /* Control message is for the HUB? */
Cliff Cai94cfe2a2011-04-21 12:42:10 -0400756 if (devnum == rh_devnum) {
757 int stat = musb_submit_rh_msg(dev, pipe, buffer, len, setup);
758 if (stat)
759 return stat;
760 }
Bryan Wu73073cc2010-01-09 16:53:54 -0500761#endif
762
Thomas Abraham38f424f2009-01-04 09:41:03 +0530763 /* select control endpoint */
764 writeb(MUSB_CONTROL_EP, &musbr->index);
Anatolij Gustschinb2aed5d2011-11-19 13:12:09 +0000765 readw(&musbr->txcsr);
Thomas Abraham38f424f2009-01-04 09:41:03 +0530766
Bryan Wu784f1382009-12-16 22:04:00 -0500767#ifndef MUSB_NO_MULTIPOINT
Thomas Abraham38f424f2009-01-04 09:41:03 +0530768 /* target addr and (for multipoint) hub addr/port */
769 writeb(devnum, &musbr->tar[MUSB_CONTROL_EP].txfuncaddr);
770 writeb(devnum, &musbr->tar[MUSB_CONTROL_EP].rxfuncaddr);
Bryan Wu784f1382009-12-16 22:04:00 -0500771#endif
Thomas Abraham38f424f2009-01-04 09:41:03 +0530772
773 /* configure the hub address and the port number as required */
774 devspeed = get_dev_speed(dev);
775 if ((musb_ishighspeed()) && (dev->parent != NULL) &&
776 (devspeed != MUSB_TYPE_SPEED_HIGH)) {
777 config_hub_port(dev, MUSB_CONTROL_EP);
778 writeb(devspeed << 6, &musbr->txtype);
779 } else {
780 writeb(musb_cfg.musb_speed << 6, &musbr->txtype);
Bryan Wu784f1382009-12-16 22:04:00 -0500781#ifndef MUSB_NO_MULTIPOINT
Thomas Abraham38f424f2009-01-04 09:41:03 +0530782 writeb(0, &musbr->tar[MUSB_CONTROL_EP].txhubaddr);
783 writeb(0, &musbr->tar[MUSB_CONTROL_EP].txhubport);
784 writeb(0, &musbr->tar[MUSB_CONTROL_EP].rxhubaddr);
785 writeb(0, &musbr->tar[MUSB_CONTROL_EP].rxhubport);
Bryan Wu784f1382009-12-16 22:04:00 -0500786#endif
Thomas Abraham38f424f2009-01-04 09:41:03 +0530787 }
788
789 /* Control transfer setup phase */
790 if (ctrlreq_setup_phase(dev, setup) < 0)
791 return 0;
792
793 switch (setup->request) {
794 case USB_REQ_GET_DESCRIPTOR:
795 case USB_REQ_GET_CONFIGURATION:
796 case USB_REQ_GET_INTERFACE:
797 case USB_REQ_GET_STATUS:
798 case USB_MSC_BBB_GET_MAX_LUN:
799 /* control transfer in-data-phase */
800 if (ctrlreq_in_data_phase(dev, len, buffer) < 0)
801 return 0;
802 /* control transfer out-status-phase */
803 if (ctrlreq_out_status_phase(dev) < 0)
804 return 0;
805 break;
806
807 case USB_REQ_SET_ADDRESS:
808 case USB_REQ_SET_CONFIGURATION:
809 case USB_REQ_SET_FEATURE:
810 case USB_REQ_SET_INTERFACE:
811 case USB_REQ_CLEAR_FEATURE:
812 case USB_MSC_BBB_RESET:
813 /* control transfer in status phase */
814 if (ctrlreq_in_status_phase(dev) < 0)
815 return 0;
816 break;
817
818 case USB_REQ_SET_DESCRIPTOR:
819 /* control transfer out data phase */
820 if (ctrlreq_out_data_phase(dev, len, buffer) < 0)
821 return 0;
822 /* control transfer in status phase */
823 if (ctrlreq_in_status_phase(dev) < 0)
824 return 0;
825 break;
826
827 default:
828 /* unhandled control transfer */
829 return -1;
830 }
831
832 dev->status = 0;
833 dev->act_len = len;
Bryan Wu953ee312010-08-09 18:41:12 -0400834
835#ifdef MUSB_NO_MULTIPOINT
836 /* Set device address to USB_FADDR register */
837 if (setup->request == USB_REQ_SET_ADDRESS)
838 writeb(dev->devnum, &musbr->faddr);
839#endif
840
Thomas Abraham38f424f2009-01-04 09:41:03 +0530841 return len;
842}
843
844/*
845 * do a bulk transfer
846 */
847int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
848 void *buffer, int len)
849{
850 int dir_out = usb_pipeout(pipe);
851 int ep = usb_pipeendpoint(pipe);
Bryan Wu784f1382009-12-16 22:04:00 -0500852#ifndef MUSB_NO_MULTIPOINT
Thomas Abraham38f424f2009-01-04 09:41:03 +0530853 int devnum = usb_pipedevice(pipe);
Bryan Wu784f1382009-12-16 22:04:00 -0500854#endif
Thomas Abraham38f424f2009-01-04 09:41:03 +0530855 u8 type;
856 u16 csr;
857 u32 txlen = 0;
858 u32 nextlen = 0;
859 u8 devspeed;
860
861 /* select bulk endpoint */
862 writeb(MUSB_BULK_EP, &musbr->index);
863
Bryan Wu784f1382009-12-16 22:04:00 -0500864#ifndef MUSB_NO_MULTIPOINT
Thomas Abraham38f424f2009-01-04 09:41:03 +0530865 /* write the address of the device */
866 if (dir_out)
867 writeb(devnum, &musbr->tar[MUSB_BULK_EP].txfuncaddr);
868 else
869 writeb(devnum, &musbr->tar[MUSB_BULK_EP].rxfuncaddr);
Bryan Wu784f1382009-12-16 22:04:00 -0500870#endif
Thomas Abraham38f424f2009-01-04 09:41:03 +0530871
872 /* configure the hub address and the port number as required */
873 devspeed = get_dev_speed(dev);
874 if ((musb_ishighspeed()) && (dev->parent != NULL) &&
875 (devspeed != MUSB_TYPE_SPEED_HIGH)) {
876 /*
877 * MUSB is in high speed and the destination device is full
878 * speed device. So configure the hub address and port
879 * address registers.
880 */
881 config_hub_port(dev, MUSB_BULK_EP);
882 } else {
Bryan Wu784f1382009-12-16 22:04:00 -0500883#ifndef MUSB_NO_MULTIPOINT
Thomas Abraham38f424f2009-01-04 09:41:03 +0530884 if (dir_out) {
885 writeb(0, &musbr->tar[MUSB_BULK_EP].txhubaddr);
886 writeb(0, &musbr->tar[MUSB_BULK_EP].txhubport);
887 } else {
888 writeb(0, &musbr->tar[MUSB_BULK_EP].rxhubaddr);
889 writeb(0, &musbr->tar[MUSB_BULK_EP].rxhubport);
890 }
Bryan Wu784f1382009-12-16 22:04:00 -0500891#endif
Thomas Abraham38f424f2009-01-04 09:41:03 +0530892 devspeed = musb_cfg.musb_speed;
893 }
894
895 /* Write the saved toggle bit value */
896 write_toggle(dev, ep, dir_out);
897
898 if (dir_out) { /* bulk-out transfer */
899 /* Program the TxType register */
900 type = (devspeed << MUSB_TYPE_SPEED_SHIFT) |
901 (MUSB_TYPE_PROTO_BULK << MUSB_TYPE_PROTO_SHIFT) |
902 (ep & MUSB_TYPE_REMOTE_END);
903 writeb(type, &musbr->txtype);
904
905 /* Write maximum packet size to the TxMaxp register */
906 writew(dev->epmaxpacketout[ep], &musbr->txmaxp);
907 while (txlen < len) {
908 nextlen = ((len-txlen) < dev->epmaxpacketout[ep]) ?
909 (len-txlen) : dev->epmaxpacketout[ep];
910
911 /* Write the data to the FIFO */
912 write_fifo(MUSB_BULK_EP, nextlen,
913 (void *)(((u8 *)buffer) + txlen));
914
915 /* Set the TxPktRdy bit */
916 csr = readw(&musbr->txcsr);
917 writew(csr | MUSB_TXCSR_TXPKTRDY, &musbr->txcsr);
918
919 /* Wait until the TxPktRdy bit is cleared */
Andrew Murrayca6dfde2013-10-01 15:58:56 +0100920 if (wait_until_txep_ready(dev, MUSB_BULK_EP) != 1) {
Thomas Abraham38f424f2009-01-04 09:41:03 +0530921 readw(&musbr->txcsr);
922 usb_settoggle(dev, ep, dir_out,
923 (csr >> MUSB_TXCSR_H_DATATOGGLE_SHIFT) & 1);
924 dev->act_len = txlen;
925 return 0;
926 }
927 txlen += nextlen;
928 }
929
930 /* Keep a copy of the data toggle bit */
931 csr = readw(&musbr->txcsr);
932 usb_settoggle(dev, ep, dir_out,
933 (csr >> MUSB_TXCSR_H_DATATOGGLE_SHIFT) & 1);
934 } else { /* bulk-in transfer */
935 /* Write the saved toggle bit value */
936 write_toggle(dev, ep, dir_out);
937
938 /* Program the RxType register */
939 type = (devspeed << MUSB_TYPE_SPEED_SHIFT) |
940 (MUSB_TYPE_PROTO_BULK << MUSB_TYPE_PROTO_SHIFT) |
941 (ep & MUSB_TYPE_REMOTE_END);
942 writeb(type, &musbr->rxtype);
943
944 /* Write the maximum packet size to the RxMaxp register */
945 writew(dev->epmaxpacketin[ep], &musbr->rxmaxp);
946 while (txlen < len) {
947 nextlen = ((len-txlen) < dev->epmaxpacketin[ep]) ?
948 (len-txlen) : dev->epmaxpacketin[ep];
949
950 /* Set the ReqPkt bit */
Bryan Wu65b99d32009-12-16 22:04:01 -0500951 csr = readw(&musbr->rxcsr);
952 writew(csr | MUSB_RXCSR_H_REQPKT, &musbr->rxcsr);
Thomas Abraham38f424f2009-01-04 09:41:03 +0530953
954 /* Wait until the RxPktRdy bit is set */
Andrew Murrayca6dfde2013-10-01 15:58:56 +0100955 if (wait_until_rxep_ready(dev, MUSB_BULK_EP) != 1) {
Thomas Abraham38f424f2009-01-04 09:41:03 +0530956 csr = readw(&musbr->rxcsr);
957 usb_settoggle(dev, ep, dir_out,
958 (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
959 csr &= ~MUSB_RXCSR_RXPKTRDY;
960 writew(csr, &musbr->rxcsr);
961 dev->act_len = txlen;
962 return 0;
963 }
964
965 /* Read the data from the FIFO */
966 read_fifo(MUSB_BULK_EP, nextlen,
967 (void *)(((u8 *)buffer) + txlen));
968
969 /* Clear the RxPktRdy bit */
970 csr = readw(&musbr->rxcsr);
971 csr &= ~MUSB_RXCSR_RXPKTRDY;
972 writew(csr, &musbr->rxcsr);
973 txlen += nextlen;
974 }
975
976 /* Keep a copy of the data toggle bit */
977 csr = readw(&musbr->rxcsr);
978 usb_settoggle(dev, ep, dir_out,
979 (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
980 }
981
982 /* bulk transfer is complete */
983 dev->status = 0;
984 dev->act_len = len;
985 return 0;
986}
987
988/*
989 * This function initializes the usb controller module.
990 */
Troy Kisky8f9c49d2013-10-10 15:27:56 -0700991int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
Thomas Abraham38f424f2009-01-04 09:41:03 +0530992{
993 u8 power;
994 u32 timeout;
995
Bryan Wu73073cc2010-01-09 16:53:54 -0500996 musb_rh_init();
997
Thomas Abraham38f424f2009-01-04 09:41:03 +0530998 if (musb_platform_init() == -1)
999 return -1;
1000
1001 /* Configure all the endpoint FIFO's and start usb controller */
1002 musbr = musb_cfg.regs;
Axel Lind6272f22013-06-23 00:57:46 +08001003 musb_configure_ep(&epinfo[0], ARRAY_SIZE(epinfo));
Thomas Abraham38f424f2009-01-04 09:41:03 +05301004 musb_start();
1005
1006 /*
1007 * Wait until musb is enabled in host mode with a timeout. There
1008 * should be a usb device connected.
1009 */
1010 timeout = musb_cfg.timeout;
Matej Frančeškin36eccd22012-08-30 09:24:39 +02001011 while (--timeout)
Thomas Abraham38f424f2009-01-04 09:41:03 +05301012 if (readb(&musbr->devctl) & MUSB_DEVCTL_HM)
1013 break;
1014
1015 /* if musb core is not in host mode, then return */
1016 if (!timeout)
1017 return -1;
1018
1019 /* start usb bus reset */
1020 power = readb(&musbr->power);
1021 writeb(power | MUSB_POWER_RESET, &musbr->power);
1022
1023 /* After initiating a usb reset, wait for about 20ms to 30ms */
1024 udelay(30000);
1025
1026 /* stop usb bus reset */
1027 power = readb(&musbr->power);
1028 power &= ~MUSB_POWER_RESET;
1029 writeb(power, &musbr->power);
1030
1031 /* Determine if the connected device is a high/full/low speed device */
1032 musb_cfg.musb_speed = (readb(&musbr->power) & MUSB_POWER_HSMODE) ?
1033 MUSB_TYPE_SPEED_HIGH :
1034 ((readb(&musbr->devctl) & MUSB_DEVCTL_FSDEV) ?
1035 MUSB_TYPE_SPEED_FULL : MUSB_TYPE_SPEED_LOW);
1036 return 0;
1037}
1038
1039/*
1040 * This function stops the operation of the davinci usb module.
1041 */
Lucas Stacha3231282012-09-26 00:14:34 +02001042int usb_lowlevel_stop(int index)
Thomas Abraham38f424f2009-01-04 09:41:03 +05301043{
1044 /* Reset the USB module */
1045 musb_platform_deinit();
1046 writeb(0, &musbr->devctl);
1047 return 0;
1048}
1049
1050/*
1051 * This function supports usb interrupt transfers. Currently, usb interrupt
1052 * transfers are not supported.
1053 */
Jean-Jacques Hiblot4f34e362019-09-11 09:44:10 +02001054int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
1055 int len, int interval, bool nonblock)
Thomas Abraham38f424f2009-01-04 09:41:03 +05301056{
1057 int dir_out = usb_pipeout(pipe);
1058 int ep = usb_pipeendpoint(pipe);
Bryan Wu784f1382009-12-16 22:04:00 -05001059#ifndef MUSB_NO_MULTIPOINT
Thomas Abraham38f424f2009-01-04 09:41:03 +05301060 int devnum = usb_pipedevice(pipe);
Bryan Wu784f1382009-12-16 22:04:00 -05001061#endif
Thomas Abraham38f424f2009-01-04 09:41:03 +05301062 u8 type;
1063 u16 csr;
1064 u32 txlen = 0;
1065 u32 nextlen = 0;
1066 u8 devspeed;
1067
1068 /* select interrupt endpoint */
1069 writeb(MUSB_INTR_EP, &musbr->index);
1070
Bryan Wu784f1382009-12-16 22:04:00 -05001071#ifndef MUSB_NO_MULTIPOINT
Thomas Abraham38f424f2009-01-04 09:41:03 +05301072 /* write the address of the device */
1073 if (dir_out)
1074 writeb(devnum, &musbr->tar[MUSB_INTR_EP].txfuncaddr);
1075 else
1076 writeb(devnum, &musbr->tar[MUSB_INTR_EP].rxfuncaddr);
Bryan Wu784f1382009-12-16 22:04:00 -05001077#endif
Thomas Abraham38f424f2009-01-04 09:41:03 +05301078
1079 /* configure the hub address and the port number as required */
1080 devspeed = get_dev_speed(dev);
1081 if ((musb_ishighspeed()) && (dev->parent != NULL) &&
1082 (devspeed != MUSB_TYPE_SPEED_HIGH)) {
1083 /*
1084 * MUSB is in high speed and the destination device is full
1085 * speed device. So configure the hub address and port
1086 * address registers.
1087 */
1088 config_hub_port(dev, MUSB_INTR_EP);
1089 } else {
Bryan Wu784f1382009-12-16 22:04:00 -05001090#ifndef MUSB_NO_MULTIPOINT
Thomas Abraham38f424f2009-01-04 09:41:03 +05301091 if (dir_out) {
1092 writeb(0, &musbr->tar[MUSB_INTR_EP].txhubaddr);
1093 writeb(0, &musbr->tar[MUSB_INTR_EP].txhubport);
1094 } else {
1095 writeb(0, &musbr->tar[MUSB_INTR_EP].rxhubaddr);
1096 writeb(0, &musbr->tar[MUSB_INTR_EP].rxhubport);
1097 }
Bryan Wu784f1382009-12-16 22:04:00 -05001098#endif
Thomas Abraham38f424f2009-01-04 09:41:03 +05301099 devspeed = musb_cfg.musb_speed;
1100 }
1101
1102 /* Write the saved toggle bit value */
1103 write_toggle(dev, ep, dir_out);
1104
1105 if (!dir_out) { /* intrrupt-in transfer */
1106 /* Write the saved toggle bit value */
1107 write_toggle(dev, ep, dir_out);
1108 writeb(interval, &musbr->rxinterval);
1109
1110 /* Program the RxType register */
1111 type = (devspeed << MUSB_TYPE_SPEED_SHIFT) |
1112 (MUSB_TYPE_PROTO_INTR << MUSB_TYPE_PROTO_SHIFT) |
1113 (ep & MUSB_TYPE_REMOTE_END);
1114 writeb(type, &musbr->rxtype);
1115
1116 /* Write the maximum packet size to the RxMaxp register */
1117 writew(dev->epmaxpacketin[ep], &musbr->rxmaxp);
1118
1119 while (txlen < len) {
1120 nextlen = ((len-txlen) < dev->epmaxpacketin[ep]) ?
1121 (len-txlen) : dev->epmaxpacketin[ep];
1122
1123 /* Set the ReqPkt bit */
Bryan Wu65b99d32009-12-16 22:04:01 -05001124 csr = readw(&musbr->rxcsr);
1125 writew(csr | MUSB_RXCSR_H_REQPKT, &musbr->rxcsr);
Thomas Abraham38f424f2009-01-04 09:41:03 +05301126
1127 /* Wait until the RxPktRdy bit is set */
Andrew Murrayca6dfde2013-10-01 15:58:56 +01001128 if (wait_until_rxep_ready(dev, MUSB_INTR_EP) != 1) {
Thomas Abraham38f424f2009-01-04 09:41:03 +05301129 csr = readw(&musbr->rxcsr);
1130 usb_settoggle(dev, ep, dir_out,
1131 (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
1132 csr &= ~MUSB_RXCSR_RXPKTRDY;
1133 writew(csr, &musbr->rxcsr);
1134 dev->act_len = txlen;
1135 return 0;
1136 }
1137
1138 /* Read the data from the FIFO */
1139 read_fifo(MUSB_INTR_EP, nextlen,
1140 (void *)(((u8 *)buffer) + txlen));
1141
1142 /* Clear the RxPktRdy bit */
1143 csr = readw(&musbr->rxcsr);
1144 csr &= ~MUSB_RXCSR_RXPKTRDY;
1145 writew(csr, &musbr->rxcsr);
1146 txlen += nextlen;
1147 }
1148
1149 /* Keep a copy of the data toggle bit */
1150 csr = readw(&musbr->rxcsr);
1151 usb_settoggle(dev, ep, dir_out,
1152 (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
1153 }
1154
1155 /* interrupt transfer is complete */
1156 dev->irq_status = 0;
1157 dev->irq_act_len = len;
1158 dev->irq_handle(dev);
1159 dev->status = 0;
1160 dev->act_len = len;
1161 return 0;
1162}