--- Begin Message ---
Author: laforge
Date: 2007-02-24 14:02:27 +0100 (Sat, 24 Feb 2007)
New Revision: 1096
Modified:
trunk/src/target/u-boot/patches/uboot-s3c2410_udc.patch
Log:
* add proper handling of control write transfers
* use u-boot standard 'debug' function instead of private macros
* introduce 'neo1973 udc pullup' command
Modified: trunk/src/target/u-boot/patches/uboot-s3c2410_udc.patch
===================================================================
--- trunk/src/target/u-boot/patches/uboot-s3c2410_udc.patch 2007-02-24
12:59:47 UTC (rev 1095)
+++ trunk/src/target/u-boot/patches/uboot-s3c2410_udc.patch 2007-02-24
13:02:27 UTC (rev 1096)
@@ -2,8 +2,8 @@
Index: u-boot/drivers/Makefile
===================================================================
---- u-boot.orig/drivers/Makefile 2007-02-16 23:57:07.000000000 +0100
-+++ u-boot/drivers/Makefile 2007-02-16 23:57:08.000000000 +0100
+--- u-boot.orig/drivers/Makefile 2007-02-24 13:38:27.000000000 +0100
++++ u-boot/drivers/Makefile 2007-02-24 13:40:57.000000000 +0100
@@ -46,7 +46,7 @@
sl811_usb.o sm501.o smc91111.o smiLynxEM.o \
status_led.o sym53c8xx.o ahci.o \
@@ -16,8 +16,8 @@
Index: u-boot/drivers/usbdcore_s3c2410.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ u-boot/drivers/usbdcore_s3c2410.c 2007-02-16 23:57:23.000000000 +0100
-@@ -0,0 +1,708 @@
++++ u-boot/drivers/usbdcore_s3c2410.c 2007-02-24 13:42:08.000000000 +0100
+@@ -0,0 +1,740 @@
+/* S3C2410 USB Device Controller Driver for u-boot
+ *
+ * (C) Copyright 2007 by OpenMoko, Inc.
@@ -42,10 +42,14 @@
+ *
+ */
+
-+#include <common.h>
++#include <config.h>
+
+#if defined(CONFIG_S3C2410) && defined(CONFIG_USB_DEVICE)
+
++#include <common.h>
++
++DECLARE_GLOBAL_DATA_PTR;
++
+#include <asm/io.h>
+#include <s3c2410.h>
+
@@ -54,15 +58,6 @@
+#include "usbdcore_ep0.h"
+#include <usb_cdc_acm.h>
+
-+
-+#if 0
-+#define UDCDBG(str) serial_printf("[%s] %s:%d: " str "\n",
__FILE__,__FUNCTION__,__LINE__)
-+#define UDCDBGA(fmt,args...) serial_printf("[%s] %s:%d: " fmt "\n",
__FILE__,__FUNCTION__,__LINE__, ##args)
-+#else
-+#define UDCDBG(str)
-+#define UDCDBGA(fmt,args...)
-+#endif
-+
+enum ep0_state {
+ EP0_IDLE,
+ EP0_IN_DATA_PHASE,
@@ -182,8 +177,10 @@
+
+ /* clear stall status */
+ if (ep0csr & S3C2410_UDC_EP0_CSR_SENTSTL) {
-+ UDCDBG("Clearing SENT_STALL");
++ debug("Clearing SENT_STALL\n");
+ clear_ep0_sst();
++ if (ep0csr & S3C2410_UDC_EP0_CSR_SOPKTRDY)
++ clear_ep0_opr();
+ ep0->state = EP0_IDLE;
+ return;
+ }
@@ -191,8 +188,14 @@
+ /* clear setup end */
+ if (ep0csr & S3C2410_UDC_EP0_CSR_SE
+ /* && ep0->state != EP0_IDLE */) {
-+ UDCDBG("Clearing SETUP_END");
++ debug("Clearing SETUP_END\n");
+ clear_ep0_se();
++ if (ep0csr & S3C2410_UDC_EP0_CSR_SOPKTRDY) {
++ /* Flush FIFO */
++ while (inl(S3C2410_UDC_OUT_FIFO_CNT1_REG))
++ inl(S3C2410_UDC_EP0_FIFO_REG);
++ clear_ep0_opr();
++ }
+ ep0->state = EP0_IDLE;
+ return;
+ }
@@ -211,7 +214,7 @@
+ /* pull it out of the fifo */
+ fifo_count = fifo_count_out();
+ if (fifo_count != 8) {
-+ UDCDBGA("STRANGE FIFO COUNT: %u bytes",
fifo_count);
++ debug("STRANGE FIFO COUNT: %u bytes\n",
fifo_count);
+ set_ep0_ss();
+ return;
+ }
@@ -221,52 +224,80 @@
+ datap++;
+ }
+
++ if ((ep0_urb->device_request.bmRequestType &
USB_REQ_DIRECTION_MASK)
++ == USB_REQ_HOST2DEVICE) {
++ if (ep0_urb->device_request.wLength > 0) {
++ /* receive remainder (DATA OUT phase)
of transfer */
++ /* FIXME: Implement this via state
machine rather
++ * than busy-waiting in the interrupt
handler */
++ //ep0->state = EP0_OUT_DATA_PHASE;
++ clear_ep0_opr();
++ ep0_urb->buffer = ep0_urb->buffer_data;
++ ep0_urb->buffer_length =
sizeof(ep0_urb->buffer_data);
++ ep0_urb->actual_length = 0;
++ do {
++ u32 i;
++ u32 urb_avail =
ep0_urb->buffer_length
++ -
ep0_urb->actual_length;
++ u_int8_t *cp = ep0_urb->buffer
+ ep0_urb->actual_length;
++
++ ep0csr =
inl(S3C2410_UDC_IN_CSR1_REG);
++ if (!ep0csr &
S3C2410_UDC_EP0_CSR_OPKRDY)
++ continue;
++
++ fifo_count = fifo_count_out();
++ if (fifo_count < urb_avail)
++ urb_avail = fifo_count;
++
++ for (i = 0; i < urb_avail; i++)
++ *cp++ =
inl(S3C2410_UDC_EP0_FIFO_REG);
++
++ ep0_urb->actual_length +=
urb_avail;
++
++ if (fifo_count < 8) {
++ //ep0->state = EP0_IDLE;
++ break;
++ } else
++ clear_ep0_opr();
++ } while (1);
++ }
++ } else
++ clear_ep0_opr();
++
+ if (ep0_recv_setup(ep0_urb)) {
+ /* Not a setup packet, stall next EP0
transaction */
-+ UDCDBG("can't parse setup packet, still waiting
for setup");
++ debug("can't parse setup packet, still waiting
for setup\n");
+ set_ep0_ss();
+ return;
+ }
+
-+ /* There are two requests with which we need to deal
manually here */
++ /* There are some requests with which we need to deal
++ * manually here */
+ switch (ep0_urb->device_request.bRequest) {
+ case USB_REQ_SET_CONFIGURATION:
+ if (!ep0_urb->device_request.wValue)
-+ usbd_device_event_irq (udc_device,
DEVICE_DE_CONFIGURED, 0);
++ usbd_device_event_irq(udc_device,
++ DEVICE_DE_CONFIGURED,
0);
+ else
-+ usbd_device_event_irq (udc_device,
DEVICE_CONFIGURED, 0);
-+ set_ep0_de_out();
++ usbd_device_event_irq(udc_device,
++ DEVICE_CONFIGURED, 0);
+ break;
+ case USB_REQ_SET_ADDRESS:
+ udc_set_address(udc_device->address);
-+ usbd_device_event_irq (udc_device,
DEVICE_ADDRESS_ASSIGNED, 0);
-+ set_ep0_de_out();
++ usbd_device_event_irq(udc_device,
++
DEVICE_ADDRESS_ASSIGNED, 0);
+ break;
-+ case ACM_SET_LINE_ENCODING:
-+ /* This is an ugly hack for blocking receive of
-+ * one specific control out request with data
phase */
-+ clear_ep0_opr();
-+ do {
-+ ep0csr = inl(S3C2410_UDC_IN_CSR1_REG);
-+ if (ep0csr &
S3C2410_UDC_EP0_CSR_OPKRDY) {
-+ fifo_count = fifo_count_out();
-+ while (fifo_count--)
-+
inl(S3C2410_UDC_EP0_FIFO_REG);
-+ clear_ep0_opr();
-+ break;
-+ }
-+ } while (1);
-+ break;
+ default:
-+ clear_ep0_opr();
+ break;
+ }
+
+ /* check whether we need to write/read */
+ if ((ep0_urb->device_request.bmRequestType &
USB_REQ_DIRECTION_MASK)
+ == USB_REQ_HOST2DEVICE) {
-+ /* FIXME: implement this. We now only do
setup_out with
-+ * empty data phase */
++ /* we can't do this earlier since in the case
++ * of SET_ADDRESS we're not allowed to issues
++ * this command before we've actually set the
++ * address */
+ set_ep0_de_out();
+ } else {
+ /* device -> host */
@@ -276,13 +307,12 @@
+
+ if (s3c2410_write_noniso_tx_fifo(ep0)) {
+ ep0->state = EP0_IDLE;
-+ set_ep0_de_in();
++ set_ep0_de_in();
+ } else {
+ ep0->state = EP0_IN_DATA_PHASE;
+ set_ep0_ipr();
-+#if 1
-+ /* we currently do this blocking to
make sure
-+ * to do this within the harsh timing
constraints */
++#if 0
++ /* we optionally can do this
blocking/polling */
+ do {
+ ep0csr =
inl(S3C2410_UDC_IN_CSR1_REG);
+ if ((ep0csr &
S3C2410_UDC_EP0_CSR_IPKRDY))
@@ -293,8 +323,9 @@
+ ep0->state = EP0_IDLE;
+ set_ep0_de_in();
+ break;
-+ } else
++ } else {
+ set_ep0_ipr();
++ }
+ } while (1);
+#endif
+ }
@@ -344,19 +375,19 @@
+ if (endpoint->endpoint_address & USB_DIR_IN) {
+ /* IN transfer (device to host) */
+ ep_csr1 = inl(S3C2410_UDC_IN_CSR1_REG);
-+ UDCDBGA("for ep=%u, CSR1=0x%x", ep, ep_csr1);
++ debug("for ep=%u, CSR1=0x%x ", ep, ep_csr1);
+
+ urb = endpoint->tx_urb;
+ if (ep_csr1 & S3C2410_UDC_ICSR1_SENTSTL) {
+ /* Stall handshake */
-+ UDCDBG("stall");
++ debug("stall\n");
+ outl(0x00, S3C2410_UDC_IN_CSR1_REG);
+ return;
+ }
+ if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && urb &&
+ urb->actual_length) {
+
-+ UDCDBG("completing previously send data");
++ debug("completing previously send data ");
+ usbd_tx_complete(endpoint);
+
+ /* push pending data into FIFO */
@@ -364,19 +395,20 @@
+ (urb->actual_length - endpoint->sent -
endpoint->last == 0)) {
+ endpoint->sent += endpoint->last;
+ /* Write 0 bytes of data (ZLP) */
-+ UDCDBG("ZLP");
++ debug("ZLP ");
+ outl(ep_csr1|S3C2410_UDC_ICSR1_PKTRDY,
S3C2410_UDC_IN_CSR1_REG);
+ } else {
+ /* write actual data to fifo */
-+ UDCDBG("TX_DATA");
++ debug("TX_DATA ");
+ s3c2410_write_noniso_tx_fifo(endpoint);
+ outl(ep_csr1|S3C2410_UDC_ICSR1_PKTRDY,
S3C2410_UDC_IN_CSR1_REG);
+ }
+ }
++ debug("\n");
+ } else {
+ /* OUT transfer (host to device) */
+ ep_csr1 = inl(S3C2410_UDC_OUT_CSR1_REG);
-+ UDCDBGA("for ep=%u, CSR1=0x%x", ep, ep_csr1);
++ debug("for ep=%u, CSR1=0x%x ", ep, ep_csr1);
+
+ urb = endpoint->rcv_urb;
+ if (ep_csr1 & S3C2410_UDC_OCSR1_SENTSTL) {
@@ -394,7 +426,7 @@
+ if (fifo_count < endpoint->rcv_packetSize)
+ is_last = 1;
+
-+ UDCDBGA("fifo_count=%u is_last=%, urb_avail=%u)",
++ debug("fifo_count=%u is_last=%, urb_avail=%u)\n",
+ fifo_count, is_last, urb_avail);
+
+ if (fifo_count < urb_avail)
@@ -435,14 +467,14 @@
+ u_int32_t usb_status = inl(S3C2410_UDC_USB_INT_REG);
+ u_int32_t usbd_status = inl(S3C2410_UDC_EP_INT_REG);
+
-+ //UDCDBGA("< IRQ usbs=0x%02x, usbds=0x%02x start >", usb_status,
usbd_status);
++ //debug("< IRQ usbs=0x%02x, usbds=0x%02x start >", usb_status,
usbd_status);
+
+ /* clear interrupts */
+ outl(usb_status, S3C2410_UDC_USB_INT_REG);
+
+ if (usb_status & S3C2410_UDC_USBINT_RESET) {
+ //serial_putc('R');
-+ UDCDBGA("RESET pwr=0x%x", inl(S3C2410_UDC_PWR_REG));
++ debug("RESET pwr=0x%x\n", inl(S3C2410_UDC_PWR_REG));
+ udc_setup_ep(udc_device, 0, ep0);
+ outl(S3C2410_UDC_EP0_CSR_SSE|S3C2410_UDC_EP0_CSR_SOPKTRDY,
S3C2410_UDC_EP0_CSR_REG);
+ ep0->state = EP0_IDLE;
@@ -450,12 +482,12 @@
+ }
+
+ if (usb_status & S3C2410_UDC_USBINT_RESUME) {
-+ UDCDBG("RESUME");
++ debug("RESUME\n");
+ usbd_device_event_irq(udc_device, DEVICE_BUS_ACTIVITY, 0);
+ }
+
+ if (usb_status & S3C2410_UDC_USBINT_SUSPEND) {
-+ UDCDBG("SUSPEND");
++ debug("SUSPEND\n");
+ usbd_device_event_irq(udc_device, DEVICE_BUS_INACTIVE, 0);
+ }
+
@@ -496,11 +528,11 @@
+ unsigned short epnum =
+ endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
+
-+ UDCDBGA ("Entering for ep %x", epnum);
++ debug("Entering for ep %x ", epnum);
+
+ if (endpoint->tx_urb) {
+ u32 ep_csr1;
-+ UDCDBG ("We have an URB, transmitting");
++ debug("We have an URB, transmitting\n");
+
+ s3c2410_write_noniso_tx_fifo(endpoint);
+
@@ -508,7 +540,8 @@
+
+ ep_csr1 = inl(S3C2410_UDC_IN_CSR1_REG);
+ outl(ep_csr1|S3C2410_UDC_ICSR1_PKTRDY, S3C2410_UDC_IN_CSR1_REG);
-+ }
++ } else
++ debug("\n");
+}
+
+/* Start to initialize h/w stuff */
@@ -519,8 +552,6 @@
+
+ udc_device = NULL;
+
-+ UDCDBG ("starting");
-+
+ /* Set and check clock control.
+ * We might ought to be using the clock control API to do
+ * this instead of fiddling with the clock registers directly
@@ -530,14 +561,14 @@
+ irq->INTMSK &= ~BIT_USBD;
+
+ /* Print banner with device revision */
-+ printf ("USB: S3C2410 USB Deviced\n");
++ printf("USB: S3C2410 USB Deviced\n");
+
+ /*
+ * At this point, device is ready for configuration...
+ */
+
-+ //UDCDBG("disable USB interrupts");
-+ UDCDBG("enable USB interrupts");
++ //debug("disable USB interrupts");
++ debug("enable USB interrupts");
+ outl(0xff, S3C2410_UDC_EP_INT_EN_REG);
+ outl(0x04, S3C2410_UDC_USB_INT_EN_REG);
+
@@ -588,7 +619,7 @@
+ else
+ maxp = S3C2410_UDC_MAXP_64;
+
-+ UDCDBGA("setting up endpoint %u addr %x packet_size %u maxp %u", ep,
++ debug("setting up endpoint %u addr %x packet_size %u maxp %u\n", ep,
+ endpoint->endpoint_address, packet_size, maxp);
+
+ /* Set maximum packet size */
@@ -614,24 +645,26 @@
+/* Turn on the USB connection by enabling the pullup resistor */
+void udc_connect (void)
+{
-+ UDCDBG ("connect, enable Pullup");
++ debug("connect, enable Pullup\n");
++ S3C24X0_INTERRUPT * irq = S3C24X0_GetBase_INTERRUPT();
+#if defined(CONFIG_ARCH_GTA01_v4) || defined(CONFIG_ARCH_GTA01B_v2) ||
defined(CONFIG_ARCH_GTA01B_v3)
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ /* create a short disconnect, since we might come out of reset */
+ //s3c2410_gpio_setpin(GTA01_GPIO_USB_PULLUP, 0);
+ gpio->GPBDAT &= ~(1 << 9);
-+ udelay(1000);
++ udelay(10000);
+
+ // s3c2410_gpio_setpin(GTA01_GPIO_USB_PULLUP, 1);
+ gpio->GPBDAT |= (1 << 9);
+#endif
++ irq->INTMSK &= ~BIT_USBD;
+}
+
+/* Turn off the USB connection by disabling the pullup resistor */
+void udc_disconnect (void)
+{
-+ UDCDBG ("disconnect, disable Pullup");
++ debug("disconnect, disable Pullup\n");
+ S3C24X0_INTERRUPT * irq = S3C24X0_GetBase_INTERRUPT();
+#if defined(CONFIG_ARCH_GTA01_v4) || defined(CONFIG_ARCH_GTA01B_v2) ||
defined(CONFIG_ARCH_GTA01B_v3)
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
@@ -647,20 +680,18 @@
+/* Switch on the UDC */
+void udc_enable (struct usb_device_instance *device)
+{
-+ UDCDBGA ("enable device %p, status %d", device, device->status);
++ debug("enable device %p, status %d\n", device, device->status);
+
+ /* Save the device structure pointer */
+ udc_device = device;
+
+ /* Setup ep0 urb */
-+ if (!ep0_urb) {
-+ ep0_urb =
-+ usbd_alloc_urb (udc_device,
-+ udc_device->bus->endpoint_array);
-+ } else {
-+ serial_printf ("udc_enable: ep0_urb already allocated %p\n",
++ if (!ep0_urb)
++ ep0_urb = usbd_alloc_urb(udc_device,
++ udc_device->bus->endpoint_array);
++ else
++ serial_printf("udc_enable: ep0_urb already allocated %p\n",
+ ep0_urb);
-+ }
+
+ s3c2410_configure_device(device);
+}
@@ -668,7 +699,7 @@
+/* Switch off the UDC */
+void udc_disable (void)
+{
-+ UDCDBG ("disable UDC");
++ debug("disable UDC\n");
+
+ s3c2410_deconfigure_device();
+
@@ -725,11 +756,12 @@
+{
+ /* FIXME: implement this */
+}
-+#endif
++
++#endif /* CONFIG_S3C2410 && CONFIG_USB_DEVICE */
Index: u-boot/drivers/usbdcore_s3c2410.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ u-boot/drivers/usbdcore_s3c2410.h 2007-02-16 23:57:08.000000000 +0100
++++ u-boot/drivers/usbdcore_s3c2410.h 2007-02-24 13:38:29.000000000 +0100
@@ -0,0 +1,273 @@
+/* linux/include/asm/arch-s3c2410/regs-udc.h
+ *
@@ -1006,8 +1038,8 @@
+#endif
Index: u-boot/drivers/usbdcore_ep0.c
===================================================================
---- u-boot.orig/drivers/usbdcore_ep0.c 2007-02-21 15:54:34.000000000 +0100
-+++ u-boot/drivers/usbdcore_ep0.c 2007-02-21 20:54:28.000000000 +0100
+--- u-boot.orig/drivers/usbdcore_ep0.c 2007-02-24 13:38:28.000000000 +0100
++++ u-boot/drivers/usbdcore_ep0.c 2007-02-24 13:40:57.000000000 +0100
@@ -43,7 +43,7 @@
#include <common.h>
@@ -1103,9 +1135,9 @@
case USB_REQ_SET_DESCRIPTOR: /* XXX should we support this?
*/
Index: u-boot/include/configs/neo1973.h
===================================================================
---- u-boot.orig/include/configs/neo1973.h 2007-02-16 23:57:08.000000000
+0100
-+++ u-boot/include/configs/neo1973.h 2007-02-16 23:57:08.000000000 +0100
-@@ -174,6 +174,16 @@
+--- u-boot.orig/include/configs/neo1973.h 2007-02-24 13:38:28.000000000
+0100
++++ u-boot/include/configs/neo1973.h 2007-02-24 13:42:25.000000000 +0100
+@@ -176,6 +176,16 @@
#define CONFIG_USB_OHCI 1
#endif
@@ -1124,8 +1156,8 @@
*/
Index: u-boot/cpu/arm920t/s3c24x0/interrupts.c
===================================================================
---- u-boot.orig/cpu/arm920t/s3c24x0/interrupts.c 2007-02-16
23:57:08.000000000 +0100
-+++ u-boot/cpu/arm920t/s3c24x0/interrupts.c 2007-02-16 23:57:08.000000000
+0100
+--- u-boot.orig/cpu/arm920t/s3c24x0/interrupts.c 2007-02-24
13:38:28.000000000 +0100
++++ u-boot/cpu/arm920t/s3c24x0/interrupts.c 2007-02-24 13:38:29.000000000
+0100
@@ -222,6 +222,13 @@
S3C24X0_INTERRUPT * irq = S3C24X0_GetBase_INTERRUPT();
u_int32_t intpnd = irq->INTPND;
@@ -1142,8 +1174,8 @@
Index: u-boot/drivers/usbtty.h
===================================================================
---- u-boot.orig/drivers/usbtty.h 2007-02-16 23:57:08.000000000 +0100
-+++ u-boot/drivers/usbtty.h 2007-02-16 23:57:08.000000000 +0100
+--- u-boot.orig/drivers/usbtty.h 2007-02-24 13:38:28.000000000 +0100
++++ u-boot/drivers/usbtty.h 2007-02-24 13:38:29.000000000 +0100
@@ -29,6 +29,8 @@
#include "usbdcore_mpc8xx.h"
#elif defined(CONFIG_OMAP1510)
@@ -1153,3 +1185,33 @@
#endif
#include <config.h>
+Index: u-boot/board/neo1973/cmd_neo1973.c
+===================================================================
+--- u-boot.orig/board/neo1973/cmd_neo1973.c 2007-02-24 13:38:28.000000000
+0100
++++ u-boot/board/neo1973/cmd_neo1973.c 2007-02-24 13:38:29.000000000 +0100
+@@ -93,6 +93,18 @@
+ neo1973_vibrator(1);
+ else
+ neo1973_vibrator(0);
++ } else if (!strcmp(argv[1], "udc")) {
++ if (argc < 3)
++ goto out_help;
++ if (!strcmp(argv[2], "udc")) {
++ if (argc < 4)
++ goto out_help;
++ if (!strcmp(argv[3], "on"))
++ udc_connect();
++ else
++ udc_disconnect();
++ } else
++ goto out_help;
+ } else {
+ out_help:
+ printf("Usage:\n%s\n", cmdtp->usage);
+@@ -116,5 +128,6 @@
+ "neo1973 charger off - disable charging\n"
+ "neo1973 backlight (on|off) - switch backlight on or off\n"
+ "neo1973 vibrator (on|off) - switch vibrator on or off\n"
++ "neo1973 udc pullup (on|off) - switch pull-up on or off\n"
+ );
+ #endif /* CFG_CMD_BDI */
--- End Message ---
--- Begin Message ---
Author: laforge
Date: 2007-02-24 14:03:41 +0100 (Sat, 24 Feb 2007)
New Revision: 1097
Modified:
trunk/src/target/u-boot/patches/uboot-dfu.patch
Log:
* bring DFU code to a state where it reliably supports UPLOAd from all
partitions and download into RAM
Modified: trunk/src/target/u-boot/patches/uboot-dfu.patch
===================================================================
--- trunk/src/target/u-boot/patches/uboot-dfu.patch 2007-02-24 13:02:27 UTC
(rev 1096)
+++ trunk/src/target/u-boot/patches/uboot-dfu.patch 2007-02-24 13:03:41 UTC
(rev 1097)
@@ -1,14 +1,87 @@
Index: u-boot/drivers/usbdcore_ep0.c
===================================================================
---- u-boot.orig/drivers/usbdcore_ep0.c 2007-02-15 18:07:52.000000000 +0100
-+++ u-boot/drivers/usbdcore_ep0.c 2007-02-15 20:50:05.000000000 +0100
-@@ -388,6 +388,11 @@
+--- u-boot.orig/drivers/usbdcore_ep0.c 2007-02-24 03:59:30.000000000 +0100
++++ u-boot/drivers/usbdcore_ep0.c 2007-02-24 04:03:05.000000000 +0100
+@@ -42,11 +42,16 @@
+ */
+
+ #include <common.h>
++DECLARE_GLOBAL_DATA_PTR;
+
+ #if defined(CONFIG_USB_DEVICE)
+ #include "usbdcore.h"
+
+-#if 0
++#ifdef CONFIG_USBD_DFU
++#include <usb_dfu.h>
++#endif
++
++#if 1
+ #define dbg_ep0(lvl,fmt,args...) serial_printf("[%s] %s:%d:
"fmt"\n",__FILE__,__FUNCTION__,__LINE__,##args)
+ #else
+ #define dbg_ep0(lvl,fmt,args...)
+@@ -213,7 +218,7 @@
+ urb->buffer = device_descriptor;
+ urb->actual_length = MIN(sizeof(*device_descriptor),
max);
+ }
+- /*dbg_ep0(3, "copied device configuration, actual_length: %x",
urb->actual_length); */
++ dbg_ep0(3, "using device configuration, actual_length: %x",
urb->actual_length);
+ break;
+
+ case USB_DESCRIPTOR_TYPE_CONFIGURATION:
+@@ -267,7 +272,24 @@
+ return -1;
+ case USB_DESCRIPTOR_TYPE_ENDPOINT:
+ return -1;
++ /* This really means "Class Specific Descriptor #1 == USB_DT_DFU */
+ case USB_DESCRIPTOR_TYPE_HID:
++#ifdef CONFIG_USBD_DFU
++ {
++ int bNumInterface =
++ le16_to_cpu(urb->device_request.wIndex);
++
++ /* In runtime mode, we only respond to the DFU
INTERFACE,
++ * whereas in DFU mode, we respond for all intrfaces */
++ if (device->dfu_state != DFU_STATE_appIDLE &&
++ device->dfu_state != DFU_STATE_appDETACH ||
++ bNumInterface == CONFIG_USBD_DFU_INTERFACE) {
++ urb->buffer = &device->dfu_cfg_desc->func_dfu;
++ urb->actual_length = sizeof(struct
usb_dfu_func_descriptor);
++ } else
++ return -1;
++ }
++#else /* CONFIG_USBD_DFU */
+ {
+ return -1; /* unsupported at this time */
+ #if 0
+@@ -294,6 +316,7 @@
+ max);
+ #endif
+ }
++#endif /* CONFIG_USBD_DFU */
+ break;
+ case USB_DESCRIPTOR_TYPE_REPORT:
+ {
+@@ -388,6 +411,24 @@
le16_to_cpu (request->wLength),
USBD_DEVICE_REQUESTS (request->bRequest));
-+#ifdef CONFIG_USB_DFU
-+ if ((request->bmRequestType & 0x3f) == USB_TYPE_DFU)
-+ return dfu_ep0_handler(urb);
++#ifdef CONFIG_USBD_DFU
++ if ((request->bmRequestType & 0x3f) == USB_TYPE_DFU &&
++ (device->dfu_state != DFU_STATE_appIDLE ||
++ le16_to_cpu(request->wIndex) == CONFIG_USBD_DFU_INTERFACE)) {
++ int rc = dfu_ep0_handler(urb);
++ switch (rc) {
++ case DFU_EP0_NONE:
++ case DFU_EP0_UNHANDLED:
++ break;
++ case DFU_EP0_ZLP:
++ case DFU_EP0_DATA:
++ return 0;
++ case DFU_EP0_STALL:
++ return -1;
++ }
++ }
+#endif /* CONFIG_USB_DFU */
+
/* handle USB Standard Request (c.f. USB Spec table 9-2) */
@@ -17,14 +90,13 @@
Index: u-boot/drivers/usbdfu.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ u-boot/drivers/usbdfu.c 2007-02-16 18:59:54.000000000 +0100
-@@ -0,0 +1,352 @@
++++ u-boot/drivers/usbdfu.c 2007-02-24 04:03:05.000000000 +0100
+@@ -0,0 +1,553 @@
+/*
+ * (C) 2007 by OpenMoko, Inc.
+ * Author: Harald Welte <[EMAIL PROTECTED]>
+ *
+ * based on existing SAM7DFU code from OpenPCD:
-+ *
+ * (C) Copyright 2006 by Harald Welte <[EMAIL PROTECTED]>
+ *
+ * See file CREDITS for list of people who contributed to this
@@ -45,141 +117,326 @@
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
-+static u_int32_t dfu_state = DFU_STATE_appIDLE;
+
-+static int handle_dnload(u_int16_t val, u_int16_t len)
++#include <config.h>
++#if defined(CONFIG_USBD_DFU)
++
++//#define DEBUG
++
++#include <common.h>
++DECLARE_GLOBAL_DATA_PTR;
++
++#include <linux/types.h>
++#include <asm/errno.h>
++#include <usbdcore.h>
++#include <usb_dfu.h>
++#include <usb_dfu_descriptors.h>
++
++#include "usbdcore_s3c2410.h"
++
++#define RET_NOTHING 0
++#define RET_ZLP 1
++#define RET_STALL 2
++
++#define LOAD_ADDR 0x32000000
++
++static char *ptr;
++
++static int handle_dnload(struct urb *urb, u_int16_t val, u_int16_t len, int
first)
+{
-+ volatile u_int32_t *p = (volatile u_int32_t *)ptr;
-+ u_int8_t *pagebuf = (u_int8_t *) pagebuf32;
++ struct usb_device_instance *dev = urb->device;
++ debug("download ");
++
+ int i;
+
-+ DEBUGE("download ");
-+
-+ if (len > AT91C_IFLASH_PAGE_SIZE) {
++ if (len > CONFIG_USBD_DFU_XFER_SIZE) {
+ /* Too big. Not that we'd really care, but it's a
+ * DFU protocol violation */
-+ DEBUGP("length exceeds flash page size ");
-+ dfu_state = DFU_STATE_dfuERROR;
-+ dfu_status = DFU_STATUS_errADDRESS;
++ debug("length exceeds flash page size ");
++ dev->dfu_state = DFU_STATE_dfuERROR;
++ dev->dfu_status = DFU_STATUS_errADDRESS;
+ return RET_STALL;
+ }
++#if 0
+ if (len & 0x3) {
+ /* reject non-four-byte-aligned writes */
-+ DEBUGP("not four-byte-aligned length ");
-+ dfu_state = DFU_STATE_dfuERROR;
-+ dfu_status = DFU_STATUS_errADDRESS;
++ debug("not four-byte-aligned length ");
++ dev->dfu_state = DFU_STATE_dfuERROR;
++ dev->dfu_status = DFU_STATUS_errADDRESS;
+ return RET_STALL;
+ }
++#endif
+ if (len == 0) {
-+ DEBUGP("zero-size write -> MANIFEST_SYNC ");
-+ flash_page(p);
-+ dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
++ debug("zero-size write -> MANIFEST_SYNC ");
++ //flash_page(p);
++ dev->dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
+ return RET_ZLP;
+ }
-+ if (ptr + len > (u_int8_t *) AT91C_IFLASH + AT91C_IFLASH_SIZE) {
-+ DEBUGP("end of write exceeds flash end ");
-+ dfu_state = DFU_STATE_dfuERROR;
-+ dfu_status = DFU_STATUS_errADDRESS;
++ if (ptr + len > LOAD_ADDR + 0x200000) {
++ debug("end of write exceeds flash end ");
++ dev->dfu_state = DFU_STATE_dfuERROR;
++ dev->dfu_status = DFU_STATUS_errADDRESS;
+ return RET_STALL;
+ }
+
-+ DEBUGP("try_to_recv=%u ", len);
-+ udp_ep0_recv_data(pagebuf, len);
++ if (urb->actual_length != len) {
++ debug("urb->actual_length(%u) != len(%u) ?!?\n",
++ urb->actual_length, len);
++ return RET_STALL;
++ }
+
-+ DEBUGR(hexdump(pagebuf, len));
++ /* actually write the data somewhere */
++ switch (dev->alternate) {
++ case 0:
++ if (first)
++ ptr = LOAD_ADDR;
++ memcpy(ptr, urb->buffer, len);
++ ptr += len;
++ break;
++ default:
++ debug("[yet] unsupported altsetting %u\n", dev->alternate);
++ break;
++ }
+
-+ /* FXIME: actually write the data somewhere */
-+
+ return RET_ZLP;
+}
+
-+#define AT91C_IFLASH_END ((u_int8_t *)AT91C_IFLASH + AT91C_IFLASH_SIZE)
-+static dfufunc int handle_upload(u_int16_t val, u_int16_t len)
++static int handle_upload(struct urb *urb, u_int16_t val, u_int16_t len, int
first)
+{
-+ DEBUGE("upload ");
-+ if (len > AT91C_IFLASH_PAGE_SIZE) {
++ struct usb_device_instance *dev = urb->device;
++ debug("upload(val=0x%02x, len=%u, first=%u) ", val, len, first);
++
++ if (len > CONFIG_USBD_DFU_XFER_SIZE) {
+ /* Too big */
-+ dfu_state = DFU_STATE_dfuERROR;
-+ dfu_status = DFU_STATUS_errADDRESS;
-+ udp_ep0_send_stall();
++ dev->dfu_state = DFU_STATE_dfuERROR;
++ dev->dfu_status = DFU_STATUS_errADDRESS;
++ //udc_ep0_send_stall();
++ debug("Error: Transfer size > CONFIG_USBD_DFU_XFER_SIZE\n");
+ return -EINVAL;
+ }
+
-+ if (ptr + len > AT91C_IFLASH_END)
-+ len = AT91C_IFLASH_END - (u_int8_t *)ptr;
++ if (first) {
++ ptr = LOAD_ADDR;
++ /* the first of many upload requests */
++ switch (dev->alternate) {
++ case 0:
++ /* upload RAM contents ?!? */
++ break;
++ case 1:
++ /* u-boot */
++ run_command("nand read.e 0x32000000 u-boot", 0);
++ break;
++ case 2:
++ run_command("nand read.e 0x32000000 u-boot_env", 0);
++ break;
++ case 3:
++ run_command("nand read.e 0x32000000 splash", 0);
++ break;
++ case 4:
++ run_command("nand read.e 0x32000000 kernel", 0);
++ break;
++ default:
++ return -EINVAL;
++ }
++ }
+
-+ udp_ep0_send_data((char *)ptr, len);
++
++ if (ptr + len > LOAD_ADDR + 0x200000)
++ len = (char *)(LOAD_ADDR + 0x200000) - ptr;
++
++ urb->buffer = ptr;
++ urb->actual_length = len;
+ ptr+= len;
+
++ printf("returning len=%u\n", len);
+ return len;
+}
+
-+static void handle_getstatus(void)
++static void handle_getstatus(struct urb *urb, int max)
+{
-+ struct dfu_status dstat;
-+ u_int32_t fsr = AT91F_MC_EFC_GetStatus(AT91C_BASE_MC);
++ struct usb_device_instance *dev = urb->device;
++ struct dfu_status *dstat = urb->buffer;
++ u_int32_t fsr = 0;//AT91F_MC_EFC_GetStatus(AT91C_BASE_MC);
+
-+ DEBUGE("getstatus(fsr=0x%08x) ", fsr);
++ debug("getstatus(fsr=0x%08x) ", fsr);
+
-+ switch (dfu_state) {
++ if (!urb->buffer || urb->buffer_length < sizeof(*dstat)) {
++ debug("invalid urb! ");
++ return;
++ }
++
++ switch (dev->dfu_state) {
+ case DFU_STATE_dfuDNLOAD_SYNC:
+ case DFU_STATE_dfuDNBUSY:
++#if 0
+ if (fsr & AT91C_MC_PROGE) {
-+ DEBUGE("errPROG ");
-+ dfu_status = DFU_STATUS_errPROG;
-+ dfu_state = DFU_STATE_dfuERROR;
++ debug("errPROG ");
++ dev->dfu_status = DFU_STATUS_errPROG;
++ dev->dfu_state = DFU_STATE_dfuERROR;
+ } else if (fsr & AT91C_MC_LOCKE) {
-+ DEBUGE("errWRITE ");
-+ dfu_status = DFU_STATUS_errWRITE;
-+ dfu_state = DFU_STATE_dfuERROR;
++ debug("errWRITE ");
++ dev->dfu_status = DFU_STATUS_errWRITE;
++ dev->dfu_state = DFU_STATE_dfuERROR;
+ } else if (fsr & AT91C_MC_FRDY) {
-+ DEBUGE("DNLOAD_IDLE ");
-+ dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
++#endif
++ debug("DNLOAD_IDLE ");
++ dev->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
++#if 0
+ } else {
-+ DEBUGE("DNBUSY ");
-+ dfu_state = DFU_STATE_dfuDNBUSY;
++ debug("DNBUSY ");
++ dev->dfu_state = DFU_STATE_dfuDNBUSY;
+ }
++#endif
+ break;
+ case DFU_STATE_dfuMANIFEST_SYNC:
-+ dfu_state = DFU_STATE_dfuMANIFEST;
++ dev->dfu_state = DFU_STATE_dfuMANIFEST;
+ break;
++ default:
++ //return;
++ break;
+ }
+
+ /* send status response */
-+ dstat.bStatus = dfu_status;
-+ dstat.bState = dfu_state;
-+ dstat.iString = 0;
-+ /* FIXME: set dstat.bwPollTimeout */
++ dstat->bStatus = dev->dfu_status;
++ dstat->bState = dev->dfu_state;
++ dstat->iString = 0;
++ /* FIXME: set dstat->bwPollTimeout */
++ urb->actual_length = MIN(sizeof(*dstat), max);
+
-+ udp_ep0_send_data((char *)&dstat, sizeof(dstat));
++ /* we don't need to explicitly send data here, will
++ * be done by the original caller! */
+}
+
-+static void handle_getstate(void)
++static void handle_getstate(struct urb *urb, int max)
+{
-+ u_int8_t u8 = dfu_state;
-+ DEBUGE("getstate ");
++ debug("getstate ");
+
-+ udp_ep0_send_data((char *)&u8, sizeof(u8));
++ if (!urb->buffer || urb->buffer_length < sizeof(u_int8_t)) {
++ debug("invalid urb! ");
++ return;
++ }
++
++ urb->buffer[0] = urb->device->dfu_state & 0xff;
++ urb->actual_length = sizeof(u_int8_t);
+}
+
++#ifndef CONFIG_USBD_PRODUCTID_DFU
++#define CONFIG_USBD_PRODUCTID_DFU CONFIG_USBD_PRODUCTID_CDCACM
++#endif
+
++static const struct usb_device_descriptor dfu_dev_descriptor = {
++ .bLength = USB_DT_DEVICE_SIZE,
++ .bDescriptorType = USB_DT_DEVICE,
++ .bcdUSB = 0x0100,
++ .bDeviceClass = 0x00,
++ .bDeviceSubClass = 0x00,
++ .bDeviceProtocol = 0x00,
++ .bMaxPacketSize0 = EP0_MAX_PACKET_SIZE,
++ .idVendor = CONFIG_USBD_VENDORID,
++ .idProduct = CONFIG_USBD_PRODUCTID_DFU,
++ .bcdDevice = 0x0000,
++ .iManufacturer = 1,
++ .iProduct = 2,
++ .iSerialNumber = 0x00,
++ .bNumConfigurations = 0x01,
++};
++
++static const struct _dfu_desc dfu_cfg_descriptor = {
++ .ucfg = {
++ .bLength = USB_DT_CONFIG_SIZE,
++ .bDescriptorType = USB_DT_CONFIG,
++ .wTotalLength = USB_DT_CONFIG_SIZE +
++ 5*USB_DT_INTERFACE_SIZE +
++ USB_DT_DFU_SIZE,
++ .bNumInterfaces = 5,
++ .bConfigurationValue = 1,
++#ifdef CONFIG_USBD_STRING
++ .iConfiguration = 3,
++#else
++ .iConfiguration = 0,
++#endif
++ .bmAttributes = BMATTRIBUTE_RESERVED,
++ .bMaxPower = 50,
++ },
++ .uif[0] = {
++ .bLength = USB_DT_INTERFACE_SIZE,
++ .bDescriptorType = USB_DT_INTERFACE,
++ .bInterfaceNumber = 0x00,
++ .bAlternateSetting = 0x00,
++ .bNumEndpoints = 0x00,
++ .bInterfaceClass = 0xfe,
++ .bInterfaceSubClass = 0x01,
++ .bInterfaceProtocol = 0x02,
++ .iInterface = 0,
++ },
++ .uif[1] = {
++ .bLength = USB_DT_INTERFACE_SIZE,
++ .bDescriptorType = USB_DT_INTERFACE,
++ .bInterfaceNumber = 0x00,
++ .bAlternateSetting = 0x01,
++ .bNumEndpoints = 0x00,
++ .bInterfaceClass = 0xfe,
++ .bInterfaceSubClass = 0x01,
++ .bInterfaceProtocol = 0x02,
++ .iInterface = 0,
++ },
++ .uif[2] = {
++ .bLength = USB_DT_INTERFACE_SIZE,
++ .bDescriptorType = USB_DT_INTERFACE,
++ .bInterfaceNumber = 0x00,
++ .bAlternateSetting = 0x02,
++ .bNumEndpoints = 0x00,
++ .bInterfaceClass = 0xfe,
++ .bInterfaceSubClass = 0x01,
++ .bInterfaceProtocol = 0x02,
++ .iInterface = 0,
++ },
++ .uif[3] = {
++ .bLength = USB_DT_INTERFACE_SIZE,
++ .bDescriptorType = USB_DT_INTERFACE,
++ .bInterfaceNumber = 0x00,
++ .bAlternateSetting = 0x03,
++ .bNumEndpoints = 0x00,
++ .bInterfaceClass = 0xfe,
++ .bInterfaceSubClass = 0x01,
++ .bInterfaceProtocol = 0x02,
++ .iInterface = 0,
++ },
++ .uif[4] = {
++ .bLength = USB_DT_INTERFACE_SIZE,
++ .bDescriptorType = USB_DT_INTERFACE,
++ .bInterfaceNumber = 0x00,
++ .bAlternateSetting = 0x04,
++ .bNumEndpoints = 0x00,
++ .bInterfaceClass = 0xfe,
++ .bInterfaceSubClass = 0x01,
++ .bInterfaceProtocol = 0x02,
++ .iInterface = 0,
++ },
++ .func_dfu = DFU_FUNC_DESC,
++};
++
+int dfu_ep0_handler(struct urb *urb)
+{
+ int rc, ret = RET_NOTHING;
++ u_int8_t req = urb->device_request.bRequest;
++ u_int16_t val = urb->device_request.wValue;
++ u_int16_t len = urb->device_request.wLength;
++ struct usb_device_instance *dev = urb->device;
+
-+ DEBUGE("old_state = %u ", dfu_state);
++ debug("old_state = %u ", dev->dfu_state);
+
-+ switch (dfu_state) {
++ switch (dev->dfu_state) {
+ case DFU_STATE_appIDLE:
+ switch (req) {
+ case USB_REQ_DFU_GETSTATUS:
-+ handle_getstatus();
++ handle_getstatus(urb, len);
+ break;
+ case USB_REQ_DFU_GETSTATE:
-+ handle_getstate();
++ handle_getstate(urb, len);
+ break;
+ case USB_REQ_DFU_DETACH:
-+ dfu_state = DFU_STATE_appDETACH;
++ dev->dfu_state = DFU_STATE_appDETACH;
+ ret = RET_ZLP;
+ goto out;
+ break;
@@ -190,13 +447,13 @@
+ case DFU_STATE_appDETACH:
+ switch (req) {
+ case USB_REQ_DFU_GETSTATUS:
-+ handle_getstatus();
++ handle_getstatus(urb, len);
+ break;
+ case USB_REQ_DFU_GETSTATE:
-+ handle_getstate();
++ handle_getstate(urb, len);
+ break;
+ default:
-+ dfu_state = DFU_STATE_appIDLE;
++ dev->dfu_state = DFU_STATE_appIDLE;
+ ret = RET_STALL;
+ goto out;
+ break;
@@ -207,31 +464,31 @@
+ switch (req) {
+ case USB_REQ_DFU_DNLOAD:
+ if (len == 0) {
-+ dfu_state = DFU_STATE_dfuERROR;
++ dev->dfu_state = DFU_STATE_dfuERROR;
+ ret = RET_STALL;
+ goto out;
+ }
-+ dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
-+ ptr = (u_int8_t *) AT91C_IFLASH + SAM7DFU_SIZE;
-+ ret = handle_dnload(val, len);
++ dev->dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
++ //ptr = (u_int8_t *) AT91C_IFLASH + SAM7DFU_SIZE;
++ ret = handle_dnload(urb, val, len, 1);
+ break;
+ case USB_REQ_DFU_UPLOAD:
-+ ptr = (u_int8_t *) AT91C_IFLASH + SAM7DFU_SIZE;
-+ dfu_state = DFU_STATE_dfuUPLOAD_IDLE;
-+ handle_upload(val, len);
++ //ptr = (u_int8_t *) AT91C_IFLASH + SAM7DFU_SIZE;
++ dev->dfu_state = DFU_STATE_dfuUPLOAD_IDLE;
++ handle_upload(urb, val, len, 1);
+ break;
+ case USB_REQ_DFU_ABORT:
+ /* no zlp? */
+ ret = RET_ZLP;
+ break;
+ case USB_REQ_DFU_GETSTATUS:
-+ handle_getstatus();
++ handle_getstatus(urb, len);
+ break;
+ case USB_REQ_DFU_GETSTATE:
-+ handle_getstate();
++ handle_getstate(urb, len);
+ break;
+ default:
-+ dfu_state = DFU_STATE_dfuERROR;
++ dev->dfu_state = DFU_STATE_dfuERROR;
+ ret = RET_STALL;
+ goto out;
+ break;
@@ -240,14 +497,14 @@
+ case DFU_STATE_dfuDNLOAD_SYNC:
+ switch (req) {
+ case USB_REQ_DFU_GETSTATUS:
-+ handle_getstatus();
++ handle_getstatus(urb, len);
+ /* FIXME: state transition depending on block
completeness */
+ break;
+ case USB_REQ_DFU_GETSTATE:
-+ handle_getstate();
++ handle_getstate(urb, len);
+ break;
+ default:
-+ dfu_state = DFU_STATE_dfuERROR;
++ dev->dfu_state = DFU_STATE_dfuERROR;
+ ret = RET_STALL;
+ goto out;
+ }
@@ -257,10 +514,10 @@
+ case USB_REQ_DFU_GETSTATUS:
+ /* FIXME: only accept getstatus if bwPollTimeout
+ * has elapsed */
-+ handle_getstatus();
++ handle_getstatus(urb, len);
+ break;
+ default:
-+ dfu_state = DFU_STATE_dfuERROR;
++ dev->dfu_state = DFU_STATE_dfuERROR;
+ ret = RET_STALL;
+ goto out;
+ }
@@ -268,21 +525,21 @@
+ case DFU_STATE_dfuDNLOAD_IDLE:
+ switch (req) {
+ case USB_REQ_DFU_DNLOAD:
-+ dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
-+ ret = handle_dnload(val, len);
++ dev->dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
++ ret = handle_dnload(urb, val, len, 0);
+ break;
+ case USB_REQ_DFU_ABORT:
-+ dfu_state = DFU_STATE_dfuIDLE;
++ dev->dfu_state = DFU_STATE_dfuIDLE;
+ ret = RET_ZLP;
+ break;
+ case USB_REQ_DFU_GETSTATUS:
-+ handle_getstatus();
++ handle_getstatus(urb, len);
+ break;
+ case USB_REQ_DFU_GETSTATE:
-+ handle_getstate();
++ handle_getstate(urb, len);
+ break;
+ default:
-+ dfu_state = DFU_STATE_dfuERROR;
++ dev->dfu_state = DFU_STATE_dfuERROR;
+ ret = RET_STALL;
+ break;
+ }
@@ -290,19 +547,19 @@
+ case DFU_STATE_dfuMANIFEST_SYNC:
+ switch (req) {
+ case USB_REQ_DFU_GETSTATUS:
-+ handle_getstatus();
++ handle_getstatus(urb, len);
+ break;
+ case USB_REQ_DFU_GETSTATE:
-+ handle_getstate();
++ handle_getstate(urb, len);
+ break;
+ default:
-+ dfu_state = DFU_STATE_dfuERROR;
++ dev->dfu_state = DFU_STATE_dfuERROR;
+ ret = RET_STALL;
+ break;
+ }
+ break;
+ case DFU_STATE_dfuMANIFEST:
-+ dfu_state = DFU_STATE_dfuERROR;
++ dev->dfu_state = DFU_STATE_dfuERROR;
+ ret = RET_STALL;
+ break;
+ case DFU_STATE_dfuMANIFEST_WAIT_RST:
@@ -312,23 +569,23 @@
+ switch (req) {
+ case USB_REQ_DFU_UPLOAD:
+ /* state transition if less data then requested */
-+ rc = handle_upload(val, len);
++ rc = handle_upload(urb, val, len, 0);
+ if (rc >= 0 && rc < len)
-+ dfu_state = DFU_STATE_dfuIDLE;
++ dev->dfu_state = DFU_STATE_dfuIDLE;
+ break;
+ case USB_REQ_DFU_ABORT:
-+ dfu_state = DFU_STATE_dfuIDLE;
++ dev->dfu_state = DFU_STATE_dfuIDLE;
+ /* no zlp? */
+ ret = RET_ZLP;
+ break;
+ case USB_REQ_DFU_GETSTATUS:
-+ handle_getstatus();
++ handle_getstatus(urb, len);
+ break;
+ case USB_REQ_DFU_GETSTATE:
-+ handle_getstate();
++ handle_getstate(urb, len);
+ break;
+ default:
-+ dfu_state = DFU_STATE_dfuERROR;
++ dev->dfu_state = DFU_STATE_dfuERROR;
+ ret = RET_STALL;
+ break;
+ }
@@ -336,38 +593,434 @@
+ case DFU_STATE_dfuERROR:
+ switch (req) {
+ case USB_REQ_DFU_GETSTATUS:
-+ handle_getstatus();
++ handle_getstatus(urb, len);
+ break;
+ case USB_REQ_DFU_GETSTATE:
-+ handle_getstate();
++ handle_getstate(dev, len);
+ break;
+ case USB_REQ_DFU_CLRSTATUS:
-+ dfu_state = DFU_STATE_dfuIDLE;
-+ dfu_status = DFU_STATUS_OK;
++ dev->dfu_state = DFU_STATE_dfuIDLE;
++ dev->dfu_status = DFU_STATUS_OK;
+ /* no zlp? */
+ ret = RET_ZLP;
+ break;
+ default:
-+ dfu_state = DFU_STATE_dfuERROR;
++ dev->dfu_state = DFU_STATE_dfuERROR;
+ ret = RET_STALL;
+ break;
+ }
+ break;
++ default:
++ return DFU_EP0_UNHANDLED;
++ break;
+ }
+
+out:
-+ DEBUGE("new_state = %u\r\n", dfu_state);
++ debug("new_state = %u, ret = %u\n", dev->dfu_state, ret);
+
+ switch (ret) {
-+ case RET_NOTHING:
-+ break;
+ case RET_ZLP:
-+ udp_ep0_send_zlp();
++ //udc_ep0_send_zlp();
++ urb->actual_length = 0;
++ return DFU_EP0_ZLP;
+ break;
+ case RET_STALL:
-+ udp_ep0_send_stall();
++ //udc_ep0_send_stall();
++ return DFU_EP0_STALL;
+ break;
++ case RET_NOTHING:
++ break;
+ }
++
++ return DFU_EP0_DATA;
++}
++
++int dfu_init_instance(struct usb_device_instance *dev)
++{
++ dev->dfu_dev_desc = &dfu_dev_descriptor;
++ dev->dfu_cfg_desc = &dfu_cfg_descriptor;
++ dev->dfu_state = DFU_STATE_appIDLE;
++ dev->dfu_status = DFU_STATUS_OK;
++
+ return 0;
++}
++#endif /* CONFIG_USBD_DFU */
+Index: u-boot/drivers/Makefile
+===================================================================
+--- u-boot.orig/drivers/Makefile 2007-02-24 03:59:30.000000000 +0100
++++ u-boot/drivers/Makefile 2007-02-24 04:03:05.000000000 +0100
+@@ -46,7 +46,7 @@
+ sl811_usb.o sm501.o smc91111.o smiLynxEM.o \
+ status_led.o sym53c8xx.o ahci.o \
+ ti_pci1410a.o tigon3.o tsec.o \
+- usbdcore.o usbdcore_ep0.o usbdcore_omap1510.o usbdcore_s3c2410.o
usbtty.o \
++ usbdcore.o usbdfu.o usbdcore_ep0.o usbdcore_omap1510.o
usbdcore_s3c2410.o usbtty.o \
+ videomodes.o w83c553f.o \
+ ks8695eth.o \
+ pxa_pcmcia.o mpc8xx_pcmcia.o tqm8xx_pcmcia.o \
+Index: u-boot/drivers/usbdcore.c
+===================================================================
+--- u-boot.orig/drivers/usbdcore.c 2007-02-24 03:58:21.000000000 +0100
++++ u-boot/drivers/usbdcore.c 2007-02-24 04:03:05.000000000 +0100
+@@ -31,6 +31,7 @@
+
+ #include <malloc.h>
+ #include "usbdcore.h"
++#include <usb_dfu.h>
+
+ #define MAX_INTERFACES 2
+
+@@ -212,6 +213,10 @@
+ */
+ struct usb_device_descriptor *usbd_device_device_descriptor (struct
usb_device_instance *device, int port)
+ {
++#ifdef CONFIG_USBD_DFU
++ if (device->dfu_state != DFU_STATE_appIDLE)
++ return device->dfu_dev_desc;
++#endif
+ return (device->device_descriptor);
+ }
+
+@@ -232,6 +237,10 @@
+ if (!(configuration_instance = usbd_device_configuration_instance
(device, port, configuration))) {
+ return NULL;
+ }
++#ifdef CONFIG_USBD_DFU
++ if (device->dfu_state != DFU_STATE_appIDLE)
++ return (&device->dfu_cfg_desc->ucfg);
++#endif
+ return (configuration_instance->configuration_descriptor);
+ }
+
+@@ -253,6 +262,13 @@
+ if (!(interface_instance = usbd_device_interface_instance (device,
port, configuration, interface))) {
+ return NULL;
+ }
++#ifdef CONFIG_USBD_DFU
++ if (device->dfu_state != DFU_STATE_appIDLE) {
++ if (alternate < 0 || alternate >= DFU_NUM_ALTERNATES)
++ return NULL;
++ return &device->dfu_cfg_desc->uif[alternate];
++ }
++#endif
+ if ((alternate < 0) || (alternate >= interface_instance->alternates)) {
+ return NULL;
+ }
+@@ -623,6 +639,12 @@
+ case DEVICE_RESET:
+ device->device_state = STATE_DEFAULT;
+ device->address = 0;
++#ifdef CONFIG_USBD_DFU
++ if (device->dfu_state == DFU_STATE_appDETACH) {
++ debug("DFU SWITCH\n");
++ device->dfu_state = DFU_STATE_dfuIDLE;
++ }
++#endif
+ break;
+
+ case DEVICE_ADDRESS_ASSIGNED:
+Index: u-boot/drivers/usbtty.c
+===================================================================
+--- u-boot.orig/drivers/usbtty.c 2007-02-24 03:59:29.000000000 +0100
++++ u-boot/drivers/usbtty.c 2007-02-24 04:03:05.000000000 +0100
+@@ -31,6 +31,8 @@
+ #include "usbtty.h"
+ #include "usb_cdc_acm.h"
+ #include "usbdescriptors.h"
++#include <usb_dfu_descriptors.h>
++#include <usb_dfu.h>
+ #include <config.h> /* If defined, override Linux identifiers with
+ * vendor specific ones */
+
+@@ -169,6 +171,10 @@
+ struct usb_interface_descriptor data_class_interface;
+ struct usb_endpoint_descriptor
+ data_endpoints[NUM_ENDPOINTS-1] __attribute__((packed));
++#ifdef CONFIG_USBD_DFU
++ struct usb_interface_descriptor uif_dfu;
++ struct usb_dfu_func_descriptor func_dfu;
++#endif
+ } __attribute__((packed));
+
+ static struct acm_config_desc acm_configuration_descriptors[NUM_CONFIGS] = {
+@@ -179,7 +185,11 @@
+ .bDescriptorType = USB_DT_CONFIG,
+ .wTotalLength =
+ cpu_to_le16(sizeof(struct acm_config_desc)),
++#ifdef CONFIG_USBD_DFU
++ .bNumInterfaces = NUM_ACM_INTERFACES +1,
++#else
+ .bNumInterfaces = NUM_ACM_INTERFACES,
++#endif
+ .bConfigurationValue = 1,
+ .iConfiguration = STR_CONFIG,
+ .bmAttributes =
+@@ -278,6 +288,11 @@
+ .bInterval = 0xFF,
+ },
+ },
++#ifdef CONFIG_USBD_DFU
++ /* Interface 3 */
++ .uif_dfu = DFU_RT_IF_DESC,
++ .func_dfu = DFU_FUNC_DESC,
++#endif
+ },
+ };
+
+@@ -652,6 +667,9 @@
+ device_instance->bus = bus_instance;
+ device_instance->configurations = NUM_CONFIGS;
+ device_instance->configuration_instance_array = config_instance;
++#ifdef CONFIG_USBD_DFU
++ dfu_init_instance(device_instance);
++#endif
+
+ /* initialize bus instance */
+ memset (bus_instance, 0, sizeof (struct usb_bus_instance));
+Index: u-boot/include/configs/neo1973.h
+===================================================================
+--- u-boot.orig/include/configs/neo1973.h 2007-02-24 04:03:04.000000000
+0100
++++ u-boot/include/configs/neo1973.h 2007-02-24 04:03:05.000000000 +0100
+@@ -182,6 +182,10 @@
+ #define CONFIG_USBD_MANUFACTURER "OpenMoko, Inc"
+ #define CONFIG_USBD_PRODUCT_NAME "Neo1973 Bootloader " U_BOOT_VERSION
+ #define CONFIG_EXTRA_ENV_SETTINGS "usbtty=cdc_acm\0"
++#define CONFIG_USBD_DFU 1
++#define CONFIG_USBD_DFU_XFER_SIZE 0x4000
++#define CONFIG_USBD_DFU_INTERFACE 2
+
+
+ /*-----------------------------------------------------------------------
+ * Physical Memory Map
+Index: u-boot/include/usb_dfu.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ u-boot/include/usb_dfu.h 2007-02-24 04:03:05.000000000 +0100
+@@ -0,0 +1,91 @@
++#ifndef _DFU_H
++#define _DFU_H
++
++/* USB Device Firmware Update Implementation for u-boot
++ * (C) 2007 by OpenMoko, Inc.
++ * Author: Harald Welte <[EMAIL PROTECTED]>
++ *
++ * based on: USB Device Firmware Update Implementation for OpenPCD
++ * (C) 2006 by Harald Welte <[EMAIL PROTECTED]>
++ *
++ * This ought to be compliant to the USB DFU Spec 1.0 as available from
++ * http://www.usb.org/developers/devclass_docs/usbdfu10.pdf
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <asm/types.h>
++#include <usbdescriptors.h>
++#include <usb_dfu_descriptors.h>
++#include <config.h>
++
++/* USB DFU functional descriptor */
++#define DFU_FUNC_DESC { \
++ .bLength = USB_DT_DFU_SIZE, \
++ .bDescriptorType = USB_DT_DFU, \
++ .bmAttributes = USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD, \
++ .wDetachTimeOut = 0xff00, \
++ .wTransferSize = CONFIG_USBD_DFU_XFER_SIZE, \
++ .bcdDFUVersion = 0x0100, \
+}
++
++/* USB Interface descriptor in Runtime mode */
++#ifdef CONFIG_USB_STRING
++#define DFU_RT_IF_DESC {
\
++ .bLength = USB_DT_INTERFACE_SIZE, \
++ .bDescriptorType = USB_DT_INTERFACE, \
++ .bInterfaceNumber = CONFIG_USBD_DFU_INTERFACE, \
++ .bAlternateSetting = 0x00, \
++ .bNumEndpoints = 0x00, \
++ .bInterfaceClass = 0xfe, \
++ .bInterfaceSubClass = 0x01, \
++ .bInterfaceProtocol = 0x01, \
++ .iInterface = 1, \
++}
++#else
++#define DFU_RT_IF_DESC {
\
++ .bLength = USB_DT_INTERFACE_SIZE, \
++ .bDescriptorType = USB_DT_INTERFACE, \
++ .bInterfaceNumber = CONFIG_USBD_DFU_INTERFACE, \
++ .bAlternateSetting = 0x00, \
++ .bNumEndpoints = 0x00, \
++ .bInterfaceClass = 0xfe, \
++ .bInterfaceSubClass = 0x01, \
++ .bInterfaceProtocol = 0x01, \
++ .iInterface = 0, \
++}
++#endif
++
++#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
++
++#define DFU_NUM_ALTERNATES 5
++
++struct _dfu_desc {
++ struct usb_configuration_descriptor ucfg;
++ struct usb_interface_descriptor uif[DFU_NUM_ALTERNATES];
++ struct usb_dfu_func_descriptor func_dfu;
++};
++
++int dfu_init_instance(struct usb_device_instance *dev);
++
++#define DFU_EP0_NONE 0
++#define DFU_EP0_UNHANDLED 1
++#define DFU_EP0_STALL 2
++#define DFU_EP0_ZLP 3
++#define DFU_EP0_DATA 4
++
++int dfu_ep0_handler(struct urb *urb);
++
++#endif /* _DFU_H */
+Index: u-boot/include/usb_dfu_descriptors.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ u-boot/include/usb_dfu_descriptors.h 2007-02-24 04:03:05.000000000
+0100
+@@ -0,0 +1,94 @@
++#ifndef _USB_DFU_H
++#define _USB_DFU_H
++/* USB Device Firmware Update Implementation for OpenPCD
++ * (C) 2006 by Harald Welte <[EMAIL PROTECTED]>
++ *
++ * Protocol definitions for USB DFU
++ *
++ * This ought to be compliant to the USB DFU Spec 1.0 as available from
++ * http://www.usb.org/developers/devclass_docs/usbdfu10.pdf
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/types.h>
++
++#define USB_DT_DFU 0x21
++
++struct usb_dfu_func_descriptor {
++ u_int8_t bLength;
++ u_int8_t bDescriptorType;
++ u_int8_t bmAttributes;
++#define USB_DFU_CAN_DOWNLOAD (1 << 0)
++#define USB_DFU_CAN_UPLOAD (1 << 1)
++#define USB_DFU_MANIFEST_TOL (1 << 2)
++#define USB_DFU_WILL_DETACH (1 << 3)
++ u_int16_t wDetachTimeOut;
++ u_int16_t wTransferSize;
++ u_int16_t bcdDFUVersion;
++} __attribute__ ((packed));
++
++#define USB_DT_DFU_SIZE 9
++
++#define USB_TYPE_DFU (USB_TYPE_CLASS|USB_RECIP_INTERFACE)
++
++/* DFU class-specific requests (Section 3, DFU Rev 1.1) */
++#define USB_REQ_DFU_DETACH 0x00
++#define USB_REQ_DFU_DNLOAD 0x01
++#define USB_REQ_DFU_UPLOAD 0x02
++#define USB_REQ_DFU_GETSTATUS 0x03
++#define USB_REQ_DFU_CLRSTATUS 0x04
++#define USB_REQ_DFU_GETSTATE 0x05
++#define USB_REQ_DFU_ABORT 0x06
++
++struct dfu_status {
++ u_int8_t bStatus;
++ u_int8_t bwPollTimeout[3];
++ u_int8_t bState;
++ u_int8_t iString;
++} __attribute__((packed));
++
++#define DFU_STATUS_OK 0x00
++#define DFU_STATUS_errTARGET 0x01
++#define DFU_STATUS_errFILE 0x02
++#define DFU_STATUS_errWRITE 0x03
++#define DFU_STATUS_errERASE 0x04
++#define DFU_STATUS_errCHECK_ERASED 0x05
++#define DFU_STATUS_errPROG 0x06
++#define DFU_STATUS_errVERIFY 0x07
++#define DFU_STATUS_errADDRESS 0x08
++#define DFU_STATUS_errNOTDONE 0x09
++#define DFU_STATUS_errFIRMWARE 0x0a
++#define DFU_STATUS_errVENDOR 0x0b
++#define DFU_STATUS_errUSBR 0x0c
++#define DFU_STATUS_errPOR 0x0d
++#define DFU_STATUS_errUNKNOWN 0x0e
++#define DFU_STATUS_errSTALLEDPKT 0x0f
++
++enum dfu_state {
++ DFU_STATE_appIDLE = 0,
++ DFU_STATE_appDETACH = 1,
++ DFU_STATE_dfuIDLE = 2,
++ DFU_STATE_dfuDNLOAD_SYNC = 3,
++ DFU_STATE_dfuDNBUSY = 4,
++ DFU_STATE_dfuDNLOAD_IDLE = 5,
++ DFU_STATE_dfuMANIFEST_SYNC = 6,
++ DFU_STATE_dfuMANIFEST = 7,
++ DFU_STATE_dfuMANIFEST_WAIT_RST = 8,
++ DFU_STATE_dfuUPLOAD_IDLE = 9,
++ DFU_STATE_dfuERROR = 10,
++};
++
++#endif /* _USB_DFU_H */
+Index: u-boot/include/usbdcore.h
+===================================================================
+--- u-boot.orig/include/usbdcore.h 2007-02-24 03:59:29.000000000 +0100
++++ u-boot/include/usbdcore.h 2007-02-24 04:03:05.000000000 +0100
+@@ -33,6 +33,7 @@
+
+ #include <common.h>
+ #include "usbdescriptors.h"
++#include <usb_dfu_descriptors.h>
+
+
+ #define MAX_URBS_QUEUED 5
+@@ -475,7 +476,11 @@
+ * function driver to inform it that data has arrived.
+ */
+
++#ifdef CONFIG_USBD_DFU
++#define URB_BUF_SIZE (128+CONFIG_USBD_DFU_XFER_SIZE)
++#else
+ #define URB_BUF_SIZE 128 /* in linux we'd malloc this, but in u-boot we
prefer static data */
++#endif
+ struct urb {
+
+ struct usb_endpoint_instance *endpoint;
+@@ -603,6 +608,12 @@
+ unsigned long usbd_rxtx_timestamp;
+ unsigned long usbd_last_rxtx_timestamp;
+
++#ifdef CONFIG_USBD_DFU
++ struct usb_device_descriptor *dfu_dev_desc;
++ struct _dfu_desc *dfu_cfg_desc;
++ enum dfu_state dfu_state;
++ u_int8_t dfu_status;
++#endif
+ };
+
+ /* Bus Interface configuration structure
--- End Message ---