]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/usb/mxc/v2_0/src/mxc-pcd.c
Initial revision
[karo-tx-redboot.git] / packages / devs / usb / mxc / v2_0 / src / mxc-pcd.c
1 /*
2  * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
3  */
4
5 /* Modified from Belcarra Linux USB driver by Yi Li */
6
7 /*
8  * The code contained herein is licensed under the GNU General Public
9  * License. You may obtain a copy of the GNU General Public License
10  * Version 2 or later at the following locations:
11  *
12  * http://www.opensource.org/licenses/gpl-license.html
13  * http://www.gnu.org/copyleft/gpl.html
14  */
15
16 #include <pkgconf/hal.h>
17 #include <cyg/hal/hal_arch.h>
18 #include <cyg/hal/hal_cache.h>
19 #include <redboot.h>
20 #include <stdlib.h>
21 #include <cyg/hal/hal_io.h>
22
23 #include "../include/mxc-hardware.h"
24 #include "../include/usbp-chap9.h"
25
26 #define CONFIG_OTG_ZASEVB_DIFFERENTIAL_UNIDIRECTIONAL 1
27 #define MXC_CONFIG_MC13783      1
28 //#define MXC_USB_DEBUG 1
29 #ifdef MXC_USB_DEBUG
30 #define dbug_usb diag_printf
31 #else 
32 #define dbug_usb(fmt, ...) do{}while(0) 
33 #endif
34
35 extern unsigned int pmic_reg(unsigned int reg, unsigned int val, unsigned int write);
36
37 static void do_usb(int argc, char *argv[]);
38 RedBoot_cmd("usb",
39             "Load data from usb into RAM", 
40             "XXX",
41             do_usb
42            );
43
44 #define CONFIG_REDBOOT_VENDORID         0x15A2
45 #define CONFIG_REDBOOT_PRODUCTID        0x001F
46 #define CONFIG_REDBOOT_BCDDEVICE        0x0100
47 #define CONFIG_REDBOOT_MANUFACTURER 0
48 #define CONFIG_REDBOOT_PRODUCT_NAME 0
49
50 u8 mxc_new_address, mxc_usb_address;    /* used to save and set USB address */
51 struct usbd_endpoint_instance endpoint_zero;
52 struct usbd_endpoint_instance endpoint_bulk_in;
53 struct usbd_endpoint_instance endpoint_bulk_out;
54
55 u8 *ram_buffer = (u8 *)0x100000;
56 int ram_transfered = 0;
57 int transfer_done = 0;
58
59 static void inline mxc_reset_toggles(void)
60 {
61         fs_wl(OTG_FUNC_EP_TOGGLE, fs_rl(OTG_FUNC_EP_TOGGLE));
62 }
63
64 static void inline mxc_reset_toggle_ep(int ep_num)
65 {
66         if (fs_rl(OTG_FUNC_EP_TOGGLE) & ep_num)
67                 fs_wl(OTG_FUNC_EP_TOGGLE, ep_num);
68 }
69
70 static void inline mxc_set_toggle_ep(int ep_num)
71 {
72         dbug_usb("mxc_set_toggle_ep\n");
73         if ((fs_rl(OTG_FUNC_EP_TOGGLE) & ep_num) == 0)
74             fs_wl(OTG_FUNC_EP_TOGGLE, ep_num);
75 }
76
77 static void mxc_reset_ep_rdy(int ep_num)
78 {
79         if (fs_rl(OTG_FUNC_EP_RDY) & ep_num) 
80                 fs_wl(OTG_FUNC_EP_RDY_CLR, ep_num);
81 }
82
83 static void mxc_set_ep_rdy(int ep_num)
84 {
85         if ((fs_rl(OTG_FUNC_EP_RDY) & ep_num) == 0)
86             fs_wl(OTG_FUNC_EP_RDY, ep_num);   
87 }
88
89 static void 
90 mxc_ep_config(int epn, int dir, u32 ep_num, int wMaxPacketSize, int buffersize,
91         int format, int ttlbtecnt)
92 {
93         u32 ep0 = (wMaxPacketSize << 16) | ((format & 3) << 14);
94         u32 ep1 = ttlbtecnt ? (data_y_buf(epn, dir) << 16) | data_x_buf(epn, dir) : 0;
95         u32 ep3 = ((buffersize - 1) << 21) | (ttlbtecnt & 0x1fffff);
96
97         dbug_usb("mxc_ep_config epn %x dir %x %x %x %x\n", epn, dir, ep0, ep1, ep3);
98         fs_wl(ep_word(epn, dir, 0), ep0);
99         fs_wl(ep_word(epn, dir, 1), ep1);
100         fs_wl(ep_word(epn, dir, 3), ep3);
101
102         fs_orl(OTG_FUNC_EP_EN, ep_num);
103 }
104
105 static void
106 mxc_ep_config_nodma(int epn, int dir, int wMaxPacketSize, int format, int ttlbtecnt)
107 {
108         u32 ep_num = ep_num_dir(epn, dir);
109
110         mxc_ep_config(epn, dir, ep_num, wMaxPacketSize, wMaxPacketSize, format, ttlbtecnt);
111
112         mxc_set_ep_rdy(ep_num);
113 }
114
115 static void 
116 mxc_pcd_set_address(u8 address)
117 {
118         mxc_usb_address = 0;
119         mxc_new_address = address;      /* this will be used in the interrupt handler */
120     dbug_usb("mxc_pcd_set_address to %d\n", address);
121 }
122
123 static int 
124 usbd_get_descriptor(u8 *buffer, int wLength, int descriptor_type)
125 {
126         int actual_length = 0;
127     struct usbd_device_descriptor *device_descriptor;
128     u8 iManufacturer;
129     u8 iProduct;
130     u8 iSerialNumber = 0;
131     struct usbd_configuration_descriptor configuration_descriptor;
132         struct usbd_interface_descriptor interface_descriptor;
133         struct usbd_endpoint_descriptor endpoint_descriptor;
134
135     switch (descriptor_type) {
136     case USB_DT_DEVICE: {
137         dbug_usb("USB_DT_DEVICE\n");
138         iManufacturer = CONFIG_REDBOOT_MANUFACTURER;
139         iProduct = CONFIG_REDBOOT_PRODUCT_NAME;
140
141         device_descriptor = (struct usbd_device_descriptor *) buffer;
142
143         device_descriptor->bLength = 18;
144         device_descriptor->bDescriptorType = USB_DT_DEVICE;
145         device_descriptor->bcdUSB = 0x0110;
146         device_descriptor->bDeviceClass = 0;
147         device_descriptor->bDeviceSubClass = 0;
148         device_descriptor->bDeviceProtocol = 0;
149         device_descriptor->bMaxPacketSize0 = 64;
150
151         if (wLength > 8) {
152             device_descriptor->idVendor = cpu_to_le16(CONFIG_REDBOOT_VENDORID); 
153             device_descriptor->idProduct = cpu_to_le16(CONFIG_REDBOOT_PRODUCTID);
154             device_descriptor->bcdDevice = cpu_to_le16(CONFIG_REDBOOT_BCDDEVICE);
155             device_descriptor->iManufacturer = iManufacturer;
156             device_descriptor->iProduct = iProduct;
157             device_descriptor->iSerialNumber = iSerialNumber;
158             device_descriptor->bNumConfigurations = 1;
159             actual_length += 18;
160         }
161         else
162             actual_length += wLength;
163         break;
164     }
165     case USB_DT_CONFIGURATION: {
166         dbug_usb("USB_DT_CONFIGURATION\n");
167         configuration_descriptor.bLength = 9;
168         configuration_descriptor.bDescriptorType = USB_DT_CONFIGURATION;
169         configuration_descriptor.bNumInterfaces = 1;
170         configuration_descriptor.bConfigurationValue = 1;
171         configuration_descriptor.iConfiguration = '\0';
172         configuration_descriptor.bmAttributes = 0;
173         configuration_descriptor.bMaxPower = 0;
174         actual_length = 9;
175
176         interface_descriptor.bLength = 9;
177         interface_descriptor.bDescriptorType = USB_DT_INTERFACE;
178         interface_descriptor.bInterfaceNumber = 1;
179         interface_descriptor.bAlternateSetting = 0;
180         interface_descriptor.bNumEndpoints = 1;
181         interface_descriptor.bInterfaceClass = 0;
182         interface_descriptor.bInterfaceSubClass = 0;
183         interface_descriptor.bInterfaceProtocol = 0;
184         interface_descriptor.iInterface = '\0';
185         actual_length += 9;
186
187         endpoint_descriptor.bLength = 7;
188         endpoint_descriptor.bDescriptorType = USB_DT_ENDPOINT;
189         endpoint_descriptor.bEndpointAddress = 1;
190         endpoint_descriptor.bmAttributes = USB_ENDPOINT_BULK;
191         endpoint_descriptor.wMaxPacketSize = 64;
192         endpoint_descriptor.bInterval = 0;
193         actual_length += 7;
194
195         configuration_descriptor.wTotalLength = actual_length;
196                 memcpy(buffer, &configuration_descriptor, 9); 
197                 if (wLength > 9) {
198                         memcpy(buffer + 9, &interface_descriptor, 9); 
199                         memcpy(buffer + 18, &endpoint_descriptor, 7); 
200                 }
201                 actual_length = (wLength > actual_length) ? actual_length : wLength; 
202         break;
203     }
204     case USB_DT_STRING: {
205         *buffer = '\0';
206         break;
207     }
208     default:
209         return -1;
210     }
211
212     dbug_usb("usbd_get_descriptor actual_length %d\n", actual_length);
213     return actual_length;
214 }
215
216 struct usbd_urb *
217 usbd_alloc_urb(int length, struct usbd_endpoint_instance *endpoint)
218 {
219     struct usbd_urb *urb;
220
221     urb = (struct usbd_urb *) malloc(sizeof(struct usbd_urb));
222     urb->endpoint = endpoint;
223     urb->buffer_length = length;
224
225     if (length) {
226         urb->buffer = (u8 *) malloc(length);
227     }
228         endpoint->urb = urb;
229     return urb;
230 }
231
232 static void usbd_free_urb(struct usbd_urb *urb)
233 {
234         if (urb) {
235                 if (urb->endpoint)
236                         urb->endpoint->urb = NULL;
237                 if (urb->buffer) 
238                         free(urb->buffer);
239                 free(urb);
240         }
241 }
242
243 static void 
244 mxc_sendzlp(int epn, struct usbd_endpoint_instance *endpoint, int wMaxPacketSize)
245 {
246         u32 ep_num_in = ep_num_in(epn);
247
248         if (!(fs_rl(OTG_FUNC_XFILL_STAT) & ep_num_in))
249                 fs_wl(OTG_FUNC_XFILL_STAT, ep_num_in);
250         else if (!(fs_rl(OTG_FUNC_YFILL_STAT) & ep_num_in))
251                 fs_wl(OTG_FUNC_YFILL_STAT, ep_num_in);
252
253         mxc_ep_config_nodma(epn, USB_DIR_IN, endpoint->wMaxPacketSize,
254             endpoint->bmAttributes & 0x3, 0);
255 }
256
257 static void 
258 mxc_stop_ep(int epn, int dir)
259 {
260         int ep_num = ep_num_dir(epn, dir);
261
262         mxc_reset_ep_rdy(ep_num);
263         fs_wl(OTG_DMA_EP_CH_CLR, ep_num);
264         fs_wl(OTG_FUNC_IINT_CLR, ep_num);
265         fs_wl(OTG_FUNC_XINT_STAT, ep_num);
266         fs_wl(OTG_FUNC_YINT_STAT, ep_num);
267         if (epn == 0)
268                 return;
269
270         fs_wl(OTG_FUNC_XFILL_STAT, ep_num);
271         fs_wl(OTG_FUNC_YFILL_STAT, ep_num);
272         fs_wl(OTG_FUNC_XFILL_STAT, ep_num);
273         fs_wl(OTG_FUNC_YFILL_STAT, ep_num);
274 }
275
276 static void
277 mxc_pcd_start_ep_setup(struct usbd_endpoint_instance *endpoint)
278 {
279         mxc_ep_config_nodma(0, USB_DIR_OUT, endpoint->wMaxPacketSize,
280             EP_FORMAT_CONTROL, endpoint->wMaxPacketSize);
281         mxc_ep_config_nodma(0, USB_DIR_IN, endpoint->wMaxPacketSize,
282             EP_FORMAT_CONTROL, 0);
283 }
284
285 static void
286 mxc_pcd_start_ep_out(struct usbd_endpoint_instance *endpoint)
287 {
288         struct usbd_urb *urb;
289         int epn = endpoint->bEndpointAddress & 0x7f;
290         u32 ep_num = ep_num_dir(epn, USB_DIR_OUT);
291
292         urb = endpoint->urb; 
293         endpoint->planed = urb->buffer_length;
294         mxc_ep_config(epn, USB_DIR_OUT, ep_num, endpoint->wMaxPacketSize,
295                 endpoint->wMaxPacketSize, endpoint->bmAttributes & 0x3, 
296                 endpoint->planed);
297
298         mxc_set_ep_rdy(ep_num);
299 }
300
301 static void
302 mxc_pcd_start_ep_in(struct usbd_endpoint_instance *endpoint)
303 {
304         struct usbd_urb *urb;
305         int epn = endpoint->bEndpointAddress & 0x7f;
306         u32 ep_num = ep_num_dir(epn, USB_DIR_IN);
307         int wMaxPacketSize = endpoint->wMaxPacketSize;
308
309         urb = endpoint->urb;
310
311         /* check if xfil/yfil bits are set, clear if necessary */
312         if (epn && fs_rl(OTG_FUNC_XFILL_STAT) & ep_num) {
313                 fs_wl(OTG_FUNC_XFILL_STAT, ep_num);
314         }
315         if (epn && fs_rl(OTG_FUNC_YFILL_STAT) & ep_num) {
316                 fs_wl(OTG_FUNC_YFILL_STAT, ep_num);
317         }
318
319         endpoint->planed = urb->actual_length;
320
321         mxc_ep_config(epn, USB_DIR_IN, ep_num, wMaxPacketSize, 
322                 (endpoint->planed > wMaxPacketSize) ? wMaxPacketSize : endpoint->planed,
323                 endpoint->bmAttributes & 0x3, endpoint->planed);
324
325         memcpy((void *)data_x_address(epn, USB_DIR_IN), 
326                 urb->buffer, endpoint->planed);
327         fs_wl(OTG_FUNC_XFILL_STAT, ep_num);
328         fs_wl(OTG_FUNC_YFILL_STAT, ep_num);
329
330         mxc_set_ep_rdy(ep_num);
331 }
332
333 static int do_device_request(struct usbd_device_request *request)
334 {
335     struct usbd_urb *urb;
336     u8 bmRequestType = request->bmRequestType;
337     u8 bRequest = request->bRequest;
338     u16 wValue = le16_to_cpu(request->wValue);
339     u16 wLength = le16_to_cpu(request->wLength);
340
341         dbug_usb("do_device_request %x %x %x %x\n", 
342                 bmRequestType, bRequest, wValue, wLength);
343     if ((bmRequestType & USB_REQ_DIRECTION_MASK)) {
344         urb = usbd_alloc_urb(64, &endpoint_zero);
345         dbug_usb("allocating urb length: %d at %x\n", wLength, urb);
346
347         switch (bRequest) {
348             case USB_REQ_GET_DESCRIPTOR:
349                 dbug_usb("USB_REQ_GET_DESCRIPTOR\n");
350                 urb->actual_length = 
351                         usbd_get_descriptor(urb->buffer, wLength, wValue >> 8);
352                                 dbug_usb("buffer %x %x %x %x %x %x %x %x %x\n", 
353                                         *(urb->buffer), *(urb->buffer+1), *(urb->buffer+2), 
354                                         *(urb->buffer+3), *(urb->buffer+4), *(urb->buffer+5), 
355                                         *(urb->buffer+6), *(urb->buffer+7), *(urb->buffer+8)); 
356                 break;
357             case USB_REQ_GET_CONFIGURATION:
358                 urb->actual_length = 1;
359                 urb->buffer[0] = 1;
360                 break;
361             case USB_REQ_GET_INTERFACE:
362                 urb->buffer[0] = 0;
363                 urb->actual_length = 1;
364                 break;
365             default:
366                 dbug_usb("bad descriptor type");
367                 return -1;
368         }
369
370         mxc_pcd_start_ep_in(urb->endpoint);
371                 return 0;
372     }
373     else {
374         switch (bRequest) {
375             case USB_REQ_SET_ADDRESS:
376                 mxc_pcd_set_address(wValue);
377                 break;
378             case USB_REQ_SET_CONFIGURATION:
379                 urb = usbd_alloc_urb(64 * 2, &endpoint_bulk_out);
380                             urb->actual_length = 0;
381                             mxc_pcd_start_ep_out(urb->endpoint);
382                                 break;
383             case USB_REQ_SET_INTERFACE:
384             default: 
385                 return -1;
386         }
387
388                 mxc_sendzlp(0, &endpoint_zero, endpoint_zero.wMaxPacketSize);
389                 hal_delay_us(5000);
390                 return 0;
391     }
392     return -1;
393 }
394
395 static void
396 mxc_pcd_stop_ep_out(int epn, struct usbd_endpoint_instance *endpoint)
397 {
398         u32 transfer;
399         u32 ep_num = ep_num_dir(epn, USB_DIR_OUT);
400     char *endstring = "redboot dummy";
401
402         transfer = endpoint->planed - (fs_rl(ep_word(epn, USB_DIR_OUT, 3)) & 0x1fffff);
403         dbug_usb("mxc_pcd_stop_ep_out received %d\n", transfer);
404         //mxc_stop_ep(epn, USB_DIR_OUT);
405
406         if (epn == 0) {
407 #if 0
408                 usbd_free_urb(endpoint->urb);
409 #endif
410         }
411         else {
412                 if (transfer > endpoint->wMaxPacketSize) {
413 //diag_printf("transfer  %d\n", transfer);
414                         memcpy(ram_buffer + ram_transfered, 
415                                 (void *)data_x_address(epn, USB_DIR_OUT), endpoint->wMaxPacketSize);
416                         memcpy(ram_buffer + ram_transfered + endpoint->wMaxPacketSize, 
417                                 (void *)data_y_address(epn, USB_DIR_OUT), transfer - endpoint->wMaxPacketSize);
418                 }
419                 else {
420                         memcpy(ram_buffer + ram_transfered, 
421                                 (void *)data_x_address(epn, USB_DIR_OUT), transfer);
422             if (transfer == sizeof(endstring)) {
423                 if (memcmp(endstring, ram_buffer + ram_transfered, sizeof(endstring))
424                     == 0) {
425                     transfer = 0;
426                 }
427             }
428                 }
429                 ram_transfered += transfer;
430                 dbug_usb("ram_transfered %d, %x %x %x %x %x %x %x %x %x %x %x %x\n", 
431                 ram_transfered, 
432                 *(ram_buffer+0), *(ram_buffer+1), *(ram_buffer+2), *(ram_buffer+3),
433                 *(ram_buffer+4), *(ram_buffer+5), *(ram_buffer+6), *(ram_buffer+7),
434                 *(ram_buffer+8), *(ram_buffer+9), *(ram_buffer+10), *(ram_buffer+11));
435
436                 /* check if xfil/yfil bits are set, clear if necessary */
437                 if (epn && fs_rl(OTG_FUNC_XFILL_STAT) & ep_num) {
438                         fs_wl(OTG_FUNC_XFILL_STAT, ep_num);
439                 }
440                 if (epn && fs_rl(OTG_FUNC_YFILL_STAT) & ep_num) {
441                         fs_wl(OTG_FUNC_YFILL_STAT, ep_num);
442                 }
443
444                 /* re-arm */
445                 mxc_ep_config(epn, USB_DIR_OUT, ep_num, endpoint->wMaxPacketSize,
446                         endpoint->wMaxPacketSize, endpoint->bmAttributes & 0x3, 
447                         endpoint->planed);
448
449                 mxc_set_ep_rdy(ep_num);
450
451                 if (transfer < endpoint->planed) {
452                         transfer_done = 1;
453                         return;
454                 }       
455         }
456 }
457
458 static void
459 mxc_pcd_stop_ep_setup(struct usbd_endpoint_instance *endpoint)
460 {
461         static struct usbd_device_request request;
462
463         u32 ep0 = fs_rl(ep_word(0, USB_DIR_OUT, 0));
464
465         dbug_usb("mxc_pcd_stop_ep_setup ep0 %x\n", ep0);
466         if ((ep0 & EP0_SETUP) == 0) {
467                 dbug_usb("ep0 out received.\n");
468                 mxc_pcd_stop_ep_out(0, endpoint);
469                 return;
470         }
471
472         dbug_usb("setup received OTG_FUNC_XINT_STAT %x.\n", fs_rl(OTG_FUNC_XINT_STAT));
473         mxc_set_toggle_ep(2);
474
475         dbug_usb("copy x buffer\n");
476         fs_memcpy((u8 *) &request, (u8 *) data_x_address(0, USB_DIR_OUT), 8);
477         fs_wl(OTG_FUNC_XINT_STAT, ep_num_out(0));
478         fs_wl(OTG_FUNC_XFILL_STAT, ep_num_out(0));
479
480         do_device_request(&request);
481
482         if ((request.bmRequestType & USB_REQ_DIRECTION_MASK) == USB_REQ_HOST2DEVICE) {
483                 if (mxc_new_address != mxc_usb_address) {
484                         dbug_usb("Actual set new address to %d\n", mxc_new_address);
485                         mxc_usb_address = mxc_new_address;
486                         fs_wl(OTG_FUNC_DEV_ADDR, mxc_usb_address);
487                 }
488         }
489 }
490
491 static void
492 mxc_pcd_stop_ep_in(int epn, struct usbd_endpoint_instance *endpoint)
493 {
494         mxc_stop_ep(epn, USB_DIR_IN);
495         usbd_free_urb(endpoint->urb);
496
497         /* for the ZLP */
498         if (!epn) {
499                 mxc_ep_config_nodma(0, USB_DIR_OUT, endpoint->wMaxPacketSize,
500                     EP_FORMAT_CONTROL, endpoint->wMaxPacketSize);
501         }
502 }
503
504 int mxc_pcd_int_hndlr(long buffer, long length)
505 {
506         u32 cmd_stat, sint_stat, ep_dstat, ep_stats;
507         //u8 first_time = 1;
508         int temp;
509         ram_buffer = (u8 *)buffer;
510         
511         dbug_usb("mxc_pcd_int_hndlr +\n");
512         while (1) {
513                 if ((sint_stat = fs_rl(OTG_FUNC_SINT_STAT)))
514                         fs_wl(OTG_FUNC_SINT_STAT, sint_stat);
515
516                 cmd_stat = fs_rl(OTG_FUNC_CMD_STAT);
517
518                 if ((cmd_stat & COMMAND_RESETDET) || (sint_stat & SYSTEM_RESETINT)/* || first_time*/) {
519                         dbug_usb("reset received.\n");
520                         fs_wl(OTG_FUNC_DEV_ADDR, 0);
521                         mxc_new_address = mxc_usb_address = 0;
522                         fs_wl(OTG_DMA_EP_CH_CLR, 0xffffffff);
523                         fs_wl(OTG_FUNC_IINT_CLR, 0xffffffff);
524                         fs_wl(OTG_FUNC_EP_DEN_CLR, 0xffffffff); 
525                         mxc_reset_toggles();
526                         fs_wl(OTG_FUNC_EP_RDY_CLR, fs_rl(OTG_FUNC_EP_RDY));
527                         fs_wl(OTG_FUNC_EP_DSTAT, fs_rl(OTG_FUNC_EP_DSTAT));
528                         fs_wl(OTG_FUNC_XINT_STAT, fs_rl(OTG_FUNC_XINT_STAT));
529                         fs_wl(OTG_FUNC_YINT_STAT, fs_rl(OTG_FUNC_YINT_STAT));
530                         //mxc_pcd_start_ep_setup(&endpoint_zero);
531                         //first_time = 0;
532                 }
533
534                 ep_dstat = fs_rl(OTG_FUNC_EP_DSTAT);
535                 if (ep_dstat) {
536                         ep_stats = ep_dstat | fs_rl(OTG_FUNC_XINT_STAT) | fs_rl(OTG_FUNC_YINT_STAT);
537
538                         /* clear the done status flags */
539                         fs_wl(OTG_FUNC_EP_DSTAT, ep_dstat);
540
541                         if (ep_stats & EP_IN) {
542                                 dbug_usb("ep0 in received %x\n", ep_stats);
543                                 mxc_pcd_stop_ep_in(0, &endpoint_zero);
544                         }
545
546                         if (ep_stats & EP_OUT) {
547                                 dbug_usb("ep0 out/setup received %x\n", ep_stats);
548                                 mxc_pcd_stop_ep_setup(&endpoint_zero);
549                         }
550
551                         if (ep_dstat & EP_OUT << 2) {
552                                 dbug_usb("bulk out received.\n");
553                                 mxc_pcd_stop_ep_out(1, &endpoint_bulk_out);
554                         }
555                         if (ep_dstat & EP_IN << 2) {
556                                 dbug_usb("bulk in received.\n");
557                                 mxc_pcd_stop_ep_in(1, &endpoint_bulk_in);
558                         }
559                 }
560
561                 if ((transfer_done == 1) || (ram_transfered == length)) {
562                         temp = ram_transfered;
563                         ram_transfered = 0;
564                         return temp;
565                 }                       
566         }
567 }
568
569 static void 
570 iomux_config_mux(u32 pin, int out, int in)
571 {
572         volatile unsigned int *base =
573             (volatile unsigned int *)(IO_ADDRESS(IOMUXC_BASE_ADDR) + 0x034);
574         u32 mux_index = PIN_TO_IOMUX_INDEX(pin);
575         u32 mux_field = PIN_TO_IOMUX_FIELD(pin);
576
577         base[mux_index] =
578             (base[mux_index] & (~(0xFF << (mux_field * MUX_CTL_BIT_LEN)))) |
579             (((out << 4) | in) << (mux_field * MUX_CTL_BIT_LEN));
580 }
581
582 static int 
583 mxc_iomux_gpio_mc13783_set(int usb_mode)
584 {
585         iomux_config_mux(PIN_USB_XRXD, 1, 2);
586         iomux_config_mux(PIN_USB_VMOUT, 1, 2);
587         iomux_config_mux(PIN_USB_VPOUT, 1, 2);
588         iomux_config_mux(PIN_USB_VPIN, 1, 2);
589         iomux_config_mux(PIN_USB_TXENB, 1, 2);
590         iomux_config_mux(PIN_USB_VMIN, 1, 2);
591
592         return 0;
593 }
594
595 static void 
596 mxc_set_transceiver_mode(int mode)
597 {
598         fs_andl(OTG_CORE_HWMODE, ~0xf0);
599         fs_orl(OTG_CORE_HWMODE, (mode << 6) | (mode << 4));     // set to software hnp
600 }
601
602 int mc13783_tcd_mod_init(void)
603 {
604 #ifdef CONFIG_OTG_ZASEVB_DIFFERENTIAL_BIDIRECTIONAL
605         int hwmode = XCVR_D_D;
606         int newmode = XCVR_D_D;
607 #elif CONFIG_OTG_ZASEVB_DIFFERENTIAL_UNIDIRECTIONAL
608         int hwmode = XCVR_D_SE0_NEW;
609         int newmode = XCVR_D_D;
610 #elif CONFIG_OTG_ZASEVB_SINGLE_ENDED_UNIDIRECTIONAL
611         int hwmode = XCVR_SE0_D_NEW;
612         int newmode = XCVR_SE0_D_NEW;
613 #elif CONFIG_OTG_ZASEVB_SINGLE_ENDED_BIDIRECTIONAL
614         int hwmode = XCVR_SE0_SE0;
615         int newmode = XCVR_SE0_SE0;
616 #endif
617
618         mxc_iomux_gpio_mc13783_set(hwmode);
619
620         mxc_set_transceiver_mode(newmode);
621
622 #ifdef MXC_CONFIG_MC13783
623         pmic_reg(49, 0x1844, 1);
624         pmic_reg(50, 0xe, 1);
625 #endif
626
627         return 0;
628 }
629
630 void mxc_pcd_exit(void)
631 {
632         dbug_usb("mxc_pcd_exit\n");
633         mxc_func_clock_off();
634         mxc_main_clock_off();
635 #ifdef MXC_CONFIG_MC13783
636         pmic_reg(49, 0xa0060, 1);
637         pmic_reg(50, 0x6, 1);
638 #endif
639         transfer_done = 0;
640         ram_transfered = 0;
641 }
642 void mxc_pcd_open(void)
643 {
644         mxc_main_clock_on();
645
646         mc13783_tcd_mod_init();
647
648         fs_clear_words((volatile u32 *)IO_ADDRESS(OTG_EP_BASE), (NUM_ETDS * 16 / 4));
649         fs_clear_words((volatile u32 *)IO_ADDRESS(OTG_EP_BASE), 0x200 / 4);
650         fs_clear_words((volatile u32 *)IO_ADDRESS(OTG_DATA_BASE), 0x400 / 4);
651
652         //fs_wl(OTG_DMA_MISC_CTRL, OTG_DMA_MISC_ARBMODE);       /* round-robin mode */
653         fs_andl(OTG_CORE_HWMODE, ~MODULE_CRECFG_HOST);  // set to FUNCTION hnp
654         fs_orl(OTG_CORE_HWMODE, MODULE_CRECFG_FUNC);    // set to software hnp
655
656         mxc_func_clock_on();
657
658         endpoint_zero.wMaxPacketSize = 64;
659         endpoint_zero.bEndpointAddress = 0;
660         endpoint_zero.bmAttributes = USB_ENDPOINT_CONTROL;
661         mxc_pcd_start_ep_setup(&endpoint_zero);
662
663         endpoint_bulk_out.wMaxPacketSize = 64;
664         endpoint_bulk_out.bEndpointAddress = 1;
665         endpoint_bulk_out.bmAttributes = USB_ENDPOINT_BULK;
666
667         endpoint_bulk_in.wMaxPacketSize = 64;
668         endpoint_bulk_in.bEndpointAddress = 1;
669         endpoint_bulk_in.bmAttributes = USB_ENDPOINT_BULK;
670
671         fs_andl(OTG_CORE_HNP_CSTAT, ~(MODULE_MASTER | MODULE_SLAVE |
672             MODULE_CMPEN | MODULE_BGEN | MODULE_SWAUTORST |     MODULE_ABBUSREQ));
673         fs_orl(OTG_CORE_HNP_CSTAT, MODULE_SLAVE | MODULE_CMPEN | MODULE_BGEN |
674                  MODULE_SWAUTORST | MODULE_ABBUSREQ);
675 }
676
677 static int mxc_pcd_init(void)
678 {
679         dbug_usb("mxc_pcd_init\n");
680     
681     mxc_pcd_open();
682         mxc_pcd_int_hndlr(0x100000, 0x200000);
683
684         mxc_pcd_exit();
685         return 0;
686 }
687
688 static void
689 do_usb(int argc, char *argv[])
690 {
691     dbug_usb("do_usb\n");
692         mxc_pcd_init();
693 }