summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_jz47xx/usb-jz4760.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips/ingenic_jz47xx/usb-jz4760.c')
-rw-r--r--firmware/target/mips/ingenic_jz47xx/usb-jz4760.c870
1 files changed, 870 insertions, 0 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4760.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4760.c
new file mode 100644
index 0000000000..bc2158fb6f
--- /dev/null
+++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4760.c
@@ -0,0 +1,870 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2016 by Roman Stolyarov
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23/*#define LOGF_ENABLE*/
24#include "logf.h"
25#include "system.h"
26#include "usb_ch9.h"
27#include "usb_drv.h"
28#include "usb_core.h"
29#include "cpu.h"
30#include "thread.h"
31
32#define PIN_USB_DET (32*4+19)
33#define IRQ_USB_DET GPIO_IRQ(PIN_USB_DET)
34#define GPIO_USB_DET GPIO147
35
36#define PIN_USB_DRVVBUS (32*4+10)
37#define PIN_USB_OTG_ID (32*3+7)
38
39#define EP_BUF_LEFT(ep) ((ep)->length - (ep)->sent)
40#define EP_PTR(ep) ((void*)((unsigned int)(ep)->buf + (ep)->sent))
41#define EP_NUMBER(ep) (((int)(ep) - (int)&endpoints[0])/sizeof(struct usb_endpoint))
42#define EP_NUMBER2(ep) (EP_NUMBER((ep))/2)
43#define TOTAL_EP() (sizeof(endpoints)/sizeof(struct usb_endpoint))
44#define EP_IS_IN(ep) (EP_NUMBER((ep))%2)
45
46enum ep_type
47{
48 ep_control,
49 ep_bulk,
50 ep_interrupt,
51 ep_isochronous
52};
53
54struct usb_endpoint
55{
56 void *buf;
57 size_t length;
58 union
59 {
60 size_t sent;
61 size_t received;
62 };
63 bool busy;
64
65 const enum ep_type type;
66 const bool use_dma;
67
68 const long fifo_addr;
69 unsigned short fifo_size;
70
71 bool wait;
72 struct semaphore complete;
73};
74
75#define EP_INIT(_type, _fifo_addr, _fifo_size, _buf, _use_dma) \
76 { .type = (_type), .fifo_addr = (_fifo_addr), .fifo_size = (_fifo_size), \
77 .buf = (_buf), .use_dma = (_use_dma), .length = 0, .busy = false, .wait = false }
78
79static unsigned char ep0_rx_buf[64];
80static struct usb_endpoint endpoints[] =
81{
82 EP_INIT(ep_control, USB_FIFO_EP(0), 64, NULL, false),
83 EP_INIT(ep_control, USB_FIFO_EP(0), 64, &ep0_rx_buf, false),
84 EP_INIT(ep_bulk, USB_FIFO_EP(1), 512, NULL, false),
85 EP_INIT(ep_bulk, USB_FIFO_EP(1), 512, NULL, false),
86 EP_INIT(ep_interrupt, USB_FIFO_EP(2), 64, NULL, false),
87 EP_INIT(ep_interrupt, USB_FIFO_EP(2), 64, NULL, false),
88};
89
90static inline void select_endpoint(int ep)
91{
92 REG_USB_INDEX = ep;
93}
94
95static void readFIFO(struct usb_endpoint *ep, unsigned int size)
96{
97 logf("%s(EP%d, %d)", __func__, EP_NUMBER2(ep), size);
98
99 register unsigned char *ptr = (unsigned char*)EP_PTR(ep);
100 register unsigned int *ptr32 = (unsigned int*)ptr;
101 register unsigned int s = size >> 2;
102 register unsigned int x;
103
104 if(size > 0)
105 {
106 if( ((unsigned int)ptr & 3) == 0 )
107 {
108 while(s--)
109 *ptr32++ = REG32(ep->fifo_addr);
110
111 ptr = (unsigned char*)ptr32;
112 }
113 else
114 {
115 while(s--)
116 {
117 x = REG32(ep->fifo_addr);
118 *ptr++ = x & 0xFF; x >>= 8;
119 *ptr++ = x & 0xFF; x >>= 8;
120 *ptr++ = x & 0xFF; x >>= 8;
121 *ptr++ = x;
122 }
123 }
124
125 s = size & 3;
126 while(s--)
127 *ptr++ = REG8(ep->fifo_addr);
128 }
129}
130
131static void writeFIFO(struct usb_endpoint *ep, size_t size)
132{
133 logf("%s(EP%d, %d)", __func__, EP_NUMBER2(ep), size);
134
135 register unsigned int *d32 = (unsigned int *)EP_PTR(ep);
136 register size_t s = size >> 2;
137
138 if(size > 0)
139 {
140 while (s--)
141 REG32(ep->fifo_addr) = *d32++;
142
143 if( (s = size & 3) )
144 {
145 register unsigned char *d8 = (unsigned char *)d32;
146 while (s--)
147 REG8(ep->fifo_addr) = *d8++;
148 }
149 }
150}
151
152static void flushFIFO(struct usb_endpoint *ep)
153{
154 logf("%s(%d)", __func__, EP_NUMBER(ep));
155
156 switch (ep->type)
157 {
158 case ep_control:
159 break;
160
161 case ep_bulk:
162 case ep_interrupt:
163 case ep_isochronous:
164 if(EP_IS_IN(ep))
165 REG_USB_INCSR |= (USB_INCSR_FF | USB_INCSR_CDT);
166 else
167 REG_USB_OUTCSR |= (USB_OUTCSR_FF | USB_OUTCSR_CDT);
168 break;
169 }
170}
171
172static inline void ep_transfer_completed(struct usb_endpoint* ep)
173{
174 ep->sent = 0;
175 ep->length = 0;
176 ep->buf = NULL;
177 ep->busy = false;
178 if(ep->wait)
179 semaphore_release(&ep->complete);
180}
181
182static void EP0_send(void)
183{
184 struct usb_endpoint* ep = &endpoints[0];
185 unsigned int length;
186 unsigned char csr0;
187
188 select_endpoint(0);
189 csr0 = REG_USB_CSR0;
190
191 if(ep->sent == 0)
192 length = MIN(ep->length, ep->fifo_size);
193 else
194 length = MIN(EP_BUF_LEFT(ep), ep->fifo_size);
195
196 writeFIFO(ep, length);
197 ep->sent += length;
198
199 if(ep->sent >= ep->length)
200 {
201 REG_USB_CSR0 = (csr0 | USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */
202 usb_core_transfer_complete(0, USB_DIR_IN, 0, ep->sent);
203 ep_transfer_completed(ep);
204 }
205 else
206 REG_USB_CSR0 = (csr0 | USB_CSR0_INPKTRDY);
207}
208
209static void EP0_handler(void)
210{
211 logf("%s()", __func__);
212
213 unsigned char csr0;
214 struct usb_endpoint *ep_send = &endpoints[0];
215 struct usb_endpoint *ep_recv = &endpoints[1];
216
217 /* Read CSR0 */
218 select_endpoint(0);
219 csr0 = REG_USB_CSR0;
220
221 /* Check for SentStall:
222 This bit is set when a STALL handshake is transmitted. The CPU should clear this bit.
223 */
224 if(csr0 & USB_CSR0_SENTSTALL)
225 {
226 REG_USB_CSR0 = csr0 & ~USB_CSR0_SENTSTALL;
227 return;
228 }
229
230 /* Check for SetupEnd:
231 This bit will be set when a control transaction ends before the DataEnd bit has been set.
232 An interrupt will be generated and the FIFO flushed at this time.
233 The bit is cleared by the CPU writing a 1 to the ServicedSetupEnd bit.
234 */
235 if(csr0 & USB_CSR0_SETUPEND)
236 {
237 REG_USB_CSR0 = csr0 | USB_CSR0_SVDSETUPEND;
238 return;
239 }
240
241 /* Call relevant routines for endpoint 0 state */
242 if(ep_send->busy)
243 EP0_send();
244 else if(csr0 & USB_CSR0_OUTPKTRDY) /* There is a packet in the fifo */
245 {
246 readFIFO(ep_recv, REG_USB_COUNT0);
247 REG_USB_CSR0 = csr0 | USB_CSR0_SVDOUTPKTRDY; /* clear OUTPKTRDY bit */
248 usb_core_control_request((struct usb_ctrlrequest*)ep_recv->buf);
249 }
250}
251
252static void EPIN_handler(unsigned int endpoint)
253{
254 struct usb_endpoint* ep = &endpoints[endpoint*2];
255 unsigned int length, csr;
256
257 select_endpoint(endpoint);
258 csr = REG_USB_INCSR;
259 logf("%s(%d): 0x%x", __func__, endpoint, csr);
260
261 if(!ep->busy)
262 {
263 logf("Entered EPIN handler without work!");
264 return;
265 }
266
267 if(csr & USB_INCSR_SENTSTALL)
268 {
269 REG_USB_INCSR = csr & ~USB_INCSR_SENTSTALL;
270 return;
271 }
272
273 if(ep->use_dma)
274 return;
275
276 if(csr & USB_INCSR_FFNOTEMPT)
277 {
278 logf("FIFO is not empty! 0x%x", csr);
279 return;
280 }
281
282 logf("EP%d: %d -> %d", endpoint, ep->sent, ep->length);
283
284 if(ep->sent == 0)
285 length = MIN(ep->length, ep->fifo_size);
286 else
287 length = MIN(EP_BUF_LEFT(ep), ep->fifo_size);
288
289 writeFIFO(ep, length);
290 REG_USB_INCSR = csr | USB_INCSR_INPKTRDY;
291 ep->sent += length;
292
293 if(ep->sent >= ep->length)
294 {
295 usb_core_transfer_complete(endpoint, USB_DIR_IN, 0, ep->sent);
296 ep_transfer_completed(ep);
297 logf("sent complete");
298 }
299}
300
301static void EPOUT_handler(unsigned int endpoint)
302{
303 struct usb_endpoint* ep = &endpoints[endpoint*2+1];
304 unsigned int size, csr;
305
306 if(!ep->busy)
307 {
308 logf("Entered EPOUT handler without work!");
309 return;
310 }
311
312 select_endpoint(endpoint);
313 while((csr = REG_USB_OUTCSR) & (USB_OUTCSR_SENTSTALL|USB_OUTCSR_OUTPKTRDY))
314 {
315 logf("%s(%d): 0x%x", __func__, endpoint, csr);
316 if(csr & USB_OUTCSR_SENTSTALL)
317 {
318 logf("stall sent, flushing fifo..");
319 flushFIFO(ep);
320 REG_USB_OUTCSR = csr & ~USB_OUTCSR_SENTSTALL;
321 return;
322 }
323
324 if(ep->use_dma)
325 return;
326
327 if(csr & USB_OUTCSR_OUTPKTRDY) /* There is a packet in the fifo */
328 {
329 size = REG_USB_OUTCOUNT;
330
331 readFIFO(ep, size);
332 ep->received += size;
333
334 /*if(csr & USB_OUTCSR_FFFULL)
335 csr &= ~USB_OUTCSR_FFFULL;*/
336
337 REG_USB_OUTCSR = csr & ~USB_OUTCSR_OUTPKTRDY;
338
339 logf("received: %d max length: %d", ep->received, ep->length);
340
341 if(size < ep->fifo_size || ep->received >= ep->length)
342 {
343 usb_core_transfer_complete(endpoint, USB_DIR_OUT, 0, ep->received);
344 ep_transfer_completed(ep);
345 logf("receive transfer_complete");
346 }
347 }
348 }
349}
350
351static void EPDMA_handler(int number)
352{
353 int endpoint = -1;
354 unsigned int size = 0;
355
356 if(number == USB_INTR_DMA_BULKIN)
357 endpoint = (REG_USB_CNTL(0) >> 4) & 0xF;
358 else if(number == USB_INTR_DMA_BULKOUT)
359 endpoint = (REG_USB_CNTL(1) >> 4) & 0xF;
360
361 struct usb_endpoint* ep = &endpoints[endpoint];
362 logf("DMA_BULK%d %d", number, endpoint);
363
364 if(number == USB_INTR_DMA_BULKIN)
365 size = (unsigned int)ep->buf - REG_USB_ADDR(0);
366 else if(number == USB_INTR_DMA_BULKOUT)
367 size = (unsigned int)ep->buf - REG_USB_ADDR(1);
368
369 if(number == USB_INTR_DMA_BULKOUT)
370 {
371 /* Disable DMA */
372 REG_USB_CNTL(1) = 0;
373
374 __dcache_invalidate_all();
375
376 select_endpoint(endpoint);
377 /* Read out last packet manually */
378 unsigned int lpack_size = REG_USB_OUTCOUNT;
379 if(lpack_size > 0)
380 {
381 ep->buf += ep->length - lpack_size;
382 readFIFO(ep, lpack_size);
383 REG_USB_OUTCSR &= ~USB_OUTCSR_OUTPKTRDY;
384 }
385 }
386 else if(number == USB_INTR_DMA_BULKIN && size % ep->fifo_size)
387 {
388 /* If the last packet is less than MAXP, set INPKTRDY manually */
389 REG_USB_INCSR |= USB_INCSR_INPKTRDY;
390 }
391
392 usb_core_transfer_complete(endpoint, EP_IS_IN(ep) ? USB_DIR_IN : USB_DIR_OUT,
393 0, ep->length);
394 ep_transfer_completed(ep);
395}
396
397static void setup_endpoint(struct usb_endpoint *ep)
398{
399 int csr, csrh;
400
401 select_endpoint(EP_NUMBER2(ep));
402
403 ep->busy = false;
404 ep->wait = false;
405 ep->sent = 0;
406 ep->length = 0;
407
408 if(ep->type == ep_bulk)
409 {
410 if(REG_USB_POWER & USB_POWER_HSMODE)
411 ep->fifo_size = 512;
412 else
413 ep->fifo_size = 64;
414 }
415
416 if(EP_IS_IN(ep))
417 {
418 csr = (USB_INCSR_FF | USB_INCSR_CDT);
419 csrh = USB_INCSRH_MODE;
420
421 if(ep->use_dma)
422 csrh |= (USB_INCSRH_DMAREQENAB | USB_INCSRH_AUTOSET | USB_INCSRH_DMAREQMODE);
423
424 if(ep->type == ep_interrupt)
425 csrh |= USB_INCSRH_FRCDATATOG;
426
427 REG_USB_INMAXP = ep->fifo_size;
428 REG_USB_INCSR = csr;
429 REG_USB_INCSRH = csrh;
430 REG_USB_INTRINE |= USB_INTR_EP(EP_NUMBER2(ep));
431 }
432 else
433 {
434 csr = (USB_OUTCSR_FF | USB_OUTCSR_CDT);
435 csrh = 0;
436
437 if(ep->type == ep_interrupt)
438 csrh |= USB_OUTCSRH_DNYT;
439
440 if(ep->use_dma)
441 csrh |= (USB_OUTCSRH_DMAREQENAB | USB_OUTCSRH_AUTOCLR | USB_OUTCSRH_DMAREQMODE);
442
443 REG_USB_OUTMAXP = ep->fifo_size;
444 REG_USB_OUTCSR = csr;
445 REG_USB_OUTCSRH = csrh;
446 REG_USB_INTROUTE |= USB_INTR_EP(EP_NUMBER2(ep));
447 }
448}
449
450static void udc_reset(void)
451{
452 /* From the datasheet:
453
454 When a reset condition is detected on the USB, the controller performs the following actions:
455 * Sets FAddr to 0.
456 * Sets Index to 0.
457 * Flushes all endpoint FIFOs.
458 * Clears all control/status registers.
459 * Enables all endpoint interrupts.
460 * Generates a Reset interrupt.
461 */
462
463 logf("%s()", __func__);
464
465 unsigned int i;
466
467 REG_USB_FADDR = 0;
468 REG_USB_INDEX = 0;
469
470 /* Disable interrupts */
471 REG_USB_INTRINE = 0;
472 REG_USB_INTROUTE = 0;
473 REG_USB_INTRUSBE = 0;
474
475 /* Disable DMA */
476 REG_USB_CNTL(0) = 0;
477 REG_USB_CNTL(1) = 0;
478
479 /* High speed, softconnect */
480 REG_USB_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB);
481
482 /* Reset EP0 */
483 select_endpoint(0);
484 REG_USB_CSR0 = (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_SVDSETUPEND | USB_CSR0_FLUSHFIFO);
485
486 /* Reset other endpoints */
487 for(i=2; i<TOTAL_EP(); i++)
488 setup_endpoint(&endpoints[i]);
489
490 /* Enable interrupts */
491 REG_USB_INTRINE |= USB_INTR_EP(0);
492 REG_USB_INTRUSBE |= USB_INTR_RESET;
493
494 usb_core_bus_reset();
495}
496
497/* Interrupt handler */
498void OTG(void)
499{
500 /* Read interrupt registers */
501 unsigned char intrUSB = REG_USB_INTRUSB & 0x07; /* Mask SOF */
502 unsigned short intrIn = REG_USB_INTRIN;
503 unsigned short intrOut = REG_USB_INTROUT;
504 unsigned char intrDMA = REG_USB_INTR;
505
506 logf("%x %x %x %x", intrUSB, intrIn, intrOut, intrDMA);
507
508 /* EPIN & EPOUT are all handled in DMA */
509 if(intrIn & USB_INTR_EP(0))
510 EP0_handler();
511 if(intrIn & USB_INTR_EP(1))
512 EPIN_handler(1);
513 if(intrIn & USB_INTR_EP(2))
514 EPIN_handler(2);
515 if(intrOut & USB_INTR_EP(1))
516 EPOUT_handler(1);
517 if(intrOut & USB_INTR_EP(2))
518 EPOUT_handler(2);
519 if(intrUSB & USB_INTR_RESET)
520 udc_reset();
521 if(intrUSB & USB_INTR_SUSPEND)
522 logf("USB suspend");
523 if(intrUSB & USB_INTR_RESUME)
524 logf("USB resume");
525 if(intrDMA & USB_INTR_DMA_BULKIN)
526 EPDMA_handler(USB_INTR_DMA_BULKIN);
527 if(intrDMA & USB_INTR_DMA_BULKOUT)
528 EPDMA_handler(USB_INTR_DMA_BULKOUT);
529}
530
531bool usb_drv_stalled(int endpoint, bool in)
532{
533 endpoint &= 0x7F;
534
535 logf("%s(%d, %s)", __func__, endpoint, in?"IN":"OUT");
536
537 select_endpoint(endpoint);
538
539 if(endpoint == EP_CONTROL)
540 return (REG_USB_CSR0 & USB_CSR0_SENDSTALL) != 0;
541 else
542 {
543 if(in)
544 return (REG_USB_INCSR & USB_INCSR_SENDSTALL) != 0;
545 else
546 return (REG_USB_OUTCSR & USB_OUTCSR_SENDSTALL) != 0;
547 }
548}
549
550void usb_drv_stall(int endpoint, bool stall, bool in)
551{
552 endpoint &= 0x7F;
553
554 logf("%s(%d,%s,%s)", __func__, endpoint, stall?"Y":"N", in?"IN":"OUT");
555
556 select_endpoint(endpoint);
557
558 if(endpoint == EP_CONTROL)
559 {
560 if(stall)
561 REG_USB_CSR0 |= USB_CSR0_SENDSTALL;
562 else
563 REG_USB_CSR0 &= ~USB_CSR0_SENDSTALL;
564 }
565 else
566 {
567 if(in)
568 {
569 if(stall)
570 REG_USB_INCSR |= USB_INCSR_SENDSTALL;
571 else
572 REG_USB_INCSR = (REG_USB_INCSR & ~USB_INCSR_SENDSTALL) | USB_INCSR_CDT;
573 }
574 else
575 {
576 if(stall)
577 REG_USB_OUTCSR |= USB_OUTCSR_SENDSTALL;
578 else
579 REG_USB_OUTCSR = (REG_USB_OUTCSR & ~USB_OUTCSR_SENDSTALL) | USB_OUTCSR_CDT;
580 }
581 }
582}
583
584int usb_detect(void)
585{
586 return (__gpio_get_pin(PIN_USB_DET) == 1)
587 ? USB_INSERTED : USB_EXTRACTED;
588}
589
590void usb_init_device(void)
591{
592 __gpio_clear_pin(PIN_USB_DRVVBUS);
593 __gpio_as_output(PIN_USB_DRVVBUS);
594
595 __gpio_as_input(PIN_USB_OTG_ID);
596 __gpio_as_input(PIN_USB_DET);
597
598 __gpio_disable_pull(PIN_USB_OTG_ID);
599 __gpio_disable_pull(PIN_USB_DET);
600
601#ifdef USB_STATUS_BY_EVENT
602 __gpio_as_irq_rise_edge(PIN_USB_DET);
603 system_enable_irq(IRQ_USB_DET);
604#endif
605
606 system_enable_irq(IRQ_OTG);
607
608 for(unsigned i=0; i<TOTAL_EP(); i++)
609 semaphore_init(&endpoints[i].complete, 1, 0);
610}
611
612#ifdef USB_STATUS_BY_EVENT
613static int usb_oneshot_callback(struct timeout *tmo)
614{
615 (void)tmo;
616 int state = usb_detect();
617
618 /* This is called only if the state was stable for HZ/16 - check state
619 * and post appropriate event. */
620 usb_status_event(state);
621
622 if(state == USB_EXTRACTED)
623 __gpio_as_irq_rise_edge(PIN_USB_DET);
624 else
625 __gpio_as_irq_fall_edge(PIN_USB_DET);
626
627 return 0;
628}
629
630void GPIO_USB_DET(void)
631{
632 static struct timeout usb_oneshot;
633 timeout_register(&usb_oneshot, usb_oneshot_callback, (HZ/16), 0);
634}
635#endif
636
637void usb_enable(bool on)
638{
639 if(on)
640 usb_core_init();
641 else
642 usb_core_exit();
643}
644
645void usb_attach(void)
646{
647 usb_enable(true);
648}
649
650void usb_drv_init(void)
651{
652 logf("%s()", __func__);
653
654 /* Dis- and reconnect from USB */
655 REG_USB_POWER &= ~USB_POWER_SOFTCONN;
656 mdelay(20);
657 REG_USB_POWER |= USB_POWER_SOFTCONN;
658 mdelay(20);
659
660 udc_reset();
661}
662
663void usb_drv_exit(void)
664{
665 logf("%s()", __func__);
666
667 REG_USB_FADDR = 0;
668 REG_USB_INDEX = 0;
669
670 /* Disable interrupts */
671 REG_USB_INTRINE = 0;
672 REG_USB_INTROUTE = 0;
673 REG_USB_INTRUSBE = 0;
674
675 /* Disable DMA */
676 REG_USB_CNTL(0) = 0;
677 REG_USB_CNTL(1) = 0;
678
679 /* Disconnect from USB */
680 REG_USB_POWER &= ~USB_POWER_SOFTCONN;
681}
682
683void usb_drv_set_address(int address)
684{
685 logf("%s(%d)", __func__, address);
686
687 REG_USB_FADDR = address;
688}
689
690static void usb_drv_send_internal(struct usb_endpoint* ep, void* ptr, int length, bool blocking)
691{
692 if(ep->type == ep_control && ptr == NULL && length == 0)
693 return; /* ACK request, handled in the ISR */
694
695 int flags = disable_irq_save();
696
697 ep->buf = ptr;
698 ep->sent = 0;
699 ep->length = length;
700 ep->busy = true;
701 if(blocking)
702 ep->wait = true;
703
704 if(ep->type == ep_control)
705 {
706 EP0_send();
707 }
708 else
709 {
710 if(ep->use_dma)
711 {
712 //dma_cache_wback_inv((unsigned long)ptr, length);
713 __dcache_writeback_all();
714 REG_USB_ADDR(0) = PHYSADDR((unsigned long)ptr);
715 REG_USB_COUNT(0) = length;
716 REG_USB_CNTL(0) = (USB_CNTL_INTR_EN | USB_CNTL_MODE_1 |
717 USB_CNTL_DIR_IN | USB_CNTL_ENA |
718 USB_CNTL_EP(EP_NUMBER2(ep)) | USB_CNTL_BURST_16);
719 }
720 else
721 EPIN_handler(EP_NUMBER2(ep));
722 }
723
724 restore_irq(flags);
725
726 if(blocking)
727 {
728 semaphore_wait(&ep->complete, TIMEOUT_BLOCK);
729 ep->wait = false;
730 }
731}
732
733int usb_drv_send_nonblocking(int endpoint, void* ptr, int length)
734{
735 logf("%s(%d, 0x%x, %d)", __func__, endpoint, (int)ptr, length);
736
737 usb_drv_send_internal(&endpoints[(endpoint & 0x7F)*2], ptr, length, false);
738
739 return 0;
740}
741
742int usb_drv_send(int endpoint, void* ptr, int length)
743{
744 logf("%s(%d, 0x%x, %d)", __func__, endpoint, (int)ptr, length);
745
746 usb_drv_send_internal(&endpoints[(endpoint & 0x7F)*2], ptr, length, true);
747
748 return 0;
749}
750
751int usb_drv_recv(int endpoint, void* ptr, int length)
752{
753 int flags;
754 struct usb_endpoint *ep;
755 endpoint &= 0x7F;
756
757 logf("%s(%d, 0x%x, %d)", __func__, endpoint, (int)ptr, length);
758
759 if(endpoint == EP_CONTROL)
760 return 0; /* all EP0 OUT transactions are handled within the ISR */
761 else
762 {
763 flags = disable_irq_save();
764 ep = &endpoints[endpoint*2+1];
765
766 ep->buf = ptr;
767 ep->received = 0;
768 ep->length = length;
769 ep->busy = true;
770 if(ep->use_dma)
771 {
772 //dma_cache_wback_inv((unsigned long)ptr, length);
773 __dcache_writeback_all();
774 REG_USB_ADDR(1) = PHYSADDR((unsigned long)ptr);
775 REG_USB_COUNT(1) = length;
776 REG_USB_CNTL(1) = (USB_CNTL_INTR_EN | USB_CNTL_MODE_1 |
777 USB_CNTL_ENA | USB_CNTL_EP(endpoint) |
778 USB_CNTL_BURST_16);
779 }
780 else
781 EPOUT_handler(endpoint);
782
783 restore_irq(flags);
784 return 0;
785 }
786}
787
788void usb_drv_set_test_mode(int mode)
789{
790 logf("%s(%d)", __func__, mode);
791
792 switch(mode)
793 {
794 case 0:
795 REG_USB_TESTMODE &= ~USB_TEST_ALL;
796 break;
797 case 1:
798 REG_USB_TESTMODE |= USB_TEST_J;
799 break;
800 case 2:
801 REG_USB_TESTMODE |= USB_TEST_K;
802 break;
803 case 3:
804 REG_USB_TESTMODE |= USB_TEST_SE0NAK;
805 break;
806 case 4:
807 REG_USB_TESTMODE |= USB_TEST_PACKET;
808 break;
809 }
810}
811
812int usb_drv_port_speed(void)
813{
814 return (REG_USB_POWER & USB_POWER_HSMODE) ? 1 : 0;
815}
816
817void usb_drv_cancel_all_transfers(void)
818{
819 logf("%s()", __func__);
820
821 unsigned int i, flags;
822 flags = disable_irq_save();
823
824 for(i=0; i<TOTAL_EP(); i++)
825 {
826 if(i != 1) /* ep0 out needs special handling */
827 endpoints[i].buf = NULL;
828
829 endpoints[i].sent = 0;
830 endpoints[i].length = 0;
831
832 select_endpoint(i/2);
833 flushFIFO(&endpoints[i]);
834 }
835 restore_irq(flags);
836}
837
838
839void usb_drv_release_endpoint(int ep)
840{
841 (void)ep;
842 logf("%s(%d, %s)", __func__, (ep & 0x7F), (ep >> 7) ? "IN" : "OUT");
843}
844
845int usb_drv_request_endpoint(int type, int dir)
846{
847 logf("%s(%d, %s)", __func__, type, (dir == USB_DIR_IN) ? "IN" : "OUT");
848
849 dir &= USB_ENDPOINT_DIR_MASK;
850 type &= USB_ENDPOINT_XFERTYPE_MASK;
851
852 /* There are only 3+2 endpoints, so hardcode this ... */
853 switch(type)
854 {
855 case USB_ENDPOINT_XFER_BULK:
856 if(dir == USB_DIR_IN)
857 return (1 | USB_DIR_IN);
858 else
859 return (1 | USB_DIR_OUT);
860
861 case USB_ENDPOINT_XFER_INT:
862 if(dir == USB_DIR_IN)
863 return (2 | USB_DIR_IN);
864 else
865 return (2 | USB_DIR_OUT);
866
867 default:
868 return -1;
869 }
870}