summaryrefslogtreecommitdiffstats
path: root/meta/packages/uboot/u-boot-mkimage-openmoko-native/uboot-s3c2410_udc.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/packages/uboot/u-boot-mkimage-openmoko-native/uboot-s3c2410_udc.patch')
-rw-r--r--meta/packages/uboot/u-boot-mkimage-openmoko-native/uboot-s3c2410_udc.patch1263
1 files changed, 1263 insertions, 0 deletions
diff --git a/meta/packages/uboot/u-boot-mkimage-openmoko-native/uboot-s3c2410_udc.patch b/meta/packages/uboot/u-boot-mkimage-openmoko-native/uboot-s3c2410_udc.patch
new file mode 100644
index 0000000000..16bee3e26a
--- /dev/null
+++ b/meta/packages/uboot/u-boot-mkimage-openmoko-native/uboot-s3c2410_udc.patch
@@ -0,0 +1,1263 @@
1USB Device Controller Driver for Samsung S3C2410 SoC
2
3Index: 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 \
16Index: 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 */
751Index: 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
1029Index: 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? */
1126Index: 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 */
1147Index: 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
1165Index: 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>
1178Index: 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 */
1208Index: 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)
1221Index: 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+}
1249Index: 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