Merge branch 'holger/openmoko-merges' into org.openembedded.dev
[vuplus_openembedded] / packages / u-boot / u-boot-mkimage-openmoko-native / uboot-s3c2410_udc.patch
1 USB Device Controller Driver for Samsung S3C2410 SoC
2
3 Index: u-boot/drivers/Makefile
4 ===================================================================
5 --- u-boot.orig/drivers/Makefile
6 +++ u-boot/drivers/Makefile
7 @@ -47,7 +47,7 @@
8           status_led.o sym53c8xx.o systemace.o ahci.o \
9           ti_pci1410a.o tigon3.o tsec.o \
10           tsi108_eth.o tsi108_i2c.o tsi108_pci.o \
11 -         usbdcore.o usbdcore_ep0.o usbdcore_omap1510.o usbtty.o \
12 +         usbdcore.o usbdcore_ep0.o usbdcore_omap1510.o usbdcore_s3c2410.o usbtty.o \
13           videomodes.o w83c553f.o \
14           ks8695eth.o \
15           pcf50606.o \
16 Index: u-boot/drivers/usbdcore_s3c2410.c
17 ===================================================================
18 --- /dev/null
19 +++ u-boot/drivers/usbdcore_s3c2410.c
20 @@ -0,0 +1,730 @@
21 +/* S3C2410 USB Device Controller Driver for u-boot
22 + *
23 + * (C) Copyright 2007 by Openmoko, Inc.
24 + * Author: Harald Welte <laforge@openmoko.org>
25 + *
26 + * based on Linux' s3c2410_udc.c, which is
27 + * Copyright (C) 2004-2006 Herbert Pƶtzl - Arnaud Patard
28 + *
29 + * This program is free software; you can redistribute it and/or modify
30 + * it under the terms of the GNU General Public License as published by
31 + * the Free Software Foundation; either version 2 of the License, or
32 + * (at your option) any later version.
33 + *
34 + * This program is distributed in the hope that it will be useful,
35 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
37 + * GNU General Public License for more details.
38 + *
39 + * You should have received a copy of the GNU General Public License
40 + * along with this program; if not, write to the Free Software
41 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307         USA
42 + *
43 + */
44 +
45 +#include <config.h>
46 +
47 +#if defined(CONFIG_S3C2410) && defined(CONFIG_USB_DEVICE)
48 +
49 +#include <common.h>
50 +
51 +/* we can't use the regular debug macros since the console might be
52 + * set to usbtty, which would cause deadlocks! */
53 +#ifdef DEBUG
54 +#undef debug
55 +#undef debugX
56 +#define debug(fmt,args...)     serial_printf (fmt ,##args)
57 +#define debugX(level,fmt,args...) if (DEBUG>=level) serial_printf(fmt,##args)
58 +#endif
59 +
60 +DECLARE_GLOBAL_DATA_PTR;
61 +
62 +#include <asm/io.h>
63 +#include <s3c2410.h>
64 +
65 +#include "usbdcore.h"
66 +#include "usbdcore_s3c2410.h"
67 +#include "usbdcore_ep0.h"
68 +#include <usb_cdc_acm.h>
69 +
70 +enum ep0_state {
71 +        EP0_IDLE,
72 +        EP0_IN_DATA_PHASE,
73 +        EP0_OUT_DATA_PHASE,
74 +        EP0_END_XFER,
75 +        EP0_STALL,
76 +};
77 +
78 +static struct urb *ep0_urb = NULL;
79 +
80 +static struct usb_device_instance *udc_device; /* Used in interrupt handler */
81 +
82 +static inline int fifo_count_out(void)
83 +{
84 +       int tmp;
85 +
86 +       tmp = inl(S3C2410_UDC_OUT_FIFO_CNT2_REG) << 8;
87 +       tmp |= inl(S3C2410_UDC_OUT_FIFO_CNT1_REG);
88 +
89 +       return tmp & 0xffff;
90 +}
91 +
92 +static const unsigned long ep_fifo_reg[S3C2410_UDC_NUM_ENDPOINTS] = {
93 +       S3C2410_UDC_EP0_FIFO_REG,
94 +       S3C2410_UDC_EP1_FIFO_REG,
95 +       S3C2410_UDC_EP2_FIFO_REG,
96 +       S3C2410_UDC_EP3_FIFO_REG,
97 +       S3C2410_UDC_EP4_FIFO_REG,
98 +};
99 +
100 +static int s3c2410_write_noniso_tx_fifo(struct usb_endpoint_instance *endpoint)
101 +{
102 +       struct urb *urb = endpoint->tx_urb;
103 +       unsigned int last, i;
104 +       unsigned int ep = endpoint->endpoint_address & 0x7f;
105 +       unsigned long fifo_reg = ep_fifo_reg[ep];
106 +
107 +       /* WARNING: don't ever put serial debug printf's in non-error codepaths
108 +        * here, it is called from the time critical EP0 codepath ! */
109 +
110 +       if (!urb || ep >= S3C2410_UDC_NUM_ENDPOINTS) {
111 +               serial_printf("no urb or wrong endpoint\n");
112 +               return -1;
113 +       }
114 +
115 +       S3C2410_UDC_SETIX(ep);
116 +       if ((last = MIN(urb->actual_length - endpoint->sent,
117 +                       endpoint->tx_packetSize))) {
118 +               u8 *cp = urb->buffer + endpoint->sent;
119 +
120 +               for (i = 0; i < last; i++)
121 +                       outb(*(cp+i), fifo_reg);
122 +       }
123 +       endpoint->last = last;
124 +
125 +       if (endpoint->sent + last < urb->actual_length) {
126 +               /* not all data has been transmitted so far */
127 +               return 0;
128 +       }
129 +
130 +       if (last == endpoint->tx_packetSize) {
131 +               /* we need to send one more packet (ZLP) */
132 +               return 0;
133 +       }
134 +
135 +       return 1;
136 +}
137 +
138 +
139 +static void s3c2410_deconfigure_device (void)
140 +{
141 +       /* FIXME: Implement this */
142 +}
143 +
144 +static void s3c2410_configure_device (struct usb_device_instance *device)
145 +{
146 +       S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
147 +       S3C24X0_CLOCK_POWER * const cpower = S3C24X0_GetBase_CLOCK_POWER();
148 +
149 +       /* disable EP0-4 SUBD interrupts ? */
150 +       outl(0x00, S3C2410_UDC_USB_INT_EN_REG);
151 +
152 +       /* UPLL already configured by board-level init code */
153 +
154 +       /* configure USB pads to device mode */
155 +       gpio->MISCCR &= ~(S3C2410_MISCCR_USBHOST|S3C2410_MISCCR_USBSUSPND1);
156 +
157 +       /* don't disable USB clock */
158 +       cpower->CLKSLOW &= ~S3C2410_CLKSLOW_UCLK_OFF;
159 +
160 +       /* clear interrupt registers */
161 +       inl(S3C2410_UDC_EP_INT_REG);
162 +       inl(S3C2410_UDC_USB_INT_REG);
163 +       outl(0xff, S3C2410_UDC_EP_INT_REG);
164 +       outl(0xff, S3C2410_UDC_USB_INT_REG);
165 +
166 +       /* enable USB interrupts for RESET and SUSPEND/RESUME */
167 +       outl(S3C2410_UDC_USBINT_RESET|S3C2410_UDC_USBINT_SUSPEND,
168 +            S3C2410_UDC_USB_INT_EN_REG);
169 +}
170 +
171 +static void udc_set_address(unsigned char address)
172 +{
173 +       address |= 0x80; /* ADDR_UPDATE bit */
174 +       outl(address, S3C2410_UDC_FUNC_ADDR_REG);
175 +}
176 +
177 +extern struct usb_device_descriptor device_descriptor;
178 +
179 +static void s3c2410_udc_ep0(void)
180 +{
181 +       u_int8_t ep0csr;
182 +       struct usb_endpoint_instance *ep0 = udc_device->bus->endpoint_array;
183 +
184 +       S3C2410_UDC_SETIX(0);
185 +       ep0csr = inl(S3C2410_UDC_IN_CSR1_REG);
186 +
187 +       /* clear stall status */
188 +       if (ep0csr & S3C2410_UDC_EP0_CSR_SENTSTL) {
189 +               serial_printf("Clearing SENT_STALL\n");
190 +               clear_ep0_sst();
191 +               if (ep0csr & S3C2410_UDC_EP0_CSR_SOPKTRDY)
192 +                       clear_ep0_opr();
193 +               ep0->state = EP0_IDLE;
194 +               return;
195 +       }
196 +
197 +       /* clear setup end */
198 +       if (ep0csr & S3C2410_UDC_EP0_CSR_SE
199 +           /* && ep0->state != EP0_IDLE */) {
200 +               serial_printf("Clearing SETUP_END\n");
201 +               clear_ep0_se();
202 +#if 1
203 +               if (ep0csr & S3C2410_UDC_EP0_CSR_SOPKTRDY) {
204 +                       /* Flush FIFO */
205 +                       while (inl(S3C2410_UDC_OUT_FIFO_CNT1_REG))
206 +                               inl(S3C2410_UDC_EP0_FIFO_REG);
207 +                       clear_ep0_opr();
208 +               }
209 +#endif
210 +               ep0->state = EP0_IDLE;
211 +               return;
212 +       }
213 +
214 +       /* Don't ever put [serial] debugging in non-error codepaths here, it
215 +        * will violate the tight timing constraints of this USB Device
216 +        * controller (and lead to bus enumeration failures) */
217 +
218 +       switch (ep0->state) {
219 +               int i, fifo_count;
220 +               unsigned char *datap;
221 +       case EP0_IDLE:
222 +               if (!(ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY))
223 +                       break;
224 +
225 +               datap = (unsigned char *) &ep0_urb->device_request;
226 +               /* host->device packet has been received */
227 +
228 +               /* pull it out of the fifo */
229 +               fifo_count = fifo_count_out();
230 +               for (i = 0; i < fifo_count; i++) {
231 +                       *datap = (unsigned char)inl(S3C2410_UDC_EP0_FIFO_REG);
232 +                       datap++;
233 +               }
234 +               if (fifo_count != 8) {
235 +                       debug("STRANGE FIFO COUNT: %u bytes\n", fifo_count);
236 +                       set_ep0_ss();
237 +                       return;
238 +               }
239 +
240 +               if (ep0_urb->device_request.wLength == 0) {
241 +                       if (ep0_recv_setup(ep0_urb)) {
242 +                               /* Not a setup packet, stall next EP0 transaction */
243 +                               debug("can't parse setup packet1\n");
244 +                               set_ep0_ss();
245 +                               set_ep0_de_out();
246 +                               ep0->state = EP0_IDLE;
247 +                               return;
248 +                       }
249 +                       /* There are some requests with which we need to deal
250 +                        * manually here */
251 +                       switch (ep0_urb->device_request.bRequest) {
252 +                       case USB_REQ_SET_CONFIGURATION:
253 +                               if (!ep0_urb->device_request.wValue)
254 +                                       usbd_device_event_irq(udc_device,
255 +                                                       DEVICE_DE_CONFIGURED, 0);
256 +                               else
257 +                                       usbd_device_event_irq(udc_device,
258 +                                                       DEVICE_CONFIGURED, 0);
259 +                               break;
260 +                       case USB_REQ_SET_ADDRESS:
261 +                               udc_set_address(udc_device->address);
262 +                               usbd_device_event_irq(udc_device,
263 +                                               DEVICE_ADDRESS_ASSIGNED, 0);
264 +                               break;
265 +                       default:
266 +                               break;
267 +                       }
268 +                       set_ep0_de_out();
269 +                       ep0->state = EP0_IDLE;
270 +               } else {
271 +                       if ((ep0_urb->device_request.bmRequestType & USB_REQ_DIRECTION_MASK)
272 +                           == USB_REQ_HOST2DEVICE) {
273 +                               clear_ep0_opr();
274 +                               ep0->state = EP0_OUT_DATA_PHASE;
275 +                               ep0_urb->buffer = ep0_urb->buffer_data;
276 +                               ep0_urb->buffer_length = sizeof(ep0_urb->buffer_data);
277 +                               ep0_urb->actual_length = 0;
278 +                       } else {
279 +                               ep0->state = EP0_IN_DATA_PHASE;
280 +
281 +                               if (ep0_recv_setup(ep0_urb)) {
282 +                                       /* Not a setup packet, stall next EP0 transaction */
283 +                                       debug("can't parse setup packet2\n");
284 +                                       set_ep0_ss();
285 +                                       //set_ep0_de_out();
286 +                                       ep0->state = EP0_IDLE;
287 +                                       return;
288 +                               }
289 +                               clear_ep0_opr();
290 +                               ep0->tx_urb = ep0_urb;
291 +                               ep0->sent = ep0->last = 0;
292 +
293 +                               if (s3c2410_write_noniso_tx_fifo(ep0)) {
294 +                                       ep0->state = EP0_IDLE;
295 +                                       set_ep0_de_in();
296 +                               } else
297 +                                       set_ep0_ipr();
298 +                       }
299 +               }
300 +               break;
301 +       case EP0_IN_DATA_PHASE:
302 +               if (!(ep0csr & S3C2410_UDC_EP0_CSR_IPKRDY)) {
303 +                       ep0->sent += ep0->last;
304 +
305 +                       if (s3c2410_write_noniso_tx_fifo(ep0)) {
306 +                               ep0->state = EP0_IDLE;
307 +                               set_ep0_de_in();
308 +                       } else
309 +                               set_ep0_ipr();
310 +               }
311 +               break;
312 +       case EP0_OUT_DATA_PHASE:
313 +               if (ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY) {
314 +                       u32 urb_avail = ep0_urb->buffer_length - ep0_urb->actual_length;
315 +                       u_int8_t *cp = ep0_urb->buffer + ep0_urb->actual_length;
316 +                       int i, fifo_count;
317 +
318 +                       fifo_count = fifo_count_out();
319 +                       if (fifo_count < urb_avail)
320 +                               urb_avail = fifo_count;
321 +
322 +                       for (i = 0; i < urb_avail; i++)
323 +                               *cp++ = inl(S3C2410_UDC_EP0_FIFO_REG);
324 +
325 +                       ep0_urb->actual_length += urb_avail;
326 +
327 +                       if (fifo_count < ep0->rcv_packetSize ||
328 +                           ep0_urb->actual_length >= ep0_urb->device_request.wLength) {
329 +                               ep0->state = EP0_IDLE;
330 +                               if (ep0_recv_setup(ep0_urb)) {
331 +                                       /* Not a setup packet, stall next EP0 transaction */
332 +                                       debug("can't parse setup packet3\n");
333 +                                       set_ep0_ss();
334 +                                       //set_ep0_de_out();
335 +                                       return;
336 +                               }
337 +                               set_ep0_de_out();
338 +                       } else
339 +                               clear_ep0_opr();
340 +               }
341 +               break;
342 +       case EP0_END_XFER:
343 +               ep0->state = EP0_IDLE;
344 +               break;
345 +       case EP0_STALL:
346 +               //set_ep0_ss;
347 +               ep0->state = EP0_IDLE;
348 +               break;
349 +       }
350 +}
351 +
352 +
353 +static void s3c2410_udc_epn(int ep)
354 +{
355 +       struct usb_endpoint_instance *endpoint;
356 +       struct urb *urb;
357 +       u32 ep_csr1;
358 +
359 +       if (ep >= S3C2410_UDC_NUM_ENDPOINTS)
360 +               return;
361 +
362 +       endpoint = &udc_device->bus->endpoint_array[ep];
363 +
364 +       S3C2410_UDC_SETIX(ep);
365 +
366 +       if (endpoint->endpoint_address & USB_DIR_IN) {
367 +               /* IN transfer (device to host) */
368 +               ep_csr1 = inl(S3C2410_UDC_IN_CSR1_REG);
369 +               debug("for ep=%u, CSR1=0x%x ", ep, ep_csr1);
370 +
371 +               urb = endpoint->tx_urb;
372 +               if (ep_csr1 & S3C2410_UDC_ICSR1_SENTSTL) {
373 +                       /* Stall handshake */
374 +                       debug("stall\n");
375 +                       outl(0x00, S3C2410_UDC_IN_CSR1_REG);
376 +                       return;
377 +               }
378 +               if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && urb &&
379 +                     urb->actual_length) {
380 +
381 +                       debug("completing previously send data ");
382 +                       usbd_tx_complete(endpoint);
383 +
384 +                       /* push pending data into FIFO */
385 +                       if ((endpoint->last == endpoint->tx_packetSize) &&
386 +                           (urb->actual_length - endpoint->sent - endpoint->last == 0)) {
387 +                               endpoint->sent += endpoint->last;
388 +                               /* Write 0 bytes of data (ZLP) */
389 +                               debug("ZLP ");
390 +                               outl(ep_csr1|S3C2410_UDC_ICSR1_PKTRDY, S3C2410_UDC_IN_CSR1_REG);
391 +                       } else {
392 +                               /* write actual data to fifo */
393 +                               debug("TX_DATA ");
394 +                               s3c2410_write_noniso_tx_fifo(endpoint);
395 +                               outl(ep_csr1|S3C2410_UDC_ICSR1_PKTRDY, S3C2410_UDC_IN_CSR1_REG);
396 +                       }
397 +               }
398 +               debug("\n");
399 +       } else {
400 +               /* OUT transfer (host to device) */
401 +               ep_csr1 = inl(S3C2410_UDC_OUT_CSR1_REG);
402 +               debug("for ep=%u, CSR1=0x%x ", ep, ep_csr1);
403 +
404 +               urb = endpoint->rcv_urb;
405 +               if (ep_csr1 & S3C2410_UDC_OCSR1_SENTSTL) {
406 +                       /* Stall handshake */
407 +                       outl(0x00, S3C2410_UDC_IN_CSR1_REG);
408 +                       return;
409 +               }
410 +               if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && urb) {
411 +                       /* Read pending data from fifo */
412 +                       u32 fifo_count = fifo_count_out();
413 +                       int is_last = 0;
414 +                       u32 i, urb_avail = urb->buffer_length - urb->actual_length;
415 +                       u8 *cp = urb->buffer + urb->actual_length;
416 +
417 +                       if (fifo_count < endpoint->rcv_packetSize)
418 +                               is_last = 1;
419 +
420 +                       debug("fifo_count=%u is_last=%, urb_avail=%u)\n",
421 +                               fifo_count, is_last, urb_avail);
422 +
423 +                       if (fifo_count < urb_avail)
424 +                               urb_avail = fifo_count;
425 +
426 +                       for (i = 0; i < urb_avail; i++)
427 +                               *cp++ = inb(ep_fifo_reg[ep]);
428 +
429 +                       if (is_last)
430 +                               outl(ep_csr1 & ~S3C2410_UDC_OCSR1_PKTRDY,
431 +                                    S3C2410_UDC_OUT_CSR1_REG);
432 +
433 +                       usbd_rcv_complete(endpoint, urb_avail, 0);
434 +               }
435 +       }
436 +
437 +       urb = endpoint->rcv_urb;
438 +}
439 +
440 +/*
441 +-------------------------------------------------------------------------------
442 +*/
443 +
444 +/* this is just an empty wrapper for usbtty who assumes polling operation */
445 +void udc_irq(void)
446 +{
447 +}
448 +
449 +/* Handle general USB interrupts and dispatch according to type.
450 + * This function implements TRM Figure 14-13.
451 + */
452 +void s3c2410_udc_irq(void)
453 +{
454 +       struct usb_endpoint_instance *ep0 = udc_device->bus->endpoint_array;
455 +       u_int32_t save_idx = inl(S3C2410_UDC_INDEX_REG);
456 +
457 +       /* read interrupt sources */
458 +       u_int32_t usb_status = inl(S3C2410_UDC_USB_INT_REG);
459 +       u_int32_t usbd_status = inl(S3C2410_UDC_EP_INT_REG);
460 +
461 +       //debug("< IRQ usbs=0x%02x, usbds=0x%02x start >", usb_status, usbd_status);
462 +
463 +       /* clear interrupts */
464 +       outl(usb_status, S3C2410_UDC_USB_INT_REG);
465 +
466 +       if (usb_status & S3C2410_UDC_USBINT_RESET) {
467 +               //serial_putc('R');
468 +               debug("RESET pwr=0x%x\n", inl(S3C2410_UDC_PWR_REG));
469 +               udc_setup_ep(udc_device, 0, ep0);
470 +               outl(S3C2410_UDC_EP0_CSR_SSE|S3C2410_UDC_EP0_CSR_SOPKTRDY, S3C2410_UDC_EP0_CSR_REG);
471 +               ep0->state = EP0_IDLE;
472 +               usbd_device_event_irq (udc_device, DEVICE_RESET, 0);
473 +       }
474 +
475 +       if (usb_status & S3C2410_UDC_USBINT_RESUME) {
476 +               debug("RESUME\n");
477 +               usbd_device_event_irq(udc_device, DEVICE_BUS_ACTIVITY, 0);
478 +       }
479 +
480 +       if (usb_status & S3C2410_UDC_USBINT_SUSPEND) {
481 +               debug("SUSPEND\n");
482 +               usbd_device_event_irq(udc_device, DEVICE_BUS_INACTIVE, 0);
483 +       }
484 +
485 +       /* Endpoint Interrupts */
486 +       if (usbd_status) {
487 +               int i;
488 +
489 +               if (usbd_status & S3C2410_UDC_INT_EP0) {
490 +                       outl(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_REG);
491 +                       s3c2410_udc_ep0();
492 +               }
493 +
494 +               for (i = 1; i < 5; i++) {
495 +                       u_int32_t tmp = 1 << i;
496 +
497 +                       if (usbd_status & tmp) {
498 +                               /* FIXME: Handle EP X */
499 +                               outl(tmp, S3C2410_UDC_EP_INT_REG);
500 +                               s3c2410_udc_epn(i);
501 +                       }
502 +               }
503 +       }
504 +       S3C2410_UDC_SETIX(save_idx);
505 +}
506 +
507 +/*
508 +-------------------------------------------------------------------------------
509 +*/
510 +
511 +
512 +/*
513 + * Start of public functions.
514 + */
515 +
516 +/* Called to start packet transmission. */
517 +void udc_endpoint_write (struct usb_endpoint_instance *endpoint)
518 +{
519 +       unsigned short epnum =
520 +               endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
521 +
522 +       debug("Entering for ep %x ", epnum);
523 +
524 +       if (endpoint->tx_urb) {
525 +               u32 ep_csr1;
526 +               debug("We have an URB, transmitting\n");
527 +
528 +               s3c2410_write_noniso_tx_fifo(endpoint);
529 +
530 +               S3C2410_UDC_SETIX(epnum);
531 +
532 +               ep_csr1 = inl(S3C2410_UDC_IN_CSR1_REG);
533 +               outl(ep_csr1|S3C2410_UDC_ICSR1_PKTRDY, S3C2410_UDC_IN_CSR1_REG);
534 +       } else
535 +               debug("\n");
536 +}
537 +
538 +/* Start to initialize h/w stuff */
539 +int udc_init (void)
540 +{
541 +       S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
542 +       S3C24X0_INTERRUPT * irq = S3C24X0_GetBase_INTERRUPT();
543 +
544 +       udc_device = NULL;
545 +
546 +       /* Set and check clock control.
547 +        * We might ought to be using the clock control API to do
548 +        * this instead of fiddling with the clock registers directly
549 +        * here.
550 +        */
551 +       clk_power->CLKCON |= (1 << 7);
552 +
553 +       /* Print banner with device revision */
554 +       printf("USB:   S3C2410 USB Deviced\n");
555 +
556 +       /*
557 +        * At this point, device is ready for configuration...
558 +        */
559 +       outl(0x00, S3C2410_UDC_EP_INT_EN_REG);
560 +       outl(0x00, S3C2410_UDC_USB_INT_EN_REG);
561 +
562 +       irq->INTMSK &= ~BIT_USBD;
563 +
564 +       return 0;
565 +}
566 +
567 +/*
568 + * udc_setup_ep - setup endpoint
569 + *
570 + * Associate a physical endpoint with endpoint_instance
571 + */
572 +int udc_setup_ep (struct usb_device_instance *device,
573 +                  unsigned int ep, struct usb_endpoint_instance *endpoint)
574 +{
575 +       int ep_addr = endpoint->endpoint_address;
576 +       int packet_size;
577 +       int attributes;
578 +       u_int32_t maxp;
579 +
580 +       S3C2410_UDC_SETIX(ep);
581 +
582 +       if (ep) {
583 +               if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
584 +                       /* IN endpoint */
585 +                       outl(S3C2410_UDC_ICSR1_FFLUSH|S3C2410_UDC_ICSR1_CLRDT,
586 +                            S3C2410_UDC_IN_CSR1_REG);
587 +                       outl(S3C2410_UDC_ICSR2_MODEIN, S3C2410_UDC_IN_CSR2_REG);
588 +                       packet_size = endpoint->tx_packetSize;
589 +                       attributes = endpoint->tx_attributes;
590 +               } else {
591 +                       /* OUT endpoint */
592 +                       outl(S3C2410_UDC_ICSR1_CLRDT, S3C2410_UDC_IN_CSR1_REG);
593 +                       outl(0, S3C2410_UDC_IN_CSR2_REG);
594 +                       outl(S3C2410_UDC_OCSR1_FFLUSH|S3C2410_UDC_OCSR1_CLRDT,
595 +                            S3C2410_UDC_OUT_CSR1_REG);
596 +                       outl(0, S3C2410_UDC_OUT_CSR2_REG);
597 +                       packet_size = endpoint->rcv_packetSize;
598 +                       attributes = endpoint->rcv_attributes;
599 +               }
600 +       } else
601 +               packet_size = endpoint->tx_packetSize;
602 +
603 +       switch (packet_size) {
604 +       case 8:
605 +               maxp = S3C2410_UDC_MAXP_8;
606 +               break;
607 +       case 16:
608 +               maxp = S3C2410_UDC_MAXP_16;
609 +               break;
610 +       case 32:
611 +               maxp = S3C2410_UDC_MAXP_32;
612 +               break;
613 +       case 64:
614 +               maxp = S3C2410_UDC_MAXP_64;
615 +               break;
616 +       default:
617 +               debug("invalid packet size %u\n", packet_size);
618 +               return -1;
619 +       }
620 +
621 +       debug("setting up endpoint %u addr %x packet_size %u maxp %u\n", ep,
622 +               endpoint->endpoint_address, packet_size, maxp);
623 +
624 +       /* Set maximum packet size */
625 +       writel(maxp, S3C2410_UDC_MAXP_REG);
626 +
627 +       return 0;
628 +}
629 +
630 +/* ************************************************************************** */
631 +
632 +/**
633 + * udc_connected - is the USB cable connected
634 + *
635 + * Return non-zero if cable is connected.
636 + */
637 +#if 0
638 +int udc_connected (void)
639 +{
640 +       return ((inw (UDC_DEVSTAT) & UDC_ATT) == UDC_ATT);
641 +}
642 +#endif
643 +
644 +/* Turn on the USB connection by enabling the pullup resistor */
645 +void udc_connect (void)
646 +{
647 +       debug("connect, enable Pullup\n");
648 +       S3C24X0_INTERRUPT * irq = S3C24X0_GetBase_INTERRUPT();
649 +
650 +       udc_ctrl(UDC_CTRL_PULLUP_ENABLE, 0);
651 +       udelay(10000);
652 +       udc_ctrl(UDC_CTRL_PULLUP_ENABLE, 1);
653 +
654 +       irq->INTMSK &= ~BIT_USBD;
655 +}
656 +
657 +/* Turn off the USB connection by disabling the pullup resistor */
658 +void udc_disconnect (void)
659 +{
660 +       debug("disconnect, disable Pullup\n");
661 +       S3C24X0_INTERRUPT * irq = S3C24X0_GetBase_INTERRUPT();
662 +
663 +       udc_ctrl(UDC_CTRL_PULLUP_ENABLE, 0);
664 +
665 +       /* Disable interrupt (we don't want to get interrupts while the kernel
666 +        * is relocating itself */
667 +       irq->INTMSK |= BIT_USBD;
668 +}
669 +
670 +/* Switch on the UDC */
671 +void udc_enable (struct usb_device_instance *device)
672 +{
673 +       debug("enable device %p, status %d\n", device, device->status);
674 +
675 +       /* Save the device structure pointer */
676 +       udc_device = device;
677 +
678 +       /* Setup ep0 urb */
679 +       if (!ep0_urb)
680 +               ep0_urb = usbd_alloc_urb(udc_device,
681 +                                        udc_device->bus->endpoint_array);
682 +       else
683 +               serial_printf("udc_enable: ep0_urb already allocated %p\n",
684 +                              ep0_urb);
685 +
686 +       s3c2410_configure_device(device);
687 +}
688 +
689 +/* Switch off the UDC */
690 +void udc_disable (void)
691 +{
692 +       debug("disable UDC\n");
693 +
694 +       s3c2410_deconfigure_device();
695 +
696 +       /* Free ep0 URB */
697 +       if (ep0_urb) {
698 +               /*usbd_dealloc_urb(ep0_urb); */
699 +               ep0_urb = NULL;
700 +       }
701 +
702 +       /* Reset device pointer.
703 +        * We ought to do this here to balance the initialization of udc_device
704 +        * in udc_enable, but some of our other exported functions get called
705 +        * by the bus interface driver after udc_disable, so we have to hang on
706 +        * to the device pointer to avoid a null pointer dereference. */
707 +       /* udc_device = NULL; */
708 +}
709 +
710 +/**
711 + * udc_startup - allow udc code to do any additional startup
712 + */
713 +void udc_startup_events (struct usb_device_instance *device)
714 +{
715 +       /* The DEVICE_INIT event puts the USB device in the state STATE_INIT. */
716 +       usbd_device_event_irq (device, DEVICE_INIT, 0);
717 +
718 +       /* The DEVICE_CREATE event puts the USB device in the state
719 +        * STATE_ATTACHED.
720 +        */
721 +       usbd_device_event_irq (device, DEVICE_CREATE, 0);
722 +
723 +       /* Some USB controller driver implementations signal
724 +        * DEVICE_HUB_CONFIGURED and DEVICE_RESET events here.
725 +        * DEVICE_HUB_CONFIGURED causes a transition to the state STATE_POWERED,
726 +        * and DEVICE_RESET causes a transition to the state STATE_DEFAULT.
727 +        * The OMAP USB client controller has the capability to detect when the
728 +        * USB cable is connected to a powered USB bus via the ATT bit in the
729 +        * DEVSTAT register, so we will defer the DEVICE_HUB_CONFIGURED and
730 +        * DEVICE_RESET events until later.
731 +        */
732 +
733 +       /* The GTA01 can detect usb device attachment, but we just assume being
734 +        * attached for now (go to STATE_POWERED) */
735 +       usbd_device_event_irq (device, DEVICE_HUB_CONFIGURED, 0);
736 +
737 +       udc_enable (device);
738 +}
739 +
740 +void udc_set_nak(int epid)
741 +{
742 +       /* FIXME: implement this */
743 +}
744 +
745 +void udc_unset_nak(int epid)
746 +{
747 +       /* FIXME: implement this */
748 +}
749 +
750 +#endif /* CONFIG_S3C2410 && CONFIG_USB_DEVICE */
751 Index: u-boot/drivers/usbdcore_s3c2410.h
752 ===================================================================
753 --- /dev/null
754 +++ u-boot/drivers/usbdcore_s3c2410.h
755 @@ -0,0 +1,273 @@
756 +/* linux/include/asm/arch-s3c2410/regs-udc.h
757 + *
758 + * Copyright (C) 2004 Herbert Poetzl <herbert@13thfloor.at>
759 + *
760 + * This include file is free software; you can redistribute it and/or
761 + * modify it under the terms of the GNU General Public License as
762 + * published by the Free Software Foundation; either version 2 of
763 + * the License, or (at your option) any later version.
764 + *
765 + *  Changelog:
766 + *    01-08-2004       Initial creation
767 + *    12-09-2004       Cleanup for submission
768 + *    24-10-2004       Fixed S3C2410_UDC_MAXP_REG definition
769 + *    10-03-2005       Changed S3C2410_VA to S3C24XX_VA
770 + *    10-01-2007       Modify for u-boot
771 + */
772 +
773 +#ifndef __ASM_ARCH_REGS_UDC_H
774 +#define __ASM_ARCH_REGS_UDC_H
775 +
776 +#define S3C2410_UDC_REG_BASE_PHYS      0x52000000
777 +#define S3C2410_UDC_NUM_ENDPOINTS      5
778 +
779 +#define S3C2410_USBDREG(x) (x + S3C2410_UDC_REG_BASE_PHYS)
780 +
781 +#define S3C2410_UDC_FUNC_ADDR_REG      S3C2410_USBDREG(0x0140)
782 +#define S3C2410_UDC_PWR_REG            S3C2410_USBDREG(0x0144)
783 +#define S3C2410_UDC_EP_INT_REG         S3C2410_USBDREG(0x0148)
784 +
785 +#define S3C2410_UDC_USB_INT_REG                S3C2410_USBDREG(0x0158)
786 +#define S3C2410_UDC_EP_INT_EN_REG      S3C2410_USBDREG(0x015c)
787 +
788 +#define S3C2410_UDC_USB_INT_EN_REG     S3C2410_USBDREG(0x016c)
789 +
790 +#define S3C2410_UDC_FRAME_NUM1_REG     S3C2410_USBDREG(0x0170)
791 +#define S3C2410_UDC_FRAME_NUM2_REG     S3C2410_USBDREG(0x0174)
792 +
793 +#define S3C2410_UDC_EP0_FIFO_REG       S3C2410_USBDREG(0x01c0)
794 +#define S3C2410_UDC_EP1_FIFO_REG       S3C2410_USBDREG(0x01c4)
795 +#define S3C2410_UDC_EP2_FIFO_REG       S3C2410_USBDREG(0x01c8)
796 +#define S3C2410_UDC_EP3_FIFO_REG       S3C2410_USBDREG(0x01cc)
797 +#define S3C2410_UDC_EP4_FIFO_REG       S3C2410_USBDREG(0x01d0)
798 +
799 +#define S3C2410_UDC_EP1_DMA_CON                S3C2410_USBDREG(0x0200)
800 +#define S3C2410_UDC_EP1_DMA_UNIT       S3C2410_USBDREG(0x0204)
801 +#define S3C2410_UDC_EP1_DMA_FIFO       S3C2410_USBDREG(0x0208)
802 +#define S3C2410_UDC_EP1_DMA_TTC_L      S3C2410_USBDREG(0x020c)
803 +#define S3C2410_UDC_EP1_DMA_TTC_M      S3C2410_USBDREG(0x0210)
804 +#define S3C2410_UDC_EP1_DMA_TTC_H      S3C2410_USBDREG(0x0214)
805 +
806 +#define S3C2410_UDC_EP2_DMA_CON                S3C2410_USBDREG(0x0218)
807 +#define S3C2410_UDC_EP2_DMA_UNIT       S3C2410_USBDREG(0x021c)
808 +#define S3C2410_UDC_EP2_DMA_FIFO       S3C2410_USBDREG(0x0220)
809 +#define S3C2410_UDC_EP2_DMA_TTC_L      S3C2410_USBDREG(0x0224)
810 +#define S3C2410_UDC_EP2_DMA_TTC_M      S3C2410_USBDREG(0x0228)
811 +#define S3C2410_UDC_EP2_DMA_TTC_H      S3C2410_USBDREG(0x022c)
812 +
813 +#define S3C2410_UDC_EP3_DMA_CON                S3C2410_USBDREG(0x0240)
814 +#define S3C2410_UDC_EP3_DMA_UNIT       S3C2410_USBDREG(0x0244)
815 +#define S3C2410_UDC_EP3_DMA_FIFO       S3C2410_USBDREG(0x0248)
816 +#define S3C2410_UDC_EP3_DMA_TTC_L      S3C2410_USBDREG(0x024c)
817 +#define S3C2410_UDC_EP3_DMA_TTC_M      S3C2410_USBDREG(0x0250)
818 +#define S3C2410_UDC_EP3_DMA_TTC_H      S3C2410_USBDREG(0x0254)
819 +
820 +#define S3C2410_UDC_EP4_DMA_CON                S3C2410_USBDREG(0x0258)
821 +#define S3C2410_UDC_EP4_DMA_UNIT       S3C2410_USBDREG(0x025c)
822 +#define S3C2410_UDC_EP4_DMA_FIFO       S3C2410_USBDREG(0x0260)
823 +#define S3C2410_UDC_EP4_DMA_TTC_L      S3C2410_USBDREG(0x0264)
824 +#define S3C2410_UDC_EP4_DMA_TTC_M      S3C2410_USBDREG(0x0268)
825 +#define S3C2410_UDC_EP4_DMA_TTC_H      S3C2410_USBDREG(0x026c)
826 +
827 +#define S3C2410_UDC_INDEX_REG          S3C2410_USBDREG(0x0178)
828 +
829 +/* indexed registers */
830 +
831 +#define S3C2410_UDC_MAXP_REG           S3C2410_USBDREG(0x0180)
832 +
833 +#define S3C2410_UDC_EP0_CSR_REG                S3C2410_USBDREG(0x0184)
834 +
835 +#define S3C2410_UDC_IN_CSR1_REG                S3C2410_USBDREG(0x0184)
836 +#define S3C2410_UDC_IN_CSR2_REG                S3C2410_USBDREG(0x0188)
837 +
838 +#define S3C2410_UDC_OUT_CSR1_REG       S3C2410_USBDREG(0x0190)
839 +#define S3C2410_UDC_OUT_CSR2_REG       S3C2410_USBDREG(0x0194)
840 +#define S3C2410_UDC_OUT_FIFO_CNT1_REG  S3C2410_USBDREG(0x0198)
841 +#define S3C2410_UDC_OUT_FIFO_CNT2_REG  S3C2410_USBDREG(0x019c)
842 +
843 +
844 +
845 +#define S3C2410_UDC_PWR_ISOUP          (1<<7) // R/W
846 +#define S3C2410_UDC_PWR_RESET          (1<<3) // R
847 +#define S3C2410_UDC_PWR_RESUME         (1<<2) // R/W
848 +#define S3C2410_UDC_PWR_SUSPEND                (1<<1) // R
849 +#define S3C2410_UDC_PWR_ENSUSPEND      (1<<0) // R/W
850 +
851 +#define S3C2410_UDC_PWR_DEFAULT                0x00
852 +
853 +#define S3C2410_UDC_INT_EP4            (1<<4) // R/W (clear only)
854 +#define S3C2410_UDC_INT_EP3            (1<<3) // R/W (clear only)
855 +#define S3C2410_UDC_INT_EP2            (1<<2) // R/W (clear only)
856 +#define S3C2410_UDC_INT_EP1            (1<<1) // R/W (clear only)
857 +#define S3C2410_UDC_INT_EP0            (1<<0) // R/W (clear only)
858 +
859 +#define S3C2410_UDC_USBINT_RESET       (1<<2) // R/W (clear only)
860 +#define S3C2410_UDC_USBINT_RESUME      (1<<1) // R/W (clear only)
861 +#define S3C2410_UDC_USBINT_SUSPEND     (1<<0) // R/W (clear only)
862 +
863 +#define S3C2410_UDC_INTE_EP4           (1<<4) // R/W
864 +#define S3C2410_UDC_INTE_EP3           (1<<3) // R/W
865 +#define S3C2410_UDC_INTE_EP2           (1<<2) // R/W
866 +#define S3C2410_UDC_INTE_EP1           (1<<1) // R/W
867 +#define S3C2410_UDC_INTE_EP0           (1<<0) // R/W
868 +
869 +#define S3C2410_UDC_USBINTE_RESET      (1<<2) // R/W
870 +#define S3C2410_UDC_USBINTE_SUSPEND    (1<<0) // R/W
871 +
872 +
873 +#define S3C2410_UDC_INDEX_EP0          (0x00)
874 +#define S3C2410_UDC_INDEX_EP1          (0x01) // ??
875 +#define S3C2410_UDC_INDEX_EP2          (0x02) // ??
876 +#define S3C2410_UDC_INDEX_EP3          (0x03) // ??
877 +#define S3C2410_UDC_INDEX_EP4          (0x04) // ??
878 +
879 +#define S3C2410_UDC_ICSR1_CLRDT                (1<<6) // R/W
880 +#define S3C2410_UDC_ICSR1_SENTSTL      (1<<5) // R/W (clear only)
881 +#define S3C2410_UDC_ICSR1_SENDSTL      (1<<4) // R/W
882 +#define S3C2410_UDC_ICSR1_FFLUSH       (1<<3) // W   (set only)
883 +#define S3C2410_UDC_ICSR1_UNDRUN       (1<<2) // R/W (clear only)
884 +#define S3C2410_UDC_ICSR1_PKTRDY       (1<<0) // R/W (set only)
885 +
886 +#define S3C2410_UDC_ICSR2_AUTOSET      (1<<7) // R/W
887 +#define S3C2410_UDC_ICSR2_ISO          (1<<6) // R/W
888 +#define S3C2410_UDC_ICSR2_MODEIN       (1<<5) // R/W
889 +#define S3C2410_UDC_ICSR2_DMAIEN       (1<<4) // R/W
890 +
891 +#define S3C2410_UDC_OCSR1_CLRDT                (1<<7) // R/W
892 +#define S3C2410_UDC_OCSR1_SENTSTL      (1<<6) // R/W (clear only)
893 +#define S3C2410_UDC_OCSR1_SENDSTL      (1<<5) // R/W
894 +#define S3C2410_UDC_OCSR1_FFLUSH       (1<<4) // R/W
895 +#define S3C2410_UDC_OCSR1_DERROR       (1<<3) // R
896 +#define S3C2410_UDC_OCSR1_OVRRUN       (1<<2) // R/W (clear only)
897 +#define S3C2410_UDC_OCSR1_PKTRDY       (1<<0) // R/W (clear only)
898 +
899 +#define S3C2410_UDC_OCSR2_AUTOCLR      (1<<7) // R/W
900 +#define S3C2410_UDC_OCSR2_ISO          (1<<6) // R/W
901 +#define S3C2410_UDC_OCSR2_DMAIEN       (1<<5) // R/W
902 +
903 +#define S3C2410_UDC_SETIX(X)   writel(X, S3C2410_UDC_INDEX_REG)
904 +
905 +#define S3C2410_UDC_EP0_CSR_OPKRDY     (1<<0)
906 +#define S3C2410_UDC_EP0_CSR_IPKRDY     (1<<1)
907 +#define S3C2410_UDC_EP0_CSR_SENTSTL    (1<<2)
908 +#define S3C2410_UDC_EP0_CSR_DE         (1<<3)
909 +#define S3C2410_UDC_EP0_CSR_SE         (1<<4)
910 +#define S3C2410_UDC_EP0_CSR_SENDSTL    (1<<5)
911 +#define S3C2410_UDC_EP0_CSR_SOPKTRDY   (1<<6)
912 +#define S3C2410_UDC_EP0_CSR_SSE        (1<<7)
913 +
914 +#define S3C2410_UDC_MAXP_8             (1<<0)
915 +#define S3C2410_UDC_MAXP_16            (1<<1)
916 +#define S3C2410_UDC_MAXP_32            (1<<2)
917 +#define S3C2410_UDC_MAXP_64            (1<<3)
918 +
919 +/****************** MACROS ******************/
920 +#define BIT_MASK       0xFF
921 +
922 +#if 1
923 +#define maskl(v,m,a)      \
924 +               writel((readl(a) & ~(m))|((v)&(m)), (a))
925 +#else
926 +#define maskl(v,m,a)   do {                                    \
927 +       unsigned long foo = readl(a);                           \
928 +       unsigned long bar = (foo & ~(m)) | ((v)&(m));           \
929 +       serial_printf("0x%08x:0x%x->0x%x\n", (a), foo, bar);    \
930 +       writel(bar, (a));                                       \
931 +} while(0)
932 +#endif
933 +
934 +#define clear_ep0_sst() do {                   \
935 +       S3C2410_UDC_SETIX(0);                   \
936 +       writel(0x00, S3C2410_UDC_EP0_CSR_REG);  \
937 +} while(0)
938 +
939 +#define clear_ep0_se() do {                            \
940 +       S3C2410_UDC_SETIX(0);                           \
941 +       maskl(S3C2410_UDC_EP0_CSR_SSE,                  \
942 +               BIT_MASK, S3C2410_UDC_EP0_CSR_REG);     \
943 +} while(0)
944 +
945 +#define clear_ep0_opr() do {                           \
946 +       S3C2410_UDC_SETIX(0);                           \
947 +       maskl(S3C2410_UDC_EP0_CSR_SOPKTRDY,             \
948 +               BIT_MASK, S3C2410_UDC_EP0_CSR_REG);     \
949 +} while(0)
950 +
951 +#define set_ep0_ipr() do {                             \
952 +       S3C2410_UDC_SETIX(0);                           \
953 +       maskl(S3C2410_UDC_EP0_CSR_IPKRDY,               \
954 +               BIT_MASK, S3C2410_UDC_EP0_CSR_REG);     \
955 +} while(0)
956 +
957 +#define set_ep0_de() do {                              \
958 +       S3C2410_UDC_SETIX(0);                           \
959 +       maskl(S3C2410_UDC_EP0_CSR_DE,                   \
960 +               BIT_MASK, S3C2410_UDC_EP0_CSR_REG);     \
961 +} while(0)
962 +
963 +#define set_ep0_ss() do {                              \
964 +       S3C2410_UDC_SETIX(0);                           \
965 +       maskl(S3C2410_UDC_EP0_CSR_SENDSTL,              \
966 +               BIT_MASK, S3C2410_UDC_EP0_CSR_REG);     \
967 +} while(0)
968 +
969 +#define set_ep0_de_out() do {                          \
970 +       S3C2410_UDC_SETIX(0);                           \
971 +       maskl((S3C2410_UDC_EP0_CSR_SOPKTRDY             \
972 +               | S3C2410_UDC_EP0_CSR_DE),              \
973 +               BIT_MASK, S3C2410_UDC_EP0_CSR_REG);     \
974 +} while(0)
975 +
976 +#define set_ep0_sse_out() do {                         \
977 +       S3C2410_UDC_SETIX(0);                           \
978 +       maskl((S3C2410_UDC_EP0_CSR_SOPKTRDY             \
979 +               | S3C2410_UDC_EP0_CSR_SSE),             \
980 +               BIT_MASK, S3C2410_UDC_EP0_CSR_REG);     \
981 +} while(0)
982 +
983 +#define set_ep0_de_in() do {                           \
984 +       S3C2410_UDC_SETIX(0);                           \
985 +       maskl((S3C2410_UDC_EP0_CSR_IPKRDY               \
986 +               | S3C2410_UDC_EP0_CSR_DE),              \
987 +               BIT_MASK, S3C2410_UDC_EP0_CSR_REG);     \
988 +} while(0)
989 +
990 +
991 +#if 0
992 +
993 +#define clear_stall_ep1_out(base) do {                 \
994 +       S3C2410_UDC_SETIX(base,EP1);                    \
995 +       orl(0,base+S3C2410_UDC_OUT_CSR1_REG);           \
996 +} while(0)
997 +
998 +
999 +#define clear_stall_ep2_out(base) do {                 \
1000 +       S3C2410_UDC_SETIX(base,EP2);                    \
1001 +       orl(0, base+S3C2410_UDC_OUT_CSR1_REG);          \
1002 +} while(0)
1003 +
1004 +
1005 +#define clear_stall_ep3_out(base) do {                 \
1006 +       S3C2410_UDC_SETIX(base,EP3);                    \
1007 +       orl(0,base+S3C2410_UDC_OUT_CSR1_REG);           \
1008 +} while(0)
1009 +
1010 +
1011 +#define clear_stall_ep4_out(base) do {                 \
1012 +       S3C2410_UDC_SETIX(base,EP4);                    \
1013 +       orl(0, base+S3C2410_UDC_OUT_CSR1_REG);          \
1014 +} while(0)
1015 +
1016 +#endif
1017 +
1018 +/* S3C2410 Endpoint parameters */
1019 +#define EP0_MAX_PACKET_SIZE    16
1020 +#define UDC_OUT_ENDPOINT       2
1021 +#define UDC_OUT_PACKET_SIZE    64
1022 +#define UDC_IN_ENDPOINT                1
1023 +#define UDC_IN_PACKET_SIZE     64
1024 +#define UDC_INT_ENDPOINT       5
1025 +#define UDC_INT_PACKET_SIZE    16
1026 +#define UDC_BULK_PACKET_SIZE   16
1027 +
1028 +#endif
1029 Index: u-boot/drivers/usbdcore_ep0.c
1030 ===================================================================
1031 --- u-boot.orig/drivers/usbdcore_ep0.c
1032 +++ u-boot/drivers/usbdcore_ep0.c
1033 @@ -43,7 +43,7 @@
1034  
1035  #include <common.h>
1036  
1037 -#if defined(CONFIG_OMAP1510) && defined(CONFIG_USB_DEVICE)
1038 +#if defined(CONFIG_USB_DEVICE)
1039  #include "usbdcore.h"
1040  
1041  #if 0
1042 @@ -187,9 +187,13 @@
1043         if (!urb || !urb->buffer || !urb->buffer_length
1044             || (urb->buffer_length < 255)) {
1045                 dbg_ep0 (2, "invalid urb %p", urb);
1046 +               serial_printf("invalid urb %p", urb);
1047                 return -1L;
1048         }
1049  
1050 +       /* re-initialize the ep0 buffer pointer */
1051 +       urb->buffer = (u8 *) urb->buffer_data;
1052 +
1053         /* setup tx urb */
1054         urb->actual_length = 0;
1055         cp = urb->buffer;
1056 @@ -206,17 +210,8 @@
1057                              usbd_device_device_descriptor (device, port))) {
1058                                 return -1;
1059                         }
1060 -                       /* copy descriptor for this device */
1061 -                       copy_config (urb, device_descriptor,
1062 -                                    sizeof (struct usb_device_descriptor),
1063 -                                    max);
1064 -
1065 -                       /* correct the correct control endpoint 0 max packet size into the descriptor */
1066 -                       device_descriptor =
1067 -                               (struct usb_device_descriptor *) urb->buffer;
1068 -                       device_descriptor->bMaxPacketSize0 =
1069 -                               urb->device->bus->maxpacketsize;
1070 -
1071 +                       urb->buffer = device_descriptor;
1072 +                       urb->actual_length = MIN(sizeof(*device_descriptor), max);
1073                 }
1074                 /*dbg_ep0(3, "copied device configuration, actual_length: %x", urb->actual_length); */
1075                 break;
1076 @@ -250,11 +245,9 @@
1077                                          index);
1078                                 return -1;
1079                         }
1080 -                       copy_config (urb, configuration_descriptor,
1081 -                                    sizeof (struct
1082 -                                            usb_configuration_descriptor),
1083 -                                    max);
1084 -
1085 +                       urb->buffer = configuration_descriptor;
1086 +                       urb->actual_length =
1087 +                               MIN(le16_to_cpu(configuration_descriptor->wTotalLength), max);
1088                 }
1089                 break;
1090  
1091 @@ -376,6 +369,7 @@
1092         dbg_ep0 (0, "entering ep0_recv_setup()");
1093         if (!urb || !urb->device) {
1094                 dbg_ep0 (3, "invalid URB %p", urb);
1095 +               serial_printf("invalid URB %p", urb);
1096                 return -1;
1097         }
1098  
1099 @@ -400,6 +394,7 @@
1100                         return device->cdc_recv_setup(request, urb);
1101                 dbg_ep0 (1, "non standard request: %x",
1102                          request->bmRequestType & USB_REQ_TYPE_MASK);
1103 +               serial_printf("non standard request: %x", request->bmRequestType & USB_REQ_TYPE_MASK);
1104                 return -1;      /* Stall here */
1105         }
1106  
1107 @@ -448,6 +443,8 @@
1108                 dbg_ep0 (1, "request %s not allowed in UNKNOWN state: %s",
1109                          USBD_DEVICE_REQUESTS (request->bRequest),
1110                          usbd_device_states[device->device_state]);
1111 +               serial_printf("request %s not allowed in UNKNOWN state: %s", USBD_DEVICE_REQUESTS (request->bRequest), usbd_device_states[device->device_state]);
1112 +               break;
1113                 return -1;
1114         }
1115  
1116 @@ -545,7 +542,8 @@
1117                         /*dbg_ep0(2, "address: %d %d %d", */
1118                         /*        request->wValue, le16_to_cpu(request->wValue), device->address); */
1119  
1120 -                       serial_printf ("DEVICE_ADDRESS_ASSIGNED.. event?\n");
1121 +                       //serial_printf ("DEVICE_ADDRESS_ASSIGNED.. event?\n");
1122 +                       //udc_set_address(device->address);
1123                         return 0;
1124  
1125                 case USB_REQ_SET_DESCRIPTOR:    /* XXX should we support this? */
1126 Index: u-boot/include/configs/neo1973_gta01.h
1127 ===================================================================
1128 --- u-boot.orig/include/configs/neo1973_gta01.h
1129 +++ u-boot/include/configs/neo1973_gta01.h
1130 @@ -173,6 +173,16 @@
1131  #define CONFIG_USB_OHCI                1
1132  #endif
1133  
1134 +#define CONFIG_USB_DEVICE      1
1135 +#define CONFIG_USB_TTY         1
1136 +#define CFG_CONSOLE_IS_IN_ENV  1
1137 +#define CONFIG_USBD_VENDORID           0x1457     /* Linux/NetChip */
1138 +#define CONFIG_USBD_PRODUCTID_GSERIAL  0x5120    /* gserial */
1139 +#define CONFIG_USBD_PRODUCTID_CDCACM   0x5119    /* CDC ACM */
1140 +#define CONFIG_USBD_MANUFACTURER       "Openmoko, Inc"
1141 +#define CONFIG_USBD_PRODUCT_NAME       "Neo1973 Bootloader " U_BOOT_VERSION
1142 +#define CONFIG_EXTRA_ENV_SETTINGS      "usbtty=cdc_acm\0"
1143 +
1144  /*-----------------------------------------------------------------------
1145   * Physical Memory Map
1146   */
1147 Index: u-boot/cpu/arm920t/s3c24x0/interrupts.c
1148 ===================================================================
1149 --- u-boot.orig/cpu/arm920t/s3c24x0/interrupts.c
1150 +++ u-boot/cpu/arm920t/s3c24x0/interrupts.c
1151 @@ -222,6 +222,13 @@
1152         S3C24X0_INTERRUPT * irq = S3C24X0_GetBase_INTERRUPT();
1153         u_int32_t intpnd = irq->INTPND;
1154  
1155 +#ifdef CONFIG_USB_DEVICE
1156 +       if (intpnd & BIT_USBD) {
1157 +               s3c2410_udc_irq();
1158 +               irq->SRCPND = BIT_USBD;
1159 +               irq->INTPND = BIT_USBD;
1160 +       }
1161 +#endif /* USB_DEVICE */
1162  }
1163  #endif /* USE_IRQ */
1164  
1165 Index: u-boot/drivers/usbtty.h
1166 ===================================================================
1167 --- u-boot.orig/drivers/usbtty.h
1168 +++ u-boot/drivers/usbtty.h
1169 @@ -29,6 +29,8 @@
1170  #include "usbdcore_mpc8xx.h"
1171  #elif defined(CONFIG_OMAP1510)
1172  #include "usbdcore_omap1510.h"
1173 +#elif defined(CONFIG_S3C2410)
1174 +#include "usbdcore_s3c2410.h"
1175  #endif
1176  
1177  #include <config.h>
1178 Index: u-boot/board/neo1973/common/cmd_neo1973.c
1179 ===================================================================
1180 --- u-boot.orig/board/neo1973/common/cmd_neo1973.c
1181 +++ u-boot/board/neo1973/common/cmd_neo1973.c
1182 @@ -72,6 +72,18 @@
1183                         neo1973_vibrator(1);
1184                 else
1185                         neo1973_vibrator(0);
1186 +       } else if (!strcmp(argv[1], "udc")) {
1187 +               if (argc < 3)
1188 +                       goto out_help;
1189 +               if (!strcmp(argv[2], "udc")) {
1190 +                       if (argc < 4)
1191 +                               goto out_help;
1192 +                       if (!strcmp(argv[3], "on"))
1193 +                               udc_connect();
1194 +                       else
1195 +                               udc_disconnect();
1196 +               } else
1197 +                       goto out_help;
1198         } else {
1199  out_help:
1200                 printf("Usage:\n%s\n", cmdtp->usage);
1201 @@ -95,5 +107,6 @@
1202         "neo1973 charger off - disable charging\n"
1203         "neo1973 backlight (on|off) - switch backlight on or off\n"
1204         "neo1973 vibrator (on|off) - switch vibrator on or off\n"
1205 +       "neo1973 udc pullup (on|off) - switch pull-up on or off\n"
1206  );
1207  #endif /* CFG_CMD_BDI */
1208 Index: u-boot/board/neo1973/gta01/Makefile
1209 ===================================================================
1210 --- u-boot.orig/board/neo1973/gta01/Makefile
1211 +++ u-boot/board/neo1973/gta01/Makefile
1212 @@ -25,7 +25,7 @@
1213  
1214  LIB    = lib$(BOARD).a
1215  
1216 -OBJS   := gta01.o pcf50606.o ../common/cmd_neo1973.o ../common/jbt6k74.o
1217 +OBJS   := gta01.o pcf50606.o ../common/cmd_neo1973.o ../common/jbt6k74.o ../common/udc.o
1218  SOBJS  := ../common/lowlevel_init.o
1219  
1220  $(LIB):        $(OBJS) $(SOBJS)
1221 Index: u-boot/board/neo1973/common/udc.c
1222 ===================================================================
1223 --- /dev/null
1224 +++ u-boot/board/neo1973/common/udc.c
1225 @@ -0,0 +1,23 @@
1226 +
1227 +#include <common.h>
1228 +#include <usbdcore.h>
1229 +#include <s3c2410.h>
1230 +
1231 +void udc_ctrl(enum usbd_event event, int param)
1232 +{
1233 +       S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
1234 +
1235 +       switch (event) {
1236 +       case UDC_CTRL_PULLUP_ENABLE:
1237 +#if defined(CONFIG_ARCH_GTA01_v4) || defined(CONFIG_ARCH_GTA01B_v2) || \
1238 +    defined(CONFIG_ARCH_GTA01B_v3) || defined(CONFIG_ARCH_GTA01B_v4)
1239 +               if (param)
1240 +                       gpio->GPBDAT |= (1 << 9);
1241 +               else
1242 +                       gpio->GPBDAT &= ~(1 << 9);
1243 +#endif
1244 +               break;
1245 +       default:
1246 +               break;
1247 +       }
1248 +}
1249 Index: u-boot/include/usbdcore.h
1250 ===================================================================
1251 --- u-boot.orig/include/usbdcore.h
1252 +++ u-boot/include/usbdcore.h
1253 @@ -671,4 +671,10 @@
1254  void usbd_rcv_complete(struct usb_endpoint_instance *endpoint, int len, int urb_bad);
1255  void usbd_tx_complete (struct usb_endpoint_instance *endpoint);
1256  
1257 +enum usbd_event {
1258 +       UDC_CTRL_PULLUP_ENABLE,
1259 +};
1260 +
1261 +void udc_ctrl(enum usbd_event event, int param);
1262 +#endif
1263  #endif