1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45#include <common.h>
46#include <config.h>
47#include <commproc.h>
48#include <usbdevice.h>
49#include <usb/mpc8xx_udc.h>
50#include <usb/udc.h>
51
52#include "ep0.h"
53
54DECLARE_GLOBAL_DATA_PTR;
55
56#define ERR(fmt, args...)\
57 serial_printf("ERROR : [%s] %s:%d: "fmt,\
58 __FILE__,__FUNCTION__,__LINE__, ##args)
59#ifdef __DEBUG_UDC__
60#define DBG(fmt,args...)\
61 serial_printf("[%s] %s:%d: "fmt,\
62 __FILE__,__FUNCTION__,__LINE__, ##args)
63#else
64#define DBG(fmt,args...)
65#endif
66
67
68#ifdef __SIMULATE_ERROR__
69static char err_poison_test = 0;
70#endif
71static struct mpc8xx_ep ep_ref[MAX_ENDPOINTS];
72static u32 address_base = STATE_NOT_READY;
73static mpc8xx_udc_state_t udc_state = 0;
74static struct usb_device_instance *udc_device = 0;
75static volatile usb_epb_t *endpoints[MAX_ENDPOINTS];
76static volatile cbd_t *tx_cbd[TX_RING_SIZE];
77static volatile cbd_t *rx_cbd[RX_RING_SIZE];
78static volatile immap_t *immr = 0;
79static volatile cpm8xx_t *cp = 0;
80static volatile usb_pram_t *usb_paramp = 0;
81static volatile usb_t *usbp = 0;
82static int rx_ct = 0;
83static int tx_ct = 0;
84
85
86static void mpc8xx_udc_state_transition_up (usb_device_state_t initial,
87 usb_device_state_t final);
88static void mpc8xx_udc_state_transition_down (usb_device_state_t initial,
89 usb_device_state_t final);
90static void mpc8xx_udc_stall (unsigned int ep);
91static void mpc8xx_udc_flush_tx_fifo (int epid);
92static void mpc8xx_udc_flush_rx_fifo (void);
93static void mpc8xx_udc_clear_rxbd (volatile cbd_t * rx_cbdp);
94static void mpc8xx_udc_init_tx (struct usb_endpoint_instance *epi,
95 struct urb *tx_urb);
96static void mpc8xx_udc_dump_request (struct usb_device_request *request);
97static void mpc8xx_udc_clock_init (volatile immap_t * immr,
98 volatile cpm8xx_t * cp);
99static int mpc8xx_udc_ep_tx (struct usb_endpoint_instance *epi);
100static int mpc8xx_udc_epn_rx (unsigned int epid, volatile cbd_t * rx_cbdp);
101static void mpc8xx_udc_ep0_rx (volatile cbd_t * rx_cbdp);
102static void mpc8xx_udc_cbd_init (void);
103static void mpc8xx_udc_endpoint_init (void);
104static void mpc8xx_udc_cbd_attach (int ep, uchar tx_size, uchar rx_size);
105static u32 mpc8xx_udc_alloc (u32 data_size, u32 alignment);
106static int mpc8xx_udc_ep0_rx_setup (volatile cbd_t * rx_cbdp);
107static void mpc8xx_udc_set_nak (unsigned int ep);
108static short mpc8xx_udc_handle_txerr (void);
109static void mpc8xx_udc_advance_rx (volatile cbd_t ** rx_cbdp, int epid);
110
111
112
113
114
115
116
117
118
119int udc_init (void)
120{
121
122 immr = (immap_t *) CONFIG_SYS_IMMR;
123 cp = (cpm8xx_t *) & (immr->im_cpm);
124 usb_paramp = (usb_pram_t *) & (cp->cp_dparam[PROFF_USB]);
125 usbp = (usb_t *) & (cp->cp_scc[0]);
126
127 memset (ep_ref, 0x00, (sizeof (struct mpc8xx_ep) * MAX_ENDPOINTS));
128
129 udc_device = 0;
130 udc_state = STATE_NOT_READY;
131
132 usbp->usmod = 0x00;
133 usbp->uscom = 0;
134
135
136 usbp->usaddr = 0x00;
137 mpc8xx_udc_clock_init (immr, cp);
138
139
140 immr->im_ioport.iop_padir &= ~0x0003;
141 immr->im_ioport.iop_papar |= 0x0003;
142
143
144 immr->im_ioport.iop_pcso |= 0x0030;
145
146
147 immr->im_ioport.iop_pcdir |= 0x0300;
148 immr->im_ioport.iop_pcpar |= 0x0300;
149
150
151 address_base = (u32) (cp->cp_dpmem + CPM_USB_BASE);
152
153
154 mpc8xx_udc_endpoint_init ();
155 mpc8xx_udc_cbd_init ();
156
157
158 usb_paramp->ep0ptr = (u32) endpoints[0];
159 usb_paramp->ep1ptr = (u32) endpoints[1];
160 usb_paramp->ep2ptr = (u32) endpoints[2];
161 usb_paramp->ep3ptr = (u32) endpoints[3];
162 usb_paramp->frame_n = 0;
163
164 DBG ("ep0ptr=0x%08x ep1ptr=0x%08x ep2ptr=0x%08x ep3ptr=0x%08x\n",
165 usb_paramp->ep0ptr, usb_paramp->ep1ptr, usb_paramp->ep2ptr,
166 usb_paramp->ep3ptr);
167
168 return 0;
169}
170
171
172
173
174
175void udc_irq (void)
176{
177 int epid = 0;
178 volatile cbd_t *rx_cbdp = 0;
179 volatile cbd_t *rx_cbdp_base = 0;
180
181 if (udc_state != STATE_READY) {
182 return;
183 }
184
185 if (usbp->usber & USB_E_BSY) {
186
187 usbp->usber |= USB_E_BSY;
188 mpc8xx_udc_flush_rx_fifo ();
189 }
190
191
192 for (epid = 0; epid < MAX_ENDPOINTS; epid++) {
193 if (!ep_ref[epid].prx) {
194 continue;
195 }
196 rx_cbdp = rx_cbdp_base = ep_ref[epid].prx;
197
198 do {
199 if (!(rx_cbdp->cbd_sc & RX_BD_E)) {
200
201 if (rx_cbdp->cbd_sc & 0x1F) {
202
203
204
205 mpc8xx_udc_clear_rxbd (rx_cbdp);
206
207 } else {
208 if (!epid) {
209 mpc8xx_udc_ep0_rx (rx_cbdp);
210
211 } else {
212
213 mpc8xx_udc_set_nak (epid);
214 mpc8xx_udc_epn_rx (epid, rx_cbdp);
215 mpc8xx_udc_clear_rxbd (rx_cbdp);
216 }
217 }
218
219
220 mpc8xx_udc_advance_rx (&rx_cbdp, epid);
221 ep_ref[epid].prx = rx_cbdp;
222 } else {
223
224 mpc8xx_udc_advance_rx (&rx_cbdp, epid);
225 }
226
227 } while (rx_cbdp != rx_cbdp_base);
228 }
229
230
231
232
233
234 if (usbp->usber & USB_E_TXB) {
235 usbp->usber |= USB_E_TXB;
236 }
237
238 if (usbp->usber & (USB_TX_ERRMASK)) {
239 mpc8xx_udc_handle_txerr ();
240 }
241
242
243 if (usbp->usber & USB_E_RESET) {
244 usbp->usber |= USB_E_RESET;
245 usbp->usaddr = 0x00;
246 udc_device->device_state = STATE_DEFAULT;
247 }
248
249
250
251
252
253
254
255
256
257
258
259
260 return;
261}
262
263
264
265
266
267int udc_endpoint_write (struct usb_endpoint_instance *epi)
268{
269 int ep = 0;
270 short epid = 1, unnak = 0, ret = 0;
271
272 if (udc_state != STATE_READY) {
273 ERR ("invalid udc_state != STATE_READY!\n");
274 return -1;
275 }
276
277 if (!udc_device || !epi) {
278 return -1;
279 }
280
281 if (udc_device->device_state != STATE_CONFIGURED) {
282 return -1;
283 }
284
285 ep = epi->endpoint_address & 0x03;
286 if (ep >= MAX_ENDPOINTS) {
287 return -1;
288 }
289
290
291 for (epid = 1; epid < MAX_ENDPOINTS; epid++) {
292
293
294 if (ep_ref[epid].sc & USB_DIR_IN) {
295 continue;
296 }
297
298 if (!(usbp->usep[epid] & (USEP_THS_NAK | USEP_RHS_NAK))) {
299 unnak |= 1 << epid;
300 }
301
302 mpc8xx_udc_set_nak (epid);
303 }
304
305 mpc8xx_udc_init_tx (&udc_device->bus->endpoint_array[ep],
306 epi->tx_urb);
307 ret = mpc8xx_udc_ep_tx (&udc_device->bus->endpoint_array[ep]);
308
309
310 for (epid = 1; epid < MAX_ENDPOINTS; epid++) {
311 if (unnak & (1 << epid)) {
312 udc_unset_nak (epid);
313 }
314 }
315
316 return ret;
317}
318
319
320
321
322
323static int mpc8xx_udc_assign_urb (int ep, char direction)
324{
325 struct usb_endpoint_instance *epi = 0;
326
327 if (ep >= MAX_ENDPOINTS) {
328 goto err;
329 }
330 epi = &udc_device->bus->endpoint_array[ep];
331 if (!epi) {
332 goto err;
333 }
334
335 if (!ep_ref[ep].urb) {
336 ep_ref[ep].urb = usbd_alloc_urb (udc_device, udc_device->bus->endpoint_array);
337 if (!ep_ref[ep].urb) {
338 goto err;
339 }
340 } else {
341 ep_ref[ep].urb->actual_length = 0;
342 }
343
344 switch (direction) {
345 case USB_DIR_IN:
346 epi->tx_urb = ep_ref[ep].urb;
347 break;
348 case USB_DIR_OUT:
349 epi->rcv_urb = ep_ref[ep].urb;
350 break;
351 default:
352 goto err;
353 }
354 return 0;
355
356 err:
357 udc_state = STATE_ERROR;
358 return -1;
359}
360
361
362
363
364
365
366void udc_setup_ep (struct usb_device_instance *device, unsigned int ep,
367 struct usb_endpoint_instance *epi)
368{
369 uchar direction = 0;
370 int ep_attrib = 0;
371
372 if (epi && (ep < MAX_ENDPOINTS)) {
373
374 if (ep == 0) {
375 if (epi->rcv_attributes != USB_ENDPOINT_XFER_CONTROL
376 || epi->tx_attributes !=
377 USB_ENDPOINT_XFER_CONTROL) {
378
379
380 udc_state = STATE_ERROR;
381 return;
382
383 }
384 if (!(ep_ref[ep].sc & EP_ATTACHED)) {
385 mpc8xx_udc_cbd_attach (ep, epi->tx_packetSize,
386 epi->rcv_packetSize);
387 }
388 usbp->usep[ep] = 0x0000;
389 return;
390 }
391
392 if ((epi->endpoint_address & USB_ENDPOINT_DIR_MASK)
393 == USB_DIR_IN) {
394
395 direction = 1;
396 ep_attrib = epi->tx_attributes;
397 epi->rcv_packetSize = 0;
398 ep_ref[ep].sc |= USB_DIR_IN;
399 } else {
400
401 direction = 0;
402 ep_attrib = epi->rcv_attributes;
403 epi->tx_packetSize = 0;
404 ep_ref[ep].sc &= ~USB_DIR_IN;
405 }
406
407 if (mpc8xx_udc_assign_urb (ep, epi->endpoint_address
408 & USB_ENDPOINT_DIR_MASK)) {
409 return;
410 }
411
412 switch (ep_attrib) {
413 case USB_ENDPOINT_XFER_CONTROL:
414 if (!(ep_ref[ep].sc & EP_ATTACHED)) {
415 mpc8xx_udc_cbd_attach (ep,
416 epi->tx_packetSize,
417 epi->rcv_packetSize);
418 }
419 usbp->usep[ep] = ep << 12;
420 epi->rcv_urb = epi->tx_urb = ep_ref[ep].urb;
421
422 break;
423 case USB_ENDPOINT_XFER_BULK:
424 case USB_ENDPOINT_XFER_INT:
425 if (!(ep_ref[ep].sc & EP_ATTACHED)) {
426 if (direction) {
427 mpc8xx_udc_cbd_attach (ep,
428 epi->tx_packetSize,
429 0);
430 } else {
431 mpc8xx_udc_cbd_attach (ep,
432 0,
433 epi->rcv_packetSize);
434 }
435 }
436 usbp->usep[ep] = (ep << 12) | ((ep_attrib) << 8);
437
438 break;
439 case USB_ENDPOINT_XFER_ISOC:
440 default:
441 serial_printf ("Error endpoint attrib %d>3\n", ep_attrib);
442 udc_state = STATE_ERROR;
443 break;
444 }
445 }
446
447}
448
449
450
451
452
453void udc_connect (void)
454{
455
456
457
458
459 if (udc_state != STATE_ERROR) {
460 udc_state = STATE_READY;
461 usbp->usmod |= USMOD_EN;
462 }
463}
464
465
466
467
468
469void udc_disconnect (void)
470{
471
472
473
474
475 if (udc_state != STATE_ERROR) {
476 udc_state = STATE_NOT_READY;
477 }
478 usbp->usmod &= ~USMOD_EN;
479}
480
481
482
483
484
485void udc_enable (struct usb_device_instance *device)
486{
487 if (udc_state == STATE_ERROR) {
488 return;
489 }
490
491 udc_device = device;
492
493 if (!ep_ref[0].urb) {
494 ep_ref[0].urb = usbd_alloc_urb (device, device->bus->endpoint_array);
495 }
496
497
498 usbp->usber = 0x03FF;
499 usbp->usbmr = 0x02F7;
500
501 return;
502}
503
504
505
506
507
508void udc_disable (void)
509{
510 int i = 0;
511
512 if (udc_state == STATE_ERROR) {
513 DBG ("Won't disable UDC. udc_state==STATE_ERROR !\n");
514 return;
515 }
516
517 udc_device = 0;
518
519 for (; i < MAX_ENDPOINTS; i++) {
520 if (ep_ref[i].urb) {
521 usbd_dealloc_urb (ep_ref[i].urb);
522 ep_ref[i].urb = 0;
523 }
524 }
525
526 usbp->usbmr = 0x00;
527 usbp->usmod = ~USMOD_EN;
528 udc_state = STATE_NOT_READY;
529}
530
531
532
533
534
535void udc_startup_events (struct usb_device_instance *device)
536{
537 udc_enable (device);
538 if (udc_state == STATE_READY) {
539 usbd_device_event_irq (device, DEVICE_CREATE, 0);
540 }
541}
542
543
544
545
546
547
548void udc_set_nak (int epid)
549{
550 if (epid) {
551 mpc8xx_udc_set_nak (epid);
552 }
553}
554
555
556
557
558
559
560
561void udc_unset_nak (int epid)
562{
563 if (epid > MAX_ENDPOINTS) {
564 return;
565 }
566
567 if (usbp->usep[epid] & (USEP_THS_NAK | USEP_RHS_NAK)) {
568 usbp->usep[epid] &= ~(USEP_THS_NAK | USEP_RHS_NAK);
569 __asm__ ("eieio");
570 }
571}
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623static void mpc8xx_udc_state_transition_up (usb_device_state_t initial,
624 usb_device_state_t final)
625{
626 if (initial < final) {
627 switch (initial) {
628 case STATE_ATTACHED:
629 usbd_device_event_irq (udc_device,
630 DEVICE_HUB_CONFIGURED, 0);
631 if (final == STATE_POWERED)
632 break;
633 case STATE_POWERED:
634 usbd_device_event_irq (udc_device, DEVICE_RESET, 0);
635 if (final == STATE_DEFAULT)
636 break;
637 case STATE_DEFAULT:
638 usbd_device_event_irq (udc_device,
639 DEVICE_ADDRESS_ASSIGNED, 0);
640 if (final == STATE_ADDRESSED)
641 break;
642 case STATE_ADDRESSED:
643 usbd_device_event_irq (udc_device, DEVICE_CONFIGURED,
644 0);
645 case STATE_CONFIGURED:
646 break;
647 default:
648 break;
649 }
650 }
651}
652
653static void mpc8xx_udc_state_transition_down (usb_device_state_t initial,
654 usb_device_state_t final)
655{
656 if (initial > final) {
657 switch (initial) {
658 case STATE_CONFIGURED:
659 usbd_device_event_irq (udc_device,
660 DEVICE_DE_CONFIGURED, 0);
661 if (final == STATE_ADDRESSED)
662 break;
663 case STATE_ADDRESSED:
664 usbd_device_event_irq (udc_device, DEVICE_RESET, 0);
665 if (final == STATE_DEFAULT)
666 break;
667 case STATE_DEFAULT:
668 usbd_device_event_irq (udc_device,
669 DEVICE_POWER_INTERRUPTION, 0);
670 if (final == STATE_POWERED)
671 break;
672 case STATE_POWERED:
673 usbd_device_event_irq (udc_device, DEVICE_HUB_RESET,
674 0);
675 case STATE_ATTACHED:
676 break;
677 default:
678 break;
679 }
680 }
681}
682
683
684
685
686
687
688static void mpc8xx_udc_stall (unsigned int ep)
689{
690 usbp->usep[ep] |= STALL_BITMASK;
691}
692
693
694
695
696
697
698static void mpc8xx_udc_set_nak (unsigned int ep)
699{
700 usbp->usep[ep] |= NAK_BITMASK;
701 __asm__ ("eieio");
702}
703
704
705
706
707
708
709static short mpc8xx_udc_handle_txerr ()
710{
711 short ep = 0, ret = 0;
712
713 for (; ep < TX_RING_SIZE; ep++) {
714 if (usbp->usber & (0x10 << ep)) {
715
716
717 if (tx_cbd[ep]->cbd_sc & 0x06) {
718 ret = 1;
719 mpc8xx_udc_flush_tx_fifo (ep);
720
721 } else {
722 if (usbp->usep[ep] & STALL_BITMASK) {
723 if (!ep) {
724 usbp->usep[ep] &= ~STALL_BITMASK;
725 }
726 }
727 }
728 usbp->usber |= (0x10 << ep);
729 }
730 }
731 return ret;
732}
733
734
735
736
737
738static void mpc8xx_udc_advance_rx (volatile cbd_t ** rx_cbdp, int epid)
739{
740 if ((*rx_cbdp)->cbd_sc & RX_BD_W) {
741 *rx_cbdp = (volatile cbd_t *) (endpoints[epid]->rbase + CONFIG_SYS_IMMR);
742
743 } else {
744 (*rx_cbdp)++;
745 }
746}
747
748
749
750
751
752
753static void mpc8xx_udc_flush_tx_fifo (int epid)
754{
755 volatile cbd_t *tx_cbdp = 0;
756
757 if (epid > MAX_ENDPOINTS) {
758 return;
759 }
760
761
762 immr->im_cpm.cp_cpcr = ((epid << 2) | 0x1D01);
763 __asm__ ("eieio");
764 while (immr->im_cpm.cp_cpcr & 0x01);
765
766 usbp->uscom = 0x40 | 0;
767
768
769 tx_cbdp = (cbd_t *) (endpoints[epid]->tbptr + CONFIG_SYS_IMMR);
770 tx_cbdp->cbd_sc = (TX_BD_I | TX_BD_W);
771
772
773 endpoints[epid]->tptr = endpoints[epid]->tbase;
774 endpoints[epid]->tstate = 0x00;
775 endpoints[epid]->tbcnt = 0x00;
776
777
778 immr->im_cpm.cp_cpcr = ((epid << 2) | 0x2D01);
779 __asm__ ("eieio");
780 while (immr->im_cpm.cp_cpcr & 0x01);
781
782 return;
783}
784
785
786
787
788
789
790
791
792
793
794static void mpc8xx_udc_flush_rx_fifo ()
795{
796 int i = 0;
797
798 for (i = 0; i < RX_RING_SIZE; i++) {
799 if (!(rx_cbd[i]->cbd_sc & RX_BD_E)) {
800 ERR ("buf %p used rx data len = 0x%x sc=0x%x!\n",
801 rx_cbd[i], rx_cbd[i]->cbd_datlen,
802 rx_cbd[i]->cbd_sc);
803
804 }
805 }
806 ERR ("BUG : Input over-run\n");
807}
808
809
810
811
812
813static void mpc8xx_udc_clear_rxbd (volatile cbd_t * rx_cbdp)
814{
815 rx_cbdp->cbd_datlen = 0x0000;
816 rx_cbdp->cbd_sc = ((rx_cbdp->cbd_sc & RX_BD_W) | (RX_BD_E | RX_BD_I));
817 __asm__ ("eieio");
818}
819
820
821
822
823
824
825static int mpc8xx_udc_tx_irq (int ep)
826{
827 int i = 0;
828
829 if (usbp->usber & (USB_TX_ERRMASK)) {
830 if (mpc8xx_udc_handle_txerr ()) {
831
832 return -1;
833 }
834 }
835
836 if (usbp->usber & (USB_E_RESET | USB_E_BSY)) {
837
838 return -2;
839 }
840
841 if (usbp->usber & USB_E_RXB) {
842 for (i = 0; i < RX_RING_SIZE; i++) {
843 if (!(rx_cbd[i]->cbd_sc & RX_BD_E)) {
844 if ((rx_cbd[i] == ep_ref[0].prx) || ep) {
845 return -2;
846 }
847 }
848 }
849 }
850
851 return 0;
852}
853
854
855
856
857
858
859
860
861
862
863static int mpc8xx_udc_ep_tx (struct usb_endpoint_instance *epi)
864{
865 struct urb *urb = epi->tx_urb;
866 volatile cbd_t *tx_cbdp = 0;
867 unsigned int ep = 0, pkt_len = 0, x = 0, tx_retry = 0;
868 int ret = 0;
869
870 if (!epi || (epi->endpoint_address & 0x03) >= MAX_ENDPOINTS || !urb) {
871 return -1;
872 }
873
874 ep = epi->endpoint_address & 0x03;
875 tx_cbdp = (cbd_t *) (endpoints[ep]->tbptr + CONFIG_SYS_IMMR);
876
877 if (tx_cbdp->cbd_sc & TX_BD_R || usbp->usber & USB_E_TXB) {
878 mpc8xx_udc_flush_tx_fifo (ep);
879 usbp->usber |= USB_E_TXB;
880 };
881
882 while (tx_retry++ < 100) {
883 ret = mpc8xx_udc_tx_irq (ep);
884 if (ret == -1) {
885
886 } else if (ret == -2) {
887
888 mpc8xx_udc_flush_tx_fifo (ep);
889 return -1;
890 }
891
892 tx_cbdp = (cbd_t *) (endpoints[ep]->tbptr + CONFIG_SYS_IMMR);
893 while (tx_cbdp->cbd_sc & TX_BD_R) {
894 };
895 tx_cbdp->cbd_sc = (tx_cbdp->cbd_sc & TX_BD_W);
896
897 pkt_len = urb->actual_length - epi->sent;
898
899 if (pkt_len > epi->tx_packetSize || pkt_len > EP_MAX_PKT) {
900 pkt_len = min(epi->tx_packetSize, EP_MAX_PKT);
901 }
902
903 for (x = 0; x < pkt_len; x++) {
904 *((unsigned char *) (tx_cbdp->cbd_bufaddr + x)) =
905 urb->buffer[epi->sent + x];
906 }
907 tx_cbdp->cbd_datlen = pkt_len;
908 tx_cbdp->cbd_sc |= (CBD_TX_BITMASK | ep_ref[ep].pid);
909 __asm__ ("eieio");
910
911#ifdef __SIMULATE_ERROR__
912 if (++err_poison_test == 2) {
913 err_poison_test = 0;
914 tx_cbdp->cbd_sc &= ~TX_BD_TC;
915 }
916#endif
917
918 usbp->uscom = (USCOM_STR | ep);
919
920 while (!(usbp->usber & USB_E_TXB)) {
921 ret = mpc8xx_udc_tx_irq (ep);
922 if (ret == -1) {
923
924 break;
925 } else if (ret == -2) {
926 if (usbp->usber & USB_E_TXB) {
927 usbp->usber |= USB_E_TXB;
928 }
929 mpc8xx_udc_flush_tx_fifo (ep);
930 return -1;
931 }
932 };
933
934 if (usbp->usber & USB_E_TXB) {
935 usbp->usber |= USB_E_TXB;
936 }
937
938
939 if (ret == -1) {
940 continue;
941 }
942
943
944 epi->sent += pkt_len;
945 epi->last = min(urb->actual_length - epi->sent, epi->tx_packetSize);
946 TOGGLE_TX_PID (ep_ref[ep].pid);
947
948 if (epi->sent >= epi->tx_urb->actual_length) {
949
950 epi->tx_urb->actual_length = 0;
951 epi->sent = 0;
952
953 if (ep_ref[ep].sc & EP_SEND_ZLP) {
954 ep_ref[ep].sc &= ~EP_SEND_ZLP;
955 } else {
956 return 0;
957 }
958 }
959 }
960
961 ERR ("TX fail, endpoint 0x%x tx bytes 0x%x/0x%x\n", ep, epi->sent,
962 epi->tx_urb->actual_length);
963
964 return -1;
965}
966
967
968
969
970
971static void mpc8xx_udc_dump_request (struct usb_device_request *request)
972{
973 DBG ("bmRequestType:%02x bRequest:%02x wValue:%04x "
974 "wIndex:%04x wLength:%04x ?\n",
975 request->bmRequestType,
976 request->bRequest,
977 request->wValue, request->wIndex, request->wLength);
978
979 return;
980}
981
982
983
984
985
986static int mpc8xx_udc_ep0_rx_setup (volatile cbd_t * rx_cbdp)
987{
988 unsigned int x = 0;
989 struct urb *purb = ep_ref[0].urb;
990 struct usb_endpoint_instance *epi =
991 &udc_device->bus->endpoint_array[0];
992
993 for (; x < rx_cbdp->cbd_datlen; x++) {
994 *(((unsigned char *) &ep_ref[0].urb->device_request) + x) =
995 *((unsigned char *) (rx_cbdp->cbd_bufaddr + x));
996 }
997
998 mpc8xx_udc_clear_rxbd (rx_cbdp);
999
1000 if (ep0_recv_setup (purb)) {
1001 mpc8xx_udc_dump_request (&purb->device_request);
1002 return -1;
1003 }
1004
1005 if ((purb->device_request.bmRequestType & USB_REQ_DIRECTION_MASK)
1006 == USB_REQ_HOST2DEVICE) {
1007
1008 switch (purb->device_request.bRequest) {
1009 case USB_REQ_SET_ADDRESS:
1010
1011 ep_ref[0].pid = TX_BD_PID_DATA1;
1012 purb->actual_length = 0;
1013 mpc8xx_udc_init_tx (epi, purb);
1014 mpc8xx_udc_ep_tx (epi);
1015
1016
1017 usbp->usaddr = udc_device->address;
1018 mpc8xx_udc_state_transition_up (udc_device->device_state,
1019 STATE_ADDRESSED);
1020 return 0;
1021
1022 case USB_REQ_SET_CONFIGURATION:
1023 if (!purb->device_request.wValue) {
1024
1025 usbp->usaddr = 0x00;
1026 mpc8xx_udc_state_transition_down (udc_device->device_state,
1027 STATE_ADDRESSED);
1028 } else {
1029
1030 mpc8xx_udc_state_transition_up (udc_device->device_state,
1031 STATE_CONFIGURED);
1032 for (x = 1; x < MAX_ENDPOINTS; x++) {
1033 if ((udc_device->bus->endpoint_array[x].endpoint_address & USB_ENDPOINT_DIR_MASK)
1034 == USB_DIR_IN) {
1035 ep_ref[x].pid = TX_BD_PID_DATA0;
1036 } else {
1037 ep_ref[x].pid = RX_BD_PID_DATA0;
1038 }
1039
1040 usbp->usep[x] &= ~STALL_BITMASK;
1041 }
1042 }
1043 break;
1044 default:
1045
1046 break;
1047 }
1048
1049
1050 ep_ref[0].pid = TX_BD_PID_DATA1;
1051 purb->actual_length = 0;
1052 mpc8xx_udc_init_tx (epi, purb);
1053 mpc8xx_udc_ep_tx (epi);
1054
1055 } else {
1056
1057 if (purb->actual_length) {
1058 ep_ref[0].pid = TX_BD_PID_DATA1;
1059 mpc8xx_udc_init_tx (epi, purb);
1060
1061 if (!(purb->actual_length % EP0_MAX_PACKET_SIZE)) {
1062 ep_ref[0].sc |= EP_SEND_ZLP;
1063 }
1064
1065 if (purb->device_request.wValue ==
1066 USB_DESCRIPTOR_TYPE_DEVICE) {
1067 if (le16_to_cpu (purb->device_request.wLength)
1068 > purb->actual_length) {
1069
1070
1071
1072 if (purb->actual_length > epi->tx_packetSize) {
1073 purb->actual_length = epi->tx_packetSize;
1074 }
1075 }
1076 }
1077 mpc8xx_udc_ep_tx (epi);
1078
1079 } else {
1080
1081 ERR ("Zero length data or SETUP with DATA-IN phase ?\n");
1082 return 1;
1083 }
1084 }
1085 return 0;
1086}
1087
1088
1089
1090
1091
1092static void mpc8xx_udc_init_tx (struct usb_endpoint_instance *epi,
1093 struct urb *tx_urb)
1094{
1095 epi->sent = 0;
1096 epi->last = 0;
1097 epi->tx_urb = tx_urb;
1098}
1099
1100
1101
1102
1103
1104static void mpc8xx_udc_ep0_rx (volatile cbd_t * rx_cbdp)
1105{
1106 if (rx_cbdp->cbd_sc & RX_BD_PID_SETUP) {
1107
1108
1109 if (mpc8xx_udc_ep0_rx_setup (rx_cbdp)) {
1110 mpc8xx_udc_stall (0);
1111 }
1112
1113 } else {
1114
1115 mpc8xx_udc_clear_rxbd (rx_cbdp);
1116
1117 if ((rx_cbdp->cbd_datlen - 2)) {
1118
1119
1120
1121
1122 mpc8xx_udc_stall (0);
1123 }
1124 }
1125}
1126
1127
1128
1129
1130
1131
1132static int mpc8xx_udc_epn_rx (unsigned int epid, volatile cbd_t * rx_cbdp)
1133{
1134 struct usb_endpoint_instance *epi = 0;
1135 struct urb *urb = 0;
1136 unsigned int x = 0;
1137
1138 if (epid >= MAX_ENDPOINTS || !rx_cbdp->cbd_datlen) {
1139 return 0;
1140 }
1141
1142
1143
1144
1145 if (ep_ref[epid].pid != (rx_cbdp->cbd_sc & 0xC0)) {
1146 return 1;
1147 }
1148 TOGGLE_RX_PID (ep_ref[epid].pid);
1149
1150 epi = &udc_device->bus->endpoint_array[epid];
1151 urb = epi->rcv_urb;
1152
1153 for (; x < (rx_cbdp->cbd_datlen - 2); x++) {
1154 *((unsigned char *) (urb->buffer + urb->actual_length + x)) =
1155 *((unsigned char *) (rx_cbdp->cbd_bufaddr + x));
1156 }
1157
1158 if (x) {
1159 usbd_rcv_complete (epi, x, 0);
1160 if (ep_ref[epid].urb->status == RECV_ERROR) {
1161 DBG ("RX error unset NAK\n");
1162 udc_unset_nak (epid);
1163 }
1164 }
1165 return x;
1166}
1167
1168
1169
1170
1171
1172static void mpc8xx_udc_clock_init (volatile immap_t * immr,
1173 volatile cpm8xx_t * cp)
1174{
1175
1176#if defined(CONFIG_SYS_USB_EXTC_CLK)
1177
1178
1179 switch (CONFIG_SYS_USB_EXTC_CLK) {
1180 case 1:
1181 immr->im_ioport.iop_papar |= 0x0100;
1182 immr->im_ioport.iop_padir &= ~0x0100;
1183 cp->cp_sicr |= 0x24;
1184 break;
1185 case 2:
1186 immr->im_ioport.iop_papar |= 0x0200;
1187 immr->im_ioport.iop_padir &= ~0x0200;
1188 cp->cp_sicr |= 0x2D;
1189 break;
1190 case 3:
1191 immr->im_ioport.iop_papar |= 0x0400;
1192 immr->im_ioport.iop_padir &= ~0x0400;
1193 cp->cp_sicr |= 0x36;
1194 break;
1195 case 4:
1196 immr->im_ioport.iop_papar |= 0x0800;
1197 immr->im_ioport.iop_padir &= ~0x0800;
1198 cp->cp_sicr |= 0x3F;
1199 break;
1200 default:
1201 udc_state = STATE_ERROR;
1202 break;
1203 }
1204
1205#elif defined(CONFIG_SYS_USB_BRGCLK)
1206
1207
1208 int divisor = 0;
1209
1210 if (gd->cpu_clk < 48000000L) {
1211 ERR ("brgclk is too slow for full-speed USB!\n");
1212 udc_state = STATE_ERROR;
1213 return;
1214 }
1215
1216
1217
1218
1219 divisor = (gd->cpu_clk / 48000000L) - 1;
1220 cp->cp_sicr &= ~0x0000003F;
1221
1222 switch (CONFIG_SYS_USB_BRGCLK) {
1223 case 1:
1224 cp->cp_brgc1 |= (divisor | CPM_BRG_EN);
1225 cp->cp_sicr &= ~0x2F;
1226 break;
1227 case 2:
1228 cp->cp_brgc2 |= (divisor | CPM_BRG_EN);
1229 cp->cp_sicr |= 0x00000009;
1230 break;
1231 case 3:
1232 cp->cp_brgc3 |= (divisor | CPM_BRG_EN);
1233 cp->cp_sicr |= 0x00000012;
1234 break;
1235 case 4:
1236 cp->cp_brgc4 = (divisor | CPM_BRG_EN);
1237 cp->cp_sicr |= 0x0000001B;
1238 break;
1239 default:
1240 udc_state = STATE_ERROR;
1241 break;
1242 }
1243
1244#else
1245#error "CONFIG_SYS_USB_EXTC_CLK or CONFIG_SYS_USB_BRGCLK must be defined"
1246#endif
1247
1248}
1249
1250
1251
1252
1253
1254static void mpc8xx_udc_cbd_attach (int ep, uchar tx_size, uchar rx_size)
1255{
1256
1257 if (!tx_cbd[ep] || !rx_cbd[ep] || ep >= MAX_ENDPOINTS) {
1258 udc_state = STATE_ERROR;
1259 return;
1260 }
1261
1262 if (tx_size > USB_MAX_PKT || rx_size > USB_MAX_PKT ||
1263 (!tx_size && !rx_size)) {
1264 udc_state = STATE_ERROR;
1265 return;
1266 }
1267
1268
1269 if (rx_size) {
1270 endpoints[ep]->rbase = (u32) rx_cbd[rx_ct];
1271 endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct];
1272 rx_ct++;
1273
1274 if (!ep) {
1275
1276 endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct];
1277 rx_cbd[rx_ct]->cbd_sc |= RX_BD_W;
1278 rx_ct++;
1279
1280 } else {
1281 rx_ct += 2;
1282 endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct];
1283 rx_cbd[rx_ct]->cbd_sc |= RX_BD_W;
1284 rx_ct++;
1285 }
1286
1287
1288 ep_ref[ep].prx = rx_cbd[rx_ct - 1];
1289 } else {
1290
1291 ep_ref[ep].prx = 0;
1292 endpoints[ep]->rbase = 0;
1293 endpoints[ep]->rbptr = 0;
1294 }
1295
1296 if (tx_size) {
1297 endpoints[ep]->tbase = (u32) tx_cbd[tx_ct];
1298 endpoints[ep]->tbptr = (u32) tx_cbd[tx_ct];
1299 tx_ct++;
1300 } else {
1301 endpoints[ep]->tbase = 0;
1302 endpoints[ep]->tbptr = 0;
1303 }
1304
1305 endpoints[ep]->tstate = 0;
1306 endpoints[ep]->tbcnt = 0;
1307 endpoints[ep]->mrblr = EP_MAX_PKT;
1308 endpoints[ep]->rfcr = 0x18;
1309 endpoints[ep]->tfcr = 0x18;
1310 ep_ref[ep].sc |= EP_ATTACHED;
1311
1312 DBG ("ep %d rbase 0x%08x rbptr 0x%08x tbase 0x%08x tbptr 0x%08x prx = %p\n",
1313 ep, endpoints[ep]->rbase, endpoints[ep]->rbptr,
1314 endpoints[ep]->tbase, endpoints[ep]->tbptr,
1315 ep_ref[ep].prx);
1316
1317 return;
1318}
1319
1320
1321
1322
1323
1324static void mpc8xx_udc_cbd_init (void)
1325{
1326 int i = 0;
1327
1328 for (; i < TX_RING_SIZE; i++) {
1329 tx_cbd[i] = (cbd_t *)
1330 mpc8xx_udc_alloc (sizeof (cbd_t), sizeof (int));
1331 }
1332
1333 for (i = 0; i < RX_RING_SIZE; i++) {
1334 rx_cbd[i] = (cbd_t *)
1335 mpc8xx_udc_alloc (sizeof (cbd_t), sizeof (int));
1336 }
1337
1338 for (i = 0; i < TX_RING_SIZE; i++) {
1339 tx_cbd[i]->cbd_bufaddr =
1340 mpc8xx_udc_alloc (EP_MAX_PKT, sizeof (int));
1341
1342 tx_cbd[i]->cbd_sc = (TX_BD_I | TX_BD_W);
1343 tx_cbd[i]->cbd_datlen = 0x0000;
1344 }
1345
1346
1347 for (i = 0; i < RX_RING_SIZE; i++) {
1348 rx_cbd[i]->cbd_bufaddr =
1349 mpc8xx_udc_alloc (EP_MAX_PKT, sizeof (int));
1350 rx_cbd[i]->cbd_sc = (RX_BD_I | RX_BD_E);
1351 rx_cbd[i]->cbd_datlen = 0x0000;
1352
1353 }
1354
1355 return;
1356}
1357
1358
1359
1360
1361
1362static void mpc8xx_udc_endpoint_init (void)
1363{
1364 int i = 0;
1365
1366 for (; i < MAX_ENDPOINTS; i++) {
1367 endpoints[i] = (usb_epb_t *)
1368 mpc8xx_udc_alloc (sizeof (usb_epb_t), 32);
1369 }
1370}
1371
1372
1373
1374
1375
1376static u32 mpc8xx_udc_alloc (u32 data_size, u32 alignment)
1377{
1378 u32 retaddr = address_base;
1379
1380 while (retaddr % alignment) {
1381 retaddr++;
1382 }
1383 address_base += data_size;
1384
1385 return retaddr;
1386}
1387