Add support for Siemens SX1 mobile phone;
authorwdenk <wdenk>
Fri, 12 Mar 2004 00:14:09 +0000 (00:14 +0000)
committerwdenk <wdenk>
Fri, 12 Mar 2004 00:14:09 +0000 (00:14 +0000)
add support for USB-based console
(enable with "setenv stdout usbtty; setenv stdin usbtty")

31 files changed:
CHANGELOG
Makefile
board/sx1/Makefile [new file with mode: 0644]
board/sx1/config.mk [new file with mode: 0644]
board/sx1/flash.c [new file with mode: 0644]
board/sx1/platform.S [new file with mode: 0644]
board/sx1/sx1.c [new file with mode: 0644]
board/sx1/u-boot.lds [new file with mode: 0644]
common/Makefile
common/circbuf.c [new file with mode: 0644]
common/cmd_load.c
common/devices.c
cpu/arm925t/interrupts.c
drivers/Makefile
drivers/ns16550.c
drivers/omap1510_i2c.c [new file with mode: 0644]
drivers/usbdcore.c [new file with mode: 0644]
drivers/usbdcore_ep0.c [new file with mode: 0644]
drivers/usbdcore_omap1510.c [new file with mode: 0644]
drivers/usbtty.c [new file with mode: 0644]
drivers/usbtty.h [new file with mode: 0644]
include/circbuf.h [new file with mode: 0644]
include/configs/SX1.h [new file with mode: 0644]
include/configs/omap1510.h
include/devices.h
include/usbdcore.h [new file with mode: 0644]
include/usbdcore_ep0.h [new file with mode: 0644]
include/usbdcore_omap1510.h [new file with mode: 0644]
include/usbdescriptors.h [new file with mode: 0644]
lib_arm/armlinux.c
net/bootp.c

index aa6bfe5acf7440cc183e51372e4bba84cf16e1dc..9bebdeb944201f8eca661e39a3f22f592c17426b 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,9 @@
 Changes for U-Boot 1.0.2:
 ======================================================================
 
+* Add support for SX1 mobile phone; add support for USB-based console
+  (enable with "setenv stdout usbtty; setenv stdin usbtty")
+
 * Fix LOWBOOT configuration for MPC5200 with DDR memory
 
 * Fix SDRAM timings for LITE5200 / IceCube board
@@ -15,7 +18,7 @@ Changes for U-Boot 1.0.2:
 
 * Patch by Stephan Linz, 26 Feb 2004:
   Bug fix for NFS code on NIOS targets
-  
+
 * Patch by Stephen Williams, 26 Feb 2004:
   Break up SystemACE reads of large block counts
 
index b10acbb6e18754410a2132f852d52d993aff55fe..d1593eefd8205476d70a04903918e3b05ac41aef 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -921,6 +921,9 @@ xtract_trab = $(subst _bigram,,$(subst _bigflash,,$(subst _old,,$(subst _config,
 
 xtract_omap1610xxx = $(subst _cs0boot,,$(subst _cs3boot,, $(subst _config,,$1)))
 
+SX1_config :           unconfig
+       @./mkconfig $(@:_config=) arm arm925t sx1
+
 omap1510inn_config :   unconfig
        @./mkconfig $(@:_config=) arm arm925t omap1510inn
 
diff --git a/board/sx1/Makefile b/board/sx1/Makefile
new file mode 100644 (file)
index 0000000..808c76a
--- /dev/null
@@ -0,0 +1,47 @@
+#
+# (C) Copyright 2004
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 $(TOPDIR)/config.mk
+
+LIB    = lib$(BOARD).a
+
+OBJS   := sx1.o flash.o
+SOBJS  := platform.o
+
+$(LIB):        $(OBJS) $(SOBJS)
+       $(AR) crv $@ $^
+
+clean:
+       rm -f $(SOBJS) $(OBJS)
+
+distclean:     clean
+       rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+.depend:       Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+               $(CC) -M $(CPPFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+-include .depend
+
+#########################################################################
diff --git a/board/sx1/config.mk b/board/sx1/config.mk
new file mode 100644 (file)
index 0000000..4902e82
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# (C) Copyright 2004
+# Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+#
+# SX1 board with OMAP1510 (ARM925T) cpu
+# see http://www.ti.com/ for more information on Texas Insturments
+#
+# SX1 has 1 bank of 256 MB SDRAM
+# Physical Address:
+# 1000'0000 to 2000'0000
+#
+#
+# Linux-Kernel is expected to be at 1000'8000, entry 1000'8000  (mem base + reserved)
+#
+# we load ourself to 1108'0000
+#
+#
+
+TEXT_BASE = 0x11080000
diff --git a/board/sx1/flash.c b/board/sx1/flash.c
new file mode 100644 (file)
index 0000000..a4bed61
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * (C) Copyright 2001
+ * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
+ *
+ * (C) Copyright 2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <common.h>
+#include <linux/byteorder/swab.h>
+
+#define PHYS_FLASH_SECT_SIZE   0x00020000      /* 256 KB sectors (x2) */
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];  /* info for FLASH chips    */
+
+/* Board support for 1 or 2 flash devices */
+#undef FLASH_PORT_WIDTH32
+#define FLASH_PORT_WIDTH16
+
+#ifdef FLASH_PORT_WIDTH16
+#define FLASH_PORT_WIDTH       ushort
+#define FLASH_PORT_WIDTHV      vu_short
+#define SWAP(x)                        __swab16(x)
+#else
+#define FLASH_PORT_WIDTH       ulong
+#define FLASH_PORT_WIDTHV      vu_long
+#define SWAP(x)                        __swab32(x)
+#endif
+
+#define FPW    FLASH_PORT_WIDTH
+#define FPWV   FLASH_PORT_WIDTHV
+
+#define mb() __asm__ __volatile__ ("" : : : "memory")
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (FPW * addr, flash_info_t * info);
+static int write_data (flash_info_t * info, ulong dest, FPW data);
+static void flash_get_offsets (ulong base, flash_info_t * info);
+void inline spin_wheel (void);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+       int i;
+       ulong size = 0;
+
+       for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
+               switch (i) {
+               case 0:
+                       flash_get_size ((FPW *) PHYS_FLASH_1, &flash_info[i]);
+                       flash_get_offsets (PHYS_FLASH_1, &flash_info[i]);
+                       break;
+               case 1:
+                       flash_get_size ((FPW *) PHYS_FLASH_2, &flash_info[i]);
+                       flash_get_offsets (PHYS_FLASH_2, &flash_info[i]);
+                       break;
+               default:
+                       panic ("configured too many flash banks!\n");
+                       break;
+               }
+               size += flash_info[i].size;
+       }
+
+       /* Protect monitor and environment sectors
+        */
+       flash_protect ( FLAG_PROTECT_SET,
+                       CFG_FLASH_BASE,
+                       CFG_FLASH_BASE + monitor_flash_len - 1,
+                       &flash_info[0]);
+
+       flash_protect ( FLAG_PROTECT_SET,
+                       CFG_ENV_ADDR,
+                       CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
+                       &flash_info[0]);
+
+       return size;
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t * info)
+{
+       int i;
+
+       if (info->flash_id == FLASH_UNKNOWN) {
+               return;
+       }
+
+       if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
+               for (i = 0; i < info->sector_count; i++) {
+                       info->start[i] = base + (i * PHYS_FLASH_SECT_SIZE);
+                       info->protect[i] = 0;
+               }
+       }
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t * info)
+{
+       int i;
+
+       if (info->flash_id == FLASH_UNKNOWN) {
+               printf ("missing or unknown FLASH type\n");
+               return;
+       }
+
+       switch (info->flash_id & FLASH_VENDMASK) {
+       case FLASH_MAN_INTEL:
+               printf ("INTEL ");
+               break;
+       default:
+               printf ("Unknown Vendor ");
+               break;
+       }
+
+       switch (info->flash_id & FLASH_TYPEMASK) {
+       case FLASH_28F128J3A:
+               printf ("28F128J3A\n");
+               break;
+       case FLASH_28F640J3A:
+               printf ("28F640J3A\n");
+               break;
+       default:
+               printf ("Unknown Chip Type\n");
+               break;
+       }
+
+       printf ("  Size: %ld MB in %d Sectors\n",
+               info->size >> 20, info->sector_count);
+
+       printf ("  Sector Start Addresses:");
+       for (i = 0; i < info->sector_count; ++i) {
+               if ((i % 5) == 0)
+                       printf ("\n   ");
+               printf (" %08lX%s",
+                       info->start[i],
+                       info->protect[i] ? " (RO)" : "     ");
+       }
+       printf ("\n");
+       return;
+}
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+static ulong flash_get_size (FPW * addr, flash_info_t * info)
+{
+       volatile FPW value;
+
+       /* Write auto select command: read Manufacturer ID */
+       addr[0x5555] = (FPW) 0x00AA00AA;
+       addr[0x2AAA] = (FPW) 0x00550055;
+       addr[0x5555] = (FPW) 0x00900090;
+
+       mb ();
+       value = addr[0];
+
+       switch (value) {
+       case (FPW) INTEL_MANUFACT:
+               info->flash_id = FLASH_MAN_INTEL;
+               break;
+       default:
+               info->flash_id = FLASH_UNKNOWN;
+               info->sector_count = 0;
+               info->size = 0;
+               addr[0] = (FPW) 0x00FF00FF;     /* restore read mode */
+               return (0);                     /* no or unknown flash  */
+       }
+
+       mb ();
+       value = addr[1];                        /* device ID        */
+       switch (value) {
+       case (FPW) INTEL_ID_28F128J3A:
+               info->flash_id += FLASH_28F128J3A;
+               info->sector_count = 128;
+               info->size = 0x01000000;
+               break;                          /* => 16 MB     */
+       case (FPW) INTEL_ID_28F640J3A:
+               info->flash_id += FLASH_28F640J3A;
+               info->sector_count = 64;
+               info->size = 0x00800000;
+               break;                          /* => 8 MB     */
+       default:
+               info->flash_id = FLASH_UNKNOWN;
+               break;
+       }
+
+       if (info->sector_count > CFG_MAX_FLASH_SECT) {
+               printf ("** ERROR: sector count %d > max (%d) **\n",
+                       info->sector_count, CFG_MAX_FLASH_SECT);
+               info->sector_count = CFG_MAX_FLASH_SECT;
+       }
+
+       addr[0] = (FPW) 0x00FF00FF;     /* restore read mode */
+
+       return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int flash_erase (flash_info_t * info, int s_first, int s_last)
+{
+       int flag, prot, sect;
+       ulong type, start, last;
+       int rcode = 0;
+
+       if ((s_first < 0) || (s_first > s_last)) {
+               if (info->flash_id == FLASH_UNKNOWN) {
+                       printf ("- missing\n");
+               } else {
+                       printf ("- no sectors to erase\n");
+               }
+               return 1;
+       }
+
+       type = (info->flash_id & FLASH_VENDMASK);
+       if ((type != FLASH_MAN_INTEL)) {
+               printf ("Can't erase unknown flash type %08lx - aborted\n",
+                       info->flash_id);
+               return 1;
+       }
+
+       prot = 0;
+       for (sect = s_first; sect <= s_last; ++sect) {
+               if (info->protect[sect]) {
+                       prot++;
+               }
+       }
+
+       if (prot) {
+               printf ("- Warning: %d protected sectors will not be erased!\n",
+                       prot);
+       } else {
+               printf ("\n");
+       }
+
+       /*start = get_timer (0); */
+       last = start;
+
+       /* Disable interrupts which might cause a timeout here */
+       flag = disable_interrupts ();
+
+       /* Start erase on unprotected sectors */
+       for (sect = s_first; sect <= s_last; sect++) {
+               if (info->protect[sect] == 0) { /* not protected */
+                       FPWV *addr = (FPWV *) (info->start[sect]);
+                       FPW status;
+
+                       printf ("Erasing sector %2d ... ", sect);
+
+                       /* arm simple, non interrupt dependent timer */
+                       reset_timer_masked ();
+
+                       *addr = (FPW) 0x00500050;       /* clear status register */
+                       *addr = (FPW) 0x00200020;       /* erase setup */
+                       *addr = (FPW) 0x00D000D0;       /* erase confirm */
+
+                       while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) {
+                               if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
+                                       printf ("Timeout\n");
+                                       *addr = (FPW) 0x00B000B0;       /* suspend erase     */
+                                       *addr = (FPW) 0x00FF00FF;       /* reset to read mode */
+                                       rcode = 1;
+                                       break;
+                               }
+                       }
+
+                       *addr = (FPW) 0x00500050;       /* clear status register cmd.   */
+                       *addr = (FPW) 0x00FF00FF;       /* resest to read mode          */
+
+                       printf (" done\n");
+               }
+       }
+       return rcode;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ * 4 - Flash not identified
+ */
+
+int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
+{
+       ulong cp, wp;
+       FPW data;
+       int count, i, l, rc, port_width;
+
+       if (info->flash_id == FLASH_UNKNOWN) {
+               return 4;
+       }
+/* get lower word aligned address */
+#ifdef FLASH_PORT_WIDTH16
+       wp = (addr & ~1);
+       port_width = 2;
+#else
+       wp = (addr & ~3);
+       port_width = 4;
+#endif
+
+       /*
+        * handle unaligned start bytes
+        */
+       if ((l = addr - wp) != 0) {
+               data = 0;
+               for (i = 0, cp = wp; i < l; ++i, ++cp) {
+                       data = (data << 8) | (*(uchar *) cp);
+               }
+               for (; i < port_width && cnt > 0; ++i) {
+                       data = (data << 8) | *src++;
+                       --cnt;
+                       ++cp;
+               }
+               for (; cnt == 0 && i < port_width; ++i, ++cp) {
+                       data = (data << 8) | (*(uchar *) cp);
+               }
+
+               if ((rc = write_data (info, wp, SWAP (data))) != 0) {
+                       return (rc);
+               }
+               wp += port_width;
+       }
+
+       /*
+        * handle word aligned part
+        */
+       count = 0;
+       while (cnt >= port_width) {
+               data = 0;
+               for (i = 0; i < port_width; ++i) {
+                       data = (data << 8) | *src++;
+               }
+               if ((rc = write_data (info, wp, SWAP (data))) != 0) {
+                       return (rc);
+               }
+               wp += port_width;
+               cnt -= port_width;
+               if (count++ > 0x800) {
+                       spin_wheel ();
+                       count = 0;
+               }
+       }
+
+       if (cnt == 0) {
+               return (0);
+       }
+
+       /*
+        * handle unaligned tail bytes
+        */
+       data = 0;
+       for (i = 0, cp = wp; i < port_width && cnt > 0; ++i, ++cp) {
+               data = (data << 8) | *src++;
+               --cnt;
+       }
+       for (; i < port_width; ++i, ++cp) {
+               data = (data << 8) | (*(uchar *) cp);
+       }
+
+       return (write_data (info, wp, SWAP (data)));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word or halfword to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_data (flash_info_t * info, ulong dest, FPW data)
+{
+       FPWV *addr = (FPWV *) dest;
+       ulong status;
+       int flag;
+
+       /* Check if Flash is (sufficiently) erased */
+       if ((*addr & data) != data) {
+               printf ("not erased at %08lx (%x)\n", (ulong) addr, *addr);
+               return (2);
+       }
+       /* Disable interrupts which might cause a timeout here */
+       flag = disable_interrupts ();
+
+       *addr = (FPW) 0x00400040;       /* write setup */
+       *addr = data;
+
+       /* arm simple, non interrupt dependent timer */
+       reset_timer_masked ();
+
+       /* wait while polling the status register */
+       while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) {
+
+               if (get_timer_masked () > CFG_FLASH_WRITE_TOUT) {
+                       *addr = (FPW) 0x00FF00FF;       /* restore read mode */
+                       return (1);
+               }
+       }
+
+       *addr = (FPW) 0x00FF00FF;       /* restore read mode */
+
+       return (0);
+}
+
+void inline spin_wheel (void)
+{
+       static int p = 0;
+       static char w[] = "\\/-";
+
+       printf ("\010%c", w[p]);
+       (++p == 3) ? (p = 0) : 0;
+}
diff --git a/board/sx1/platform.S b/board/sx1/platform.S
new file mode 100644 (file)
index 0000000..3048128
--- /dev/null
@@ -0,0 +1,406 @@
+/*
+ * Board specific setup info
+ *
+ * (C) Copyright 2003
+ * Texas Instruments, <www.ti.com>
+ *
+ * -- Some bits of code used from rrload's head_OMAP1510.s --
+ * Copyright (C) 2002 RidgeRun, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <config.h>
+#include <version.h>
+
+#if defined(CONFIG_OMAP1510)
+#include <./configs/omap1510.h>
+#endif
+
+#define OMAP1510_CLKS ((1<<EN_XORPCK)|(1<<EN_PERCK)|(1<<EN_TIMCK)|(1<<EN_GPIOCK))
+
+
+_TEXT_BASE:
+       .word   TEXT_BASE        /* sdram load addr from config.mk */
+
+.globl platformsetup
+platformsetup:
+
+       /*
+        * Configure 1510 pins functions to match our board.
+        */
+       ldr     r0, REG_PULL_DWN_CTRL_0
+       ldr     r1, VAL_PULL_DWN_CTRL_0
+       str     r1, [r0]
+       ldr     r0, REG_PULL_DWN_CTRL_1
+       ldr     r1, VAL_PULL_DWN_CTRL_1
+       str     r1, [r0]
+       ldr     r0, REG_PULL_DWN_CTRL_2
+       ldr     r1, VAL_PULL_DWN_CTRL_2
+       str     r1, [r0]
+       ldr     r0, REG_PULL_DWN_CTRL_3
+       ldr     r1, VAL_PULL_DWN_CTRL_3
+       str     r1, [r0]
+       ldr     r0, REG_FUNC_MUX_CTRL_4
+       ldr     r1, VAL_FUNC_MUX_CTRL_4
+       str     r1, [r0]
+       ldr     r0, REG_FUNC_MUX_CTRL_5
+       ldr     r1, VAL_FUNC_MUX_CTRL_5
+       str     r1, [r0]
+       ldr     r0, REG_FUNC_MUX_CTRL_6
+       ldr     r1, VAL_FUNC_MUX_CTRL_6
+       str     r1, [r0]
+       ldr     r0, REG_FUNC_MUX_CTRL_7
+       ldr     r1, VAL_FUNC_MUX_CTRL_7
+       str     r1, [r0]
+       ldr     r0, REG_FUNC_MUX_CTRL_8
+       ldr     r1, VAL_FUNC_MUX_CTRL_8
+       str     r1, [r0]
+       ldr     r0, REG_FUNC_MUX_CTRL_9
+       ldr     r1, VAL_FUNC_MUX_CTRL_9
+       str     r1, [r0]
+       ldr     r0, REG_FUNC_MUX_CTRL_A
+       ldr     r1, VAL_FUNC_MUX_CTRL_A
+       str     r1, [r0]
+       ldr     r0, REG_FUNC_MUX_CTRL_B
+       ldr     r1, VAL_FUNC_MUX_CTRL_B
+       str     r1, [r0]
+       ldr     r0, REG_FUNC_MUX_CTRL_C
+       ldr     r1, VAL_FUNC_MUX_CTRL_C
+       str     r1, [r0]
+       ldr     r0, REG_FUNC_MUX_CTRL_D
+       ldr     r1, VAL_FUNC_MUX_CTRL_D
+       str     r1, [r0]
+       ldr     r0, REG_VOLTAGE_CTRL_0
+       ldr     r1, VAL_VOLTAGE_CTRL_0
+       str     r1, [r0]
+       ldr     r0, REG_TEST_DBG_CTRL_0
+       ldr     r1, VAL_TEST_DBG_CTRL_0
+       str     r1, [r0]
+       ldr     r0, REG_MOD_CONF_CTRL_0
+       ldr     r1, VAL_MOD_CONF_CTRL_0
+       str     r1, [r0]
+
+       /* Move to 1510 mode */
+       ldr     r0, REG_COMP_MODE_CTRL_0
+       ldr     r1, VAL_COMP_MODE_CTRL_0
+       str     r1, [r0]
+
+       /* Set up Traffic Ctlr*/
+       ldr r0, REG_TC_IMIF_PRIO
+       mov r1, #0x0
+       str r1, [r0]
+       ldr r0, REG_TC_EMIFS_PRIO
+       str r1, [r0]
+       ldr r0, REG_TC_EMIFF_PRIO
+       str r1, [r0]
+
+       ldr r0, REG_TC_EMIFS_CONFIG
+       ldr r1, [r0]
+       bic r1, r1, #0x08   /* clear the global power-down enable PDE bit */
+       bic r1, r1, #0x01   /* write protect flash by clearing the WP bit */
+       str r1, [r0]        /* EMIFS GlB Configuration. (value 0x12 most likely) */
+
+       ldr r0, _GPIO_PIN_CONTROL_REG
+       ldrh r1,[r0]
+       orr r1, r1, #0x0001 /* M_PCM_SYNC */
+       orr r1, r1, #0x4000 /* IPC_ACTIVE */
+       orr r1, r1, #0x0002 /* A_IRDA_OFF */
+       orr r1, r1, #0x0800 /* A_SWITCH   */
+       orr r1, r1, #0x8000 /* A_USB_ON   */
+       strh r1,[r0]
+
+       ldr r0, _GPIO_DIR_CONTROL_REG
+       ldrh r1,[r0]
+       bic r1, r1, #0x0001 /* M_PCM_SYNC */
+       bic r1, r1, #0x4000 /* IPC_ACTIVE */
+       bic r1, r1, #0x0002 /* A_IRDA_OFF */
+       bic r1, r1, #0x0800 /* A_SWITCH   */
+       bic r1, r1, #0x8000 /* A_USB_ON   */
+       strh r1,[r0]
+
+       ldr r0, _GPIO_DATA_OUTPUT_REG
+       ldrh r1,[r0]
+       bic r1, r1, #0x0001 /* M_PCM_SYNC */
+       orr r1, r1, #0x4000 /* IPC_ACTIVE */
+       orr r1, r1, #0x0002 /* A_IRDA_OFF */
+       bic r1, r1, #0x0800 /* A_SWITCH   */
+       bic r1, r1, #0x8000 /* A_USB_ON   */
+       strh r1,[r0]
+
+       /* Setup some clock domains */
+       ldr r1, =OMAP1510_CLKS
+       ldr r0, REG_ARM_IDLECT2
+       strh r1, [r0]  /* CLKM, Clock domain control. */
+
+       mov r1, #0x01  /* PER_EN bit */
+       ldr r0, REG_ARM_RSTCT2
+       strh r1, [r0]  /* CLKM; Peripheral reset. */
+
+       /* Set CLKM to Sync-Scalable  */
+       /* I supposidly need to enable the dsp clock before switching */
+       mov r1, #0x1000
+       ldr r0, REG_ARM_SYSST
+       strh r1, [r0]
+       mov r0, #0x400
+1:
+       subs r0, r0, #0x1   /* wait for any bubbles to finish */
+       bne 1b
+
+       ldr r1, VAL_ARM_CKCTL  /* use 12Mhz ref, PER must be <= 50Mhz so /2 */
+       ldr r0, REG_ARM_CKCTL
+       strh r1, [r0]
+
+       /* setup DPLL 1 */
+       ldr r1, VAL_DPLL1_CTL
+       ldr r0, REG_DPLL1_CTL
+       strh r1, [r0]
+       ands r1, r1, #0x10  /* Check if PLL is enabled. */
+       beq lock_end        /* Do not look for lock if BYPASS selected */
+2:
+       ldrh r1, [r0]
+       ands r1, r1, #0x01  /* Check the LOCK bit. */
+       beq 2b              /* ...loop until bit goes hi. */
+lock_end:
+
+       /* Set memory timings corresponding to the new clock speed */
+
+       /* Check execution location to determine current execution location
+        * and branch to appropriate initialization code.
+        */
+       mov r0, #0x10000000                 /* Load physical SDRAM base. */
+       mov r1, pc                          /* Get current execution location. */
+       cmp r1, r0                          /* Compare. */
+       bge skip_sdram                      /* Skip over EMIF-fast initialization if running from SDRAM. */
+
+       /*
+        * Delay for SDRAM initialization.
+        */
+       mov r3, #0x1800                        /* value should be checked */
+3:
+       subs r3, r3, #0x1                     /* Decrement count */
+       bne 3b
+
+       /*
+        * Set SDRAM control values. Disable refresh before MRS command.
+        */
+       ldr r0, VAL_TC_EMIFF_SDRAM_CONFIG   /* get good value */
+       bic r3, r0, #0xC                    /* (BIT3|BIT2) ulConfig with auto-refresh disabled. */
+       orr r3, r3, #0x8000000              /* (BIT27) Disable CLK when Power down or Self-Refresh */
+       orr r3, r3, #0x4000000              /* BIT26 Power Down Enable */
+       ldr r2, REG_TC_EMIFF_SDRAM_CONFIG   /* Point to configuration register. */
+       str r3, [r2]                        /* Store the passed value with AR disabled. */
+
+       ldr r1, VAL_TC_EMIFF_MRS            /* get MRS value */
+       ldr r2, REG_TC_EMIFF_MRS            /* Point to MRS register. */
+       str r1, [r2]                        /* Store the passed value.*/
+
+       ldr r2, REG_TC_EMIFF_SDRAM_CONFIG   /* Point to configuration register. */
+       str r0, [r2]                        /* Store the passed value. */
+
+       /*
+        * Delay for SDRAM initialization.
+        */
+       mov r3, #0x1800
+4:
+       subs r3, r3, #1                     /* Decrement count. */
+       bne 4b
+
+skip_sdram:
+
+       /* slow interface */
+       ldr r1, VAL_TC_EMIFS_CS0_CONFIG
+       ldr r0, REG_TC_EMIFS_CS0_CONFIG
+       str r1, [r0] /* Chip Select 0 */
+       ldr r1, VAL_TC_EMIFS_CS1_CONFIG
+       ldr r0, REG_TC_EMIFS_CS1_CONFIG
+       str r1, [r0] /* Chip Select 1 */
+       ldr r1, VAL_TC_EMIFS_CS2_CONFIG
+       ldr r0, REG_TC_EMIFS_CS2_CONFIG
+       str r1, [r0] /* Chip Select 2 */
+       ldr r1, VAL_TC_EMIFS_CS3_CONFIG
+       ldr r0, REG_TC_EMIFS_CS3_CONFIG
+       str r1, [r0] /* Chip Select 3 */
+
+       /* back to arch calling code */
+       mov     pc, lr
+
+/* the literal pools origin */
+       .ltorg
+
+/* OMAP configuration registers */
+REG_FUNC_MUX_CTRL_0:           /* 32 bits */
+       .word 0xfffe1000
+REG_FUNC_MUX_CTRL_1:           /* 32 bits */
+       .word 0xfffe1004
+REG_FUNC_MUX_CTRL_2:           /* 32 bits */
+       .word 0xfffe1008
+REG_COMP_MODE_CTRL_0:          /* 32 bits */
+       .word 0xfffe100c
+REG_FUNC_MUX_CTRL_3:           /* 32 bits */
+       .word 0xfffe1010
+REG_FUNC_MUX_CTRL_4:           /* 32 bits */
+       .word 0xfffe1014
+REG_FUNC_MUX_CTRL_5:           /* 32 bits */
+       .word 0xfffe1018
+REG_FUNC_MUX_CTRL_6:           /* 32 bits */
+       .word 0xfffe101c
+REG_FUNC_MUX_CTRL_7:           /* 32 bits */
+       .word 0xfffe1020
+REG_FUNC_MUX_CTRL_8:           /* 32 bits */
+       .word 0xfffe1024
+REG_FUNC_MUX_CTRL_9:           /* 32 bits */
+       .word 0xfffe1028
+REG_FUNC_MUX_CTRL_A:           /* 32 bits */
+       .word 0xfffe102C
+REG_FUNC_MUX_CTRL_B:           /* 32 bits */
+       .word 0xfffe1030
+REG_FUNC_MUX_CTRL_C:           /* 32 bits */
+       .word 0xfffe1034
+REG_FUNC_MUX_CTRL_D:           /* 32 bits */
+       .word 0xfffe1038
+REG_PULL_DWN_CTRL_0:           /* 32 bits */
+       .word 0xfffe1040
+REG_PULL_DWN_CTRL_1:           /* 32 bits */
+       .word 0xfffe1044
+REG_PULL_DWN_CTRL_2:           /* 32 bits */
+       .word 0xfffe1048
+REG_PULL_DWN_CTRL_3:           /* 32 bits */
+       .word 0xfffe104c
+REG_VOLTAGE_CTRL_0:            /* 32 bits */
+       .word 0xfffe1060
+REG_TEST_DBG_CTRL_0:           /* 32 bits */
+       .word 0xfffe1070
+REG_MOD_CONF_CTRL_0:           /* 32 bits */
+       .word 0xfffe1080
+REG_TC_IMIF_PRIO:              /* 32 bits */
+       .word 0xfffecc00
+REG_TC_EMIFS_PRIO:             /* 32 bits */
+       .word 0xfffecc04
+REG_TC_EMIFF_PRIO:             /* 32 bits */
+       .word 0xfffecc08
+REG_TC_EMIFS_CONFIG:           /* 32 bits */
+       .word 0xfffecc0c
+REG_TC_EMIFS_CS0_CONFIG:       /* 32 bits */
+       .word 0xfffecc10
+REG_TC_EMIFS_CS1_CONFIG:       /* 32 bits */
+       .word 0xfffecc14
+REG_TC_EMIFS_CS2_CONFIG:       /* 32 bits */
+       .word 0xfffecc18
+REG_TC_EMIFS_CS3_CONFIG:       /* 32 bits */
+       .word 0xfffecc1c
+REG_TC_EMIFF_SDRAM_CONFIG:     /* 32 bits */
+       .word 0xfffecc20
+REG_TC_EMIFF_MRS:              /* 32 bits */
+       .word 0xfffecc24
+/* MPU clock/reset/power mode control registers */
+REG_ARM_CKCTL:                 /* 16 bits */
+       .word 0xfffece00
+REG_ARM_IDLECT2:               /* 16 bits */
+       .word 0xfffece08
+REG_ARM_RSTCT2:                        /* 16 bits */
+       .word 0xfffece14
+REG_ARM_SYSST:                 /* 16 bits */
+       .word 0xfffece18
+/* DPLL control registers */
+REG_DPLL1_CTL:                 /* 16 bits */
+       .word 0xfffecf00
+/* identification code register */
+REG_IDCODE:                    /* 32 bits */
+       .word 0xfffed404
+
+/* SX1 specific */
+_GPIO_PIN_CONTROL_REG:
+       .word GPIO_PIN_CONTROL_REG
+_GPIO_DIR_CONTROL_REG:
+       .word GPIO_DIR_CONTROL_REG
+_GPIO_DATA_OUTPUT_REG:
+       .word GPIO_DATA_OUTPUT_REG
+
+VAL_COMP_MODE_CTRL_0:
+       .word 0x0000eaef
+VAL_FUNC_MUX_CTRL_4:
+       .word 0x00000000
+VAL_FUNC_MUX_CTRL_5:
+       .word 0x00000000
+VAL_FUNC_MUX_CTRL_6:
+       .word 0x00000001
+VAL_FUNC_MUX_CTRL_7:
+       .word 0x00001000
+VAL_FUNC_MUX_CTRL_8:
+       .word 0x00001240       /*[Knoller]  Value of Symbian Image Wing B2*/
+VAL_FUNC_MUX_CTRL_9:
+       .word 0x00201008
+VAL_FUNC_MUX_CTRL_A:
+       .word 0x00001000
+VAL_FUNC_MUX_CTRL_B:
+       .word 0x00000000
+VAL_FUNC_MUX_CTRL_C:
+       .word 0x09008001       /*[Knoller]  Value of Symbian Image Wing B2*/
+VAL_FUNC_MUX_CTRL_D:
+       .word 0x00000000
+VAL_PULL_DWN_CTRL_0:
+       .word 0xfffeffff
+VAL_PULL_DWN_CTRL_1:
+       .word 0xd1ffffec
+VAL_PULL_DWN_CTRL_2:
+       .word 0xffa80c5b
+VAL_PULL_DWN_CTRL_3:
+       .word 0xffffc0fe
+VAL_VOLTAGE_CTRL_0:
+       .word 0x00000007
+VAL_TEST_DBG_CTRL_0:
+       /* The OMAP5910 TRM says this register must be 0, but HelenConfRegs
+        * says to write a 7.  Don't know what the right thing is to do, so
+        * I'm leaving it at 7 since that's what was already here.
+        */
+       .word 0x00000007
+VAL_MOD_CONF_CTRL_0:
+       .word 0x0da20000       /*[Knoller]  Value of Symbian Image Wing B2*/
+
+VAL_ARM_CKCTL:
+       .word 0x010D
+
+VAL_DPLL1_CTL:
+       .word 0x3A33   /*[Hertle] Value of Symbian Image*/
+
+VAL_TC_EMIFS_CS1_CONFIG_PRELIM:
+       .word 0x00001149
+
+VAL_TC_EMIFS_CS2_CONFIG_PRELIM:
+       .word 0x00004158
+
+VAL_TC_EMIFS_CS0_CONFIG:
+       .word 0x00213090       /*[Knoller]  Value of Symbian Image Wing B2*/
+
+VAL_TC_EMIFS_CS1_CONFIG:
+       .word 0x00215070       /*[Knoller]  Value of Symbian Image Wing B2*/
+
+VAL_TC_EMIFS_CS2_CONFIG:
+       .word 0x00001139       /*[Knoller]  Value of Symbian Image Wing B2*/
+
+VAL_TC_EMIFS_CS3_CONFIG:
+       .word 0x00001139       /*[Knoller]  Value of Symbian Image Wing B2*/
+
+VAL_TC_EMIFF_SDRAM_CONFIG:
+       .word 0x0105f0b4       /*[Knoller]  Value of Symbian Image Wing B2*/
+
+
+VAL_TC_EMIFF_MRS:
+       .word 0x00000027       /*[Knoller]  Value of Symbian Image Wing B2*/
diff --git a/board/sx1/sx1.c b/board/sx1/sx1.c
new file mode 100644 (file)
index 0000000..c14a385
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * (C) Copyright 2004
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+ *
+ * (C) Copyright 2003
+ * Texas Instruments, <www.ti.com>
+ * Kshitij Gupta <Kshitij@ti.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <common.h>
+
+static void flash__init (void);
+static void ether__init (void);
+
+static inline void delay (unsigned long loops)
+{
+       __asm__ volatile ("1:\n"
+                         "subs %0, %1, #1\n"
+                         "bne 1b":"=r" (loops):"0" (loops));
+}
+
+/*
+ * Miscellaneous platform dependent initialisations
+ */
+
+int board_init (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       /* arch number of SX1 Board */
+       gd->bd->bi_arch_number = 241;
+
+       /* adress of boot parameters */
+       gd->bd->bi_boot_params = 0x10000100;
+
+/* kk - this speeds up your boot a quite a bit.         However to make it
+ *  work, you need make sure your kernel startup flush bug is fixed.
+ *  ... rkw ...
+ */
+       icache_enable ();
+
+       flash__init ();
+       ether__init ();
+       return 0;
+}
+
+
+int misc_init_r (void)
+{
+       /* volatile ushort *gdir = (ushort *) (GPIO_DIR_CONTROL_REG); */
+       /* volatile ushort *mdir = (ushort *) (MPUIO_DIR_CONTROL_REG); */
+
+       /* setup gpio direction to match board (no floats!) */
+       /**gdir = 0xCFF9; */
+       /**mdir = 0x103F; */
+
+       return (0);
+}
+
+/******************************
+ Routine:
+ Description:
+******************************/
+static void flash__init (void)
+{
+#define CS0_CHIP_SELECT_REG 0xfffecc10
+#define CS3_CHIP_SELECT_REG 0xfffecc1c
+#define EMIFS_GlB_Config_REG 0xfffecc0c
+
+       unsigned int regval;
+
+       regval = *((volatile unsigned int *) EMIFS_GlB_Config_REG);
+       regval = regval | 0x0001;       /* Turn off write protection for flash devices. */
+       if (regval & 0x0002) {
+               regval = regval & 0xfffd;       /* Swap CS0 and CS3 so that flash is visible at 0x0 and eeprom at 0x0c000000. */
+               /* If, instead, you want to reference flash at 0x0c000000, then it seemed the following were necessary. */
+               /* *((volatile unsigned int *)CS0_CHIP_SELECT_REG) = 0x202090; / * Overrides head.S setting of 0x212090 */
+               /* *((volatile unsigned int *)CS3_CHIP_SELECT_REG) = 0x202090; / * Let's flash chips be fully functional. */
+       }
+       *((volatile unsigned int *) EMIFS_GlB_Config_REG) = regval;
+}
+
+
+/******************************
+ Routine:
+ Description:
+******************************/
+static void ether__init (void)
+{
+#define ETH_CONTROL_REG 0x0800000b
+       /* take the Ethernet controller out of reset and wait
+        * for the EEPROM load to complete.
+        */
+       *((volatile unsigned char *) ETH_CONTROL_REG) &= ~0x01;
+       udelay (3);
+}
+
+
+int dram_init (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+       gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
+
+       return 0;
+}
diff --git a/board/sx1/u-boot.lds b/board/sx1/u-boot.lds
new file mode 100644 (file)
index 0000000..670f4db
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * (C) Copyright 2004
+ * Wolfgang Denk, DENX Software Engineering, <wg@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+       . = 0x00000000;
+
+       . = ALIGN(4);
+       .text      :
+       {
+         cpu/arm925t/start.o   (.text)
+         *(.text)
+       }
+
+       . = ALIGN(4);
+       .rodata : { *(.rodata) }
+
+       . = ALIGN(4);
+       .data : { *(.data) }
+
+       . = ALIGN(4);
+       .got : { *(.got) }
+
+       __u_boot_cmd_start = .;
+       .u_boot_cmd : { *(.u_boot_cmd) }
+       __u_boot_cmd_end = .;
+
+       . = ALIGN(4);
+       __bss_start = .;
+       .bss : { *(.bss) }
+       _end = .;
+}
index eccb4e46f09cea0426a79b9f42b75c060d85db74..4c94fc03a172ece2715d516cd3cbbec532dca64a 100644 (file)
@@ -1,5 +1,5 @@
 #
-# (C) Copyright 2000, 2001
+# (C) Copyright 2004
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 #
 # See file CREDITS for list of people who contributed to this
@@ -12,7 +12,7 @@
 #
 # 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
+# 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
@@ -47,7 +47,7 @@ COBJS = main.o ACEX1K.o altera.o bedbug.o \
          hush.o kgdb.o lists.o lynxkdi.o memsize.o miiphybb.o miiphyutil.o \
          s_record.o soft_i2c.o soft_spi.o spartan2.o \
          usb.o usb_kbd.o usb_storage.o \
-         virtex2.o xilinx.o
+         virtex2.o xilinx.o circbuf.o
 
 OBJS   = $(AOBJS) $(COBJS)
 
@@ -55,7 +55,7 @@ CPPFLAGS += -I..
 
 all:   $(LIB) $(AOBJS)
 
-$(LIB):        .depend $(OBJS)
+$(LIB): .depend $(OBJS)
        $(AR) crv $@ $(OBJS)
 
 environment.o: environment.c ../tools/envcrc
diff --git a/common/circbuf.c b/common/circbuf.c
new file mode 100644 (file)
index 0000000..2332c63
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * (C) Copyright 2003
+ * Gerry Hamel, geh@ti.com, Texas Instruments
+ *
+ * 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 <common.h>
+#include <malloc.h>
+
+#include <circbuf.h>
+
+
+int buf_init (circbuf_t * buf, unsigned int size)
+{
+       assert (buf != NULL);
+
+       buf->size = 0;
+       buf->totalsize = size;
+       buf->data = (char *) malloc (sizeof (char) * size);
+       assert (buf->data != NULL);
+
+       buf->top = buf->data;
+       buf->tail = buf->data;
+       buf->end = &(buf->data[size]);
+
+       return 1;
+}
+
+int buf_free (circbuf_t * buf)
+{
+       assert (buf != NULL);
+       assert (buf->data != NULL);
+
+       free (buf->data);
+       memset (buf, 0, sizeof (circbuf_t));
+
+       return 1;
+}
+
+int buf_pop (circbuf_t * buf, char *dest, unsigned int len)
+{
+       unsigned int i;
+       char *p = buf->top;
+
+       assert (buf != NULL);
+       assert (dest != NULL);
+
+       /* Cap to number of bytes in buffer */
+       if (len > buf->size)
+               len = buf->size;
+
+       for (i = 0; i < len; i++) {
+               dest[i] = *p++;
+               /* Bounds check. */
+               if (p == buf->end) {
+                       p = buf->data;
+               }
+       }
+
+       /* Update 'top' pointer */
+       buf->top = p;
+       buf->size -= len;
+
+       return len;
+}
+
+int buf_push (circbuf_t * buf, const char *src, unsigned int len)
+{
+       /* NOTE:  this function allows push to overwrite old data. */
+       unsigned int i;
+       char *p = buf->tail;
+
+       assert (buf != NULL);
+       assert (src != NULL);
+
+       for (i = 0; i < len; i++) {
+               *p++ = src[i];
+               if (p == buf->end) {
+                       p = buf->data;
+               }
+               /* Make sure pushing too much data just replaces old data */
+               if (buf->size < buf->totalsize) {
+                       buf->size++;
+               } else {
+                       buf->top++;
+                       if (buf->top == buf->end) {
+                               buf->top = buf->data;
+                       }
+               }
+       }
+
+       /* Update 'tail' pointer */
+       buf->tail = p;
+
+       return len;
+}
index 702cab6dc66a0e627049ec621600cd860d453453..b85db69e131361c62267bbb7ed11bedbd2a806ac 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2000-2003
+ * (C) Copyright 2000-2004
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  *
  * See file CREDITS for list of people who contributed to this
@@ -104,8 +104,8 @@ int do_load_serial (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
         * box some time (100 * 1 ms)
         */
        for (i=0; i<100; ++i) {
-               if (serial_tstc()) {
-                       (void) serial_getc();
+               if (tstc()) {
+                       (void) getc();
                }
                udelay(1000);
        }
@@ -220,9 +220,9 @@ read_record (char *buf, ulong len)
        --len;  /* always leave room for terminating '\0' byte */
 
        for (p=buf; p < buf+len; ++p) {
-               c = serial_getc();              /* read character               */
+               c = getc();             /* read character               */
                if (do_echo)
-                       serial_putc (c);        /* ... and echo it              */
+                       putc (c);       /* ... and echo it              */
 
                switch (c) {
                case '\r':
@@ -237,7 +237,7 @@ read_record (char *buf, ulong len)
                }
 
            /* Check for the console hangup (if any different from serial) */
-           if (gd->jt[XF_getc] != serial_getc) {
+           if (gd->jt[XF_getc] != getc) {
                if (ctrlc()) {
                    return (-1);
                }
@@ -387,7 +387,7 @@ write_record (char *buf)
        char c;
 
        while((c = *buf++))
-               serial_putc(c);
+               putc(c);
 
        /* Check for the console hangup (if any different from serial) */
 
@@ -531,8 +531,8 @@ static ulong load_serial_bin (ulong offset)
         * box some time (100 * 1 ms)
         */
        for (i=0; i<100; ++i) {
-               if (serial_tstc()) {
-                       (void) serial_getc();
+               if (tstc()) {
+                       (void) getc();
                }
                udelay(1000);
        }
@@ -551,7 +551,7 @@ void send_pad (void)
        int count = his_pad_count;
 
        while (count-- > 0)
-               serial_putc (his_pad_char);
+               putc (his_pad_char);
 }
 
 /* converts escaped kermit char to binary char */
@@ -579,7 +579,7 @@ void s1_sendpacket (char *packet)
 {
        send_pad ();
        while (*packet) {
-               serial_putc (*packet++);
+               putc (*packet++);
        }
 }
 
@@ -841,7 +841,7 @@ static int k_recv (void)
                /* get a packet */
                /* wait for the starting character or ^C */
                for (;;) {
-                       switch (serial_getc ()) {
+                       switch (getc ()) {
                        case START_CHAR:        /* start packet */
                                goto START;
                        case ETX_CHAR:          /* ^C waiting for packet */
@@ -853,13 +853,13 @@ static int k_recv (void)
 START:
                /* get length of packet */
                sum = 0;
-               new_char = serial_getc ();
+               new_char = getc ();
                if ((new_char & 0xE0) == 0)
                        goto packet_error;
                sum += new_char & 0xff;
                length = untochar (new_char);
                /* get sequence number */
-               new_char = serial_getc ();
+               new_char = getc ();
                if ((new_char & 0xE0) == 0)
                        goto packet_error;
                sum += new_char & 0xff;
@@ -886,7 +886,7 @@ START:
                /* END NEW CODE */
 
                /* get packet type */
-               new_char = serial_getc ();
+               new_char = getc ();
                if ((new_char & 0xE0) == 0)
                        goto packet_error;
                sum += new_char & 0xff;
@@ -896,19 +896,19 @@ START:
                if (length == -2) {
                        /* (length byte was 0, decremented twice) */
                        /* get the two length bytes */
-                       new_char = serial_getc ();
+                       new_char = getc ();
                        if ((new_char & 0xE0) == 0)
                                goto packet_error;
                        sum += new_char & 0xff;
                        len_hi = untochar (new_char);
-                       new_char = serial_getc ();
+                       new_char = getc ();
                        if ((new_char & 0xE0) == 0)
                                goto packet_error;
                        sum += new_char & 0xff;
                        len_lo = untochar (new_char);
                        length = len_hi * 95 + len_lo;
                        /* check header checksum */
-                       new_char = serial_getc ();
+                       new_char = getc ();
                        if ((new_char & 0xE0) == 0)
                                goto packet_error;
                        if (new_char != tochar ((sum + ((sum >> 6) & 0x03)) & 0x3f))
@@ -918,7 +918,7 @@ START:
                }
                /* bring in rest of packet */
                while (length > 1) {
-                       new_char = serial_getc ();
+                       new_char = getc ();
                        if ((new_char & 0xE0) == 0)
                                goto packet_error;
                        sum += new_char & 0xff;
@@ -935,13 +935,13 @@ START:
                        }
                }
                /* get and validate checksum character */
-               new_char = serial_getc ();
+               new_char = getc ();
                if ((new_char & 0xE0) == 0)
                        goto packet_error;
                if (new_char != tochar ((sum + ((sum >> 6) & 0x03)) & 0x3f))
                        goto packet_error;
                /* get END_CHAR */
-               new_char = serial_getc ();
+               new_char = getc ();
                if (new_char != END_CHAR) {
                  packet_error:
                        /* restore state machines */
index bf7486ac44262d6b818b71555394c4ea691f41d6..aa055339e80e588bb561ef829fa4ebe9037e13e5 100644 (file)
@@ -194,6 +194,9 @@ int devices_init (void)
        drv_logbuff_init ();
 #endif
        drv_system_init ();
+#ifdef CONFIG_USB_TTY
+       drv_usbtty_init ();
+#endif
 
        return (0);
 }
index 00e8c18e1d83c254d64a0598053a4a90ea0a8fe5..d77c4e6f6778f6640ef0e411c8c4bd0d14f7de35 100644 (file)
@@ -23,7 +23,7 @@
  *
  * 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
+ * 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
@@ -107,15 +107,15 @@ void show_regs (struct pt_regs *regs)
 
        flags = condition_codes (regs);
 
-       printf ("pc : [<%08lx>]    lr : [<%08lx>]\n"
-               "sp : %08lx  ip : %08lx  fp : %08lx\n",
+       printf ("pc : [<%08lx>]    lr : [<%08lx>]\n"
+               "sp : %08lx  ip : %08lx  fp : %08lx\n",
                instruction_pointer (regs),
                regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
-       printf ("r10: %08lx  r9 : %08lx  r8 : %08lx\n",
+       printf ("r10: %08lx  r9 : %08lx  r8 : %08lx\n",
                regs->ARM_r10, regs->ARM_r9, regs->ARM_r8);
-       printf ("r7 : %08lx  r6 : %08lx  r5 : %08lx  r4 : %08lx\n",
+       printf ("r7 : %08lx  r6 : %08lx  r5 : %08lx  r4 : %08lx\n",
                regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4);
-       printf ("r3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n",
+       printf ("r3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n",
                regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0);
        printf ("Flags: %c%c%c%c",
                flags & CC_N_BIT ? 'N' : 'n',
@@ -227,17 +227,17 @@ void udelay (unsigned long usec)
 #else
        ulong tmo, tmp;
 
-       if(usec >= 1000){               /* if "big" number, spread normalization to seconds */
-               tmo = usec / 1000;      /* start to normalize for usec to ticks per sec */
-               tmo *= CFG_HZ;          /* find number of "ticks" to wait to achieve target */
-               tmo /= 1000;            /* finish normalize. */
-       }else{                          /* else small number, don't kill it prior to HZ multiply */
+       if(usec >= 1000){               /* if "big" number, spread normalization to seconds */
+               tmo = usec / 1000;      /* start to normalize for usec to ticks per sec */
+               tmo *= CFG_HZ;          /* find number of "ticks" to wait to achieve target */
+               tmo /= 1000;            /* finish normalize. */
+       }else{                          /* else small number, don't kill it prior to HZ multiply */
                tmo = usec * CFG_HZ;
                tmo /= (1000*1000);
        }
 
        tmp = get_timer (0);            /* get current timestamp */
-       if( (tmo + tmp + 1) < tmp )     /* if setting this fordward will roll time stamp */
+       if( (tmo + tmp + 1) < tmp )     /* if setting this fordward will roll time stamp */
                reset_timer_masked ();  /* reset "advancing" timestamp to 0, set lastdec value */
        else
                tmo += tmp;             /* else, set advancing stamp wake up time */
@@ -251,7 +251,7 @@ void reset_timer_masked (void)
 {
        /* reset time */
        lastdec = READ_TIMER;  /* capure current decrementer value time */
-       timestamp = 0;         /* start "advancing" time stamp from 0 */
+       timestamp = 0;         /* start "advancing" time stamp from 0 */
 }
 
 ulong get_timer_masked (void)
@@ -283,13 +283,13 @@ void udelay_masked (unsigned long usec)
     for (i=time_remaining; i>0; i--) { }
 #else
 
-       ulong tmo, tmp;
+       ulong tmo;
 
-       if(usec >= 1000){               /* if "big" number, spread normalization to seconds */
-               tmo = usec / 1000;      /* start to normalize for usec to ticks per sec */
-               tmo *= CFG_HZ;          /* find number of "ticks" to wait to achieve target */
-               tmo /= 1000;            /* finish normalize. */
-       }else{                          /* else small number, don't kill it prior to HZ multiply */
+       if(usec >= 1000){               /* if "big" number, spread normalization to seconds */
+               tmo = usec / 1000;      /* start to normalize for usec to ticks per sec */
+               tmo *= CFG_HZ;          /* find number of "ticks" to wait to achieve target */
+               tmo /= 1000;            /* finish normalize. */
+       }else{                          /* else small number, don't kill it prior to HZ multiply */
                tmo = usec * CFG_HZ;
                tmo /= (1000*1000);
        }
index b333aed678658c16a26261393d6f8056c9edc23a..32a6a0607e642b560173f4fa0b9e3745ada04ea4 100644 (file)
@@ -1,5 +1,5 @@
 #
-# (C) Copyright 2000
+# (C) Copyright 2000-2004
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 #
 # See file CREDITS for list of people who contributed to this
@@ -12,7 +12,7 @@
 #
 # 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
+# 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
@@ -29,7 +29,7 @@ LIB   = libdrivers.a
 
 OBJS   = 3c589.o 5701rls.o ali512x.o \
          bcm570x.o bcm570x_autoneg.o cfb_console.o cfi_flash.o \
-         cs8900.o ct69000.o dataflash.o dc2114x.o          \
+         cs8900.o ct69000.o dataflash.o dc2114x.o          \
          e1000.o eepro100.o \
          i8042.o i82365.o inca-ip_sw.o \
          lan91c96.o natsemi.o netarm_eth.o \
@@ -40,11 +40,12 @@ OBJS        = 3c589.o 5701rls.o ali512x.o \
          rtl8019.o rtl8139.o \
          s3c24x0_i2c.o sed13806.o serial.o serial_max3100.o \
          smc91111.o smiLynxEM.o status_led.o sym53c8xx.o \
-         ti_pci1410a.o tigon3.o w83c553f.o
+         ti_pci1410a.o tigon3.o w83c553f.o omap1510_i2c.o \
+         usbdcore.o usbdcore_ep0.o usbdcore_omap1510.o usbtty.o
 
 all:   $(LIB)
 
-$(LIB):        $(OBJS)
+$(LIB): $(OBJS)
        $(AR) crv $@ $(OBJS)
 
 #########################################################################
index a7aa40ff3251493567d7354143b849bbda96d78a..05862ee6ec65dadededacf8531c66ee7786d6767 100644 (file)
@@ -18,7 +18,7 @@ void NS16550_init (NS16550_t com_port, int baud_divisor)
 {
        com_port->ier = 0x00;
 #ifdef CONFIG_OMAP1510
-       com_port->mdr1 = 0x7;   /* mode select reset TL16C750*/
+       com_port->mdr1 = 0x7;   /* mode select reset TL16C750*/
 #endif
        com_port->lcr = LCR_BKSE | LCRVAL;
        com_port->dll = baud_divisor & 0xff;
@@ -50,7 +50,12 @@ void NS16550_putc (NS16550_t com_port, char c)
 
 char NS16550_getc (NS16550_t com_port)
 {
-       while ((com_port->lsr & LSR_DR) == 0);
+       while ((com_port->lsr & LSR_DR) == 0) {
+#ifdef CONFIG_USB_TTY
+               extern void usbtty_poll(void);
+               usbtty_poll();
+#endif
+       }
        return (com_port->rbr);
 }
 
diff --git a/drivers/omap1510_i2c.c b/drivers/omap1510_i2c.c
new file mode 100644 (file)
index 0000000..04400fb
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * Basic I2C functions
+ *
+ * Copyright (c) 2003 Texas Instruments
+ *
+ * This package is free software;  you can redistribute it and/or
+ * modify it under the terms of the license found in the file
+ * named COPYING that should have accompanied this file.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author: Jian Zhang jzhang@ti.com, Texas Instruments
+ *
+ * Copyright (c) 2003 Wolfgang Denk, wd@denx.de
+ * Rewritten to fit into the current U-Boot framework
+ *
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_DRIVER_OMAP1510_I2C
+
+static void wait_for_bb (void);
+static u16 wait_for_pin (void);
+
+void i2c_init (int speed, int slaveadd)
+{
+       u16 scl;
+
+       if (inw (I2C_CON) & I2C_CON_EN) {
+               outw (0, I2C_CON);
+               udelay (5000);
+       }
+
+       /* 12Mhz I2C module clock */
+       outw (0, I2C_PSC);
+       outw (I2C_CON_EN, I2C_CON);
+       outw (0, I2C_SYSTEST);
+       /* have to enable intrrupts or OMAP i2c module doesn't work */
+       outw (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE |
+             I2C_IE_NACK_IE | I2C_IE_AL_IE, I2C_IE);
+       scl = (12000000 / 2) / speed - 6;
+       outw (scl, I2C_SCLL);
+       outw (scl, I2C_SCLH);
+       /* own address */
+       outw (slaveadd, I2C_OA);
+       outw (0, I2C_CNT);
+       udelay (1000);
+}
+
+static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
+{
+       int i2c_error = 0;
+       u16 status;
+
+       /* wait until bus not busy */
+       wait_for_bb ();
+
+       /* one byte only */
+       outw (1, I2C_CNT);
+       /* set slave address */
+       outw (devaddr, I2C_SA);
+       /* no stop bit needed here */
+       outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, I2C_CON);
+
+       status = wait_for_pin ();
+
+       if (status & I2C_STAT_XRDY) {
+               /* Important: have to use byte access */
+               *(volatile u8 *) (I2C_DATA) = regoffset;
+               udelay (20000);
+               if (inw (I2C_STAT) & I2C_STAT_NACK) {
+                       i2c_error = 1;
+               }
+       } else {
+               i2c_error = 1;
+       }
+
+       if (!i2c_error) {
+               /* free bus, otherwise we can't use a combined transction */
+               outw (0, I2C_CON);
+               while (inw (I2C_STAT) || (inw (I2C_CON) & I2C_CON_MST)) {
+                       udelay (10000);
+                       /* Have to clear pending interrupt to clear I2C_STAT */
+                       inw (I2C_IV);
+               }
+
+               wait_for_bb ();
+               /* set slave address */
+               outw (devaddr, I2C_SA);
+               /* read one byte from slave */
+               outw (1, I2C_CNT);
+               /* need stop bit here */
+               outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP,
+                     I2C_CON);
+
+               status = wait_for_pin ();
+               if (status & I2C_STAT_RRDY) {
+                       *value = inw (I2C_DATA);
+                       udelay (20000);
+               } else {
+                       i2c_error = 1;
+               }
+
+               if (!i2c_error) {
+                       outw (I2C_CON_EN, I2C_CON);
+                       while (inw (I2C_STAT)
+                              || (inw (I2C_CON) & I2C_CON_MST)) {
+                               udelay (10000);
+                               inw (I2C_IV);
+                       }
+               }
+       }
+
+       return i2c_error;
+}
+
+static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value)
+{
+       int i2c_error = 0;
+       u16 status;
+
+       /* wait until bus not busy */
+       wait_for_bb ();
+
+       /* two bytes */
+       outw (2, I2C_CNT);
+       /* set slave address */
+       outw (devaddr, I2C_SA);
+       /* stop bit needed here */
+       outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
+             I2C_CON_STP, I2C_CON);
+
+       /* wait until state change */
+       status = wait_for_pin ();
+
+       if (status & I2C_STAT_XRDY) {
+               /* send out two bytes */
+               outw ((value << 8) + regoffset, I2C_DATA);
+               /* must have enough delay to allow BB bit to go low */
+               udelay (30000);
+               if (inw (I2C_STAT) & I2C_STAT_NACK) {
+                       i2c_error = 1;
+               }
+       } else {
+               i2c_error = 1;
+       }
+
+       if (!i2c_error) {
+               outw (I2C_CON_EN, I2C_CON);
+               while (inw (I2C_STAT) || (inw (I2C_CON) & I2C_CON_MST)) {
+                       udelay (1000);
+                       /* have to read to clear intrrupt */
+                       inw (I2C_IV);
+               }
+       }
+
+       return i2c_error;
+}
+
+int i2c_probe (uchar chip)
+{
+       int res = 1;
+
+       if (chip == inw (I2C_OA)) {
+               return res;
+       }
+
+       /* wait until bus not busy */
+       wait_for_bb ();
+
+       /* try to read one byte */
+       outw (1, I2C_CNT);
+       /* set slave address */
+       outw (chip, I2C_SA);
+       /* stop bit needed here */
+       outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, I2C_CON);
+       /* enough delay for the NACK bit set */
+       udelay (2000);
+       if (!(inw (I2C_STAT) & I2C_STAT_NACK)) {
+               res = 0;
+       } else {
+               outw (inw (I2C_CON) | I2C_CON_STP, I2C_CON);
+               udelay (20);
+               wait_for_bb ();
+       }
+
+       return res;
+}
+
+int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
+{
+       int i;
+
+       if (alen > 1) {
+               printf ("I2C read: addr len %d not supported\n", alen);
+               return 1;
+       }
+
+       if (addr + len > 256) {
+               printf ("I2C read: address out of range\n");
+               return 1;
+       }
+
+       for (i = 0; i < len; i++) {
+               if (i2c_read_byte (chip, addr + i, &buffer[i])) {
+                       printf ("I2C read: I/O error\n");
+                       i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
+{
+       int i;
+
+       if (alen > 1) {
+               printf ("I2C read: addr len %d not supported\n", alen);
+               return 1;
+       }
+
+       if (addr + len > 256) {
+               printf ("I2C read: address out of range\n");
+               return 1;
+       }
+
+       for (i = 0; i < len; i++) {
+               if (i2c_write_byte (chip, addr + i, buffer[i])) {
+                       printf ("I2C read: I/O error\n");
+                       i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+static void wait_for_bb (void)
+{
+       int timeout = 10;
+
+       while ((inw (I2C_STAT) & I2C_STAT_BB) && timeout--) {
+               inw (I2C_IV);
+               udelay (1000);
+       }
+
+       if (timeout <= 0) {
+               printf ("timed out in wait_for_bb: I2C_STAT=%x\n",
+                       inw (I2C_STAT));
+       }
+}
+
+static u16 wait_for_pin (void)
+{
+       u16 status, iv;
+       int timeout = 10;
+
+       do {
+               udelay (1000);
+               status = inw (I2C_STAT);
+               iv = inw (I2C_IV);
+       } while (!iv &&
+                !(status &
+                  (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
+                   I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
+                   I2C_STAT_AL)) && timeout--);
+
+       if (timeout <= 0) {
+               printf ("timed out in wait_for_pin: I2C_STAT=%x\n",
+                       inw (I2C_STAT));
+       }
+
+       return status;
+}
+
+#endif /* CONFIG_DRIVER_OMAP1510_I2C */
diff --git a/drivers/usbdcore.c b/drivers/usbdcore.c
new file mode 100644 (file)
index 0000000..308c7ce
--- /dev/null
@@ -0,0 +1,684 @@
+/*
+ * (C) Copyright 2003
+ * Gerry Hamel, geh@ti.com, Texas Instruments
+ *
+ * Based on
+ * linux/drivers/usbd/usbd.c.c - USB Device Core Layer
+ *
+ * Copyright (c) 2000, 2001, 2002 Lineo
+ * Copyright (c) 2001 Hewlett Packard
+ *
+ * By:
+ *     Stuart Lynne <sl@lineo.com>,
+ *     Tom Rushworth <tbr@lineo.com>,
+ *     Bruce Balden <balden@lineo.com>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <malloc.h>
+#include "usbdcore.h"
+
+#define MAX_INTERFACES 2
+
+
+int maxstrings = 20;
+
+/* Global variables ************************************************************************** */
+
+struct usb_string_descriptor **usb_strings;
+
+int usb_devices;
+
+extern struct usb_function_driver ep0_driver;
+
+int registered_functions;
+int registered_devices;
+
+char *usbd_device_events[] = {
+       "DEVICE_UNKNOWN",
+       "DEVICE_INIT",
+       "DEVICE_CREATE",
+       "DEVICE_HUB_CONFIGURED",
+       "DEVICE_RESET",
+       "DEVICE_ADDRESS_ASSIGNED",
+       "DEVICE_CONFIGURED",
+       "DEVICE_SET_INTERFACE",
+       "DEVICE_SET_FEATURE",
+       "DEVICE_CLEAR_FEATURE",
+       "DEVICE_DE_CONFIGURED",
+       "DEVICE_BUS_INACTIVE",
+       "DEVICE_BUS_ACTIVITY",
+       "DEVICE_POWER_INTERRUPTION",
+       "DEVICE_HUB_RESET",
+       "DEVICE_DESTROY",
+       "DEVICE_FUNCTION_PRIVATE",
+};
+
+char *usbd_device_states[] = {
+       "STATE_INIT",
+       "STATE_CREATED",
+       "STATE_ATTACHED",
+       "STATE_POWERED",
+       "STATE_DEFAULT",
+       "STATE_ADDRESSED",
+       "STATE_CONFIGURED",
+       "STATE_UNKNOWN",
+};
+
+char *usbd_device_requests[] = {
+       "GET STATUS",           /* 0 */
+       "CLEAR FEATURE",        /* 1 */
+       "RESERVED",             /* 2 */
+       "SET FEATURE",          /* 3 */
+       "RESERVED",             /* 4 */
+       "SET ADDRESS",          /* 5 */
+       "GET DESCRIPTOR",       /* 6 */
+       "SET DESCRIPTOR",       /* 7 */
+       "GET CONFIGURATION",    /* 8 */
+       "SET CONFIGURATION",    /* 9 */
+       "GET INTERFACE",        /* 10 */
+       "SET INTERFACE",        /* 11 */
+       "SYNC FRAME",           /* 12 */
+};
+
+char *usbd_device_descriptors[] = {
+       "UNKNOWN",              /* 0 */
+       "DEVICE",               /* 1 */
+       "CONFIG",               /* 2 */
+       "STRING",               /* 3 */
+       "INTERFACE",            /* 4 */
+       "ENDPOINT",             /* 5 */
+       "DEVICE QUALIFIER",     /* 6 */
+       "OTHER SPEED",          /* 7 */
+       "INTERFACE POWER",      /* 8 */
+};
+
+char *usbd_device_status[] = {
+       "USBD_OPENING",
+       "USBD_OK",
+       "USBD_SUSPENDED",
+       "USBD_CLOSING",
+};
+
+
+/* Descriptor support functions ************************************************************** */
+
+
+/**
+ * usbd_get_string - find and return a string descriptor
+ * @index: string index to return
+ *
+ * Find an indexed string and return a pointer to a it.
+ */
+struct usb_string_descriptor *usbd_get_string (__u8 index)
+{
+       if (index >= maxstrings) {
+               return NULL;
+       }
+       return usb_strings[index];
+}
+
+
+/* Access to device descriptor functions ***************************************************** */
+
+
+/* *
+ * usbd_device_configuration_instance - find a configuration instance for this device
+ * @device:
+ * @configuration: index to configuration, 0 - N-1
+ *
+ * Get specifed device configuration. Index should be bConfigurationValue-1.
+ */
+static struct usb_configuration_instance *usbd_device_configuration_instance (struct usb_device_instance *device,
+               unsigned int port, unsigned int configuration)
+{
+       /* XXX */
+       configuration = configuration ? configuration - 1 : 0;
+
+       if (configuration >= device->configurations) {
+               return NULL;
+       }
+       return device->configuration_instance_array + configuration;
+}
+
+
+/* *
+ * usbd_device_interface_instance
+ * @device:
+ * @configuration: index to configuration, 0 - N-1
+ * @interface: index to interface
+ *
+ * Return the specified interface descriptor for the specified device.
+ */
+struct usb_interface_instance *usbd_device_interface_instance (struct usb_device_instance *device, int port, int configuration, int interface)
+{
+       struct usb_configuration_instance *configuration_instance;
+
+       if ((configuration_instance = usbd_device_configuration_instance (device, port, configuration)) == NULL) {
+               return NULL;
+       }
+       if (interface >= configuration_instance->interfaces) {
+               return NULL;
+       }
+       return configuration_instance->interface_instance_array + interface;
+}
+
+/* *
+ * usbd_device_alternate_descriptor_list
+ * @device:
+ * @configuration: index to configuration, 0 - N-1
+ * @interface: index to interface
+ * @alternate: alternate setting
+ *
+ * Return the specified alternate descriptor for the specified device.
+ */
+struct usb_alternate_instance *usbd_device_alternate_instance (struct usb_device_instance *device, int port, int configuration, int interface, int alternate)
+{
+       struct usb_interface_instance *interface_instance;
+
+       if ((interface_instance = usbd_device_interface_instance (device, port, configuration, interface)) == NULL) {
+               return NULL;
+       }
+
+       if (alternate >= interface_instance->alternates) {
+               return NULL;
+       }
+
+       return interface_instance->alternates_instance_array + alternate;
+}
+
+
+/* *
+ * usbd_device_device_descriptor
+ * @device: which device
+ * @configuration: index to configuration, 0 - N-1
+ * @port: which port
+ *
+ * Return the specified configuration descriptor for the specified device.
+ */
+struct usb_device_descriptor *usbd_device_device_descriptor (struct usb_device_instance *device, int port)
+{
+       return (device->device_descriptor);
+}
+
+
+/**
+ * usbd_device_configuration_descriptor
+ * @device: which device
+ * @port: which port
+ * @configuration: index to configuration, 0 - N-1
+ *
+ * Return the specified configuration descriptor for the specified device.
+ */
+struct usb_configuration_descriptor *usbd_device_configuration_descriptor (struct
+                                                                          usb_device_instance
+                                                                          *device, int port, int configuration)
+{
+       struct usb_configuration_instance *configuration_instance;
+       if (!(configuration_instance = usbd_device_configuration_instance (device, port, configuration))) {
+               return NULL;
+       }
+       return (configuration_instance->configuration_descriptor);
+}
+
+
+/**
+ * usbd_device_interface_descriptor
+ * @device: which device
+ * @port: which port
+ * @configuration: index to configuration, 0 - N-1
+ * @interface: index to interface
+ * @alternate: alternate setting
+ *
+ * Return the specified interface descriptor for the specified device.
+ */
+struct usb_interface_descriptor *usbd_device_interface_descriptor (struct usb_device_instance
+                                                                  *device, int port, int configuration, int interface, int alternate)
+{
+       struct usb_interface_instance *interface_instance;
+       if (!(interface_instance = usbd_device_interface_instance (device, port, configuration, interface))) {
+               return NULL;
+       }
+       if ((alternate < 0) || (alternate >= interface_instance->alternates)) {
+               return NULL;
+       }
+       return (interface_instance->alternates_instance_array[alternate].interface_descriptor);
+}
+
+/**
+ * usbd_device_endpoint_descriptor_index
+ * @device: which device
+ * @port: which port
+ * @configuration: index to configuration, 0 - N-1
+ * @interface: index to interface
+ * @alternate: index setting
+ * @index: which index
+ *
+ * Return the specified endpoint descriptor for the specified device.
+ */
+struct usb_endpoint_descriptor *usbd_device_endpoint_descriptor_index (struct usb_device_instance
+                                                                      *device, int port, int configuration, int interface, int alternate, int index)
+{
+       struct usb_alternate_instance *alternate_instance;
+
+       if (!(alternate_instance = usbd_device_alternate_instance (device, port, configuration, interface, alternate))) {
+               return NULL;
+       }
+       if (index >= alternate_instance->endpoints) {
+               return NULL;
+       }
+       return *(alternate_instance->endpoints_descriptor_array + index);
+}
+
+
+/**
+ * usbd_device_endpoint_transfersize
+ * @device: which device
+ * @port: which port
+ * @configuration: index to configuration, 0 - N-1
+ * @interface: index to interface
+ * @index: which index
+ *
+ * Return the specified endpoint transfer size;
+ */
+int usbd_device_endpoint_transfersize (struct usb_device_instance *device, int port, int configuration, int interface, int alternate, int index)
+{
+       struct usb_alternate_instance *alternate_instance;
+
+       if (!(alternate_instance = usbd_device_alternate_instance (device, port, configuration, interface, alternate))) {
+               return 0;
+       }
+       if (index >= alternate_instance->endpoints) {
+               return 0;
+       }
+       return *(alternate_instance->endpoint_transfersize_array + index);
+}
+
+
+/**
+ * usbd_device_endpoint_descriptor
+ * @device: which device
+ * @port: which port
+ * @configuration: index to configuration, 0 - N-1
+ * @interface: index to interface
+ * @alternate: alternate setting
+ * @endpoint: which endpoint
+ *
+ * Return the specified endpoint descriptor for the specified device.
+ */
+struct usb_endpoint_descriptor *usbd_device_endpoint_descriptor (struct usb_device_instance *device, int port, int configuration, int interface, int alternate, int endpoint)
+{
+       struct usb_endpoint_descriptor *endpoint_descriptor;
+       int i;
+
+       for (i = 0; !(endpoint_descriptor = usbd_device_endpoint_descriptor_index (device, port, configuration, interface, alternate, i)); i++) {
+               if (endpoint_descriptor->bEndpointAddress == endpoint) {
+                       return endpoint_descriptor;
+               }
+       }
+       return NULL;
+}
+
+/**
+ * usbd_endpoint_halted
+ * @device: point to struct usb_device_instance
+ * @endpoint: endpoint to check
+ *
+ * Return non-zero if endpoint is halted.
+ */
+int usbd_endpoint_halted (struct usb_device_instance *device, int endpoint)
+{
+       return (device->status == USB_STATUS_HALT);
+}
+
+
+/**
+ * usbd_rcv_complete - complete a receive
+ * @endpoint:
+ * @len:
+ * @urb_bad:
+ *
+ * Called from rcv interrupt to complete.
+ */
+void usbd_rcv_complete(struct usb_endpoint_instance *endpoint, int len, int urb_bad)
+{
+       if (endpoint) {
+               struct urb *rcv_urb;
+
+               /*usbdbg("len: %d urb: %p\n", len, endpoint->rcv_urb); */
+
+               /* if we had an urb then update actual_length, dispatch if neccessary */
+               if ((rcv_urb = endpoint->rcv_urb)) {
+
+                       /*usbdbg("actual: %d buffer: %d\n", */
+                       /*rcv_urb->actual_length, rcv_urb->buffer_length); */
+
+                       /* check the urb is ok, are we adding data less than the packetsize */
+                       if (!urb_bad && (len <= endpoint->rcv_packetSize)) {
+                         /*usbdbg("updating actual_length by %d\n",len); */
+
+                               /* increment the received data size */
+                               rcv_urb->actual_length += len;
+
+                       } else {
+                               usberr(" RECV_ERROR actual: %d buffer: %d urb_bad: %d\n",
+                                      rcv_urb->actual_length, rcv_urb->buffer_length, urb_bad);
+
+                               rcv_urb->actual_length = 0;
+                               rcv_urb->status = RECV_ERROR;
+                       }
+               } else {
+                       usberr("no rcv_urb!");
+               }
+       } else {
+               usberr("no endpoint!");
+       }
+
+}
+
+/**
+ * usbd_tx_complete - complete a transmit
+ * @endpoint:
+ * @resetart:
+ *
+ * Called from tx interrupt to complete.
+ */
+void usbd_tx_complete (struct usb_endpoint_instance *endpoint)
+{
+       if (endpoint) {
+               struct urb *tx_urb;
+
+               /* if we have a tx_urb advance or reset, finish if complete */
+               if ((tx_urb = endpoint->tx_urb)) {
+                       int sent = endpoint->last;
+                       endpoint->sent += sent;
+                       endpoint->last -= sent;
+
+                       if( (endpoint->tx_urb->actual_length - endpoint->sent) <= 0 ) {
+                               tx_urb->actual_length = 0;
+                               endpoint->sent = 0;
+                               endpoint->last = 0;
+
+                               /* Remove from active, save for re-use */
+                               urb_detach(tx_urb);
+                               urb_append(&endpoint->done, tx_urb);
+                               /*usbdbg("done->next %p, tx_urb %p, done %p", */
+                               /*       endpoint->done.next, tx_urb, &endpoint->done); */
+
+                               endpoint->tx_urb = first_urb_detached(&endpoint->tx);
+                               if( endpoint->tx_urb ) {
+                                       endpoint->tx_queue--;
+                                       usbdbg("got urb from tx list");
+                               }
+                               if( !endpoint->tx_urb ) {
+                                       /*usbdbg("taking urb from done list"); */
+                                       endpoint->tx_urb = first_urb_detached(&endpoint->done);
+                               }
+                               if( !endpoint->tx_urb ) {
+                                       usbdbg("allocating new urb for tx_urb");
+                                       endpoint->tx_urb = usbd_alloc_urb(tx_urb->device, endpoint);
+                               }
+                       }
+               }
+       }
+}
+
+/* URB linked list functions ***************************************************** */
+
+/*
+ * Initialize an urb_link to be a single element list.
+ * If the urb_link is being used as a distinguished list head
+ * the list is empty when the head is the only link in the list.
+ */
+void urb_link_init (urb_link * ul)
+{
+       if (ul) {
+               ul->prev = ul->next = ul;
+       }
+}
+
+/*
+ * Detach an urb_link from a list, and set it
+ * up as a single element list, so no dangling
+ * pointers can be followed, and so it can be
+ * joined to another list if so desired.
+ */
+void urb_detach (struct urb *urb)
+{
+       if (urb) {
+               urb_link *ul = &urb->link;
+               ul->next->prev = ul->prev;
+               ul->prev->next = ul->next;
+               urb_link_init (ul);
+       }
+}
+
+/*
+ * Return the first urb_link in a list with a distinguished
+ * head "hd", or NULL if the list is empty.  This will also
+ * work as a predicate, returning NULL if empty, and non-NULL
+ * otherwise.
+ */
+urb_link *first_urb_link (urb_link * hd)
+{
+       urb_link *nx;
+       if (NULL != hd && NULL != (nx = hd->next) && nx != hd) {
+               /* There is at least one element in the list */
+               /* (besides the distinguished head). */
+               return (nx);
+       }
+       /* The list is empty */
+       return (NULL);
+}
+
+/*
+ * Return the first urb in a list with a distinguished
+ * head "hd", or NULL if the list is empty.
+ */
+struct urb *first_urb (urb_link * hd)
+{
+       urb_link *nx;
+       if (NULL == (nx = first_urb_link (hd))) {
+               /* The list is empty */
+               return (NULL);
+       }
+       return (p2surround (struct urb, link, nx));
+}
+
+/*
+ * Detach and return the first urb in a list with a distinguished
+ * head "hd", or NULL if the list is empty.
+ *
+ */
+struct urb *first_urb_detached (urb_link * hd)
+{
+       struct urb *urb;
+       if ((urb = first_urb (hd))) {
+               urb_detach (urb);
+       }
+       return urb;
+}
+
+
+/*
+ * Append an urb_link (or a whole list of
+ * urb_links) to the tail of another list
+ * of urb_links.
+ */
+void urb_append (urb_link * hd, struct urb *urb)
+{
+       if (hd && urb) {
+               urb_link *new = &urb->link;
+
+               /* This allows the new urb to be a list of urbs, */
+               /* with new pointing at the first, but the link */
+               /* must be initialized. */
+               /* Order is important here... */
+               urb_link *pul = hd->prev;
+               new->prev->next = hd;
+               hd->prev = new->prev;
+               new->prev = pul;
+               pul->next = new;
+       }
+}
+
+/* URB create/destroy functions ***************************************************** */
+
+/**
+ * usbd_alloc_urb - allocate an URB appropriate for specified endpoint
+ * @device: device instance
+ * @endpoint: endpoint
+ *
+ * Allocate an urb structure. The usb device urb structure is used to
+ * contain all data associated with a transfer, including a setup packet for
+ * control transfers.
+ *
+ * NOTE: endpoint_address MUST contain a direction flag.
+ */
+struct urb *usbd_alloc_urb (struct usb_device_instance *device, struct usb_endpoint_instance *endpoint)
+{
+       struct urb *urb;
+
+       if( !(urb = (struct urb*)malloc(sizeof(struct urb))) ) {
+         usberr(" F A T A L:  malloc(%u) FAILED!!!!", sizeof(struct urb));
+         return NULL;
+       }
+
+       /* Fill in known fields */
+       memset(urb, 0, sizeof(struct urb));
+       urb->endpoint = endpoint;
+       urb->device = device;
+       urb->buffer = (u8*)urb->buffer_data;
+       urb->buffer_length = sizeof(urb->buffer_data);
+
+       urb_link_init (&urb->link);
+
+       return urb;
+}
+
+/**
+ * usbd_dealloc_urb - deallocate an URB and associated buffer
+ * @urb: pointer to an urb structure
+ *
+ * Deallocate an urb structure and associated data.
+ */
+void usbd_dealloc_urb (struct urb *urb)
+{
+       if (urb) {
+               free (urb);
+       }
+}
+
+/* Event signaling functions ***************************************************** */
+
+/**
+ * usbd_device_event - called to respond to various usb events
+ * @device: pointer to struct device
+ * @event: event to respond to
+ *
+ * Used by a Bus driver to indicate an event.
+ */
+void usbd_device_event_irq (struct usb_device_instance *device, usb_device_event_t event, int data)
+{
+       usb_device_state_t state;
+
+       if (!device || !device->bus) {
+               usberr("(%p,%d) NULL device or device->bus", device, event);
+               return;
+       }
+
+       state = device->device_state;
+
+       usbinfo("%s", usbd_device_events[event]);
+
+       switch (event) {
+       case DEVICE_UNKNOWN:
+               break;
+       case DEVICE_INIT:
+               device->device_state = STATE_INIT;
+               break;
+
+       case DEVICE_CREATE:
+               device->device_state = STATE_ATTACHED;
+               break;
+
+       case DEVICE_HUB_CONFIGURED:
+               device->device_state = STATE_POWERED;
+               break;
+
+       case DEVICE_RESET:
+               device->device_state = STATE_DEFAULT;
+               device->address = 0;
+               break;
+
+       case DEVICE_ADDRESS_ASSIGNED:
+               device->device_state = STATE_ADDRESSED;
+               break;
+
+       case DEVICE_CONFIGURED:
+               device->device_state = STATE_CONFIGURED;
+               break;
+
+       case DEVICE_DE_CONFIGURED:
+               device->device_state = STATE_ADDRESSED;
+               break;
+
+       case DEVICE_BUS_INACTIVE:
+               if (device->status != USBD_CLOSING) {
+                       device->status = USBD_SUSPENDED;
+               }
+               break;
+       case DEVICE_BUS_ACTIVITY:
+               if (device->status != USBD_CLOSING) {
+                       device->status = USBD_OK;
+               }
+               break;
+
+       case DEVICE_SET_INTERFACE:
+               break;
+       case DEVICE_SET_FEATURE:
+               break;
+       case DEVICE_CLEAR_FEATURE:
+               break;
+
+       case DEVICE_POWER_INTERRUPTION:
+               device->device_state = STATE_POWERED;
+               break;
+       case DEVICE_HUB_RESET:
+               device->device_state = STATE_ATTACHED;
+               break;
+       case DEVICE_DESTROY:
+               device->device_state = STATE_UNKNOWN;
+               break;
+
+       case DEVICE_FUNCTION_PRIVATE:
+               break;
+
+       default:
+               usbdbg("event %d - not handled",event);
+               break;
+       }
+       /*usbdbg("%s event: %d oldstate: %d newstate: %d status: %d address: %d",
+               device->name, event, state,
+               device->device_state, device->status, device->address); */
+
+       /* tell the bus interface driver */
+       if( device->event ) {
+               /* usbdbg("calling device->event"); */
+               device->event(device, event, data);
+       }
+}
diff --git a/drivers/usbdcore_ep0.c b/drivers/usbdcore_ep0.c
new file mode 100644 (file)
index 0000000..260befe
--- /dev/null
@@ -0,0 +1,686 @@
+/*
+ * (C) Copyright 2003
+ * Gerry Hamel, geh@ti.com, Texas Instruments
+ *
+ * Based on
+ * linux/drivers/usbd/ep0.c
+ *
+ * Copyright (c) 2000, 2001, 2002 Lineo
+ * Copyright (c) 2001 Hewlett Packard
+ *
+ * By:
+ *     Stuart Lynne <sl@lineo.com>,
+ *     Tom Rushworth <tbr@lineo.com>,
+ *     Bruce Balden <balden@lineo.com>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ * This is the builtin ep0 control function. It implements all required functionality
+ * for responding to control requests (SETUP packets).
+ *
+ * XXX
+ *
+ * Currently we do not pass any SETUP packets (or other) to the configured
+ * function driver. This may need to change.
+ *
+ * XXX
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_OMAP1510) && defined(CONFIG_USB_DEVICE)
+#include "usbdcore.h"
+
+#if 0
+#define dbg_ep0(lvl,fmt,args...) serial_printf("[%s] %s:%d: "fmt"\n",__FILE__,__FUNCTION__,__LINE__,##args)
+#else
+#define dbg_ep0(lvl,fmt,args...)
+#endif
+
+/* EP0 Configuration Set ********************************************************************* */
+
+
+/**
+ * ep0_get_status - fill in URB data with appropriate status
+ * @device:
+ * @urb:
+ * @index:
+ * @requesttype:
+ *
+ */
+static int ep0_get_status (struct usb_device_instance *device,
+                          struct urb *urb, int index, int requesttype)
+{
+       char *cp;
+
+       urb->actual_length = 2;
+       cp = urb->buffer;
+       cp[0] = cp[1] = 0;
+
+       switch (requesttype) {
+       case USB_REQ_RECIPIENT_DEVICE:
+               cp[0] = USB_STATUS_SELFPOWERED;
+               break;
+       case USB_REQ_RECIPIENT_INTERFACE:
+               break;
+       case USB_REQ_RECIPIENT_ENDPOINT:
+               cp[0] = usbd_endpoint_halted (device, index);
+               break;
+       case USB_REQ_RECIPIENT_OTHER:
+               urb->actual_length = 0;
+       default:
+               break;
+       }
+       dbg_ep0 (2, "%02x %02x", cp[0], cp[1]);
+       return 0;
+}
+
+/**
+ * ep0_get_one
+ * @device:
+ * @urb:
+ * @result:
+ *
+ * Set a single byte value in the urb send buffer. Return non-zero to signal
+ * a request error.
+ */
+static int ep0_get_one (struct usb_device_instance *device, struct urb *urb,
+                       __u8 result)
+{
+       urb->actual_length = 1; /* XXX 2? */
+       ((char *) urb->buffer)[0] = result;
+       return 0;
+}
+
+/**
+ * copy_config
+ * @urb: pointer to urb
+ * @data: pointer to configuration data
+ * @length: length of data
+ *
+ * Copy configuration data to urb transfer buffer if there is room for it.
+ */
+static void copy_config (struct urb *urb, void *data, int max_length,
+                        int max_buf)
+{
+       int available;
+       int length;
+
+       /*dbg_ep0(3, "-> actual: %d buf: %d max_buf: %d max_length: %d data: %p", */
+       /*        urb->actual_length, urb->buffer_length, max_buf, max_length, data); */
+
+       if (!data) {
+               dbg_ep0 (1, "data is NULL");
+               return;
+       }
+       if (!(length = *(unsigned char *) data)) {
+               dbg_ep0 (1, "length is zero");
+               return;
+       }
+
+       if (length > max_length) {
+               dbg_ep0 (1, "length: %d >= max_length: %d", length,
+                        max_length);
+               return;
+       }
+       /*dbg_ep0(1, "   actual: %d buf: %d max_buf: %d max_length: %d length: %d", */
+       /*        urb->actual_length, urb->buffer_length, max_buf, max_length, length); */
+
+       if ((available =
+            /*urb->buffer_length */ max_buf - urb->actual_length) <= 0) {
+               return;
+       }
+       /*dbg_ep0(1, "actual: %d buf: %d max_buf: %d length: %d available: %d", */
+       /*        urb->actual_length, urb->buffer_length, max_buf, length, available); */
+
+       if (length > available) {
+               length = available;
+       }
+       /*dbg_ep0(1, "actual: %d buf: %d max_buf: %d length: %d available: %d", */
+       /*        urb->actual_length, urb->buffer_length, max_buf, length, available); */
+
+       memcpy (urb->buffer + urb->actual_length, data, length);
+       urb->actual_length += length;
+
+       dbg_ep0 (3,
+                "copy_config: <- actual: %d buf: %d max_buf: %d max_length: %d available: %d",
+                urb->actual_length, urb->buffer_length, max_buf, max_length,
+                available);
+}
+
+/**
+ * ep0_get_descriptor
+ * @device:
+ * @urb:
+ * @max:
+ * @descriptor_type:
+ * @index:
+ *
+ * Called by ep0_rx_process for a get descriptor device command. Determine what
+ * descriptor is being requested, copy to send buffer. Return zero if ok to send,
+ * return non-zero to signal a request error.
+ */
+static int ep0_get_descriptor (struct usb_device_instance *device,
+                              struct urb *urb, int max, int descriptor_type,
+                              int index)
+{
+       int port = 0;           /* XXX compound device */
+       char *cp;
+
+       /*dbg_ep0(3, "max: %x type: %x index: %x", max, descriptor_type, index); */
+
+       if (!urb || !urb->buffer || !urb->buffer_length
+           || (urb->buffer_length < 255)) {
+               dbg_ep0 (2, "invalid urb %p", urb);
+               return -1L;
+       }
+
+       /* setup tx urb */
+       urb->actual_length = 0;
+       cp = urb->buffer;
+
+       dbg_ep0 (2, "%s", USBD_DEVICE_DESCRIPTORS (descriptor_type));
+
+       switch (descriptor_type) {
+       case USB_DESCRIPTOR_TYPE_DEVICE:
+               {
+                       struct usb_device_descriptor *device_descriptor;
+
+                       if (!
+                           (device_descriptor =
+                            usbd_device_device_descriptor (device, port))) {
+                               return -1;
+                       }
+                       /* copy descriptor for this device */
+                       copy_config (urb, device_descriptor,
+                                    sizeof (struct usb_device_descriptor),
+                                    max);
+
+                       /* correct the correct control endpoint 0 max packet size into the descriptor */
+                       device_descriptor =
+                               (struct usb_device_descriptor *) urb->buffer;
+                       device_descriptor->bMaxPacketSize0 =
+                               urb->device->bus->maxpacketsize;
+
+               }
+               /*dbg_ep0(3, "copied device configuration, actual_length: %x", urb->actual_length); */
+               break;
+
+       case USB_DESCRIPTOR_TYPE_CONFIGURATION:
+               {
+                       int bNumInterface;
+                       struct usb_configuration_descriptor
+                               *configuration_descriptor;
+                       struct usb_device_descriptor *device_descriptor;
+
+                       if (!
+                           (device_descriptor =
+                            usbd_device_device_descriptor (device, port))) {
+                               return -1;
+                       }
+                       /*dbg_ep0(2, "%d %d", index, device_descriptor->bNumConfigurations); */
+                       if (index > device_descriptor->bNumConfigurations) {
+                               dbg_ep0 (0, "index too large: %d > %d", index,
+                                        device_descriptor->
+                                        bNumConfigurations);
+                               return -1;
+                       }
+
+                       if (!
+                           (configuration_descriptor =
+                            usbd_device_configuration_descriptor (device,
+                                                                  port,
+                                                                  index))) {
+                               dbg_ep0 (0,
+                                        "usbd_device_configuration_descriptor failed: %d",
+                                        index);
+                               return -1;
+                       }
+                       copy_config (urb, configuration_descriptor,
+                                    sizeof (struct
+                                            usb_configuration_descriptor),
+                                    max);
+
+
+                       /* iterate across interfaces for specified configuration */
+                       dbg_ep0 (0, "bNumInterfaces: %d",
+                                configuration_descriptor->bNumInterfaces);
+                       for (bNumInterface = 0;
+                            bNumInterface <
+                            configuration_descriptor->bNumInterfaces;
+                            bNumInterface++) {
+
+                               int bAlternateSetting;
+                               struct usb_interface_instance
+                                       *interface_instance;
+
+                               dbg_ep0 (3, "[%d] bNumInterfaces: %d",
+                                        bNumInterface,
+                                        configuration_descriptor->bNumInterfaces);
+
+                               if (! (interface_instance = usbd_device_interface_instance (device,
+                                                                    port, index, bNumInterface)))
+                               {
+                                       dbg_ep0 (3, "[%d] interface_instance NULL",
+                                                bNumInterface);
+                                       return -1;
+                               }
+                               /* iterate across interface alternates */
+                               for (bAlternateSetting = 0;
+                                    bAlternateSetting < interface_instance->alternates;
+                                    bAlternateSetting++) {
+                                       /*int class; */
+                                       int bNumEndpoint;
+                                       struct usb_interface_descriptor *interface_descriptor;
+
+                                       struct usb_alternate_instance *alternate_instance;
+
+                                       dbg_ep0 (3, "[%d:%d] alternates: %d",
+                                                bNumInterface,
+                                                bAlternateSetting,
+                                                interface_instance->alternates);
+
+                                       if (! (alternate_instance = usbd_device_alternate_instance (device, port, index, bNumInterface, bAlternateSetting))) {
+                                               dbg_ep0 (3, "[%d] alternate_instance NULL",
+                                                        bNumInterface);
+                                               return -1;
+                                       }
+                                       /* copy descriptor for this interface */
+                                       copy_config (urb, alternate_instance->interface_descriptor,
+                                                    sizeof (struct usb_interface_descriptor),
+                                                    max);
+
+                                       /*dbg_ep0(3, "[%d:%d] classes: %d endpoints: %d", bNumInterface, bAlternateSetting, */
+                                       /*        alternate_instance->classes, alternate_instance->endpoints); */
+
+                                       /* iterate across classes for this alternate interface */
+#if 0
+                                       for (class = 0;
+                                            class < alternate_instance->classes;
+                                            class++) {
+                                               struct usb_class_descriptor *class_descriptor;
+                                               /*dbg_ep0(3, "[%d:%d:%d] classes: %d", bNumInterface, bAlternateSetting, */
+                                               /*        class, alternate_instance->classes); */
+                                               if (!(class_descriptor = usbd_device_class_descriptor_index (device, port, index, bNumInterface, bAlternateSetting, class))) {
+                                                       dbg_ep0 (3, "[%d] class NULL",
+                                                                class);
+                                                       return -1;
+                                               }
+                                               /* copy descriptor for this class */
+                                               copy_config (urb, class_descriptor,
+                                                       sizeof (struct usb_class_descriptor),
+                                                       max);
+                                       }
+#endif
+
+                                       /* iterate across endpoints for this alternate interface */
+                                       interface_descriptor = alternate_instance->interface_descriptor;
+                                       for (bNumEndpoint = 0;
+                                            bNumEndpoint < alternate_instance->endpoints;
+                                            bNumEndpoint++) {
+                                               struct usb_endpoint_descriptor *endpoint_descriptor;
+                                               dbg_ep0 (3, "[%d:%d:%d] endpoint: %d",
+                                                        bNumInterface,
+                                                        bAlternateSetting,
+                                                        bNumEndpoint,
+                                                        interface_descriptor->
+                                                        bNumEndpoints);
+                                               if (!(endpoint_descriptor = usbd_device_endpoint_descriptor_index (device, port, index, bNumInterface, bAlternateSetting, bNumEndpoint))) {
+                                                       dbg_ep0 (3, "[%d] endpoint NULL",
+                                                                bNumEndpoint);
+                                                       return -1;
+                                               }
+                                               /* copy descriptor for this endpoint */
+                                               copy_config (urb, endpoint_descriptor,
+                                                            sizeof (struct usb_endpoint_descriptor),
+                                                            max);
+                                       }
+                               }
+                       }
+                       dbg_ep0 (3, "lengths: %d %d",
+                                le16_to_cpu (configuration_descriptor->wTotalLength),
+                                urb->actual_length);
+               }
+               break;
+
+       case USB_DESCRIPTOR_TYPE_STRING:
+               {
+                       struct usb_string_descriptor *string_descriptor;
+
+                       if (!(string_descriptor = usbd_get_string (index))) {
+                               return -1;
+                       }
+                       /*dbg_ep0(3, "string_descriptor: %p", string_descriptor); */
+                       copy_config (urb, string_descriptor, string_descriptor->bLength, max);
+               }
+               break;
+       case USB_DESCRIPTOR_TYPE_INTERFACE:
+               return -1;
+       case USB_DESCRIPTOR_TYPE_ENDPOINT:
+               return -1;
+       case USB_DESCRIPTOR_TYPE_HID:
+               {
+                       return -1;      /* unsupported at this time */
+#if 0
+                       int bNumInterface =
+                               le16_to_cpu (urb->device_request.wIndex);
+                       int bAlternateSetting = 0;
+                       int class = 0;
+                       struct usb_class_descriptor *class_descriptor;
+
+                       if (!(class_descriptor =
+                             usbd_device_class_descriptor_index (device,
+                                                                 port, 0,
+                                                                 bNumInterface,
+                                                                 bAlternateSetting,
+                                                                 class))
+                           || class_descriptor->descriptor.hid.bDescriptorType != USB_DT_HID) {
+                               dbg_ep0 (3, "[%d] interface is not HID",
+                                        bNumInterface);
+                               return -1;
+                       }
+                       /* copy descriptor for this class */
+                       copy_config (urb, class_descriptor,
+                                    class_descriptor->descriptor.hid.bLength,
+                                    max);
+#endif
+               }
+               break;
+       case USB_DESCRIPTOR_TYPE_REPORT:
+               {
+                       return -1;      /* unsupported at this time */
+#if 0
+                       int bNumInterface =
+                               le16_to_cpu (urb->device_request.wIndex);
+                       int bAlternateSetting = 0;
+                       int class = 0;
+                       struct usb_class_report_descriptor *report_descriptor;
+
+                       if (!(report_descriptor =
+                             usbd_device_class_report_descriptor_index
+                             (device, port, 0, bNumInterface,
+                              bAlternateSetting, class))
+                           || report_descriptor->bDescriptorType !=
+                           USB_DT_REPORT) {
+                               dbg_ep0 (3, "[%d] descriptor is not REPORT",
+                                        bNumInterface);
+                               return -1;
+                       }
+                       /* copy report descriptor for this class */
+                       /*copy_config(urb, &report_descriptor->bData[0], report_descriptor->wLength, max); */
+                       if (max - urb->actual_length > 0) {
+                               int length =
+                                       MIN (report_descriptor->wLength,
+                                            max - urb->actual_length);
+                               memcpy (urb->buffer + urb->actual_length,
+                                       &report_descriptor->bData[0], length);
+                               urb->actual_length += length;
+                       }
+#endif
+               }
+               break;
+       default:
+               return -1;
+       }
+
+
+       dbg_ep0 (1, "urb: buffer: %p buffer_length: %2d actual_length: %2d packet size: %2d",
+                urb->buffer, urb->buffer_length, urb->actual_length,
+                device->bus->endpoint_array[0].tx_packetSize);
+/*
+    if ((urb->actual_length < max) && !(urb->actual_length % device->bus->endpoint_array[0].tx_packetSize)) {
+       dbg_ep0(0, "adding null byte");
+       urb->buffer[urb->actual_length++] = 0;
+       dbg_ep0(0, "urb: buffer_length: %2d actual_length: %2d packet size: %2d",
+               urb->buffer_length, urb->actual_length device->bus->endpoint_array[0].tx_packetSize);
+    }
+*/
+       return 0;
+
+}
+
+/**
+ * ep0_recv_setup - called to indicate URB has been received
+ * @urb: pointer to struct urb
+ *
+ * Check if this is a setup packet, process the device request, put results
+ * back into the urb and return zero or non-zero to indicate success (DATA)
+ * or failure (STALL).
+ *
+ */
+int ep0_recv_setup (struct urb *urb)
+{
+       /*struct usb_device_request *request = urb->buffer; */
+       /*struct usb_device_instance *device = urb->device; */
+
+       struct usb_device_request *request;
+       struct usb_device_instance *device;
+       int address;
+
+       dbg_ep0 (0, "entering ep0_recv_setup()");
+       if (!urb || !urb->device) {
+               dbg_ep0 (3, "invalid URB %p", urb);
+               return -1;
+       }
+
+       request = &urb->device_request;
+       device = urb->device;
+
+       dbg_ep0 (3, "urb: %p device: %p", urb, urb->device);
+
+
+       /*dbg_ep0(2, "-       -       -       -       -       -       -       -       -       -"); */
+
+       dbg_ep0 (2,
+                "bmRequestType:%02x bRequest:%02x wValue:%04x wIndex:%04x wLength:%04x %s",
+                request->bmRequestType, request->bRequest,
+                le16_to_cpu (request->wValue), le16_to_cpu (request->wIndex),
+                le16_to_cpu (request->wLength),
+                USBD_DEVICE_REQUESTS (request->bRequest));
+
+       /* handle USB Standard Request (c.f. USB Spec table 9-2) */
+       if ((request->bmRequestType & USB_REQ_TYPE_MASK) != 0) {
+               dbg_ep0 (1, "non standard request: %x",
+                        request->bmRequestType & USB_REQ_TYPE_MASK);
+               return -1;      /* Stall here */
+       }
+
+       switch (device->device_state) {
+       case STATE_CREATED:
+       case STATE_ATTACHED:
+       case STATE_POWERED:
+               /* It actually is important to allow requests in these states,
+                * Windows will request descriptors before assigning an
+                * address to the client.
+                */
+
+               /*dbg_ep0 (1, "request %s not allowed in this state: %s", */
+               /*                USBD_DEVICE_REQUESTS(request->bRequest), */
+               /*                usbd_device_states[device->device_state]); */
+               /*return -1; */
+               break;
+
+       case STATE_INIT:
+       case STATE_DEFAULT:
+               switch (request->bRequest) {
+               case USB_REQ_GET_STATUS:
+               case USB_REQ_GET_INTERFACE:
+               case USB_REQ_SYNCH_FRAME:       /* XXX should never see this (?) */
+               case USB_REQ_CLEAR_FEATURE:
+               case USB_REQ_SET_FEATURE:
+               case USB_REQ_SET_DESCRIPTOR:
+                       /* case USB_REQ_SET_CONFIGURATION: */
+               case USB_REQ_SET_INTERFACE:
+                       dbg_ep0 (1,
+                                "request %s not allowed in DEFAULT state: %s",
+                                USBD_DEVICE_REQUESTS (request->bRequest),
+                                usbd_device_states[device->device_state]);
+                       return -1;
+
+               case USB_REQ_SET_CONFIGURATION:
+               case USB_REQ_SET_ADDRESS:
+               case USB_REQ_GET_DESCRIPTOR:
+               case USB_REQ_GET_CONFIGURATION:
+                       break;
+               }
+       case STATE_ADDRESSED:
+       case STATE_CONFIGURED:
+               break;
+       case STATE_UNKNOWN:
+               dbg_ep0 (1, "request %s not allowed in UNKNOWN state: %s",
+                        USBD_DEVICE_REQUESTS (request->bRequest),
+                        usbd_device_states[device->device_state]);
+               return -1;
+       }
+
+       /* handle all requests that return data (direction bit set on bm RequestType) */
+       if ((request->bmRequestType & USB_REQ_DIRECTION_MASK)) {
+
+               dbg_ep0 (3, "Device-to-Host");
+
+               switch (request->bRequest) {
+
+               case USB_REQ_GET_STATUS:
+                       return ep0_get_status (device, urb, request->wIndex,
+                                              request->bmRequestType &
+                                              USB_REQ_RECIPIENT_MASK);
+
+               case USB_REQ_GET_DESCRIPTOR:
+                       return ep0_get_descriptor (device, urb,
+                                                  le16_to_cpu (request->wLength),
+                                                  le16_to_cpu (request->wValue) >> 8,
+                                                  le16_to_cpu (request->wValue) & 0xff);
+
+               case USB_REQ_GET_CONFIGURATION:
+                       return ep0_get_one (device, urb,
+                                           device->configuration);
+
+               case USB_REQ_GET_INTERFACE:
+                       return ep0_get_one (device, urb, device->alternate);
+
+               case USB_REQ_SYNCH_FRAME:       /* XXX should never see this (?) */
+                       return -1;
+
+               case USB_REQ_CLEAR_FEATURE:
+               case USB_REQ_SET_FEATURE:
+               case USB_REQ_SET_ADDRESS:
+               case USB_REQ_SET_DESCRIPTOR:
+               case USB_REQ_SET_CONFIGURATION:
+               case USB_REQ_SET_INTERFACE:
+                       return -1;
+               }
+       }
+       /* handle the requests that do not return data */
+       else {
+
+
+               /*dbg_ep0(3, "Host-to-Device"); */
+               switch (request->bRequest) {
+
+               case USB_REQ_CLEAR_FEATURE:
+               case USB_REQ_SET_FEATURE:
+                       dbg_ep0 (0, "Host-to-Device");
+                       switch (request->
+                               bmRequestType & USB_REQ_RECIPIENT_MASK) {
+                       case USB_REQ_RECIPIENT_DEVICE:
+                               /* XXX DEVICE_REMOTE_WAKEUP or TEST_MODE would be added here */
+                               /* XXX fall through for now as we do not support either */
+                       case USB_REQ_RECIPIENT_INTERFACE:
+                       case USB_REQ_RECIPIENT_OTHER:
+                               dbg_ep0 (0, "request %s not",
+                                        USBD_DEVICE_REQUESTS (request->bRequest));
+                       default:
+                               return -1;
+
+                       case USB_REQ_RECIPIENT_ENDPOINT:
+                               dbg_ep0 (0, "ENDPOINT: %x", le16_to_cpu (request->wValue));
+                               if (le16_to_cpu (request->wValue) == USB_ENDPOINT_HALT) {
+                                       /*return usbd_device_feature (device, le16_to_cpu (request->wIndex), */
+                                       /*                    request->bRequest == USB_REQ_SET_FEATURE); */
+                                       /* NEED TO IMPLEMENT THIS!!! */
+                                       return -1;
+                               } else {
+                                       dbg_ep0 (1, "request %s bad wValue: %04x",
+                                                USBD_DEVICE_REQUESTS
+                                                (request->bRequest),
+                                                le16_to_cpu (request->wValue));
+                                       return -1;
+                               }
+                       }
+
+               case USB_REQ_SET_ADDRESS:
+                       /* check if this is a re-address, reset first if it is (this shouldn't be possible) */
+                       if (device->device_state != STATE_DEFAULT) {
+                               dbg_ep0 (1, "set_address: %02x state: %s",
+                                        le16_to_cpu (request->wValue),
+                                        usbd_device_states[device->device_state]);
+                               return -1;
+                       }
+                       address = le16_to_cpu (request->wValue);
+                       if ((address & 0x7f) != address) {
+                               dbg_ep0 (1, "invalid address %04x %04x",
+                                        address, address & 0x7f);
+                               return -1;
+                       }
+                       device->address = address;
+
+                       /*dbg_ep0(2, "address: %d %d %d", */
+                       /*        request->wValue, le16_to_cpu(request->wValue), device->address); */
+
+                       serial_printf ("DEVICE_ADDRESS_ASSIGNED.. event?\n");
+                       return 0;
+
+               case USB_REQ_SET_DESCRIPTOR:    /* XXX should we support this? */
+                       dbg_ep0 (0, "set descriptor: NOT SUPPORTED");
+                       return -1;
+
+               case USB_REQ_SET_CONFIGURATION:
+                       /* c.f. 9.4.7 - the top half of wValue is reserved */
+                       /* */
+                       if ((device->configuration =
+                            le16_to_cpu (request->wValue) & 0x7f) != 0) {
+                               /* c.f. 9.4.7 - zero is the default or addressed state, in our case this */
+                               /* is the same is configuration zero */
+                               device->configuration = 0;      /* TBR - ?????? */
+                       }
+                       /* reset interface and alternate settings */
+                       device->interface = device->alternate = 0;
+
+                       /*dbg_ep0(2, "set configuration: %d", device->configuration); */
+                       /*serial_printf("DEVICE_CONFIGURED.. event?\n"); */
+                       return 0;
+
+               case USB_REQ_SET_INTERFACE:
+                       device->interface = le16_to_cpu (request->wIndex);
+                       device->alternate = le16_to_cpu (request->wValue);
+                       /*dbg_ep0(2, "set interface: %d alternate: %d", device->interface, device->alternate); */
+                       serial_printf ("DEVICE_SET_INTERFACE.. event?\n");
+                       return 0;
+
+               case USB_REQ_GET_STATUS:
+               case USB_REQ_GET_DESCRIPTOR:
+               case USB_REQ_GET_CONFIGURATION:
+               case USB_REQ_GET_INTERFACE:
+               case USB_REQ_SYNCH_FRAME:       /* XXX should never see this (?) */
+                       return -1;
+               }
+       }
+       return -1;
+}
+
+#endif
diff --git a/drivers/usbdcore_omap1510.c b/drivers/usbdcore_omap1510.c
new file mode 100644 (file)
index 0000000..042f319
--- /dev/null
@@ -0,0 +1,1494 @@
+/*
+ * (C) Copyright 2003
+ * Gerry Hamel, geh@ti.com, Texas Instruments
+ *
+ * Based on
+ * linux/drivers/usb/device/bi/omap.c
+ * TI OMAP1510 USB bus interface driver
+ *
+ * Author: MontaVista Software, Inc.
+ *        source@mvista.com
+ *        (C) Copyright 2002
+ *
+ * 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 <common.h>
+
+#if defined(CONFIG_OMAP1510) && defined(CONFIG_USB_DEVICE)
+
+#include <asm/io.h>
+#include <i2c.h>
+
+#include "usbdcore.h"
+#include "usbdcore_omap1510.h"
+#include "usbdcore_ep0.h"
+
+
+#define UDC_MAX_ENDPOINTS           31 /* Number of endpoints on this UDC */
+
+/* Some kind of debugging output... */
+#if 1
+#define UDCDBG(str)
+#define UDCDBGA(fmt,args...)
+#else  /* The bugs still exists... */
+#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)
+#endif
+
+#if 1
+#define UDCREG(name)
+#define UDCREGL(name)
+#else  /* The bugs still exists... */
+#define UDCREG(name)    serial_printf("%s():%d: %s[%08x]=%.4x\n",__FUNCTION__,__LINE__, (#name), name, inw(name))      /* For 16-bit regs */
+#define UDCREGL(name)   serial_printf("%s():%d: %s[%08x]=%.8x\n",__FUNCTION__,__LINE__, (#name), name, inl(name))      /* For 32-bit regs */
+#endif
+
+
+static struct urb *ep0_urb = NULL;
+
+static struct usb_device_instance *udc_device; /* Used in interrupt handler */
+static u16 udc_devstat = 0;    /* UDC status (DEVSTAT) */
+static u32 udc_interrupts = 0;
+
+static void udc_stall_ep (unsigned int ep_addr);
+
+
+static struct usb_endpoint_instance *omap1510_find_ep (int ep)
+{
+       int i;
+
+       for (i = 0; i < udc_device->bus->max_endpoints; i++) {
+               if (udc_device->bus->endpoint_array[i].endpoint_address == ep)
+                       return &udc_device->bus->endpoint_array[i];
+       }
+       return NULL;
+}
+
+/* ************************************************************************** */
+/* IO
+ */
+
+/*
+ * omap1510_prepare_endpoint_for_rx
+ *
+ * This function implements TRM Figure 14-11.
+ *
+ * The endpoint to prepare for transfer is specified as a physical endpoint
+ * number.  For OUT (rx) endpoints 1 through 15, the corresponding endpoint
+ * configuration register is checked to see if the endpoint is ISO or not.
+ * If the OUT endpoint is valid and is non-ISO then its FIFO is enabled.
+ * No action is taken for endpoint 0 or for IN (tx) endpoints 16 through 30.
+ */
+static void omap1510_prepare_endpoint_for_rx (int ep_addr)
+{
+       int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK;
+
+       UDCDBGA ("omap1510_prepare_endpoint %x", ep_addr);
+       if (((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)) {
+               if ((inw (UDC_EP_RX (ep_num)) &
+                    (UDC_EPn_RX_Valid | UDC_EPn_RX_Iso)) ==
+                   UDC_EPn_RX_Valid) {
+                       /* rx endpoint is valid, non-ISO, so enable its FIFO */
+                       outw (UDC_EP_Sel | ep_num, UDC_EP_NUM);
+                       outw (UDC_Set_FIFO_En, UDC_CTRL);
+                       outw (0, UDC_EP_NUM);
+               }
+       }
+}
+
+/* omap1510_configure_endpoints
+ *
+ * This function implements TRM Figure 14-10.
+ */
+static void omap1510_configure_endpoints (struct usb_device_instance *device)
+{
+       int ep;
+       struct usb_bus_instance *bus;
+       struct usb_endpoint_instance *endpoint;
+       unsigned short ep_ptr;
+       unsigned short ep_size;
+       unsigned short ep_isoc;
+       unsigned short ep_doublebuffer;
+       int ep_addr;
+       int packet_size;
+       int buffer_size;
+       int attributes;
+
+       bus = device->bus;
+
+       /* There is a dedicated 2048 byte buffer for USB packets that may be
+        * arbitrarily partitioned among the endpoints on 8-byte boundaries.
+        * The first 8 bytes are reserved for receiving setup packets on
+        * endpoint 0.
+        */
+       ep_ptr = 8;             /* reserve the first 8 bytes for the setup fifo */
+
+       for (ep = 0; ep < bus->max_endpoints; ep++) {
+               endpoint = bus->endpoint_array + ep;
+               ep_addr = endpoint->endpoint_address;
+               if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
+                       /* IN endpoint */
+                       packet_size = endpoint->tx_packetSize;
+                       attributes = endpoint->tx_attributes;
+               } else {
+                       /* OUT endpoint */
+                       packet_size = endpoint->rcv_packetSize;
+                       attributes = endpoint->rcv_attributes;
+               }
+
+               switch (packet_size) {
+               case 0:
+                       ep_size = 0;
+                       break;
+               case 8:
+                       ep_size = 0;
+                       break;
+               case 16:
+                       ep_size = 1;
+                       break;
+               case 32:
+                       ep_size = 2;
+                       break;
+               case 64:
+                       ep_size = 3;
+                       break;
+               case 128:
+                       ep_size = 4;
+                       break;
+               case 256:
+                       ep_size = 5;
+                       break;
+               case 512:
+                       ep_size = 6;
+                       break;
+               default:
+                       UDCDBGA ("ep 0x%02x has bad packet size %d",
+                                ep_addr, packet_size);
+                       packet_size = 0;
+                       ep_size = 0;
+                       break;
+               }
+
+               switch (attributes & USB_ENDPOINT_XFERTYPE_MASK) {
+               case USB_ENDPOINT_XFER_CONTROL:
+               case USB_ENDPOINT_XFER_BULK:
+               case USB_ENDPOINT_XFER_INT:
+               default:
+                       /* A non-isochronous endpoint may optionally be
+                        * double-buffered. For now we disable
+                        * double-buffering.
+                        */
+                       ep_doublebuffer = 0;
+                       ep_isoc = 0;
+                       if (packet_size > 64)
+                               packet_size = 0;
+                       if (!ep || !ep_doublebuffer)
+                               buffer_size = packet_size;
+                       else
+                               buffer_size = packet_size * 2;
+                       break;
+               case USB_ENDPOINT_XFER_ISOC:
+                       /* Isochronous endpoints are always double-
+                        * buffered, but the double-buffering bit
+                        * in the endpoint configuration register
+                        * becomes the msb of the endpoint size so we
+                        * set the double-buffering flag to zero.
+                        */
+                       ep_doublebuffer = 0;
+                       ep_isoc = 1;
+                       buffer_size = packet_size * 2;
+                       break;
+               }
+
+               /* check to see if our packet buffer RAM is exhausted */
+               if ((ep_ptr + buffer_size) > 2048) {
+                       UDCDBGA ("out of packet RAM for ep 0x%02x buf size %d", ep_addr, buffer_size);
+                       buffer_size = packet_size = 0;
+               }
+
+               /* force a default configuration for endpoint 0 since it is
+                * always enabled
+                */
+               if (!ep && ((packet_size < 8) || (packet_size > 64))) {
+                       buffer_size = packet_size = 64;
+                       ep_size = 3;
+               }
+
+               if (!ep) {
+                       /* configure endpoint 0 */
+                       outw ((ep_size << 12) | (ep_ptr >> 3), UDC_EP0);
+                       /*UDCDBGA("ep 0 buffer offset 0x%03x packet size 0x%03x", */
+                       /*      ep_ptr, packet_size); */
+               } else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
+                       /* IN endpoint */
+                       if (packet_size) {
+                               outw ((1 << 15) | (ep_doublebuffer << 14) |
+                                     (ep_size << 12) | (ep_isoc << 11) |
+                                     (ep_ptr >> 3),
+                                     UDC_EP_TX (ep_addr &
+                                                USB_ENDPOINT_NUMBER_MASK));
+                               UDCDBGA ("IN ep %d buffer offset 0x%03x"
+                                        " packet size 0x%03x",
+                                        ep_addr & USB_ENDPOINT_NUMBER_MASK,
+                                        ep_ptr, packet_size);
+                       } else {
+                               outw (0,
+                                     UDC_EP_TX (ep_addr &
+                                                USB_ENDPOINT_NUMBER_MASK));
+                       }
+               } else {
+                       /* OUT endpoint */
+                       if (packet_size) {
+                               outw ((1 << 15) | (ep_doublebuffer << 14) |
+                                     (ep_size << 12) | (ep_isoc << 11) |
+                                     (ep_ptr >> 3),
+                                     UDC_EP_RX (ep_addr &
+                                                USB_ENDPOINT_NUMBER_MASK));
+                               UDCDBGA ("OUT ep %d buffer offset 0x%03x"
+                                        " packet size 0x%03x",
+                                        ep_addr & USB_ENDPOINT_NUMBER_MASK,
+                                        ep_ptr, packet_size);
+                       } else {
+                               outw (0,
+                                     UDC_EP_RX (ep_addr &
+                                                USB_ENDPOINT_NUMBER_MASK));
+                       }
+               }
+               ep_ptr += buffer_size;
+       }
+}
+
+/* omap1510_deconfigure_device
+ *
+ * This function balances omap1510_configure_device.
+ */
+static void omap1510_deconfigure_device (void)
+{
+       int epnum;
+
+       UDCDBG ("clear Cfg_Lock");
+       outw (inw (UDC_SYSCON1) & ~UDC_Cfg_Lock, UDC_SYSCON1);
+       UDCREG (UDC_SYSCON1);
+
+       /* deconfigure all endpoints */
+       for (epnum = 1; epnum <= 15; epnum++) {
+               outw (0, UDC_EP_RX (epnum));
+               outw (0, UDC_EP_TX (epnum));
+       }
+}
+
+/* omap1510_configure_device
+ *
+ * This function implements TRM Figure 14-9.
+ */
+static void omap1510_configure_device (struct usb_device_instance *device)
+{
+       omap1510_configure_endpoints (device);
+
+
+       /* Figure 14-9 indicates we should enable interrupts here, but we have
+        * other routines (udc_all_interrupts, udc_suspended_interrupts) to
+        * do that.
+        */
+
+       UDCDBG ("set Cfg_Lock");
+       outw (inw (UDC_SYSCON1) | UDC_Cfg_Lock, UDC_SYSCON1);
+       UDCREG (UDC_SYSCON1);
+}
+
+/* omap1510_write_noniso_tx_fifo
+ *
+ * This function implements TRM Figure 14-30.
+ *
+ * If the endpoint has an active tx_urb, then the next packet of data from the
+ * URB is written to the tx FIFO.  The total amount of data in the urb is given
+ * by urb->actual_length.  The maximum amount of data that can be sent in any
+ * one packet is given by endpoint->tx_packetSize.  The number of data bytes
+ * from this URB that have already been transmitted is given by endpoint->sent.
+ * endpoint->last is updated by this routine with the number of data bytes
+ * transmitted in this packet.
+ *
+ * In accordance with Figure 14-30, the EP_NUM register must already have been
+ * written with the value to select the appropriate tx FIFO before this routine
+ * is called.
+ */
+static void omap1510_write_noniso_tx_fifo (struct usb_endpoint_instance
+                                          *endpoint)
+{
+       struct urb *urb = endpoint->tx_urb;
+
+       if (urb) {
+               unsigned int last, i;
+
+               UDCDBGA ("urb->buffer %p, buffer_length %d, actual_length %d",
+                        urb->buffer, urb->buffer_length, urb->actual_length);
+               if ((last =
+                    MIN (urb->actual_length - endpoint->sent,
+                         endpoint->tx_packetSize))) {
+                       u8 *cp = urb->buffer + endpoint->sent;
+
+                       UDCDBGA ("endpoint->sent %d, tx_packetSize %d, last %d", endpoint->sent, endpoint->tx_packetSize, last);
+
+                       if (((u32) cp & 1) == 0) {      /* word aligned? */
+                               outsw (UDC_DATA, cp, last >> 1);
+                       } else {        /* byte aligned. */
+                               for (i = 0; i < (last >> 1); i++) {
+                                       u16 w = ((u16) cp[2 * i + 1] << 8) |
+                                               (u16) cp[2 * i];
+                                       outw (w, UDC_DATA);
+                               }
+                       }
+                       if (last & 1) {
+                               outb (*(cp + last - 1), UDC_DATA);
+                       }
+               }
+               endpoint->last = last;
+       }
+}
+
+/* omap1510_read_noniso_rx_fifo
+ *
+ * This function implements TRM Figure 14-28.
+ *
+ * If the endpoint has an active rcv_urb, then the next packet of data is read
+ * from the rcv FIFO and written to rcv_urb->buffer at offset
+ * rcv_urb->actual_length to append the packet data to the data from any
+ * previous packets for this transfer. We assume that there is sufficient room
+ * left in the buffer to hold an entire packet of data.
+ *
+ * The return value is the number of bytes read from the FIFO for this packet.
+ *
+ * In accordance with Figure 14-28, the EP_NUM register must already have been
+ * written with the value to select the appropriate rcv FIFO before this routine
+ * is called.
+ */
+static int omap1510_read_noniso_rx_fifo (struct usb_endpoint_instance
+                                        *endpoint)
+{
+       struct urb *urb = endpoint->rcv_urb;
+       int len = 0;
+
+       if (urb) {
+               len = inw (UDC_RXFSTAT);
+
+               if (len) {
+                       unsigned char *cp = urb->buffer + urb->actual_length;
+
+                       insw (UDC_DATA, cp, len >> 1);
+                       if (len & 1)
+                               *(cp + len - 1) = inb (UDC_DATA);
+               }
+       }
+       return len;
+}
+
+/* omap1510_prepare_for_control_write_status
+ *
+ * This function implements TRM Figure 14-17.
+ *
+ * We have to deal here with non-autodecoded control writes that haven't already
+ * been dealt with by ep0_recv_setup.  The non-autodecoded standard control
+ * write requests are: set/clear endpoint feature, set configuration, set
+ * interface, and set descriptor.  ep0_recv_setup handles set/clear requests for
+ * ENDPOINT_HALT by halting the endpoint for a set request and resetting the
+ * endpoint for a clear request.  ep0_recv_setup returns an error for
+ * SET_DESCRIPTOR requests which causes them to be terminated with a stall by
+ * the setup handler.  A SET_INTERFACE request is handled by ep0_recv_setup by
+ * generating a DEVICE_SET_INTERFACE event.  This leaves only the
+ * SET_CONFIGURATION event for us to deal with here.
+ *
+ */
+static void omap1510_prepare_for_control_write_status (struct urb *urb)
+{
+       struct usb_device_request *request = &urb->device_request;;
+
+       /* check for a SET_CONFIGURATION request */
+       if (request->bRequest == USB_REQ_SET_CONFIGURATION) {
+               int configuration = le16_to_cpu (request->wValue) & 0xff;
+               unsigned short devstat = inw (UDC_DEVSTAT);
+
+               if ((devstat & (UDC_ADD | UDC_CFG)) == UDC_ADD) {
+                       /* device is currently in ADDRESSED state */
+                       if (configuration) {
+                               /* Assume the specified non-zero configuration
+                                * value is valid and switch to the CONFIGURED
+                                * state.
+                                */
+                               outw (UDC_Dev_Cfg, UDC_SYSCON2);
+                       }
+               } else if ((devstat & UDC_CFG) == UDC_CFG) {
+                       /* device is currently in CONFIGURED state */
+                       if (!configuration) {
+                               /* Switch to ADDRESSED state. */
+                               outw (UDC_Clr_Cfg, UDC_SYSCON2);
+                       }
+               }
+       }
+
+       /* select EP0 tx FIFO */
+       outw (UDC_EP_Dir | UDC_EP_Sel, UDC_EP_NUM);
+       /* clear endpoint (no data bytes in status stage) */
+       outw (UDC_Clr_EP, UDC_CTRL);
+       /* enable the EP0 tx FIFO */
+       outw (UDC_Set_FIFO_En, UDC_CTRL);
+       /* deselect the endpoint */
+       outw (UDC_EP_Dir, UDC_EP_NUM);
+}
+
+/* udc_state_transition_up
+ * udc_state_transition_down
+ *
+ * Helper functions to implement device state changes. The device states and
+ * the events that transition between them are:
+ *
+ *                             STATE_ATTACHED
+ *                             ||      /\
+ *                             \/      ||
+ *     DEVICE_HUB_CONFIGURED                   DEVICE_HUB_RESET
+ *                             ||      /\
+ *                             \/      ||
+ *                             STATE_POWERED
+ *                             ||      /\
+ *                             \/      ||
+ *     DEVICE_RESET                            DEVICE_POWER_INTERRUPTION
+ *                             ||      /\
+ *                             \/      ||
+ *                             STATE_DEFAULT
+ *                             ||      /\
+ *                             \/      ||
+ *     DEVICE_ADDRESS_ASSIGNED                 DEVICE_RESET
+ *                             ||      /\
+ *                             \/      ||
+ *                             STATE_ADDRESSED
+ *                             ||      /\
+ *                             \/      ||
+ *     DEVICE_CONFIGURED                       DEVICE_DE_CONFIGURED
+ *                             ||      /\
+ *                             \/      ||
+ *                             STATE_CONFIGURED
+ *
+ * udc_state_transition_up transitions up (in the direction from STATE_ATTACHED
+ * to STATE_CONFIGURED) from the specified initial state to the specified final
+ * state, passing through each intermediate state on the way.  If the initial
+ * state is at or above (i.e. nearer to STATE_CONFIGURED) the final state, then
+ * no state transitions will take place.
+ *
+ * udc_state_transition_down transitions down (in the direction from
+ * STATE_CONFIGURED to STATE_ATTACHED) from the specified initial state to the
+ * specified final state, passing through each intermediate state on the way.
+ * If the initial state is at or below (i.e. nearer to STATE_ATTACHED) the final
+ * state, then no state transitions will take place.
+ *
+ * These functions must only be called with interrupts disabled.
+ */
+static void udc_state_transition_up (usb_device_state_t initial,
+                                    usb_device_state_t final)
+{
+       if (initial < final) {
+               switch (initial) {
+               case STATE_ATTACHED:
+                       usbd_device_event_irq (udc_device,
+                                              DEVICE_HUB_CONFIGURED, 0);
+                       if (final == STATE_POWERED)
+                               break;
+               case STATE_POWERED:
+                       usbd_device_event_irq (udc_device, DEVICE_RESET, 0);
+                       if (final == STATE_DEFAULT)
+                               break;
+               case STATE_DEFAULT:
+                       usbd_device_event_irq (udc_device,
+                                              DEVICE_ADDRESS_ASSIGNED, 0);
+                       if (final == STATE_ADDRESSED)
+                               break;
+               case STATE_ADDRESSED:
+                       usbd_device_event_irq (udc_device, DEVICE_CONFIGURED,
+                                              0);
+               case STATE_CONFIGURED:
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+
+static void udc_state_transition_down (usb_device_state_t initial,
+                                      usb_device_state_t final)
+{
+       if (initial > final) {
+               switch (initial) {
+               case STATE_CONFIGURED:
+                       usbd_device_event_irq (udc_device, DEVICE_DE_CONFIGURED, 0);
+                       if (final == STATE_ADDRESSED)
+                               break;
+               case STATE_ADDRESSED:
+                       usbd_device_event_irq (udc_device, DEVICE_RESET, 0);
+                       if (final == STATE_DEFAULT)
+                               break;
+               case STATE_DEFAULT:
+                       usbd_device_event_irq (udc_device, DEVICE_POWER_INTERRUPTION, 0);
+                       if (final == STATE_POWERED)
+                               break;
+               case STATE_POWERED:
+                       usbd_device_event_irq (udc_device, DEVICE_HUB_RESET, 0);
+               case STATE_ATTACHED:
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+
+/* Handle all device state changes.
+ * This function implements TRM Figure 14-21.
+ */
+static void omap1510_udc_state_changed (void)
+{
+       u16 bits;
+       u16 devstat = inw (UDC_DEVSTAT);
+
+       UDCDBGA ("state changed, devstat %x, old %x", devstat, udc_devstat);
+
+       bits = devstat ^ udc_devstat;
+       if (bits) {
+               if (bits & UDC_ATT) {
+                       if (devstat & UDC_ATT) {
+                               UDCDBG ("device attached and powered");
+                               udc_state_transition_up (udc_device->device_state, STATE_POWERED);
+                       } else {
+                               UDCDBG ("device detached or unpowered");
+                               udc_state_transition_down (udc_device->device_state, STATE_ATTACHED);
+                       }
+               }
+               if (bits & UDC_USB_Reset) {
+                       if (devstat & UDC_USB_Reset) {
+                               UDCDBG ("device reset in progess");
+                               udc_state_transition_down (udc_device->device_state, STATE_POWERED);
+                       } else {
+                               UDCDBG ("device reset completed");
+                       }
+               }
+               if (bits & UDC_DEF) {
+                       if (devstat & UDC_DEF) {
+                               UDCDBG ("device entering default state");
+                               udc_state_transition_up (udc_device->device_state, STATE_DEFAULT);
+                       } else {
+                               UDCDBG ("device leaving default state");
+                               udc_state_transition_down (udc_device->device_state, STATE_POWERED);
+                       }
+               }
+               if (bits & UDC_SUS) {
+                       if (devstat & UDC_SUS) {
+                               UDCDBG ("entering suspended state");
+                               usbd_device_event_irq (udc_device, DEVICE_BUS_INACTIVE, 0);
+                       } else {
+                               UDCDBG ("leaving suspended state");
+                               usbd_device_event_irq (udc_device, DEVICE_BUS_ACTIVITY, 0);
+                       }
+               }
+               if (bits & UDC_R_WK_OK) {
+                       UDCDBGA ("remote wakeup %s", (devstat & UDC_R_WK_OK)
+                                ? "enabled" : "disabled");
+               }
+               if (bits & UDC_ADD) {
+                       if (devstat & UDC_ADD) {
+                               UDCDBG ("default -> addressed");
+                               udc_state_transition_up (udc_device->device_state, STATE_ADDRESSED);
+                       } else {
+                               UDCDBG ("addressed -> default");
+                               udc_state_transition_down (udc_device->device_state, STATE_DEFAULT);
+                       }
+               }
+               if (bits & UDC_CFG) {
+                       if (devstat & UDC_CFG) {
+                               UDCDBG ("device configured");
+                               /* The ep0_recv_setup function generates the
+                                * DEVICE_CONFIGURED event when a
+                                * USB_REQ_SET_CONFIGURATION setup packet is
+                                * received, so we should already be in the
+                                * state STATE_CONFIGURED.
+                                */
+                               udc_state_transition_up (udc_device->device_state, STATE_CONFIGURED);
+                       } else {
+                               UDCDBG ("device deconfigured");
+                               udc_state_transition_down (udc_device->device_state, STATE_ADDRESSED);
+                       }
+               }
+       }
+
+       /* Clear interrupt source */
+       outw (UDC_DS_Chg, UDC_IRQ_SRC);
+
+       /* Save current DEVSTAT */
+       udc_devstat = devstat;
+}
+
+/* Handle SETUP USB interrupt.
+ * This function implements TRM Figure 14-14.
+ */
+static void omap1510_udc_setup (struct usb_endpoint_instance *endpoint)
+{
+       UDCDBG ("-> Entering device setup");
+
+       do {
+               const int setup_pktsize = 8;
+               unsigned char *datap =
+                       (unsigned char *) &ep0_urb->device_request;
+
+               /* Gain access to EP 0 setup FIFO */
+               outw (UDC_Setup_Sel, UDC_EP_NUM);
+
+               /* Read control request data */
+               insb (UDC_DATA, datap, setup_pktsize);
+
+               UDCDBGA ("EP0 setup read [%x %x %x %x %x %x %x %x]",
+                        *(datap + 0), *(datap + 1), *(datap + 2),
+                        *(datap + 3), *(datap + 4), *(datap + 5),
+                        *(datap + 6), *(datap + 7));
+
+               /* Reset EP0 setup FIFO */
+               outw (0, UDC_EP_NUM);
+       } while (inw (UDC_IRQ_SRC) & UDC_Setup);
+
+       /* Try to process setup packet */
+       if (ep0_recv_setup (ep0_urb)) {
+               /* Not a setup packet, stall next EP0 transaction */
+               udc_stall_ep (0);
+               UDCDBG ("can't parse setup packet, still waiting for setup");
+               return;
+       }
+
+       /* Check direction */
+       if ((ep0_urb->device_request.bmRequestType & USB_REQ_DIRECTION_MASK)
+           == USB_REQ_HOST2DEVICE) {
+               UDCDBG ("control write on EP0");
+               if (le16_to_cpu (ep0_urb->device_request.wLength)) {
+                       /* We don't support control write data stages.
+                        * The only standard control write request with a data
+                        * stage is SET_DESCRIPTOR, and ep0_recv_setup doesn't
+                        * support that so we just stall those requests.  A
+                        * function driver might support a non-standard
+                        * write request with a data stage, but it isn't
+                        * obvious what we would do with the data if we read it
+                        * so we'll just stall it.  It seems like the API isn't
+                        * quite right here.
+                        */
+#if 0
+                       /* Here is what we would do if we did support control
+                        * write data stages.
+                        */
+                       ep0_urb->actual_length = 0;
+                       outw (0, UDC_EP_NUM);
+                       /* enable the EP0 rx FIFO */
+                       outw (UDC_Set_FIFO_En, UDC_CTRL);
+#else
+                       /* Stall this request */
+                       UDCDBG ("Stalling unsupported EP0 control write data "
+                               "stage.");
+                       udc_stall_ep (0);
+#endif
+               } else {
+                       omap1510_prepare_for_control_write_status (ep0_urb);
+               }
+       } else {
+               UDCDBG ("control read on EP0");
+               /* The ep0_recv_setup function has already placed our response
+                * packet data in ep0_urb->buffer and the packet length in
+                * ep0_urb->actual_length.
+                */
+               endpoint->tx_urb = ep0_urb;
+               endpoint->sent = 0;
+               /* select the EP0 tx FIFO */
+               outw (UDC_EP_Dir | UDC_EP_Sel, UDC_EP_NUM);
+               /* Write packet data to the FIFO.  omap1510_write_noniso_tx_fifo
+                * will update endpoint->last with the number of bytes written
+                * to the FIFO.
+                */
+               omap1510_write_noniso_tx_fifo (endpoint);
+               /* enable the FIFO to start the packet transmission */
+               outw (UDC_Set_FIFO_En, UDC_CTRL);
+               /* deselect the EP0 tx FIFO */
+               outw (UDC_EP_Dir, UDC_EP_NUM);
+       }
+
+       UDCDBG ("<- Leaving device setup");
+}
+
+/* Handle endpoint 0 RX interrupt
+ * This routine implements TRM Figure 14-16.
+ */
+static void omap1510_udc_ep0_rx (struct usb_endpoint_instance *endpoint)
+{
+       unsigned short status;
+
+       UDCDBG ("RX on EP0");
+       /* select EP0 rx FIFO */
+       outw (UDC_EP_Sel, UDC_EP_NUM);
+
+       status = inw (UDC_STAT_FLG);
+
+       if (status & UDC_ACK) {
+               /* Check direction */
+               if ((ep0_urb->device_request.bmRequestType
+                    & USB_REQ_DIRECTION_MASK) == USB_REQ_HOST2DEVICE) {
+                       /* This rx interrupt must be for a control write data
+                        * stage packet.
+                        *
+                        * We don't support control write data stages.
+                        * We should never end up here.
+                        */
+
+                       /* clear the EP0 rx FIFO */
+                       outw (UDC_Clr_EP, UDC_CTRL);
+
+                       /* deselect the EP0 rx FIFO */
+                       outw (0, UDC_EP_NUM);
+
+                       UDCDBG ("Stalling unexpected EP0 control write "
+                               "data stage packet");
+                       udc_stall_ep (0);
+               } else {
+                       /* This rx interrupt must be for a control read status
+                        * stage packet.
+                        */
+                       UDCDBG ("ACK on EP0 control read status stage packet");
+                       /* deselect EP0 rx FIFO */
+                       outw (0, UDC_EP_NUM);
+               }
+       } else if (status & UDC_STALL) {
+               UDCDBG ("EP0 stall during RX");
+               /* deselect EP0 rx FIFO */
+               outw (0, UDC_EP_NUM);
+       } else {
+               /* deselect EP0 rx FIFO */
+               outw (0, UDC_EP_NUM);
+       }
+}
+
+/* Handle endpoint 0 TX interrupt
+ * This routine implements TRM Figure 14-18.
+ */
+static void omap1510_udc_ep0_tx (struct usb_endpoint_instance *endpoint)
+{
+       unsigned short status;
+       struct usb_device_request *request = &ep0_urb->device_request;
+
+       UDCDBG ("TX on EP0");
+       /* select EP0 TX FIFO */
+       outw (UDC_EP_Dir | UDC_EP_Sel, UDC_EP_NUM);
+
+       status = inw (UDC_STAT_FLG);
+       if (status & UDC_ACK) {
+               /* Check direction */
+               if ((request->bmRequestType & USB_REQ_DIRECTION_MASK) ==
+                   USB_REQ_HOST2DEVICE) {
+                       /* This tx interrupt must be for a control write status
+                        * stage packet.
+                        */
+                       UDCDBG ("ACK on EP0 control write status stage packet");
+                       /* deselect EP0 TX FIFO */
+                       outw (UDC_EP_Dir, UDC_EP_NUM);
+               } else {
+                       /* This tx interrupt must be for a control read data
+                        * stage packet.
+                        */
+                       int wLength = le16_to_cpu (request->wLength);
+
+                       /* Update our count of bytes sent so far in this
+                        * transfer.
+                        */
+                       endpoint->sent += endpoint->last;
+
+                       /* We are finished with this transfer if we have sent
+                        * all of the bytes in our tx urb (urb->actual_length)
+                        * unless we need a zero-length terminating packet.  We
+                        * need a zero-length terminating packet if we returned
+                        * fewer bytes than were requested (wLength) by the host,
+                        * and the number of bytes we returned is an exact
+                        * multiple of the packet size endpoint->tx_packetSize.
+                        */
+                       if ((endpoint->sent == ep0_urb->actual_length)
+                           && ((ep0_urb->actual_length == wLength)
+                               || (endpoint->last !=
+                                   endpoint->tx_packetSize))) {
+                               /* Done with control read data stage. */
+                               UDCDBG ("control read data stage complete");
+                               /* deselect EP0 TX FIFO */
+                               outw (UDC_EP_Dir, UDC_EP_NUM);
+                               /* select EP0 RX FIFO to prepare for control
+                                * read status stage.
+                                */
+                               outw (UDC_EP_Sel, UDC_EP_NUM);
+                               /* clear the EP0 RX FIFO */
+                               outw (UDC_Clr_EP, UDC_CTRL);
+                               /* enable the EP0 RX FIFO */
+                               outw (UDC_Set_FIFO_En, UDC_CTRL);
+                               /* deselect the EP0 RX FIFO */
+                               outw (0, UDC_EP_NUM);
+                       } else {
+                               /* We still have another packet of data to send
+                                * in this control read data stage or else we
+                                * need a zero-length terminating packet.
+                                */
+                               UDCDBG ("ACK control read data stage packet");
+                               omap1510_write_noniso_tx_fifo (endpoint);
+                               /* enable the EP0 tx FIFO to start transmission */
+                               outw (UDC_Set_FIFO_En, UDC_CTRL);
+                               /* deselect EP0 TX FIFO */
+                               outw (UDC_EP_Dir, UDC_EP_NUM);
+                       }
+               }
+       } else if (status & UDC_STALL) {
+               UDCDBG ("EP0 stall during TX");
+               /* deselect EP0 TX FIFO */
+               outw (UDC_EP_Dir, UDC_EP_NUM);
+       } else {
+               /* deselect EP0 TX FIFO */
+               outw (UDC_EP_Dir, UDC_EP_NUM);
+       }
+}
+
+/* Handle RX transaction on non-ISO endpoint.
+ * This function implements TRM Figure 14-27.
+ * The ep argument is a physical endpoint number for a non-ISO OUT endpoint
+ * in the range 1 to 15.
+ */
+static void omap1510_udc_epn_rx (int ep)
+{
+       unsigned short status;
+
+       /* Check endpoint status */
+       status = inw (UDC_STAT_FLG);
+
+       if (status & UDC_ACK) {
+               int nbytes;
+               struct usb_endpoint_instance *endpoint =
+                       omap1510_find_ep (ep);
+
+               nbytes = omap1510_read_noniso_rx_fifo (endpoint);
+               usbd_rcv_complete (endpoint, nbytes, 0);
+
+               /* enable rx FIFO to prepare for next packet */
+               outw (UDC_Set_FIFO_En, UDC_CTRL);
+       } else if (status & UDC_STALL) {
+               UDCDBGA ("STALL on RX endpoint %d", ep);
+       } else if (status & UDC_NAK) {
+               UDCDBGA ("NAK on RX ep %d", ep);
+       } else {
+               serial_printf ("omap-bi: RX on ep %d with status %x", ep,
+                              status);
+       }
+}
+
+/* Handle TX transaction on non-ISO endpoint.
+ * This function implements TRM Figure 14-29.
+ * The ep argument is a physical endpoint number for a non-ISO IN endpoint
+ * in the range 16 to 30.
+ */
+static void omap1510_udc_epn_tx (int ep)
+{
+       unsigned short status;
+
+       /*serial_printf("omap1510_udc_epn_tx( %x )\n",ep); */
+
+       /* Check endpoint status */
+       status = inw (UDC_STAT_FLG);
+
+       if (status & UDC_ACK) {
+               struct usb_endpoint_instance *endpoint =
+                       omap1510_find_ep (ep);
+
+               /* We need to transmit a terminating zero-length packet now if
+                * we have sent all of the data in this URB and the transfer
+                * size was an exact multiple of the packet size.
+                */
+               if (endpoint->tx_urb
+                   && (endpoint->last == endpoint->tx_packetSize)
+                   && (endpoint->tx_urb->actual_length - endpoint->sent -
+                       endpoint->last == 0)) {
+                       /* Prepare to transmit a zero-length packet. */
+                       endpoint->sent += endpoint->last;
+                       /* write 0 bytes of data to FIFO */
+                       omap1510_write_noniso_tx_fifo (endpoint);
+                       /* enable tx FIFO to start transmission */
+                       outw (UDC_Set_FIFO_En, UDC_CTRL);
+               } else if (endpoint->tx_urb
+                          && endpoint->tx_urb->actual_length) {
+                       /* retire the data that was just sent */
+                       usbd_tx_complete (endpoint);
+                       /* Check to see if we have more data ready to transmit
+                        * now.
+                        */
+                       if (endpoint->tx_urb
+                           && endpoint->tx_urb->actual_length) {
+                               /* write data to FIFO */
+                               omap1510_write_noniso_tx_fifo (endpoint);
+                               /* enable tx FIFO to start transmission */
+                               outw (UDC_Set_FIFO_En, UDC_CTRL);
+                       }
+               }
+       } else if (status & UDC_STALL) {
+               UDCDBGA ("STALL on TX endpoint %d", ep);
+       } else if (status & UDC_NAK) {
+               UDCDBGA ("NAK on TX endpoint %d", ep);
+       } else {
+               /*serial_printf("omap-bi: TX on ep %d with status %x\n", ep, status); */
+       }
+}
+
+
+/*
+-------------------------------------------------------------------------------
+*/
+
+/* Handle general USB interrupts and dispatch according to type.
+ * This function implements TRM Figure 14-13.
+ */
+void omap1510_udc_irq (void)
+{
+       u16 irq_src = inw (UDC_IRQ_SRC);
+       int valid_irq = 0;
+
+       if (!(irq_src & ~UDC_SOF_Flg))  /* ignore SOF interrupts ) */
+               return;
+
+       UDCDBGA ("< IRQ #%d start >- %x", udc_interrupts, irq_src);
+       /*serial_printf("< IRQ #%d start >- %x\n", udc_interrupts, irq_src); */
+
+       if (irq_src & UDC_DS_Chg) {
+               /* Device status changed */
+               omap1510_udc_state_changed ();
+               valid_irq++;
+       }
+       if (irq_src & UDC_EP0_RX) {
+               /* Endpoint 0 receive */
+               outw (UDC_EP0_RX, UDC_IRQ_SRC); /* ack interrupt */
+               omap1510_udc_ep0_rx (udc_device->bus->endpoint_array + 0);
+               valid_irq++;
+       }
+       if (irq_src & UDC_EP0_TX) {
+               /* Endpoint 0 transmit */
+               outw (UDC_EP0_TX, UDC_IRQ_SRC); /* ack interrupt */
+               omap1510_udc_ep0_tx (udc_device->bus->endpoint_array + 0);
+               valid_irq++;
+       }
+       if (irq_src & UDC_Setup) {
+               /* Device setup */
+               omap1510_udc_setup (udc_device->bus->endpoint_array + 0);
+               valid_irq++;
+       }
+       /*if (!valid_irq) */
+       /*      serial_printf("unknown interrupt, IRQ_SRC %.4x\n", irq_src); */
+       UDCDBGA ("< IRQ #%d end >", udc_interrupts);
+       udc_interrupts++;
+}
+
+/* This function implements TRM Figure 14-26. */
+void omap1510_udc_noniso_irq (void)
+{
+       unsigned short epnum;
+       unsigned short irq_src = inw (UDC_IRQ_SRC);
+       int valid_irq = 0;
+
+       if (!(irq_src & (UDC_EPn_RX | UDC_EPn_TX)))
+               return;
+
+       UDCDBGA ("non-ISO IRQ, IRQ_SRC %x", inw (UDC_IRQ_SRC));
+
+       if (irq_src & UDC_EPn_RX) {     /* Endpoint N OUT transaction */
+               /* Determine the endpoint number for this interrupt */
+               epnum = (inw (UDC_EPN_STAT) & 0x0f00) >> 8;
+               UDCDBGA ("RX on ep %x", epnum);
+
+               /* acknowledge interrupt */
+               outw (UDC_EPn_RX, UDC_IRQ_SRC);
+
+               if (epnum) {
+                       /* select the endpoint FIFO */
+                       outw (UDC_EP_Sel | epnum, UDC_EP_NUM);
+
+                       omap1510_udc_epn_rx (epnum);
+
+                       /* deselect the endpoint FIFO */
+                       outw (epnum, UDC_EP_NUM);
+               }
+               valid_irq++;
+       }
+       if (irq_src & UDC_EPn_TX) {     /* Endpoint N IN transaction */
+               /* Determine the endpoint number for this interrupt */
+               epnum = (inw (UDC_EPN_STAT) & 0x000f) | USB_DIR_IN;
+               UDCDBGA ("TX on ep %x", epnum);
+
+               /* acknowledge interrupt */
+               outw (UDC_EPn_TX, UDC_IRQ_SRC);
+
+               if (epnum) {
+                       /* select the endpoint FIFO */
+                       outw (UDC_EP_Sel | UDC_EP_Dir | epnum, UDC_EP_NUM);
+
+                       omap1510_udc_epn_tx (epnum);
+
+                       /* deselect the endpoint FIFO */
+                       outw (UDC_EP_Dir | epnum, UDC_EP_NUM);
+               }
+               valid_irq++;
+       }
+       if (!valid_irq)
+               serial_printf (": unknown non-ISO interrupt, IRQ_SRC %.4x\n",
+                              irq_src);
+}
+
+/*
+-------------------------------------------------------------------------------
+*/
+
+
+/*
+ * Start of public functions.
+ */
+
+/* Called to start packet transmission. */
+void udc_endpoint_write (struct usb_endpoint_instance *endpoint)
+{
+       unsigned short epnum =
+               endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
+
+       UDCDBGA ("Starting transmit on ep %x", epnum);
+
+       if (endpoint->tx_urb) {
+               /* select the endpoint FIFO */
+               outw (UDC_EP_Sel | UDC_EP_Dir | epnum, UDC_EP_NUM);
+               /* write data to FIFO */
+               omap1510_write_noniso_tx_fifo (endpoint);
+               /* enable tx FIFO to start transmission */
+               outw (UDC_Set_FIFO_En, UDC_CTRL);
+               /* deselect the endpoint FIFO */
+               outw (UDC_EP_Dir | epnum, UDC_EP_NUM);
+       }
+}
+
+/* Start to initialize h/w stuff */
+int udc_init (void)
+{
+       u16 udc_rev;
+       uchar wert;
+
+       udc_device = NULL;
+
+       UDCDBG ("starting");
+
+       /* Check peripheral reset. Must be 1 to make sure
+          MPU TIPB peripheral reset is inactive */
+       UDCREG (ARM_RSTCT2);
+
+       /* 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
+        * here.
+        */
+       outw ((1 << 4) | (1 << 5), CLOCK_CTRL);
+       UDCREG (CLOCK_CTRL);
+       /* Set and check APLL */
+       outw (0x0008, APLL_CTRL);
+       UDCREG (APLL_CTRL);
+       /* Set and check DPLL */
+       outw (0x2210, DPLL_CTRL);
+       UDCREG (DPLL_CTRL);
+       /* Set and check SOFT */
+       outw ((1 << 4) | (1 << 3) | 1, SOFT_REQ);
+       /* Short delay to wait for DPLL */
+       udelay (1000);
+
+       /* Print banner with device revision */
+       udc_rev = inw (UDC_REV) & 0xff;
+       printf ("USB:   TI OMAP1510 USB function module rev %d.%d\n",
+               udc_rev >> 4, udc_rev & 0xf);
+
+       /* Configure some Sofia Unit registers
+        */
+       i2c_read (0x32, 0x04, 1, &wert, 1);     /* SOF_Control_CONT */
+       wert |= 0x04;           /* SOF_ContCONT_dis_usb_det */
+       i2c_write (0x32, 0x04, 1, &wert, 1);
+
+       i2c_read (0x32, 0x03, 1, &wert, 1);     /* SOF_Control */
+       wert |= 0x01;           /* SOF_Cont_usb_en */
+       i2c_write (0x32, 0x03, 1, &wert, 1);
+
+       /* The VBUS_MODE bit selects whether VBUS detection is done via
+        * software (1) or hardware (0).  When software detection is
+        * selected, VBUS_CTRL selects whether USB is not connected (0)
+        * or connected (1).
+        */
+       outl (inl (FUNC_MUX_CTRL_0) | UDC_VBUS_MODE, FUNC_MUX_CTRL_0);
+       outl (inl (FUNC_MUX_CTRL_0) & ~UDC_VBUS_CTRL, FUNC_MUX_CTRL_0);
+       UDCREGL (FUNC_MUX_CTRL_0);
+
+       /*
+        * At this point, device is ready for configuration...
+        */
+
+       UDCDBG ("disable USB interrupts");
+       outw (0, UDC_IRQ_EN);
+       UDCREG (UDC_IRQ_EN);
+
+       UDCDBG ("disable USB DMA");
+       outw (0, UDC_DMA_IRQ_EN);
+       UDCREG (UDC_DMA_IRQ_EN);
+
+       UDCDBG ("initialize SYSCON1");
+       outw (UDC_Self_Pwr | UDC_Pullup_En, UDC_SYSCON1);
+       UDCREG (UDC_SYSCON1);
+
+       return 0;
+}
+
+/* Stall endpoint */
+static void udc_stall_ep (unsigned int ep_addr)
+{
+       /*int ep_addr = PHYS_EP_TO_EP_ADDR(ep); */
+       int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK;
+
+       UDCDBGA ("stall ep_addr %d", ep_addr);
+
+       /* REVISIT?
+        * The OMAP TRM section 14.2.4.2 says we must check that the FIFO
+        * is empty before halting the endpoint.  The current implementation
+        * doesn't check that the FIFO is empty.
+        */
+
+       if (!ep_num) {
+               outw (UDC_Stall_Cmd, UDC_SYSCON2);
+       } else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
+               if (inw (UDC_EP_RX (ep_num)) & UDC_EPn_RX_Valid) {
+                       /* we have a valid rx endpoint, so halt it */
+                       outw (UDC_EP_Sel | ep_num, UDC_EP_NUM);
+                       outw (UDC_Set_Halt, UDC_CTRL);
+                       outw (ep_num, UDC_EP_NUM);
+               }
+       } else {
+               if (inw (UDC_EP_TX (ep_num)) & UDC_EPn_TX_Valid) {
+                       /* we have a valid tx endpoint, so halt it */
+                       outw (UDC_EP_Sel | UDC_EP_Dir | ep_num, UDC_EP_NUM);
+                       outw (UDC_Set_Halt, UDC_CTRL);
+                       outw (ep_num, UDC_EP_NUM);
+               }
+       }
+}
+
+/* Reset endpoint */
+#if 0
+static void udc_reset_ep (unsigned int ep_addr)
+{
+       /*int ep_addr = PHYS_EP_TO_EP_ADDR(ep); */
+       int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK;
+
+       UDCDBGA ("reset ep_addr %d", ep_addr);
+
+       if (!ep_num) {
+               /* control endpoint 0 can't be reset */
+       } else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
+               UDCDBGA ("UDC_EP_RX(%d) = 0x%04x", ep_num,
+                        inw (UDC_EP_RX (ep_num)));
+               if (inw (UDC_EP_RX (ep_num)) & UDC_EPn_RX_Valid) {
+                       /* we have a valid rx endpoint, so reset it */
+                       outw (ep_num | UDC_EP_Sel, UDC_EP_NUM);
+                       outw (UDC_Reset_EP, UDC_CTRL);
+                       outw (ep_num, UDC_EP_NUM);
+                       UDCDBGA ("OUT endpoint %d reset", ep_num);
+               }
+       } else {
+               UDCDBGA ("UDC_EP_TX(%d) = 0x%04x", ep_num,
+                        inw (UDC_EP_TX (ep_num)));
+               /* Resetting of tx endpoints seems to be causing the USB function
+                * module to fail, which causes problems when the driver is
+                * uninstalled.  We'll skip resetting tx endpoints for now until
+                * we figure out what the problem is.
+                */
+#if 0
+               if (inw (UDC_EP_TX (ep_num)) & UDC_EPn_TX_Valid) {
+                       /* we have a valid tx endpoint, so reset it */
+                       outw (ep_num | UDC_EP_Dir | UDC_EP_Sel, UDC_EP_NUM);
+                       outw (UDC_Reset_EP, UDC_CTRL);
+                       outw (ep_num | UDC_EP_Dir, UDC_EP_NUM);
+                       UDCDBGA ("IN endpoint %d reset", ep_num);
+               }
+#endif
+       }
+}
+#endif
+
+/* ************************************************************************** */
+
+/**
+ * udc_check_ep - check logical endpoint
+  *
+ * Return physical endpoint number to use for this logical endpoint or zero if not valid.
+ */
+#if 0
+int udc_check_ep (int logical_endpoint, int packetsize)
+{
+       if ((logical_endpoint == 0x80) ||
+           ((logical_endpoint & 0x8f) != logical_endpoint)) {
+               return 0;
+       }
+
+       switch (packetsize) {
+       case 8:
+       case 16:
+       case 32:
+       case 64:
+       case 128:
+       case 256:
+       case 512:
+               break;
+       default:
+               return 0;
+       }
+
+       return EP_ADDR_TO_PHYS_EP (logical_endpoint);
+}
+#endif
+
+/*
+ * udc_setup_ep - setup endpoint
+ *
+ * Associate a physical endpoint with endpoint_instance
+ */
+void udc_setup_ep (struct usb_device_instance *device,
+                  unsigned int ep, struct usb_endpoint_instance *endpoint)
+{
+       UDCDBGA ("setting up endpoint addr %x", endpoint->endpoint_address);
+
+       /* This routine gets called by bi_modinit for endpoint 0 and from
+        * bi_config for all of the other endpoints.  bi_config gets called
+        * during the DEVICE_CREATE, DEVICE_CONFIGURED, and
+        * DEVICE_SET_INTERFACE events.  We need to reconfigure the OMAP packet
+        * RAM after bi_config scans the selected device configuration and
+        * initializes the endpoint structures, but before this routine enables
+        * the OUT endpoint FIFOs.  Since bi_config calls this routine in a
+        * loop for endpoints 1 through UDC_MAX_ENDPOINTS, we reconfigure our
+        * packet RAM here when ep==1.
+        * I really hate to do this here, but it seems like the API exported
+        * by the USB bus interface controller driver to the usbd-bi module
+        * isn't quite right so there is no good place to do this.
+        */
+       if (ep == 1) {
+               omap1510_deconfigure_device ();
+               omap1510_configure_device (device);
+       }
+
+       if (endpoint && (ep < UDC_MAX_ENDPOINTS)) {
+               int ep_addr = endpoint->endpoint_address;
+
+               if (!ep_addr) {
+                       /* nothing to do for endpoint 0 */
+               } else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
+                       /* nothing to do for IN (tx) endpoints */
+               } else {        /* OUT (rx) endpoint */
+                       if (endpoint->rcv_packetSize) {
+                               /*struct urb* urb = &(urb_out_array[ep&0xFF]); */
+                               /*urb->endpoint = endpoint; */
+                               /*urb->device = device; */
+                               /*urb->buffer_length = sizeof(urb->buffer); */
+
+                               /*endpoint->rcv_urb = urb; */
+                               omap1510_prepare_endpoint_for_rx (ep_addr);
+                       }
+               }
+       }
+}
+
+/**
+ * udc_disable_ep - disable endpoint
+ * @ep:
+ *
+ * Disable specified endpoint
+ */
+#if 0
+void udc_disable_ep (unsigned int ep_addr)
+{
+       /*int ep_addr = PHYS_EP_TO_EP_ADDR(ep); */
+       int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK;
+       struct usb_endpoint_instance *endpoint = omap1510_find_ep (ep_addr);    /*udc_device->bus->endpoint_array + ep; */
+
+       UDCDBGA ("disable ep_addr %d", ep_addr);
+
+       if (!ep_num) {
+               /* nothing to do for endpoint 0 */ ;
+       } else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
+               if (endpoint->tx_packetSize) {
+                       /* we have a valid tx endpoint */
+                       /*usbd_flush_tx(endpoint); */
+                       endpoint->tx_urb = NULL;
+               }
+       } else {
+               if (endpoint->rcv_packetSize) {
+                       /* we have a valid rx endpoint */
+                       /*usbd_flush_rcv(endpoint); */
+                       endpoint->rcv_urb = NULL;
+               }
+       }
+}
+#endif
+
+/* ************************************************************************** */
+
+/**
+ * udc_connected - is the USB cable connected
+ *
+ * Return non-zero if cable is connected.
+ */
+#if 0
+int udc_connected (void)
+{
+       return ((inw (UDC_DEVSTAT) & UDC_ATT) == UDC_ATT);
+}
+#endif
+
+/* Turn on the USB connection by enabling the pullup resistor */
+void udc_connect (void)
+{
+       UDCDBG ("connect, enable Pullup");
+       outl (0x00000018, FUNC_MUX_CTRL_D);
+}
+
+/* Turn off the USB connection by disabling the pullup resistor */
+void udc_disconnect (void)
+{
+       UDCDBG ("disconnect, disable Pullup");
+       outl (0x00000000, FUNC_MUX_CTRL_D);
+}
+
+/* ************************************************************************** */
+
+
+/*
+ * udc_disable_interrupts - disable interrupts
+ * switch off interrupts
+ */
+#if 0
+void udc_disable_interrupts (struct usb_device_instance *device)
+{
+       UDCDBG ("disabling all interrupts");
+       outw (0, UDC_IRQ_EN);
+}
+#endif
+
+/* ************************************************************************** */
+
+/**
+ * udc_ep0_packetsize - return ep0 packetsize
+ */
+#if 0
+int udc_ep0_packetsize (void)
+{
+       return EP0_PACKETSIZE;
+}
+#endif
+
+/* Switch on the UDC */
+void udc_enable (struct usb_device_instance *device)
+{
+       UDCDBGA ("enable device %p, status %d", device, device->status);
+
+       /* initialize driver state variables */
+       udc_devstat = 0;
+
+       /* 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",
+                              ep0_urb);
+       }
+
+       UDCDBG ("Check clock status");
+       UDCREG (STATUS_REQ);
+
+       /* The VBUS_MODE bit selects whether VBUS detection is done via
+        * software (1) or hardware (0).  When software detection is
+        * selected, VBUS_CTRL selects whether USB is not connected (0)
+        * or connected (1).
+        */
+       outl (inl (FUNC_MUX_CTRL_0) | UDC_VBUS_CTRL | UDC_VBUS_MODE,
+             FUNC_MUX_CTRL_0);
+       UDCREGL (FUNC_MUX_CTRL_0);
+
+       omap1510_configure_device (device);
+}
+
+/* Switch off the UDC */
+void udc_disable (void)
+{
+       UDCDBG ("disable UDC");
+
+       omap1510_deconfigure_device ();
+
+       /* The VBUS_MODE bit selects whether VBUS detection is done via
+        * software (1) or hardware (0).  When software detection is
+        * selected, VBUS_CTRL selects whether USB is not connected (0)
+        * or connected (1).
+        */
+       outl (inl (FUNC_MUX_CTRL_0) | UDC_VBUS_MODE, FUNC_MUX_CTRL_0);
+       outl (inl (FUNC_MUX_CTRL_0) & ~UDC_VBUS_CTRL, FUNC_MUX_CTRL_0);
+       UDCREGL (FUNC_MUX_CTRL_0);
+
+       /* Free ep0 URB */
+       if (ep0_urb) {
+               /*usbd_dealloc_urb(ep0_urb); */
+               ep0_urb = NULL;
+       }
+
+       /* Reset device pointer.
+        * We ought to do this here to balance the initialization of udc_device
+        * in udc_enable, but some of our other exported functions get called
+        * by the bus interface driver after udc_disable, so we have to hang on
+        * to the device pointer to avoid a null pointer dereference. */
+       /* udc_device = NULL; */
+}
+
+/**
+ * udc_startup - allow udc code to do any additional startup
+ */
+void udc_startup_events (struct usb_device_instance *device)
+{
+       /* The DEVICE_INIT event puts the USB device in the state STATE_INIT. */
+       usbd_device_event_irq (device, DEVICE_INIT, 0);
+
+       /* The DEVICE_CREATE event puts the USB device in the state
+        * STATE_ATTACHED.
+        */
+       usbd_device_event_irq (device, DEVICE_CREATE, 0);
+
+       /* Some USB controller driver implementations signal
+        * DEVICE_HUB_CONFIGURED and DEVICE_RESET events here.
+        * DEVICE_HUB_CONFIGURED causes a transition to the state STATE_POWERED,
+        * and DEVICE_RESET causes a transition to the state STATE_DEFAULT.
+        * The OMAP USB client controller has the capability to detect when the
+        * USB cable is connected to a powered USB bus via the ATT bit in the
+        * DEVSTAT register, so we will defer the DEVICE_HUB_CONFIGURED and
+        * DEVICE_RESET events until later.
+        */
+
+       udc_enable (device);
+}
+
+#endif
diff --git a/drivers/usbtty.c b/drivers/usbtty.c
new file mode 100644 (file)
index 0000000..2f89e2b
--- /dev/null
@@ -0,0 +1,647 @@
+/*
+ * (C) Copyright 2003
+ * Gerry Hamel, geh@ti.com, Texas Instruments
+ *
+ * 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 <common.h>
+
+#ifdef CONFIG_USB_TTY
+
+#include <circbuf.h>
+#include <devices.h>
+#include "usbtty.h"
+
+#if 0
+#define TTYDBG(fmt,args...) serial_printf("[%s] %s %d: "fmt, __FILE__,__FUNCTION__,__LINE__,##args)
+#else
+#define TTYDBG(fmt,args...) do{}while(0)
+#endif
+
+#if 0
+#define TTYERR(fmt,args...) serial_printf("ERROR![%s] %s %d: "fmt, __FILE__,__FUNCTION__,__LINE__,##args)
+#else
+#define TTYERR(fmt,args...) do{}while(0)
+#endif
+
+/*
+ * Buffers to hold input and output data
+ */
+#define USBTTY_BUFFER_SIZE 256
+static circbuf_t usbtty_input;
+static circbuf_t usbtty_output;
+
+
+/*
+ * Instance variables
+ */
+static device_t usbttydev;
+static struct usb_device_instance       device_instance[1];
+static struct usb_bus_instance          bus_instance[1];
+static struct usb_configuration_instance config_instance[NUM_CONFIGS];
+static struct usb_interface_instance    interface_instance[NUM_INTERFACES];
+static struct usb_alternate_instance    alternate_instance[NUM_INTERFACES];
+static struct usb_endpoint_instance     endpoint_instance[NUM_ENDPOINTS+1]; /* one extra for control endpoint */
+
+/*
+ * Static allocation of urbs
+ */
+#define RECV_ENDPOINT 1
+#define TX_ENDPOINT 2
+
+/*
+ * Global flag
+ */
+int usbtty_configured_flag = 0;
+
+
+/*
+ * Descriptors
+ */
+static u8 wstrLang[4] = {4,USB_DT_STRING,0x9,0x4};
+static u8 wstrManufacturer[2 + 2*(sizeof(CONFIG_USBD_MANUFACTURER)-1)];
+static u8 wstrProduct[2 + 2*(sizeof(CONFIG_USBD_PRODUCT_NAME)-1)];
+static u8 wstrSerial[2 + 2*(sizeof(CONFIG_USBD_SERIAL_NUMBER)-1)];
+static u8 wstrConfiguration[2 + 2*(sizeof(CONFIG_USBD_CONFIGURATION_STR)-1)];
+static u8 wstrInterface[2 + 2*(sizeof(CONFIG_USBD_INTERFACE_STR)-1)];
+
+static struct usb_string_descriptor *usbtty_string_table[] = {
+  (struct usb_string_descriptor*)wstrLang,
+  (struct usb_string_descriptor*)wstrManufacturer,
+  (struct usb_string_descriptor*)wstrProduct,
+  (struct usb_string_descriptor*)wstrSerial,
+  (struct usb_string_descriptor*)wstrConfiguration,
+  (struct usb_string_descriptor*)wstrInterface
+};
+extern struct usb_string_descriptor **usb_strings; /* defined and used by omap1510_ep0.c */
+
+static struct usb_device_descriptor device_descriptor = {
+  bLength:           sizeof(struct usb_device_descriptor),
+  bDescriptorType:    USB_DT_DEVICE,
+  bcdUSB:            USB_BCD_VERSION,
+  bDeviceClass:              USBTTY_DEVICE_CLASS,
+  bDeviceSubClass:    USBTTY_DEVICE_SUBCLASS,
+  bDeviceProtocol:    USBTTY_DEVICE_PROTOCOL,
+  bMaxPacketSize0:    EP0_MAX_PACKET_SIZE,
+  idVendor:          CONFIG_USBD_VENDORID,
+  idProduct:         CONFIG_USBD_PRODUCTID,
+  bcdDevice:         USBTTY_BCD_DEVICE,
+  iManufacturer:      STR_MANUFACTURER,
+  iProduct:          STR_PRODUCT,
+  iSerialNumber:      STR_SERIAL,
+  bNumConfigurations: NUM_CONFIGS
+  };
+static struct usb_configuration_descriptor config_descriptors[NUM_CONFIGS] = {
+  {
+    bLength:            sizeof(struct usb_configuration_descriptor),
+    bDescriptorType:    USB_DT_CONFIG,
+    wTotalLength:       (sizeof(struct usb_configuration_descriptor)*NUM_CONFIGS) +
+                        (sizeof(struct usb_interface_descriptor)*NUM_INTERFACES) +
+                        (sizeof(struct usb_endpoint_descriptor)*NUM_ENDPOINTS),
+    bNumInterfaces:     NUM_INTERFACES,
+    bConfigurationValue: 1,
+    iConfiguration:     STR_CONFIG,
+    bmAttributes:       BMATTRIBUTE_SELF_POWERED | BMATTRIBUTE_RESERVED,
+    bMaxPower:          USBTTY_MAXPOWER
+  },
+};
+static struct usb_interface_descriptor interface_descriptors[NUM_INTERFACES] = {
+  {
+    bLength:            sizeof(struct usb_interface_descriptor),
+    bDescriptorType:    USB_DT_INTERFACE,
+    bInterfaceNumber:   0,
+    bAlternateSetting:  0,
+    bNumEndpoints:      NUM_ENDPOINTS,
+    bInterfaceClass:    USBTTY_INTERFACE_CLASS,
+    bInterfaceSubClass:         USBTTY_INTERFACE_SUBCLASS,
+    bInterfaceProtocol:         USBTTY_INTERFACE_PROTOCOL,
+    iInterface:                 STR_INTERFACE
+  },
+};
+static struct usb_endpoint_descriptor ep_descriptors[NUM_ENDPOINTS] = {
+  {
+    bLength:            sizeof(struct usb_endpoint_descriptor),
+    bDescriptorType:    USB_DT_ENDPOINT,
+    bEndpointAddress:   CONFIG_USBD_SERIAL_OUT_ENDPOINT | USB_DIR_OUT,
+    bmAttributes:       USB_ENDPOINT_XFER_BULK,
+    wMaxPacketSize:     CONFIG_USBD_SERIAL_OUT_PKTSIZE,
+    bInterval:          0
+  },
+  {
+    bLength:            sizeof(struct usb_endpoint_descriptor),
+    bDescriptorType:    USB_DT_ENDPOINT,
+    bEndpointAddress:   CONFIG_USBD_SERIAL_IN_ENDPOINT | USB_DIR_IN,
+    bmAttributes:       USB_ENDPOINT_XFER_BULK,
+    wMaxPacketSize:     CONFIG_USBD_SERIAL_IN_PKTSIZE,
+    bInterval:          0
+  },
+  {
+    bLength:            sizeof(struct usb_endpoint_descriptor),
+    bDescriptorType:    USB_DT_ENDPOINT,
+    bEndpointAddress:   CONFIG_USBD_SERIAL_INT_ENDPOINT | USB_DIR_IN,
+    bmAttributes:       USB_ENDPOINT_XFER_INT,
+    wMaxPacketSize:     CONFIG_USBD_SERIAL_INT_PKTSIZE,
+    bInterval:          0
+  },
+};
+static struct usb_endpoint_descriptor *ep_descriptor_ptrs[NUM_ENDPOINTS] = {
+  &(ep_descriptors[0]),
+  &(ep_descriptors[1]),
+  &(ep_descriptors[2]),
+};
+
+/* utility function for converting char* to wide string used by USB */
+static void str2wide (char *str, u16 * wide)
+{
+       int i;
+
+       for (i = 0; i < strlen (str) && str[i]; i++)
+               wide[i] = (u16) str[i];
+}
+
+/*
+ * Prototypes
+ */
+static void usbtty_init_strings (void);
+static void usbtty_init_instances (void);
+static void usbtty_init_endpoints (void);
+
+static void usbtty_event_handler (struct usb_device_instance *device,
+                                 usb_device_event_t event, int data);
+static int usbtty_configured (void);
+
+static int write_buffer (circbuf_t * buf);
+static int fill_buffer (circbuf_t * buf);
+
+void usbtty_poll (void);
+static void pretend_interrupts (void);
+
+
+/*
+ * Test whether a character is in the RX buffer
+ */
+int usbtty_tstc (void)
+{
+       usbtty_poll ();
+       return (usbtty_input.size > 0);
+}
+
+/*
+ * Read a single byte from the usb client port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int usbtty_getc (void)
+{
+       char c;
+
+       while (usbtty_input.size <= 0) {
+               usbtty_poll ();
+       }
+
+       buf_pop (&usbtty_input, &c, 1);
+       return c;
+}
+
+/*
+ * Output a single byte to the usb client port.
+ */
+void usbtty_putc (const char c)
+{
+       buf_push (&usbtty_output, &c, 1);
+       /* If \n, also do \r */
+       if (c == '\n')
+               buf_push (&usbtty_output, "\r", 1);
+
+       /* Poll at end to handle new data... */
+       if ((usbtty_output.size + 2) >= usbtty_output.totalsize) {
+               usbtty_poll ();
+       }
+}
+
+
+/* usbtty_puts() helper function for finding the next '\n' in a string */
+static int next_nl_pos (const char *s)
+{
+       int i;
+
+       for (i = 0; s[i] != '\0'; i++) {
+               if (s[i] == '\n')
+                       return i;
+       }
+       return i;
+}
+
+/*
+ * Output a string to the usb client port.
+ */
+static void __usbtty_puts (const char *str, int len)
+{
+       int maxlen = usbtty_output.totalsize;
+       int space, n;
+
+       /* break str into chunks < buffer size, if needed */
+       while (len > 0) {
+               space = maxlen - usbtty_output.size;
+
+               /* Empty buffer here, if needed, to ensure space... */
+               if (space <= 0) {
+                       write_buffer (&usbtty_output);
+                       space = maxlen - usbtty_output.size;
+                       if (space <= 0) {
+                               space = len;    /* allow old data to be overwritten. */
+                       }
+               }
+
+               n = MIN (space, MIN (len, maxlen));
+               buf_push (&usbtty_output, str, n);
+
+               str += n;
+               len -= n;
+       }
+}
+
+void usbtty_puts (const char *str)
+{
+       int n;
+       int len = strlen (str);
+
+       /* add '\r' for each '\n' */
+       while (len > 0) {
+               n = next_nl_pos (str);
+
+               if (str[n] == '\n') {
+                       __usbtty_puts (str, n + 1);
+                       __usbtty_puts ("\r", 1);
+                       str += (n + 1);
+                       len -= (n + 1);
+               } else {
+                       /* No \n found.  All done. */
+                       __usbtty_puts (str, n);
+                       break;
+               }
+       }
+
+       /* Poll at end to handle new data... */
+       usbtty_poll ();
+}
+
+/*
+ * Initialize the usb client port.
+ *
+ */
+int drv_usbtty_init (void)
+{
+       int rc;
+
+
+       /* prepare buffers... */
+       buf_init (&usbtty_input, USBTTY_BUFFER_SIZE);
+       buf_init (&usbtty_output, USBTTY_BUFFER_SIZE);
+
+       /* Now, set up USB controller and infrastructure */
+       udc_init ();            /* Basic USB initialization */
+
+       usbtty_init_strings ();
+       usbtty_init_instances ();
+
+       udc_startup_events (device_instance);   /* Enable our device, initialize udc pointers */
+       udc_connect ();         /* Enable pullup for host detection */
+
+       usbtty_init_endpoints ();
+
+       /* Device initialization */
+       memset (&usbttydev, 0, sizeof (usbttydev));
+
+       strcpy (usbttydev.name, "usbtty");
+       usbttydev.ext = 0;      /* No extensions */
+       usbttydev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_OUTPUT;
+       usbttydev.tstc = usbtty_tstc;   /* 'tstc' function */
+       usbttydev.getc = usbtty_getc;   /* 'getc' function */
+       usbttydev.putc = usbtty_putc;   /* 'putc' function */
+       usbttydev.puts = usbtty_puts;   /* 'puts' function */
+
+       rc = device_register (&usbttydev);
+
+       return (rc == 0) ? 1 : rc;
+}
+
+static void usbtty_init_strings (void)
+{
+       struct usb_string_descriptor *string;
+
+       string = (struct usb_string_descriptor *) wstrManufacturer;
+       string->bLength = sizeof (wstrManufacturer);
+       string->bDescriptorType = USB_DT_STRING;
+       str2wide (CONFIG_USBD_MANUFACTURER, string->wData);
+
+       string = (struct usb_string_descriptor *) wstrProduct;
+       string->bLength = sizeof (wstrProduct);
+       string->bDescriptorType = USB_DT_STRING;
+       str2wide (CONFIG_USBD_PRODUCT_NAME, string->wData);
+
+       string = (struct usb_string_descriptor *) wstrSerial;
+       string->bLength = sizeof (wstrSerial);
+       string->bDescriptorType = USB_DT_STRING;
+       str2wide (CONFIG_USBD_SERIAL_NUMBER, string->wData);
+
+       string = (struct usb_string_descriptor *) wstrConfiguration;
+       string->bLength = sizeof (wstrConfiguration);
+       string->bDescriptorType = USB_DT_STRING;
+       str2wide (CONFIG_USBD_CONFIGURATION_STR, string->wData);
+
+       string = (struct usb_string_descriptor *) wstrInterface;
+       string->bLength = sizeof (wstrInterface);
+       string->bDescriptorType = USB_DT_STRING;
+       str2wide (CONFIG_USBD_INTERFACE_STR, string->wData);
+
+       /* Now, initialize the string table for ep0 handling */
+       usb_strings = usbtty_string_table;
+}
+
+static void usbtty_init_instances (void)
+{
+       int i;
+
+       /* initialize device instance */
+       memset (device_instance, 0, sizeof (struct usb_device_instance));
+       device_instance->device_state = STATE_INIT;
+       device_instance->device_descriptor = &device_descriptor;
+       device_instance->event = usbtty_event_handler;
+       device_instance->bus = bus_instance;
+       device_instance->configurations = NUM_CONFIGS;
+       device_instance->configuration_instance_array = config_instance;
+
+       /* initialize bus instance */
+       memset (bus_instance, 0, sizeof (struct usb_bus_instance));
+       bus_instance->device = device_instance;
+       bus_instance->endpoint_array = endpoint_instance;
+       bus_instance->max_endpoints = 1;
+       bus_instance->maxpacketsize = 64;
+       bus_instance->serial_number_str = CONFIG_USBD_SERIAL_NUMBER;
+
+       /* configuration instance */
+       memset (config_instance, 0,
+               sizeof (struct usb_configuration_instance));
+       config_instance->interfaces = NUM_INTERFACES;
+       config_instance->configuration_descriptor = config_descriptors;
+       config_instance->interface_instance_array = interface_instance;
+
+       /* interface instance */
+       memset (interface_instance, 0,
+               sizeof (struct usb_interface_instance));
+       interface_instance->alternates = 1;
+       interface_instance->alternates_instance_array = alternate_instance;
+
+       /* alternates instance */
+       memset (alternate_instance, 0,
+               sizeof (struct usb_alternate_instance));
+       alternate_instance->interface_descriptor = interface_descriptors;
+       alternate_instance->endpoints = NUM_ENDPOINTS;
+       alternate_instance->endpoints_descriptor_array = ep_descriptor_ptrs;
+
+       /* endpoint instances */
+       memset (&endpoint_instance[0], 0,
+               sizeof (struct usb_endpoint_instance));
+       endpoint_instance[0].endpoint_address = 0;
+       endpoint_instance[0].rcv_packetSize = EP0_MAX_PACKET_SIZE;
+       endpoint_instance[0].rcv_attributes = USB_ENDPOINT_XFER_CONTROL;
+       endpoint_instance[0].tx_packetSize = EP0_MAX_PACKET_SIZE;
+       endpoint_instance[0].tx_attributes = USB_ENDPOINT_XFER_CONTROL;
+       udc_setup_ep (device_instance, 0, &endpoint_instance[0]);
+
+       for (i = 1; i <= NUM_ENDPOINTS; i++) {
+               memset (&endpoint_instance[i], 0,
+                       sizeof (struct usb_endpoint_instance));
+
+               endpoint_instance[i].endpoint_address =
+                       ep_descriptors[i - 1].bEndpointAddress;
+
+               endpoint_instance[i].rcv_packetSize =
+                       ep_descriptors[i - 1].wMaxPacketSize;
+               endpoint_instance[i].rcv_attributes =
+                       ep_descriptors[i - 1].bmAttributes;
+
+               endpoint_instance[i].tx_packetSize =
+                       ep_descriptors[i - 1].wMaxPacketSize;
+               endpoint_instance[i].tx_attributes =
+                       ep_descriptors[i - 1].bmAttributes;
+
+               urb_link_init (&endpoint_instance[i].rcv);
+               urb_link_init (&endpoint_instance[i].rdy);
+               urb_link_init (&endpoint_instance[i].tx);
+               urb_link_init (&endpoint_instance[i].done);
+
+               if (endpoint_instance[i].endpoint_address & USB_DIR_IN)
+                       endpoint_instance[i].tx_urb =
+                               usbd_alloc_urb (device_instance,
+                                               &endpoint_instance[i]);
+               else
+                       endpoint_instance[i].rcv_urb =
+                               usbd_alloc_urb (device_instance,
+                                               &endpoint_instance[i]);
+       }
+}
+
+static void usbtty_init_endpoints (void)
+{
+       int i;
+
+       bus_instance->max_endpoints = NUM_ENDPOINTS + 1;
+       for (i = 0; i <= NUM_ENDPOINTS; i++) {
+               udc_setup_ep (device_instance, i, &endpoint_instance[i]);
+       }
+}
+
+
+/*********************************************************************************/
+
+static struct urb *next_urb (struct usb_device_instance *device,
+                            struct usb_endpoint_instance *endpoint)
+{
+       struct urb *current_urb = NULL;
+       int space;
+
+       /* If there's a queue, then we should add to the last urb */
+       if (!endpoint->tx_queue) {
+               current_urb = endpoint->tx_urb;
+       } else {
+               /* Last urb from tx chain */
+               current_urb =
+                       p2surround (struct urb, link, endpoint->tx.prev);
+       }
+
+       /* Make sure this one has enough room */
+       space = current_urb->buffer_length - current_urb->actual_length;
+       if (space > 0) {
+               return current_urb;
+       } else {                /* No space here */
+               /* First look at done list */
+               current_urb = first_urb_detached (&endpoint->done);
+               if (!current_urb) {
+                       current_urb = usbd_alloc_urb (device, endpoint);
+               }
+
+               urb_append (&endpoint->tx, current_urb);
+               endpoint->tx_queue++;
+       }
+       return current_urb;
+}
+
+static int write_buffer (circbuf_t * buf)
+{
+       if (!usbtty_configured ()) {
+               return 0;
+       }
+
+       if (buf->size) {
+
+               struct usb_endpoint_instance *endpoint =
+                       &endpoint_instance[TX_ENDPOINT];
+               struct urb *current_urb = NULL;
+               char *dest;
+
+               int space_avail;
+               int popnum, popped;
+               int total = 0;
+
+               /* Break buffer into urb sized pieces, and link each to the endpoint */
+               while (buf->size > 0) {
+                       current_urb = next_urb (device_instance, endpoint);
+                       if (!current_urb) {
+                               TTYERR ("current_urb is NULL, buf->size %d\n",
+                                       buf->size);
+                               return total;
+                       }
+
+                       dest = current_urb->buffer +
+                               current_urb->actual_length;
+
+                       space_avail =
+                               current_urb->buffer_length -
+                               current_urb->actual_length;
+                       popnum = MIN (space_avail, buf->size);
+                       if (popnum == 0)
+                               break;
+
+                       popped = buf_pop (buf, dest, popnum);
+                       if (popped == 0)
+                               break;
+                       current_urb->actual_length += popped;
+                       total += popped;
+
+                       /* If endpoint->last == 0, then transfers have not started on this endpoint */
+                       if (endpoint->last == 0) {
+                               udc_endpoint_write (endpoint);
+                       }
+
+               }               /* end while */
+               return total;
+       }                       /* end if tx_urb */
+
+       return 0;
+}
+
+static int fill_buffer (circbuf_t * buf)
+{
+       struct usb_endpoint_instance *endpoint =
+               &endpoint_instance[RECV_ENDPOINT];
+
+       if (endpoint->rcv_urb && endpoint->rcv_urb->actual_length) {
+               unsigned int nb = endpoint->rcv_urb->actual_length;
+               char *src = (char *) endpoint->rcv_urb->buffer;
+
+               buf_push (buf, src, nb);
+               endpoint->rcv_urb->actual_length = 0;
+
+               return nb;
+       }
+
+       return 0;
+}
+
+static int usbtty_configured (void)
+{
+       return usbtty_configured_flag;
+}
+
+/*********************************************************************************/
+
+static void usbtty_event_handler (struct usb_device_instance *device,
+                                 usb_device_event_t event, int data)
+{
+       switch (event) {
+       case DEVICE_RESET:
+       case DEVICE_BUS_INACTIVE:
+               usbtty_configured_flag = 0;
+               break;
+       case DEVICE_CONFIGURED:
+               usbtty_configured_flag = 1;
+               break;
+
+       case DEVICE_ADDRESS_ASSIGNED:
+               usbtty_init_endpoints ();
+
+       default:
+               break;
+       }
+}
+
+/*********************************************************************************/
+
+
+/*
+ * Since interrupt handling has not yet been implemented, we use this function
+ * to handle polling.  This is called by the tstc,getc,putc,puts routines to
+ * update the USB state.
+ */
+void usbtty_poll (void)
+{
+       /* New interrupts? */
+       pretend_interrupts ();
+
+       /* Write any output data to host buffer (do this before checking interrupts to avoid missing one) */
+       if (usbtty_configured ()) {
+               write_buffer (&usbtty_output);
+       }
+
+       /* New interrupts? */
+       pretend_interrupts ();
+
+       /* Check for new data from host.. (do this after checking interrupts to get latest data) */
+       if (usbtty_configured ()) {
+               fill_buffer (&usbtty_input);
+       }
+
+       /* New interrupts? */
+       pretend_interrupts ();
+}
+
+static void pretend_interrupts (void)
+{
+       /* Loop while we have interrupts.
+        * If we don't do this, the input chain
+        * polling delay is likely to miss
+        * host requests.
+        */
+       while (inw (UDC_IRQ_SRC) & ~UDC_SOF_Flg) {
+               /* Handle any new IRQs */
+               omap1510_udc_irq ();
+               omap1510_udc_noniso_irq ();
+       }
+}
+#endif
diff --git a/drivers/usbtty.h b/drivers/usbtty.h
new file mode 100644 (file)
index 0000000..79c2fe5
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * (C) Copyright 2003
+ * Gerry Hamel, geh@ti.com, Texas Instruments
+ *
+ * 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
+ *
+ */
+
+#ifndef __USB_TTY_H__
+#define __USB_TTY_H__
+
+
+#include "usbdcore.h"
+#include "usbdcore_omap1510.h"
+
+
+#define NUM_CONFIGS    1
+#define NUM_INTERFACES 1
+#define NUM_ENDPOINTS  3
+
+#define EP0_MAX_PACKET_SIZE 64
+
+#define CONFIG_USBD_CONFIGURATION_STR "TTY via USB"
+#define CONFIG_USBD_INTERFACE_STR     "Simple Serial Data Interface - Bulk Mode"
+
+
+#define CONFIG_USBD_SERIAL_OUT_ENDPOINT 2
+#define CONFIG_USBD_SERIAL_OUT_PKTSIZE 64
+#define CONFIG_USBD_SERIAL_IN_ENDPOINT 1
+#define CONFIG_USBD_SERIAL_IN_PKTSIZE  64
+#define CONFIG_USBD_SERIAL_INT_ENDPOINT 5
+#define CONFIG_USBD_SERIAL_INT_PKTSIZE 16
+
+
+#define USBTTY_DEVICE_CLASS    COMMUNICATIONS_DEVICE_CLASS
+#define USBTTY_DEVICE_SUBCLASS COMMUNICATIONS_NO_SUBCLASS
+#define USBTTY_DEVICE_PROTOCOL COMMUNICATIONS_NO_PROTOCOL
+
+#define USBTTY_INTERFACE_CLASS    0xFF /* Vendor Specific */
+#define USBTTY_INTERFACE_SUBCLASS  0x02
+#define USBTTY_INTERFACE_PROTOCOL  0x01
+
+#define USBTTY_BCD_DEVICE 0x0
+#define USBTTY_MAXPOWER          0x0
+
+#define STR_MANUFACTURER 1
+#define STR_PRODUCT     2
+#define STR_SERIAL      3
+#define STR_CONFIG      4
+#define STR_INTERFACE   5
+
+#endif
diff --git a/include/circbuf.h b/include/circbuf.h
new file mode 100644 (file)
index 0000000..e10ed95
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * (C) Copyright 2003
+ * Gerry Hamel, geh@ti.com, Texas Instruments
+ *
+ * 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
+ *
+ */
+
+#ifndef __CIRCBUF_H__
+#define __CIRCBUF_H__
+
+typedef struct circbuf {
+       unsigned int size;      /* current number of bytes held */
+       unsigned int totalsize; /* number of bytes allocated */
+
+       char *top;              /* pointer to current buffer start */
+       char *tail;             /* pointer to space for next element */
+
+       char *data;             /* all data */
+       char *end;              /* end of data buffer */
+} circbuf_t;
+
+int buf_init (circbuf_t * buf, unsigned int size);
+int buf_free (circbuf_t * buf);
+int buf_pop (circbuf_t * buf, char *dest, unsigned int len);
+int buf_push (circbuf_t * buf, const char *src, unsigned int len);
+
+#endif
diff --git a/include/configs/SX1.h b/include/configs/SX1.h
new file mode 100644 (file)
index 0000000..ca536c5
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * (C) Copyright 2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * If we are developing, we might want to start armboot from ram
+ * so we MUST NOT initialize critical regs like mem-timing ...
+ */
+#define CONFIG_INIT_CRITICAL           /* undef for developing */
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+#define CONFIG_ARM925T 1               /* This is an arm925t CPU       */
+#define CONFIG_OMAP    1               /* in a TI OMAP core    */
+#define CONFIG_OMAP1510 1              /* which is in a 1510 (helen) */
+#define CONFIG_OMAP_SX1 1              /*      a SX1 Board  */
+
+/* input clock of PLL */
+#define CONFIG_SYS_CLK_FREQ    12000000        /* the SX1 has 12MHz input clock */
+
+#undef CONFIG_USE_IRQ                  /* we don't need IRQ/FIQ stuff */
+
+#define CONFIG_MISC_INIT_R
+
+#define CONFIG_CMDLINE_TAG      1      /* enable passing of ATAGs      */
+#define CONFIG_SETUP_MEMORY_TAGS 1
+#define CONFIG_INITRD_TAG       1
+
+/*
+ * Size of malloc() pool
+ */
+#define CFG_MALLOC_LEN         (CFG_ENV_SIZE + 128*1024)
+#define CFG_GBL_DATA_SIZE      128     /* size in bytes reserved for initial data */
+
+/*
+ * Hardware drivers
+ */
+
+/*
+ * NS16550 Configuration
+ */
+#define CFG_NS16550
+#define CFG_NS16550_SERIAL
+#define CFG_NS16550_REG_SIZE   (-4)
+#define CFG_NS16550_CLK                (CONFIG_SYS_CLK_FREQ)   /* can be 12M/32Khz or 48Mhz  */
+#define CFG_NS16550_COM1       0xfffb0000              /* uart1, bluetooth uart on helen */
+
+/*
+ * select serial console configuration
+ */
+#define CONFIG_SERIAL1         1       /* we use SERIAL 1 on SX1 */
+
+/*
+ * USB device configuration
+ */
+#define CONFIG_USB_DEVICE      1
+#define CONFIG_USB_TTY         1
+
+#define CONFIG_USBD_VENDORID           0x1234
+#define CONFIG_USBD_PRODUCTID          0x5678
+#define CONFIG_USBD_MANUFACTURER       "Siemens"
+#define CONFIG_USBD_PRODUCT_NAME       "SX1"
+#define CONFIG_USBD_SERIAL_NUMBER      "000000000001"
+
+
+/*
+ * I2C configuration
+ */
+#define CONFIG_HARD_I2C
+#define CFG_I2C_SPEED          100000
+#define CFG_I2C_SLAVE          1
+#define CONFIG_DRIVER_OMAP1510_I2C
+
+#define CONFIG_ENV_OVERWRITE
+
+#define CONFIG_ENV_OVERWRITE
+#define CONFIG_CONS_INDEX      1
+#define CONFIG_BAUDRATE                115200
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
+
+#define CONFIG_COMMANDS                (( CONFIG_CMD_DFL | \
+                                  CFG_CMD_I2C ) & \
+                                 ~CFG_CMD_NET)
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+#include <configs/omap1510.h>
+
+#define CONFIG_BOOTDELAY       3
+#define CONFIG_BOOTARGS                "mem=16M console=ttyS0,115200n8 root=/dev/mtdblock3 rw"
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP                           /* undef to save memory         */
+#define CFG_PROMPT             "SX1# " /* Monitor Command Prompt       */
+#define CFG_CBSIZE             256             /* Console I/O Buffer Size      */
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define CFG_MAXARGS            16              /* max number of command args   */
+#define CFG_BARGSIZE           CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_MEMTEST_START      0x10000000      /* memtest works on     */
+#define CFG_MEMTEST_END                0x12000000      /* 32 MB in DRAM        */
+
+#undef CFG_CLKS_IN_HZ          /* everything, incl board info, in Hz */
+
+#define CFG_LOAD_ADDR          0x10000000      /* default load address */
+
+/* The 1510 has 3 timers, they can be driven by the RefClk (12Mhz) or by DPLL1.
+ * This time is further subdivided by a local divisor.
+ */
+#define CFG_TIMERBASE  0xFFFEC500          /* use timer 1 */
+#define CFG_PVT                7                   /* 2^(pvt+1), divide by 256 */
+#define CFG_HZ                 ((CONFIG_SYS_CLK_FREQ)/(2 << CFG_PVT))
+
+/*-----------------------------------------------------------------------
+ * Stack sizes
+ *
+ * The stack sizes are set up in start.S using the settings below
+ */
+#define CONFIG_STACKSIZE       (128*1024)      /* regular stack */
+#ifdef CONFIG_USE_IRQ
+#define CONFIG_STACKSIZE_IRQ   (4*1024)        /* IRQ stack */
+#define CONFIG_STACKSIZE_FIQ   (4*1024)        /* FIQ stack */
+#endif
+
+/*-----------------------------------------------------------------------
+ * Physical Memory Map
+ */
+#define CONFIG_NR_DRAM_BANKS   1          /* we have 1 bank of DRAM */
+#define PHYS_SDRAM_1           0x10000000 /* SDRAM Bank #1 */
+#define PHYS_SDRAM_1_SIZE      0x02000000 /* 32 MB */
+
+#define PHYS_FLASH_1           0x00000000 /* Flash Bank #1 */
+#define PHYS_FLASH_2           0x04000000 /* Flash Bank #2 */
+
+#define CFG_FLASH_BASE         PHYS_FLASH_1
+
+/*-----------------------------------------------------------------------
+ * FLASH and environment organization
+ */
+#define CFG_MAX_FLASH_BANKS    2       /* max number of memory banks */
+#define CFG_MAX_FLASH_SECT     (128)   /* max number of sectors on one chip */
+#define CFG_ENV_ADDR           (CFG_FLASH_BASE + 0x020000) /* addr of environment */
+
+/* timeout values are in ticks */
+#define CFG_FLASH_ERASE_TOUT   (20*CFG_HZ) /* Timeout for Flash Erase */
+#define CFG_FLASH_WRITE_TOUT   (20*CFG_HZ) /* Timeout for Flash Write */
+
+#define CFG_ENV_IS_IN_FLASH    1
+#define CFG_ENV_SIZE           0x20000 /* Total Size of Environment Sector */
+#define CFG_ENV_OFFSET         0x20000 /* environment starts here  */
+
+#endif /* __CONFIG_H */
index 2658135e9454ee4557446cef580fa71ba0e3a915..6787b1928a4c68d2fb66357f8eb77ce9796b4902 100644 (file)
 
 #define USB_OTG_CTRL                   0xFFFB040C
 #define USB_TRANSCEIVER_CTRL   0xFFFE1064
-#define PULL_DWN_CTRL_4        0xFFFE10AC
+#define PULL_DWN_CTRL_4 0xFFFE10AC
 #define PU_PD_SEL_0            0xFFFE10B4
 #define PU_PD_SEL_1            0xFFFE10B8
 #define PU_PD_SEL_2            0xFFFE10BC
 
 #define OMAP_LCD_CONTROL       TI925_LCD_CONTROL
 
+/* I2C Registers */
+
+#define I2C_BASE               0xfffb3800
+
+#define I2C_REV                        (I2C_BASE + 0x00)
+#define I2C_IE                 (I2C_BASE + 0x04)
+#define I2C_STAT               (I2C_BASE + 0x08)
+#define I2C_IV                 (I2C_BASE + 0x0c)
+#define I2C_BUF                        (I2C_BASE + 0x14)
+#define I2C_CNT                        (I2C_BASE + 0x18)
+#define I2C_DATA               (I2C_BASE + 0x1c)
+#define I2C_CON                        (I2C_BASE + 0x24)
+#define I2C_OA                 (I2C_BASE + 0x28)
+#define I2C_SA                 (I2C_BASE + 0x2c)
+#define I2C_PSC                        (I2C_BASE + 0x30)
+#define I2C_SCLL               (I2C_BASE + 0x34)
+#define I2C_SCLH               (I2C_BASE + 0x38)
+#define I2C_SYSTEST            (I2C_BASE + 0x3c)
+
+/* I2C masks */
+
+/* I2C Interrupt Enable Register (I2C_IE): */
+
+#define I2C_IE_XRDY_IE (1 << 4)        /* Transmit data ready interrupt enable */
+#define I2C_IE_RRDY_IE (1 << 3)        /* Receive data ready interrupt enable */
+#define I2C_IE_ARDY_IE (1 << 2)        /* Register access ready interrupt enable */
+#define I2C_IE_NACK_IE (1 << 1)        /* No acknowledgment interrupt enable */
+#define I2C_IE_AL_IE   (1 << 0)        /* Arbitration lost interrupt enable */
+
+/* I2C Status Register (I2C_STAT): */
+
+#define I2C_STAT_SBD   (1 << 15)       /* Single byte data */
+#define I2C_STAT_BB    (1 << 12)       /* Bus busy */
+#define I2C_STAT_ROVR  (1 << 11)       /* Receive overrun */
+#define I2C_STAT_XUDF  (1 << 10)       /* Transmit underflow */
+#define I2C_STAT_AAS   (1 << 9)        /* Address as slave */
+#define I2C_STAT_AD0   (1 << 8)        /* Address zero */
+#define I2C_STAT_XRDY  (1 << 4)        /* Transmit data ready */
+#define I2C_STAT_RRDY  (1 << 3)        /* Receive data ready */
+#define I2C_STAT_ARDY  (1 << 2)        /* Register access ready */
+#define I2C_STAT_NACK  (1 << 1)        /* No acknowledgment interrupt enable */
+#define I2C_STAT_AL    (1 << 0)        /* Arbitration lost interrupt enable */
+
+/* I2C Interrupt Vector Register (I2C_IV): */
+
+/* I2C Interrupt Code Register (I2C_INTCODE): */
+
+#define I2C_INTCODE_MASK       7
+#define I2C_INTCODE_NONE       0
+#define I2C_INTCODE_AL         1       /* Arbitration lost */
+#define I2C_INTCODE_NAK                2       /* No acknowledgement/general call */
+#define I2C_INTCODE_ARDY       3       /* Register access ready */
+#define I2C_INTCODE_RRDY       4       /* Rcv data ready */
+#define I2C_INTCODE_XRDY       5       /* Xmit data ready */
+
+/* I2C Buffer Configuration Register (I2C_BUF): */
+
+#define I2C_BUF_RDMA_EN                (1 << 15)       /* Receive DMA channel enable */
+#define I2C_BUF_XDMA_EN                (1 << 7)        /* Transmit DMA channel enable */
+
+/* I2C Configuration Register (I2C_CON): */
+
+#define I2C_CON_EN     (1 << 15)       /* I2C module enable */
+#define I2C_CON_BE     (1 << 14)       /* Big endian mode */
+#define I2C_CON_STB    (1 << 11)       /* Start byte mode (master mode only) */
+#define I2C_CON_MST    (1 << 10)       /* Master/slave mode */
+#define I2C_CON_TRX    (1 << 9)        /* Transmitter/receiver mode (master mode only) */
+#define I2C_CON_XA     (1 << 8)        /* Expand address */
+#define I2C_CON_RM     (1 << 2)        /* Repeat mode (master mode only) */
+#define I2C_CON_STP    (1 << 1)        /* Stop condition (master mode only) */
+#define I2C_CON_STT    (1 << 0)        /* Start condition (master mode only) */
+
+/* I2C System Test Register (I2C_SYSTEST): */
+
+#define I2C_SYSTEST_ST_EN      (1 << 15)       /* System test enable */
+#define I2C_SYSTEST_FREE       (1 << 14)       /* Free running mode (on breakpoint) */
+#define I2C_SYSTEST_TMODE_MASK (3 << 12)       /* Test mode select */
+#define I2C_SYSTEST_TMODE_SHIFT (12)           /* Test mode select */
+#define I2C_SYSTEST_SCL_I      (1 << 3)        /* SCL line sense input value */
+#define I2C_SYSTEST_SCL_O      (1 << 2)        /* SCL line drive output value */
+#define I2C_SYSTEST_SDA_I      (1 << 1)        /* SDA line sense input value */
+#define I2C_SYSTEST_SDA_O      (1 << 0)        /* SDA line drive output value */
+
 /*
  * MMC/SD Host Controller Registers
  */
@@ -696,3 +779,12 @@ int cpu_type(void);
 
 #define IRQ_LEVEL_INT          1
 #define IRQ_EDGE_INT           0
+
+/* Macros to access registers */
+#define outb(v,p) *(volatile u8 *) (p) = v
+#define outw(v,p) *(volatile u16 *) (p) = v
+#define outl(v,p) *(volatile u32 *) (p) = v
+
+#define inb(p) *(volatile u8 *) (p)
+#define inw(p) *(volatile u16 *) (p)
+#define inl(p) *(volatile u32 *) (p)
index a27c4e83f1e9bd8ba2ca1d1cd16a91593cca167a..9f2a0c34acc6872310456553682c6d95492cf770 100644 (file)
@@ -105,5 +105,8 @@ int drv_video_init (void);
 #ifdef CONFIG_KEYBOARD
 int    drv_keyboard_init (void);
 #endif
+#ifdef CONFIG_USB_TTY
+int    drv_usbtty_init (void);
+#endif
 
 #endif /* _DEVICES_H_ */
diff --git a/include/usbdcore.h b/include/usbdcore.h
new file mode 100644 (file)
index 0000000..6e92df1
--- /dev/null
@@ -0,0 +1,671 @@
+/*
+ * (C) Copyright 2003
+ * Gerry Hamel, geh@ti.com, Texas Instruments
+ *
+ * Based on linux/drivers/usbd/usbd.h
+ *
+ * Copyright (c) 2000, 2001, 2002 Lineo
+ * Copyright (c) 2001 Hewlett Packard
+ *
+ * By:
+ *     Stuart Lynne <sl@lineo.com>,
+ *     Tom Rushworth <tbr@lineo.com>,
+ *     Bruce Balden <balden@lineo.com>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __USBDCORE_H__
+#define __USBDCORE_H__
+
+#include <common.h>
+#include "usbdescriptors.h"
+
+
+#define MAX_URBS_QUEUED 5
+
+
+#if 1
+#define usberr(fmt,args...) serial_printf("ERROR: %s(), %d: "fmt"\n",__FUNCTION__,__LINE__,##args)
+#else
+#define usberr(fmt,args...) do{}while(0)
+#endif
+
+#if 0
+#define usbdbg(fmt,args...) serial_printf("debug: %s(), %d: "fmt"\n",__FUNCTION__,__LINE__,##args)
+#else
+#define usbdbg(fmt,args...) do{}while(0)
+#endif
+
+#if 0
+#define usbinfo(fmt,args...) serial_printf("info: %s(), %d: "fmt"\n",__FUNCTION__,__LINE__,##args)
+#else
+#define usbinfo(fmt,args...) do{}while(0)
+#endif
+
+#ifndef le16_to_cpu
+#define le16_to_cpu(x) (x)
+#endif
+
+#ifndef inb
+#define inb(p)      (*(volatile u8*)(p))
+#endif
+
+#ifndef outb
+#define outb(val,p)  (*(volatile u8*)(p) = (val))
+#endif
+
+#ifndef inw
+#define inw(p)      (*(volatile u16*)(p))
+#endif
+
+#ifndef outw
+#define outw(val,p)  (*(volatile u16*)(p) = (val))
+#endif
+
+#ifndef inl
+#define inl(p)      (*(volatile u32*)(p))
+#endif
+
+#ifndef outl
+#define outl(val,p)  (*(volatile u32*)(p) = (val))
+#endif
+
+#ifndef insw
+#define insw(p,to,len)    mmio_insw(p,to,len)
+#endif
+
+#ifndef outsw
+#define outsw(p,from,len)  mmio_outsw(p,from,len)
+#endif
+
+#ifndef insb
+#define insb(p,to,len)    mmio_insb(p,to,len)
+#endif
+
+#ifndef mmio_insw
+#define mmio_insw(r,b,l)       ({      int __i ;  \
+                                       u16 *__b2;  \
+                                       __b2 = (u16 *) b;  \
+                                       for (__i = 0; __i < l; __i++) {  \
+                                         *(__b2 + __i) = inw(r);  \
+                                       };  \
+                               })
+#endif
+
+#ifndef mmio_outsw
+#define mmio_outsw(r,b,l)      ({      int __i; \
+                                       u16 *__b2; \
+                                       __b2 = (u16 *) b; \
+                                       for (__i = 0; __i < l; __i++) { \
+                                           outw( *(__b2 + __i), r); \
+                                       } \
+                               })
+#endif
+
+#ifndef mmio_insb
+#define mmio_insb(r,b,l)       ({      int __i ;  \
+                                       u8 *__b2;  \
+                                       __b2 = (u8 *) b;  \
+                                       for (__i = 0; __i < l; __i++) {  \
+                                         *(__b2 + __i) = inb(r);  \
+                                       };  \
+                               })
+#endif
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+
+/*
+ * Structure member address manipulation macros.
+ * These are used by client code (code using the urb_link routines), since
+ * the urb_link structure is embedded in the client data structures.
+ *
+ * Note: a macro offsetof equivalent to member_offset is defined in stddef.h
+ *      but this is kept here for the sake of portability.
+ *
+ * p2surround returns a pointer to the surrounding structure given
+ * type of the surrounding structure, the name memb of the structure
+ * member pointed at by ptr.  For example, if you have:
+ *
+ *     struct foo {
+ *         int x;
+ *         float y;
+ *         char z;
+ *     } thingy;
+ *
+ *     char *cp = &thingy.z;
+ *
+ * then
+ *
+ *     &thingy == p2surround(struct foo, z, cp)
+ *
+ * Clear?
+ */
+#define _cv_(ptr)                ((char*)(void*)(ptr))
+#define member_offset(type,memb)  (_cv_(&(((type*)0)->memb))-(char*)0)
+#define p2surround(type,memb,ptr) ((type*)(void*)(_cv_(ptr)-member_offset(type,memb)))
+
+struct urb;
+
+struct usb_endpoint_instance;
+struct usb_interface_instance;
+struct usb_configuration_instance;
+struct usb_device_instance;
+struct usb_bus_instance;
+
+/*
+ * Device and/or Interface Class codes
+ */
+#define USB_CLASS_PER_INTERFACE                0       /* for DeviceClass */
+#define USB_CLASS_AUDIO                        1
+#define USB_CLASS_COMM                 2
+#define USB_CLASS_HID                  3
+#define USB_CLASS_PHYSICAL             5
+#define USB_CLASS_PRINTER              7
+#define USB_CLASS_MASS_STORAGE         8
+#define USB_CLASS_HUB                  9
+#define USB_CLASS_DATA                 10
+#define USB_CLASS_APP_SPEC             0xfe
+#define USB_CLASS_VENDOR_SPEC          0xff
+
+/*
+ * USB types
+ */
+#define USB_TYPE_STANDARD              (0x00 << 5)
+#define USB_TYPE_CLASS                 (0x01 << 5)
+#define USB_TYPE_VENDOR                        (0x02 << 5)
+#define USB_TYPE_RESERVED              (0x03 << 5)
+
+/*
+ * USB recipients
+ */
+#define USB_RECIP_DEVICE               0x00
+#define USB_RECIP_INTERFACE            0x01
+#define USB_RECIP_ENDPOINT             0x02
+#define USB_RECIP_OTHER                        0x03
+
+/*
+ * USB directions
+ */
+#define USB_DIR_OUT                    0
+#define USB_DIR_IN                     0x80
+
+/*
+ * Descriptor types
+ */
+#define USB_DT_DEVICE                  0x01
+#define USB_DT_CONFIG                  0x02
+#define USB_DT_STRING                  0x03
+#define USB_DT_INTERFACE               0x04
+#define USB_DT_ENDPOINT                        0x05
+
+#define USB_DT_HID                     (USB_TYPE_CLASS | 0x01)
+#define USB_DT_REPORT                  (USB_TYPE_CLASS | 0x02)
+#define USB_DT_PHYSICAL                        (USB_TYPE_CLASS | 0x03)
+#define USB_DT_HUB                     (USB_TYPE_CLASS | 0x09)
+
+/*
+ * Descriptor sizes per descriptor type
+ */
+#define USB_DT_DEVICE_SIZE             18
+#define USB_DT_CONFIG_SIZE             9
+#define USB_DT_INTERFACE_SIZE          9
+#define USB_DT_ENDPOINT_SIZE           7
+#define USB_DT_ENDPOINT_AUDIO_SIZE     9       /* Audio extension */
+#define USB_DT_HUB_NONVAR_SIZE         7
+#define USB_DT_HID_SIZE                        9
+
+/*
+ * Endpoints
+ */
+#define USB_ENDPOINT_NUMBER_MASK       0x0f    /* in bEndpointAddress */
+#define USB_ENDPOINT_DIR_MASK          0x80
+
+#define USB_ENDPOINT_XFERTYPE_MASK     0x03    /* in bmAttributes */
+#define USB_ENDPOINT_XFER_CONTROL      0
+#define USB_ENDPOINT_XFER_ISOC         1
+#define USB_ENDPOINT_XFER_BULK         2
+#define USB_ENDPOINT_XFER_INT          3
+
+/*
+ * USB Packet IDs (PIDs)
+ */
+#define USB_PID_UNDEF_0                               0xf0
+#define USB_PID_OUT                           0xe1
+#define USB_PID_ACK                           0xd2
+#define USB_PID_DATA0                         0xc3
+#define USB_PID_PING                          0xb4     /* USB 2.0 */
+#define USB_PID_SOF                           0xa5
+#define USB_PID_NYET                          0x96     /* USB 2.0 */
+#define USB_PID_DATA2                         0x87     /* USB 2.0 */
+#define USB_PID_SPLIT                         0x78     /* USB 2.0 */
+#define USB_PID_IN                            0x69
+#define USB_PID_NAK                           0x5a
+#define USB_PID_DATA1                         0x4b
+#define USB_PID_PREAMBLE                      0x3c     /* Token mode */
+#define USB_PID_ERR                           0x3c     /* USB 2.0: handshake mode */
+#define USB_PID_SETUP                         0x2d
+#define USB_PID_STALL                         0x1e
+#define USB_PID_MDATA                         0x0f     /* USB 2.0 */
+
+/*
+ * Standard requests
+ */
+#define USB_REQ_GET_STATUS             0x00
+#define USB_REQ_CLEAR_FEATURE          0x01
+#define USB_REQ_SET_FEATURE            0x03
+#define USB_REQ_SET_ADDRESS            0x05
+#define USB_REQ_GET_DESCRIPTOR         0x06
+#define USB_REQ_SET_DESCRIPTOR         0x07
+#define USB_REQ_GET_CONFIGURATION      0x08
+#define USB_REQ_SET_CONFIGURATION      0x09
+#define USB_REQ_GET_INTERFACE          0x0A
+#define USB_REQ_SET_INTERFACE          0x0B
+#define USB_REQ_SYNCH_FRAME            0x0C
+
+#define USBD_DEVICE_REQUESTS(x) (((unsigned int)x <= USB_REQ_SYNCH_FRAME) ? usbd_device_requests[x] : "UNKNOWN")
+
+/*
+ * HID requests
+ */
+#define USB_REQ_GET_REPORT             0x01
+#define USB_REQ_GET_IDLE               0x02
+#define USB_REQ_GET_PROTOCOL           0x03
+#define USB_REQ_SET_REPORT             0x09
+#define USB_REQ_SET_IDLE               0x0A
+#define USB_REQ_SET_PROTOCOL           0x0B
+
+
+/*
+ * USB Spec Release number
+ */
+
+#define USB_BCD_VERSION                        0x0110
+
+
+/*
+ * Device Requests     (c.f Table 9-2)
+ */
+
+#define USB_REQ_DIRECTION_MASK         0x80
+#define USB_REQ_TYPE_MASK              0x60
+#define USB_REQ_RECIPIENT_MASK         0x1f
+
+#define USB_REQ_DEVICE2HOST            0x80
+#define USB_REQ_HOST2DEVICE            0x00
+
+#define USB_REQ_TYPE_STANDARD          0x00
+#define USB_REQ_TYPE_CLASS             0x20
+#define USB_REQ_TYPE_VENDOR            0x40
+
+#define USB_REQ_RECIPIENT_DEVICE       0x00
+#define USB_REQ_RECIPIENT_INTERFACE    0x01
+#define USB_REQ_RECIPIENT_ENDPOINT     0x02
+#define USB_REQ_RECIPIENT_OTHER                0x03
+
+/*
+ * get status bits
+ */
+
+#define USB_STATUS_SELFPOWERED         0x01
+#define USB_STATUS_REMOTEWAKEUP                0x02
+
+#define USB_STATUS_HALT                        0x01
+
+/*
+ * descriptor types
+ */
+
+#define USB_DESCRIPTOR_TYPE_DEVICE                     0x01
+#define USB_DESCRIPTOR_TYPE_CONFIGURATION              0x02
+#define USB_DESCRIPTOR_TYPE_STRING                     0x03
+#define USB_DESCRIPTOR_TYPE_INTERFACE                  0x04
+#define USB_DESCRIPTOR_TYPE_ENDPOINT                   0x05
+#define USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER           0x06
+#define USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION  0x07
+#define USB_DESCRIPTOR_TYPE_INTERFACE_POWER            0x08
+#define USB_DESCRIPTOR_TYPE_HID                                0x21
+#define USB_DESCRIPTOR_TYPE_REPORT                     0x22
+
+#define USBD_DEVICE_DESCRIPTORS(x) (((unsigned int)x <= USB_DESCRIPTOR_TYPE_INTERFACE_POWER) ? \
+               usbd_device_descriptors[x] : "UNKNOWN")
+
+/*
+ * standard feature selectors
+ */
+#define USB_ENDPOINT_HALT              0x00
+#define USB_DEVICE_REMOTE_WAKEUP       0x01
+#define USB_TEST_MODE                  0x02
+
+
+/* USB Requests
+ *
+ */
+
+struct usb_device_request {
+       u8 bmRequestType;
+       u8 bRequest;
+       u16 wValue;
+       u16 wIndex;
+       u16 wLength;
+} __attribute__ ((packed));
+
+
+/* USB Status
+ *
+ */
+typedef enum urb_send_status {
+       SEND_IN_PROGRESS,
+       SEND_FINISHED_OK,
+       SEND_FINISHED_ERROR,
+       RECV_READY,
+       RECV_OK,
+       RECV_ERROR
+} urb_send_status_t;
+
+/*
+ * Device State (c.f USB Spec 2.0 Figure 9-1)
+ *
+ * What state the usb device is in.
+ *
+ * Note the state does not change if the device is suspended, we simply set a
+ * flag to show that it is suspended.
+ *
+ */
+typedef enum usb_device_state {
+       STATE_INIT,             /* just initialized */
+       STATE_CREATED,          /* just created */
+       STATE_ATTACHED,         /* we are attached */
+       STATE_POWERED,          /* we have seen power indication (electrical bus signal) */
+       STATE_DEFAULT,          /* we been reset */
+       STATE_ADDRESSED,        /* we have been addressed (in default configuration) */
+       STATE_CONFIGURED,       /* we have seen a set configuration device command */
+       STATE_UNKNOWN,          /* destroyed */
+} usb_device_state_t;
+
+#define USBD_DEVICE_STATE(x) (((unsigned int)x <= STATE_UNKNOWN) ? usbd_device_states[x] : "UNKNOWN")
+
+/*
+ * Device status
+ *
+ * Overall state
+ */
+typedef enum usb_device_status {
+       USBD_OPENING,           /* we are currently opening */
+       USBD_OK,                /* ok to use */
+       USBD_SUSPENDED,         /* we are currently suspended */
+       USBD_CLOSING,           /* we are currently closing */
+} usb_device_status_t;
+
+#define USBD_DEVICE_STATUS(x) (((unsigned int)x <= USBD_CLOSING) ? usbd_device_status[x] : "UNKNOWN")
+
+/*
+ * Device Events
+ *
+ * These are defined in the USB Spec (c.f USB Spec 2.0 Figure 9-1).
+ *
+ * There are additional events defined to handle some extra actions we need
+ * to have handled.
+ *
+ */
+typedef enum usb_device_event {
+
+       DEVICE_UNKNOWN,         /* bi - unknown event */
+       DEVICE_INIT,            /* bi  - initialize */
+       DEVICE_CREATE,          /* bi  - */
+       DEVICE_HUB_CONFIGURED,  /* bi  - bus has been plugged int */
+       DEVICE_RESET,           /* bi  - hub has powered our port */
+
+       DEVICE_ADDRESS_ASSIGNED,        /* ep0 - set address setup received */
+       DEVICE_CONFIGURED,      /* ep0 - set configure setup received */
+       DEVICE_SET_INTERFACE,   /* ep0 - set interface setup received */
+
+       DEVICE_SET_FEATURE,     /* ep0 - set feature setup received */
+       DEVICE_CLEAR_FEATURE,   /* ep0 - clear feature setup received */
+
+       DEVICE_DE_CONFIGURED,   /* ep0 - set configure setup received for ?? */
+
+       DEVICE_BUS_INACTIVE,    /* bi  - bus in inactive (no SOF packets) */
+       DEVICE_BUS_ACTIVITY,    /* bi  - bus is active again */
+
+       DEVICE_POWER_INTERRUPTION,      /* bi  - hub has depowered our port */
+       DEVICE_HUB_RESET,       /* bi  - bus has been unplugged */
+       DEVICE_DESTROY,         /* bi  - device instance should be destroyed */
+
+       DEVICE_HOTPLUG,         /* bi  - a hotplug event has occured */
+
+       DEVICE_FUNCTION_PRIVATE,        /* function - private */
+
+} usb_device_event_t;
+
+
+typedef struct urb_link {
+       struct urb_link *next;
+       struct urb_link *prev;
+} urb_link;
+
+/* USB Data structure - for passing data around.
+ *
+ * This is used for both sending and receiving data.
+ *
+ * The callback function is used to let the function driver know when
+ * transmitted data has been sent.
+ *
+ * The callback function is set by the alloc_recv function when an urb is
+ * allocated for receiving data for an endpoint and used to call the
+ * function driver to inform it that data has arrived.
+ */
+
+#define URB_BUF_SIZE 128 /* in linux we'd malloc this, but in u-boot we prefer static data */
+struct urb {
+
+       struct usb_endpoint_instance *endpoint;
+       struct usb_device_instance *device;
+
+       struct usb_device_request device_request;       /* contents of received SETUP packet */
+
+       struct urb_link link;   /* embedded struct for circular doubly linked list of urbs */
+
+       u8* buffer;
+       unsigned int buffer_length;
+       unsigned int actual_length;
+
+       urb_send_status_t status;
+       int data;
+
+       u16 buffer_data[URB_BUF_SIZE];  /* data received (OUT) or being sent (IN) */
+};
+
+/* Endpoint configuration
+ *
+ * Per endpoint configuration data. Used to track which function driver owns
+ * an endpoint.
+ *
+ */
+struct usb_endpoint_instance {
+       int endpoint_address;   /* logical endpoint address */
+
+       /* control */
+       int status;             /* halted */
+       int state;              /* available for use by bus interface driver */
+
+       /* receive side */
+       struct urb_link rcv;    /* received urbs */
+       struct urb_link rdy;    /* empty urbs ready to receive */
+       struct urb *rcv_urb;    /* active urb */
+       int rcv_attributes;     /* copy of bmAttributes from endpoint descriptor */
+       int rcv_packetSize;     /* maximum packet size from endpoint descriptor */
+       int rcv_transferSize;   /* maximum transfer size from function driver */
+       int rcv_queue;
+
+       /* transmit side */
+       struct urb_link tx;     /* urbs ready to transmit */
+       struct urb_link done;   /* transmitted urbs */
+       struct urb *tx_urb;     /* active urb */
+       int tx_attributes;      /* copy of bmAttributes from endpoint descriptor */
+       int tx_packetSize;      /* maximum packet size from endpoint descriptor */
+       int tx_transferSize;    /* maximum transfer size from function driver */
+       int tx_queue;
+
+       int sent;               /* data already sent */
+       int last;               /* data sent in last packet XXX do we need this */
+};
+
+struct usb_alternate_instance {
+       struct usb_interface_descriptor *interface_descriptor;
+
+       int endpoints;
+       int *endpoint_transfersize_array;
+       struct usb_endpoint_descriptor **endpoints_descriptor_array;
+};
+
+struct usb_interface_instance {
+       int alternates;
+       struct usb_alternate_instance *alternates_instance_array;
+};
+
+struct usb_configuration_instance {
+       int interfaces;
+       struct usb_configuration_descriptor *configuration_descriptor;
+       struct usb_interface_instance *interface_instance_array;
+};
+
+
+/* USB Device Instance
+ *
+ * For each physical bus interface we create a logical device structure. This
+ * tracks all of the required state to track the USB HOST's view of the device.
+ *
+ * Keep track of the device configuration for a real physical bus interface,
+ * this includes the bus interface, multiple function drivers, the current
+ * configuration and the current state.
+ *
+ * This will show:
+ *     the specific bus interface driver
+ *     the default endpoint 0 driver
+ *     the configured function driver
+ *     device state
+ *     device status
+ *     endpoint list
+ */
+
+struct usb_device_instance {
+
+       /* generic */
+       char *name;
+       struct usb_device_descriptor *device_descriptor;        /* per device descriptor */
+
+       void (*event) (struct usb_device_instance *device, usb_device_event_t event, int data);
+
+       /* bus interface */
+       struct usb_bus_instance *bus;   /* which bus interface driver */
+
+       /* configuration descriptors */
+       int configurations;
+       struct usb_configuration_instance *configuration_instance_array;
+
+       /* device state */
+       usb_device_state_t device_state;        /* current USB Device state */
+       usb_device_state_t device_previous_state;       /* current USB Device state */
+
+       u8 address;             /* current address (zero is default) */
+       u8 configuration;       /* current show configuration (zero is default) */
+       u8 interface;           /* current interface (zero is default) */
+       u8 alternate;           /* alternate flag */
+
+       usb_device_status_t status;     /* device status */
+
+       int urbs_queued;        /* number of submitted urbs */
+
+       /* Shouldn't need to make this atomic, all we need is a change indicator */
+       unsigned long usbd_rxtx_timestamp;
+       unsigned long usbd_last_rxtx_timestamp;
+
+};
+
+/* Bus Interface configuration structure
+ *
+ * This is allocated for each configured instance of a bus interface driver.
+ *
+ * The privdata pointer may be used by the bus interface driver to store private
+ * per instance state information.
+ */
+struct usb_bus_instance {
+
+       struct usb_device_instance *device;
+       struct usb_endpoint_instance *endpoint_array;   /* array of available configured endpoints */
+
+       int max_endpoints;      /* maximimum number of rx enpoints */
+       unsigned char                   maxpacketsize;
+
+       unsigned int serial_number;
+       char *serial_number_str;
+       void *privdata;         /* private data for the bus interface */
+
+};
+
+extern char *usbd_device_events[];
+extern char *usbd_device_states[];
+extern char *usbd_device_status[];
+extern char *usbd_device_requests[];
+extern char *usbd_device_descriptors[];
+
+void urb_link_init (urb_link * ul);
+void urb_detach (struct urb *urb);
+urb_link *first_urb_link (urb_link * hd);
+struct urb *first_urb (urb_link * hd);
+struct urb *first_urb_detached (urb_link * hd);
+void urb_append (urb_link * hd, struct urb *urb);
+
+struct urb *usbd_alloc_urb (struct usb_device_instance *device, struct usb_endpoint_instance *endpoint);
+void       usbd_dealloc_urb (struct urb *urb);
+
+/*
+ * usbd_device_event is used by bus interface drivers to tell the higher layers that
+ * certain events have taken place.
+ */
+void usbd_device_event_irq (struct usb_device_instance *conf, usb_device_event_t, int);
+void usbd_device_event (struct usb_device_instance *conf, usb_device_event_t, int);
+
+/* descriptors
+ *
+ * Various ways of finding descriptors based on the current device and any
+ * possible configuration / interface / endpoint for it.
+ */
+struct usb_configuration_descriptor *usbd_device_configuration_descriptor (struct usb_device_instance *, int, int);
+struct usb_function_instance *usbd_device_function_instance (struct usb_device_instance *, unsigned int);
+struct usb_interface_instance *usbd_device_interface_instance (struct usb_device_instance *, int, int, int);
+struct usb_alternate_instance *usbd_device_alternate_instance (struct usb_device_instance *, int, int, int, int);
+struct usb_interface_descriptor *usbd_device_interface_descriptor (struct usb_device_instance *, int, int, int, int);
+struct usb_endpoint_descriptor *usbd_device_endpoint_descriptor_index (struct usb_device_instance *, int, int, int, int, int);
+struct usb_class_descriptor *usbd_device_class_descriptor_index (struct usb_device_instance *, int, int, int, int, int);
+struct usb_class_report_descriptor *usbd_device_class_report_descriptor_index( struct usb_device_instance *, int , int , int , int , int );
+struct usb_endpoint_descriptor *usbd_device_endpoint_descriptor (struct usb_device_instance *, int, int, int, int, int);
+int                            usbd_device_endpoint_transfersize (struct usb_device_instance *, int, int, int, int, int);
+struct usb_string_descriptor *usbd_get_string (u8);
+struct usb_device_descriptor *usbd_device_device_descriptor (struct usb_device_instance *, int);
+
+int usbd_endpoint_halted (struct usb_device_instance *device, int endpoint);
+void usbd_rcv_complete(struct usb_endpoint_instance *endpoint, int len, int urb_bad);
+void usbd_tx_complete (struct usb_endpoint_instance *endpoint);
+
+#endif
diff --git a/include/usbdcore_ep0.h b/include/usbdcore_ep0.h
new file mode 100644 (file)
index 0000000..3bec106
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * (C) Copyright 2003
+ * Gerry Hamel, geh@ti.com, Texas Instruments
+ *
+ * Based on
+ * linux/drivers/usbd/ep0.c
+ *
+ * Copyright (c) 2000, 2001, 2002 Lineo
+ * Copyright (c) 2001 Hewlett Packard
+ *
+ * By:
+ *     Stuart Lynne <sl@lineo.com>,
+ *     Tom Rushworth <tbr@lineo.com>,
+ *     Bruce Balden <balden@lineo.com>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __USBDCORE_EP0_H__
+#define __USBDCORE_EP0_H__
+
+
+int ep0_recv_setup (struct urb *urb);
+
+
+#endif
diff --git a/include/usbdcore_omap1510.h b/include/usbdcore_omap1510.h
new file mode 100644 (file)
index 0000000..6ea3331
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * (C) Copyright 2003
+ * Gerry Hamel, geh@ti.com, Texas Instruments
+ *
+ * Based on
+ * linux/drivers/usb/device/bi/omap.h
+ * Register definitions for TI OMAP1510 USB bus interface driver
+ *
+ * Author: MontaVista Software, Inc.
+ *        source@mvista.com
+ *
+ * 2003 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __USBDCORE_OMAP1510_H__
+#define __USBDCORE_OMAP1510_H__
+
+
+/*
+ * 13.2 MPU Register Map
+ */
+
+/* Table 13-1. USB Function Module Registers (endpoint) */
+#define UDC_BASE                    0xFFFB4000
+#define UDC_OFFSET(offset)          (UDC_BASE + (offset))
+#define UDC_REV                             UDC_OFFSET(0x0)    /* Revision */
+#define UDC_EP_NUM                  UDC_OFFSET(0x4)    /* Endpoint selection */
+#define UDC_DATA                    UDC_OFFSET(0x08)   /* Data */
+#define UDC_CTRL                    UDC_OFFSET(0x0C)   /* Control */
+#define UDC_STAT_FLG                UDC_OFFSET(0x10)   /* Status flag */
+#define UDC_RXFSTAT                 UDC_OFFSET(0x14)   /* Receive FIFO status */
+#define UDC_SYSCON1                 UDC_OFFSET(0x18)   /* System configuration 1 */
+#define UDC_SYSCON2                 UDC_OFFSET(0x1C)   /* System configuration 2 */
+#define UDC_DEVSTAT                 UDC_OFFSET(0x20)   /* Device status */
+#define UDC_SOF                             UDC_OFFSET(0x24)   /* Start of frame */
+#define UDC_IRQ_EN                  UDC_OFFSET(0x28)   /* Interrupt enable */
+#define UDC_DMA_IRQ_EN              UDC_OFFSET(0x2C)   /* DMA interrupt enable */
+#define UDC_IRQ_SRC                 UDC_OFFSET(0x30)   /* Interrupt source */
+#define UDC_EPN_STAT                UDC_OFFSET(0x34)   /* Endpoint interrupt status */
+#define UDC_DMAN_STAT               UDC_OFFSET(0x3C)   /* DMA endpoint interrupt status */
+
+/* IRQ_EN register fields */
+#define UDC_Sof_IE                  (1 << 7)   /* Start-of-frame interrupt enabled */
+#define UDC_EPn_RX_IE               (1 << 5)   /* Receive endpoint interrupt enabled */
+#define UDC_EPn_TX_IE               (1 << 4)   /* Transmit endpoint interrupt enabled */
+#define UDC_DS_Chg_IE               (1 << 3)   /* Device state changed interrupt enabled */
+#define UDC_EP0_IE                  (1 << 0)   /* EP0 transaction interrupt enabled */
+
+/* IRQ_SRC register fields */
+#define UDC_TXn_Done                (1 << 10)  /* Transmit DMA channel n done */
+#define UDC_RXn_Cnt                 (1 << 9)   /* Receive DMA channel n transactions count */
+#define UDC_RXn_EOT                 (1 << 8)   /* Receive DMA channel n end of transfer */
+#define UDC_SOF_Flg                 (1 << 7)   /* Start-of-frame interrupt flag */
+#define UDC_EPn_RX                  (1 << 5)   /* Endpoint n OUT transaction */
+#define UDC_EPn_TX                  (1 << 4)   /* Endpoint n IN transaction */
+#define UDC_DS_Chg                  (1 << 3)   /* Device state changed */
+#define UDC_Setup                   (1 << 2)   /* Setup transaction */
+#define UDC_EP0_RX                  (1 << 1)   /* EP0 OUT transaction */
+#define UDC_EP0_TX                  (1 << 0)   /* EP0 IN transaction */
+
+/* DEVSTAT register fields, 14.2.9 */
+#define UDC_R_WK_OK                 (1 << 6)   /* Remote wakeup granted */
+#define UDC_USB_Reset               (1 << 5)   /* USB reset signalling is active */
+#define UDC_SUS                             (1 << 4)   /* Suspended state */
+#define UDC_CFG                             (1 << 3)   /* Configured state */
+#define UDC_ADD                             (1 << 2)   /* Addressed state */
+#define UDC_DEF                             (1 << 1)   /* Default state */
+#define UDC_ATT                             (1 << 0)   /* Attached state */
+
+/* SYSCON1 register fields */
+#define UDC_Cfg_Lock                (1 << 8)   /* Device configuration locked */
+#define UDC_Nak_En                  (1 << 4)   /* NAK enable */
+#define UDC_Self_Pwr                (1 << 2)   /* Device is self-powered */
+#define UDC_Soff_Dis                (1 << 1)   /* Shutoff disabled */
+#define UDC_Pullup_En               (1 << 0)   /* External pullup enabled */
+
+/* SYSCON2 register fields */
+#define UDC_Rmt_Wkp                 (1 << 6)   /* Remote wakeup */
+#define UDC_Stall_Cmd               (1 << 5)   /* Stall endpoint */
+#define UDC_Dev_Cfg                 (1 << 3)   /* Device configured */
+#define UDC_Clr_Cfg                 (1 << 2)   /* Clear configured */
+
+/*
+ * Select and enable endpoints
+ */
+
+/* Table 13-1. USB Function Module Registers (endpoint configuration) */
+#define UDC_EPBASE                  UDC_OFFSET(0x80)   /* Endpoints base address */
+#define UDC_EP0                             UDC_EPBASE /* Control endpoint configuration */
+#define UDC_EP_RX_BASE              UDC_OFFSET(0x84)   /* Receive endpoints base address */
+#define UDC_EP_RX(endpoint)         (UDC_EP_RX_BASE + ((endpoint) - 1) * 4)
+#define UDC_EP_TX_BASE              UDC_OFFSET(0xC4)   /* Transmit endpoints base address */
+#define UDC_EP_TX(endpoint)         (UDC_EP_TX_BASE + ((endpoint) - 1) * 4)
+
+/* EP_NUM register fields */
+#define UDC_Setup_Sel               (1 << 6)   /* Setup FIFO select */
+#define UDC_EP_Sel                  (1 << 5)   /* TX/RX FIFO select */
+#define UDC_EP_Dir                  (1 << 4)   /* Endpoint direction */
+
+/* CTRL register fields */
+#define UDC_Clr_Halt                (1 << 7)   /* Clear halt endpoint */
+#define UDC_Set_Halt                (1 << 6)   /* Set halt endpoint */
+#define UDC_Set_FIFO_En                     (1 << 2)   /* Set FIFO enable */
+#define UDC_Clr_EP                  (1 << 1)   /* Clear endpoint */
+#define UDC_Reset_EP                (1 << 0)   /* Reset endpoint */
+
+/* STAT_FLG register fields */
+#define UDC_Miss_In                 (1 << 14)
+#define UDC_Data_Flush              (1 << 13)
+#define UDC_ISO_Err                 (1 << 12)
+#define UDC_ISO_FIFO_Empty          (1 << 9)
+#define UDC_ISO_FIFO_Full           (1 << 8)
+#define UDC_EP_Halted               (1 << 6)
+#define UDC_STALL                   (1 << 5)
+#define UDC_NAK                             (1 << 4)
+#define UDC_ACK                             (1 << 3)
+#define UDC_FIFO_En                 (1 << 2)
+#define UDC_Non_ISO_FIFO_Empty      (1 << 1)
+#define UDC_Non_ISO_FIFO_Full       (1 << 0)
+
+/* EPn_RX register fields */
+#define UDC_EPn_RX_Valid            (1 << 15)  /* valid */
+#define UDC_EPn_RX_Db               (1 << 14)  /* double-buffer */
+#define UDC_EPn_RX_Iso              (1 << 11)  /* isochronous */
+
+/* EPn_TX register fields */
+#define UDC_EPn_TX_Valid            (1 << 15)  /* valid */
+#define UDC_EPn_TX_Db               (1 << 14)  /* double-buffer */
+#define UDC_EPn_TX_Iso              (1 << 11)  /* isochronous */
+
+#define EP0_PACKETSIZE              0x40
+
+/* physical to logical endpoint mapping
+ * Physical endpoints are an index into device->bus->endpoint_array.
+ * Logical endpoints are endpoints 0 to 15 IN and OUT as defined in
+ * the USB specification.
+ *
+ *     physical ep     logical ep      direction       endpoint_address
+ *     0               0               IN and OUT      0x00
+ *     1 to 15         1 to 15         OUT             0x01 to 0x0f
+ *     16 to 30        1 to 15         IN              0x81 to 0x8f
+ */
+#define PHYS_EP_TO_EP_ADDR(ep) (((ep) < 16) ? (ep) : (((ep) - 15) | 0x80))
+#define EP_ADDR_TO_PHYS_EP(a) (((a) & 0x80) ? (((a) & ~0x80) + 15) : (a))
+
+/* MOD_CONF_CTRL_0 bits (FIXME: move to board hardware.h ?) */
+#define CONF_MOD_USB_W2FC_VBUS_MODE_R (1 << 17)
+
+/* Other registers (may be) related to USB */
+
+#define CLOCK_CTRL         (0xFFFE0830)
+#define APLL_CTRL          (0xFFFE084C)
+#define DPLL_CTRL          (0xFFFE083C)
+#define SOFT_REQ           (0xFFFE0834)
+#define STATUS_REQ         (0xFFFE0840)
+
+/* FUNC_MUX_CTRL_0 bits related to USB */
+#define UDC_VBUS_CTRL      (1 << 19)
+#define UDC_VBUS_MODE      (1 << 18)
+
+
+void omap1510_udc_irq(void);
+void omap1510_udc_noniso_irq(void);
+
+
+/* Higher level functions for abstracting away from specific device */
+void udc_endpoint_write(struct usb_endpoint_instance *endpoint);
+
+int  udc_init (void);
+
+void udc_enable(struct usb_device_instance *device);
+void udc_disable(void);
+
+void udc_connect(void);
+void udc_disconnect(void);
+
+void udc_startup_events(struct usb_device_instance *device);
+void udc_setup_ep(struct usb_device_instance *device, unsigned int ep, struct usb_endpoint_instance *endpoint);
+
+#endif
diff --git a/include/usbdescriptors.h b/include/usbdescriptors.h
new file mode 100644 (file)
index 0000000..2d9f739
--- /dev/null
@@ -0,0 +1,497 @@
+/*
+ * (C) Copyright 2003
+ * Gerry Hamel, geh@ti.com, Texas Instruments
+ *
+ * Based on
+ * linux/drivers/usbd/usb-function.h - USB Function
+ *
+ * Copyright (c) 2000, 2001, 2002 Lineo
+ * Copyright (c) 2001 Hewlett Packard
+ *
+ * By:
+ *     Stuart Lynne <sl@lineo.com>,
+ *     Tom Rushworth <tbr@lineo.com>,
+ *     Bruce Balden <balden@lineo.com>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/* USB Descriptors - Create a complete description of all of the
+ * function driver capabilities. These map directly to the USB descriptors.
+ *
+ * This heirarchy is created by the functions drivers and is passed to the
+ * usb-device driver when the function driver is registered.
+ *
+ *  device
+ *     configuration
+ *          interface
+ *             alternate
+ *                  class
+ *                  class
+ *             alternate
+ *                  endpoint
+ *                  endpoint
+ *          interface
+ *             alternate
+ *                  endpoint
+ *                  endpoint
+ *     configuration
+ *          interface
+ *             alternate
+ *                  endpoint
+ *                  endpoint
+ *
+ *
+ * The configuration structures refer to the USB Configurations that will be
+ * made available to a USB HOST during the enumeration process.
+ *
+ * The USB HOST will select a configuration and optionally an interface with
+ * the usb set configuration and set interface commands.
+ *
+ * The selected interface (or the default interface if not specifically
+ * selected) will define the list of endpoints that will be used.
+ *
+ * The configuration and interfaces are stored in an array that is indexed
+ * by the specified configuratin or interface number minus one.
+ *
+ * A configuration number of zero is used to specify a return to the unconfigured
+ * state.
+ *
+ */
+
+
+#ifndef __USBDESCRIPTORS_H__
+#define __USBDESCRIPTORS_H__
+
+#include <asm/types.h>
+
+/*
+ * communications class types
+ *
+ * c.f. CDC  USB Class Definitions for Communications Devices
+ * c.f. WMCD USB CDC Subclass Specification for Wireless Mobile Communications Devices
+ *
+ */
+
+#define CLASS_BCD_VERSION              0x0110
+
+/* c.f. CDC 4.1 Table 14 */
+#define COMMUNICATIONS_DEVICE_CLASS    0x02
+
+/* c.f. CDC 4.2 Table 15 */
+#define COMMUNICATIONS_INTERFACE_CLASS 0x02
+
+/* c.f. CDC 4.3 Table 16 */
+#define COMMUNICATIONS_NO_SUBCLASS     0x00
+#define COMMUNICATIONS_DLCM_SUBCLASS   0x01
+#define COMMUNICATIONS_ACM_SUBCLASS    0x02
+#define COMMUNICATIONS_TCM_SUBCLASS    0x03
+#define COMMUNICATIONS_MCCM_SUBCLASS   0x04
+#define COMMUNICATIONS_CCM_SUBCLASS    0x05
+#define COMMUNICATIONS_ENCM_SUBCLASS   0x06
+#define COMMUNICATIONS_ANCM_SUBCLASS   0x07
+
+/* c.f. WMCD 5.1 */
+#define COMMUNICATIONS_WHCM_SUBCLASS   0x08
+#define COMMUNICATIONS_DMM_SUBCLASS    0x09
+#define COMMUNICATIONS_MDLM_SUBCLASS   0x0a
+#define COMMUNICATIONS_OBEX_SUBCLASS   0x0b
+
+/* c.f. CDC 4.6 Table 18 */
+#define DATA_INTERFACE_CLASS           0x0a
+
+/* c.f. CDC 4.7 Table 19 */
+#define COMMUNICATIONS_NO_PROTOCOL     0x00
+
+
+/* c.f. CDC 5.2.3 Table 24 */
+#define CS_INTERFACE                   0x24
+#define CS_ENDPOINT                    0x25
+
+/*
+ * bDescriptorSubtypes
+ *
+ * c.f. CDC 5.2.3 Table 25
+ * c.f. WMCD 5.3 Table 5.3
+ */
+
+#define USB_ST_HEADER                  0x00
+#define USB_ST_CMF                     0x01
+#define USB_ST_ACMF                    0x02
+#define USB_ST_DLMF                    0x03
+#define USB_ST_TRF                     0x04
+#define USB_ST_TCLF                    0x05
+#define USB_ST_UF                      0x06
+#define USB_ST_CSF                     0x07
+#define USB_ST_TOMF                    0x08
+#define USB_ST_USBTF                   0x09
+#define USB_ST_NCT                     0x0a
+#define USB_ST_PUF                     0x0b
+#define USB_ST_EUF                     0x0c
+#define USB_ST_MCMF                    0x0d
+#define USB_ST_CCMF                    0x0e
+#define USB_ST_ENF                     0x0f
+#define USB_ST_ATMNF                   0x10
+
+#define USB_ST_WHCM                    0x11
+#define USB_ST_MDLM                    0x12
+#define USB_ST_MDLMD                   0x13
+#define USB_ST_DMM                     0x14
+#define USB_ST_OBEX                    0x15
+#define USB_ST_CS                      0x16
+#define USB_ST_CSD                     0x17
+#define USB_ST_TCM                     0x18
+
+/* endpoint modifiers
+ * static struct usb_endpoint_description function_default_A_1[] = {
+ *
+ *     {this_endpoint: 0, attributes: CONTROL,  max_size: 8,  polling_interval: 0 },
+ *     {this_endpoint: 1, attributes: BULK,     max_size: 64, polling_interval: 0, direction: IN},
+ *     {this_endpoint: 2, attributes: BULK,     max_size: 64, polling_interval: 0, direction: OUT},
+ *     {this_endpoint: 3, attributes: INTERRUPT, max_size: 8,  polling_interval: 0},
+ *
+ *
+ */
+#define OUT            0x00
+#define IN             0x80
+
+#define CONTROL                0x00
+#define ISOCHRONOUS    0x01
+#define BULK           0x02
+#define INTERRUPT      0x03
+
+
+/* configuration modifiers
+ */
+#define BMATTRIBUTE_RESERVED           0x80
+#define BMATTRIBUTE_SELF_POWERED       0x40
+
+/*
+ * standard usb descriptor structures
+ */
+
+struct usb_endpoint_descriptor {
+       u8 bLength;
+       u8 bDescriptorType;     /* 0x5 */
+       u8 bEndpointAddress;
+       u8 bmAttributes;
+       u16 wMaxPacketSize;
+       u8 bInterval;
+} __attribute__ ((packed));
+
+struct usb_interface_descriptor {
+       u8 bLength;
+       u8 bDescriptorType;     /* 0x04 */
+       u8 bInterfaceNumber;
+       u8 bAlternateSetting;
+       u8 bNumEndpoints;
+       u8 bInterfaceClass;
+       u8 bInterfaceSubClass;
+       u8 bInterfaceProtocol;
+       u8 iInterface;
+} __attribute__ ((packed));
+
+struct usb_configuration_descriptor {
+       u8 bLength;
+       u8 bDescriptorType;     /* 0x2 */
+       u16 wTotalLength;
+       u8 bNumInterfaces;
+       u8 bConfigurationValue;
+       u8 iConfiguration;
+       u8 bmAttributes;
+       u8 bMaxPower;
+} __attribute__ ((packed));
+
+struct usb_device_descriptor {
+       u8 bLength;
+       u8 bDescriptorType;     /* 0x01 */
+       u16 bcdUSB;
+       u8 bDeviceClass;
+       u8 bDeviceSubClass;
+       u8 bDeviceProtocol;
+       u8 bMaxPacketSize0;
+       u16 idVendor;
+       u16 idProduct;
+       u16 bcdDevice;
+       u8 iManufacturer;
+       u8 iProduct;
+       u8 iSerialNumber;
+       u8 bNumConfigurations;
+} __attribute__ ((packed));
+
+struct usb_string_descriptor {
+       u8 bLength;
+       u8 bDescriptorType;     /* 0x03 */
+       u16 wData[0];
+} __attribute__ ((packed));
+
+struct usb_generic_descriptor {
+       u8 bLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;
+} __attribute__ ((packed));
+
+
+/*
+ * communications class descriptor structures
+ *
+ * c.f. CDC 5.2 Table 25c
+ */
+
+struct usb_class_function_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;
+} __attribute__ ((packed));
+
+struct usb_class_function_descriptor_generic {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;
+       u8 bmCapabilities;
+} __attribute__ ((packed));
+
+struct usb_class_header_function_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x00 */
+       u16 bcdCDC;
+} __attribute__ ((packed));
+
+struct usb_class_call_management_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x01 */
+       u8 bmCapabilities;
+       u8 bDataInterface;
+} __attribute__ ((packed));
+
+struct usb_class_abstract_control_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x02 */
+       u8 bmCapabilities;
+} __attribute__ ((packed));
+
+struct usb_class_direct_line_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x03 */
+} __attribute__ ((packed));
+
+struct usb_class_telephone_ringer_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x04 */
+       u8 bRingerVolSeps;
+       u8 bNumRingerPatterns;
+} __attribute__ ((packed));
+
+struct usb_class_telephone_call_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x05 */
+       u8 bmCapabilities;
+} __attribute__ ((packed));
+
+struct usb_class_union_function_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x06 */
+       u8 bMasterInterface;
+       u8 bSlaveInterface0[0];
+} __attribute__ ((packed));
+
+struct usb_class_country_selection_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x07 */
+       u8 iCountryCodeRelDate;
+       u16 wCountryCode0[0];
+} __attribute__ ((packed));
+
+
+struct usb_class_telephone_operational_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x08 */
+       u8 bmCapabilities;
+} __attribute__ ((packed));
+
+
+struct usb_class_usb_terminal_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x09 */
+       u8 bEntityId;
+       u8 bInterfaceNo;
+       u8 bOutInterfaceNo;
+       u8 bmOptions;
+       u8 bChild0[0];
+} __attribute__ ((packed));
+
+struct usb_class_network_channel_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x0a */
+       u8 bEntityId;
+       u8 iName;
+       u8 bChannelIndex;
+       u8 bPhysicalInterface;
+} __attribute__ ((packed));
+
+struct usb_class_protocol_unit_function_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x0b */
+       u8 bEntityId;
+       u8 bProtocol;
+       u8 bChild0[0];
+} __attribute__ ((packed));
+
+struct usb_class_extension_unit_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x0c */
+       u8 bEntityId;
+       u8 bExtensionCode;
+       u8 iName;
+       u8 bChild0[0];
+} __attribute__ ((packed));
+
+struct usb_class_multi_channel_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x0d */
+       u8 bmCapabilities;
+} __attribute__ ((packed));
+
+struct usb_class_capi_control_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x0e */
+       u8 bmCapabilities;
+} __attribute__ ((packed));
+
+struct usb_class_ethernet_networking_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x0f */
+       u8 iMACAddress;
+       u32 bmEthernetStatistics;
+       u16 wMaxSegmentSize;
+       u16 wNumberMCFilters;
+       u8 bNumberPowerFilters;
+} __attribute__ ((packed));
+
+struct usb_class_atm_networking_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x10 */
+       u8 iEndSystermIdentifier;
+       u8 bmDataCapabilities;
+       u8 bmATMDeviceStatistics;
+       u16 wType2MaxSegmentSize;
+       u16 wType3MaxSegmentSize;
+       u16 wMaxVC;
+} __attribute__ ((packed));
+
+
+struct usb_class_mdlm_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x12 */
+       u16 bcdVersion;
+       u8 bGUID[16];
+} __attribute__ ((packed));
+
+struct usb_class_mdlmd_descriptor {
+       u8 bFunctionLength;
+       u8 bDescriptorType;
+       u8 bDescriptorSubtype;  /* 0x13 */
+       u8 bGuidDescriptorType;
+       u8 bDetailData[0];
+
+} __attribute__ ((packed));
+
+/*
+ * HID class descriptor structures
+ *
+ * c.f. HID 6.2.1
+ */
+
+struct usb_class_hid_descriptor {
+    u8       bLength;
+    u8       bDescriptorType;
+    u16              bcdCDC;
+    u8       bCountryCode;
+    u8       bNumDescriptors;  /* 0x01 */
+    u8       bDescriptorType0;
+    u16              wDescriptorLength0;
+    /* optional descriptors are not supported. */
+} __attribute__((packed));
+
+struct usb_class_report_descriptor {
+    u8       bLength;  /* dummy */
+    u8       bDescriptorType;
+    u16              wLength;
+    u8         bData[0];
+} __attribute__((packed));
+
+/*
+ * descriptor union structures
+ */
+
+struct usb_descriptor {
+       union {
+               struct usb_generic_descriptor generic;
+               struct usb_endpoint_descriptor endpoint;
+               struct usb_interface_descriptor interface;
+               struct usb_configuration_descriptor configuration;
+               struct usb_device_descriptor device;
+               struct usb_string_descriptor string;
+       } descriptor;
+
+} __attribute__ ((packed));
+
+struct usb_class_descriptor {
+       union {
+               struct usb_class_function_descriptor function;
+               struct usb_class_function_descriptor_generic generic;
+               struct usb_class_header_function_descriptor header_function;
+               struct usb_class_call_management_descriptor call_management;
+               struct usb_class_abstract_control_descriptor abstract_control;
+               struct usb_class_direct_line_descriptor direct_line;
+               struct usb_class_telephone_ringer_descriptor telephone_ringer;
+               struct usb_class_telephone_operational_descriptor telephone_operational;
+               struct usb_class_telephone_call_descriptor telephone_call;
+               struct usb_class_union_function_descriptor union_function;
+               struct usb_class_country_selection_descriptor country_selection;
+               struct usb_class_usb_terminal_descriptor usb_terminal;
+               struct usb_class_network_channel_descriptor network_channel;
+               struct usb_class_extension_unit_descriptor extension_unit;
+               struct usb_class_multi_channel_descriptor multi_channel;
+               struct usb_class_capi_control_descriptor capi_control;
+               struct usb_class_ethernet_networking_descriptor ethernet_networking;
+               struct usb_class_atm_networking_descriptor atm_networking;
+               struct usb_class_mdlm_descriptor mobile_direct;
+               struct usb_class_mdlmd_descriptor mobile_direct_detail;
+               struct usb_class_hid_descriptor hid;
+       } descriptor;
+
+} __attribute__ ((packed));
+
+#endif
index 8ba9f0c797a230e279eb2b737736158d06047a8a..8ace062750ead973f0672ba95ec1af2ae76f7599 100644 (file)
  *
  * 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
+ * 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
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307         USA
  *
  */
 
@@ -256,6 +256,13 @@ void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
        /* we assume that the kernel is in place */
        printf ("\nStarting kernel ...\n\n");
 
+#ifdef CONFIG_USB_DEVICE
+       {
+               extern void udc_disconnect (void);
+               udc_disconnect ();
+       }
+#endif
+
        cleanup_before_linux ();
 
        theKernel (0, bd->bi_arch_number, bd->bi_boot_params);
index e02372cb287ee44787ed936b8d88c8fd91ee8eae..f5adce4f5e34d7f40fe67bf74e85da1cc35865dc 100644 (file)
@@ -5,12 +5,12 @@
  *     (See License)
  *     Copyright 2000 Roland Borde
  *     Copyright 2000 Paolo Scaffardi
- *     Copyright 2000-2002 Wolfgang Denk, wd@denx.de
+ *     Copyright 2000-2004 Wolfgang Denk, wd@denx.de
  */
 
 #if 0
-#define        DEBUG           1       /* general debug */
-#define DEBUG_BOOTP_EXT        1       /* Debug received vendor fields */
+#define DEBUG          1       /* general debug */
+#define DEBUG_BOOTP_EXT 1      /* Debug received vendor fields */
 #endif
 
 #ifdef DEBUG_BOOTP_EXT
 #include <net.h>
 #include "bootp.h"
 #include "tftp.h"
+#include "nfs.h"
 #ifdef CONFIG_STATUS_LED
 #include <status_led.h>
 #endif
 
-#define        BOOTP_VENDOR_MAGIC      0x63825363      /* RFC1048 Magic Cookie         */
+#define BOOTP_VENDOR_MAGIC     0x63825363      /* RFC1048 Magic Cookie         */
 
 #if (CONFIG_COMMANDS & CFG_CMD_NET)
 
 #define TIMEOUT                5               /* Seconds before trying BOOTP again    */
-#ifndef        CONFIG_NET_RETRY_COUNT
+#ifndef CONFIG_NET_RETRY_COUNT
 # define TIMEOUT_COUNT 5               /* # of timeouts before giving up  */
 #else
-# define TIMEOUT_COUNT  (CONFIG_NET_RETRY_COUNT)
+# define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT)
 #endif
 
 #define PORT_BOOTPS    67              /* BOOTP server UDP port                */
 #define PORT_BOOTPC    68              /* BOOTP client UDP port                */
 
 #ifndef CONFIG_DHCP_MIN_EXT_LEN                /* minimal length of extension list     */
-#define        CONFIG_DHCP_MIN_EXT_LEN 64
+#define CONFIG_DHCP_MIN_EXT_LEN 64
 #endif
 
 ulong          BootpID;
@@ -63,13 +64,13 @@ static void DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len);
 static char *dhcpmsg2str(int type)
 {
        switch (type) {
-       case 1:  return "DHCPDISCOVER"; break;
-       case 2:  return "DHCPOFFER";    break;
-       case 3:  return "DHCPREQUEST";  break;
-       case 4:  return "DHCPDECLINE";  break;
-       case 5:  return "DHCPACK";      break;
-       case 6:  return "DHCPNACK";     break;
-       case 7:  return "DHCPRELEASE";  break;
+       case 1:  return "DHCPDISCOVER"; break;
+       case 2:  return "DHCPOFFER";    break;
+       case 3:  return "DHCPREQUEST";  break;
+       case 4:  return "DHCPDECLINE";  break;
+       case 5:  return "DHCPACK";      break;
+       case 6:  return "DHCPNACK";     break;
+       case 7:  return "DHCPRELEASE";  break;
        default: return "UNKNOWN/INVALID MSG TYPE"; break;
        }
 }
@@ -144,159 +145,158 @@ static int truncate_sz (const char *name, int maxlen, int curlen)
 
 #if !(CONFIG_COMMANDS & CFG_CMD_DHCP)
 
-static void BootpVendorFieldProcess(u8 *ext)
+static void BootpVendorFieldProcess (u8 * ext)
 {
-    int size = *(ext+1) ;
+       int size = *(ext + 1);
 
-    debug_ext ("[BOOTP] Processing extension %d... (%d bytes)\n", *ext, *(ext+1));
+       debug_ext ("[BOOTP] Processing extension %d... (%d bytes)\n", *ext,
+                  *(ext + 1));
 
-    NetBootFileSize = 0;
+       NetBootFileSize = 0;
 
-    switch (*ext) {
-    /* Fixed length fields */
-       case 1:         /* Subnet mask                                  */
+       switch (*ext) {
+               /* Fixed length fields */
+       case 1:                 /* Subnet mask                                  */
                if (NetOurSubnetMask == 0)
-                       NetCopyIP(&NetOurSubnetMask, (IPaddr_t*)(ext+2));
+                       NetCopyIP (&NetOurSubnetMask, (IPaddr_t *) (ext + 2));
                break;
-       case 2:         /* Time offset - Not yet supported              */
+       case 2:                 /* Time offset - Not yet supported              */
                break;
-    /* Variable length fields */
-       case 3:         /* Gateways list                                */
+               /* Variable length fields */
+       case 3:                 /* Gateways list                                */
                if (NetOurGatewayIP == 0) {
-                       NetCopyIP(&NetOurGatewayIP, (IPaddr_t*)(ext+2));
+                       NetCopyIP (&NetOurGatewayIP, (IPaddr_t *) (ext + 2));
                }
                break;
-       case 4:         /* Time server - Not yet supported              */
+       case 4:                 /* Time server - Not yet supported              */
                break;
-       case 5:         /* IEN-116 name server - Not yet supported      */
+       case 5:                 /* IEN-116 name server - Not yet supported      */
                break;
        case 6:
                if (NetOurDNSIP == 0) {
-                       NetCopyIP(&NetOurDNSIP, (IPaddr_t*)(ext+2));
+                       NetCopyIP (&NetOurDNSIP, (IPaddr_t *) (ext + 2));
                }
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2)
                if ((NetOurDNS2IP == 0) && (size > 4)) {
-                       NetCopyIP(&NetOurDNS2IP, (IPaddr_t*)(ext+2+4));
+                       NetCopyIP (&NetOurDNS2IP, (IPaddr_t *) (ext + 2 + 4));
                }
 #endif
                break;
-       case 7:         /* Log server - Not yet supported               */
+       case 7:                 /* Log server - Not yet supported               */
                break;
-       case 8:         /* Cookie/Quote server - Not yet supported      */
+       case 8:                 /* Cookie/Quote server - Not yet supported      */
                break;
-       case 9:         /* LPR server - Not yet supported               */
+       case 9:                 /* LPR server - Not yet supported               */
                break;
-       case 10:        /* Impress server - Not yet supported           */
+       case 10:                /* Impress server - Not yet supported           */
                break;
-       case 11:        /* RPL server - Not yet supported               */
+       case 11:                /* RPL server - Not yet supported               */
                break;
-       case 12:        /* Host name                                    */
+       case 12:                /* Host name                                    */
                if (NetOurHostName[0] == 0) {
-                   size = truncate_sz("Host Name", sizeof(NetOurHostName), size);
-                   memcpy(&NetOurHostName, ext+2, size);
-                   NetOurHostName[size] = 0 ;
+                       size = truncate_sz ("Host Name", sizeof (NetOurHostName), size);
+                       memcpy (&NetOurHostName, ext + 2, size);
+                       NetOurHostName[size] = 0;
                }
                break;
-       case 13:        /* Boot file size                               */
+       case 13:                /* Boot file size                               */
                if (size == 2)
-                       NetBootFileSize = ntohs(*(ushort*)(ext+2));
+                       NetBootFileSize = ntohs (*(ushort *) (ext + 2));
                else if (size == 4)
-                       NetBootFileSize = ntohl(*(ulong*)(ext+2));
+                       NetBootFileSize = ntohl (*(ulong *) (ext + 2));
                break;
-       case 14:        /* Merit dump file - Not yet supported          */
+       case 14:                /* Merit dump file - Not yet supported          */
                break;
-       case 15:        /* Domain name - Not yet supported              */
+       case 15:                /* Domain name - Not yet supported              */
                break;
-       case 16:        /* Swap server - Not yet supported              */
+       case 16:                /* Swap server - Not yet supported              */
                break;
-       case 17:        /* Root path                                    */
+       case 17:                /* Root path                                    */
                if (NetOurRootPath[0] == 0) {
-                   size = truncate_sz("Root Path", sizeof(NetOurRootPath), size);
-                   memcpy(&NetOurRootPath, ext+2, size);
-                   NetOurRootPath[size] = 0 ;
+                       size = truncate_sz ("Root Path", sizeof (NetOurRootPath), size);
+                       memcpy (&NetOurRootPath, ext + 2, size);
+                       NetOurRootPath[size] = 0;
                }
                break;
-       case 18:        /* Extension path - Not yet supported           */
+       case 18:                /* Extension path - Not yet supported           */
                /*
                 * This can be used to send the information of the
                 * vendor area in another file that the client can
                 * access via TFTP.
                 */
                break;
-    /* IP host layer fields */
-       case 40:        /* NIS Domain name                              */
+               /* IP host layer fields */
+       case 40:                /* NIS Domain name                              */
                if (NetOurNISDomain[0] == 0) {
-                   size = truncate_sz ("NIS Domain Name",
-                                       sizeof(NetOurNISDomain),
-                                       size);
-                   memcpy(&NetOurNISDomain, ext+2, size);
-                   NetOurNISDomain[size] = 0 ;
+                       size = truncate_sz ("NIS Domain Name", sizeof (NetOurNISDomain), size);
+                       memcpy (&NetOurNISDomain, ext + 2, size);
+                       NetOurNISDomain[size] = 0;
                }
                break;
-    /* Application layer fields */
-       case 43:        /* Vendor specific info - Not yet supported     */
+               /* Application layer fields */
+       case 43:                /* Vendor specific info - Not yet supported     */
                /*
                 * Binary information to exchange specific
                 * product information.
                 */
                break;
-    /* Reserved (custom) fields (128..254) */
-    }
+               /* Reserved (custom) fields (128..254) */
+       }
 }
 
-static void BootpVendorProcess(u8 *ext, int size)
+static void BootpVendorProcess (u8 * ext, int size)
 {
-    u8 *end = ext + size ;
+       u8 *end = ext + size;
 
-    debug_ext ("[BOOTP] Checking extension (%d bytes)...\n", size);
+       debug_ext ("[BOOTP] Checking extension (%d bytes)...\n", size);
 
-    while ((ext < end) && (*ext != 0xff)) {
-       if (*ext == 0) {
-           ext ++ ;
-       } else {
-               u8 *opt = ext ;
-               ext += ext[1] + 2 ;
-               if (ext <= end)
-                   BootpVendorFieldProcess (opt) ;
+       while ((ext < end) && (*ext != 0xff)) {
+               if (*ext == 0) {
+                       ext++;
+               } else {
+                       u8 *opt = ext;
+
+                       ext += ext[1] + 2;
+                       if (ext <= end)
+                               BootpVendorFieldProcess (opt);
+               }
        }
-    }
 
 #ifdef DEBUG_BOOTP_EXT
-    printf("[BOOTP] Received fields: \n");
-    if (NetOurSubnetMask) {
-       puts ("NetOurSubnetMask : ");
-       print_IPaddr (NetOurSubnetMask);
-       putc('\n');
-    }
-
-    if (NetOurGatewayIP) {
-       puts ("NetOurGatewayIP  : ");
-       print_IPaddr (NetOurGatewayIP);
-       putc('\n');
-    }
-
-    if (NetBootFileSize) {
-       printf("NetBootFileSize : %d\n", NetBootFileSize);
-    }
-
-    if (NetOurHostName[0]) {
-       printf("NetOurHostName  : %s\n", NetOurHostName);
-    }
-
-    if (NetOurRootPath[0]) {
-       printf("NetOurRootPath  : %s\n", NetOurRootPath);
-    }
-
-    if (NetOurNISDomain[0]) {
-       printf("NetOurNISDomain : %s\n", NetOurNISDomain);
-    }
-
-    if (NetBootFileSize) {
-       printf("NetBootFileSize: %d\n", NetBootFileSize);
-    }
-#endif /* DEBUG_BOOTP_EXT */
-}
+       printf ("[BOOTP] Received fields: \n");
+       if (NetOurSubnetMask) {
+               puts ("NetOurSubnetMask : ");
+               print_IPaddr (NetOurSubnetMask);
+               putc ('\n');
+       }
+
+       if (NetOurGatewayIP) {
+               puts ("NetOurGatewayIP  : ");
+               print_IPaddr (NetOurGatewayIP);
+               putc ('\n');
+       }
+
+       if (NetBootFileSize) {
+               printf ("NetBootFileSize : %d\n", NetBootFileSize);
+       }
 
+       if (NetOurHostName[0]) {
+               printf ("NetOurHostName  : %s\n", NetOurHostName);
+       }
+
+       if (NetOurRootPath[0]) {
+               printf ("NetOurRootPath  : %s\n", NetOurRootPath);
+       }
+
+       if (NetOurNISDomain[0]) {
+               printf ("NetOurNISDomain : %s\n", NetOurNISDomain);
+       }
+
+       if (NetBootFileSize) {
+               printf ("NetBootFileSize: %d\n", NetBootFileSize);
+       }
+#endif /* DEBUG_BOOTP_EXT */
+}
 /*
  *     Handle a BOOTP received packet.
  */
@@ -311,11 +311,11 @@ BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
 
        bp = (Bootp_t *)pkt;
 
-       if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
+       if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
                return;
 
        /*
-        *      Got a good BOOTP reply.  Copy the data into our variables.
+        *      Got a good BOOTP reply.  Copy the data into our variables.
         */
 #ifdef CONFIG_STATUS_LED
        status_led_set (STATUS_LED_BOOT, STATUS_LED_OFF);
@@ -371,179 +371,180 @@ BootpTimeout(void)
  *     Initialize BOOTP extension fields in the request.
  */
 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
-static int DhcpExtended(u8 *e, int message_type, IPaddr_t ServerID, IPaddr_t RequestedIP)
+static int DhcpExtended (u8 * e, int message_type, IPaddr_t ServerID, IPaddr_t RequestedIP)
 {
-    u8 *start = e ;
-    u8 *cnt;
+       u8 *start = e;
+       u8 *cnt;
+
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
-    u8 *x;
+       u8 *x;
 #endif
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SEND_HOSTNAME)
-    uchar *hostname;
+       uchar *hostname;
 #endif
 
-    *e++ =  99;                /* RFC1048 Magic Cookie */
-    *e++ = 130;
-    *e++ =  83;
-    *e++ =  99;
-
-    *e++ = 53;         /* DHCP Message Type */
-    *e++ = 1;
-    *e++ = message_type;
+       *e++ = 99;              /* RFC1048 Magic Cookie */
+       *e++ = 130;
+       *e++ = 83;
+       *e++ = 99;
 
-    *e++ = 57;         /* Maximum DHCP Message Size */
-    *e++ = 2;
-    *e++ = (576-312+OPT_SIZE) >> 8;
-    *e++ = (576-312+OPT_SIZE) & 0xff;
+       *e++ = 53;              /* DHCP Message Type */
+       *e++ = 1;
+       *e++ = message_type;
 
-    if ( ServerID ) {
-           int tmp = ntohl(ServerID);
+       *e++ = 57;              /* Maximum DHCP Message Size */
+       *e++ = 2;
+       *e++ = (576 - 312 + OPT_SIZE) >> 8;
+       *e++ = (576 - 312 + OPT_SIZE) & 0xff;
 
-           *e++ = 54;  /* ServerID */
-           *e++ = 4;
-           *e++ = tmp >> 24;
-           *e++ = tmp >> 16;
-           *e++ = tmp >> 8;
-           *e++ = tmp & 0xff;
-    }
+       if (ServerID) {
+               int tmp = ntohl (ServerID);
 
-    if ( RequestedIP ) {
-           int tmp = ntohl(RequestedIP);
+               *e++ = 54;      /* ServerID */
+               *e++ = 4;
+               *e++ = tmp >> 24;
+               *e++ = tmp >> 16;
+               *e++ = tmp >> 8;
+               *e++ = tmp & 0xff;
+       }
 
-           *e++ = 50;  /* Requested IP */
-           *e++ = 4;
-           *e++ = tmp >> 24;
-           *e++ = tmp >> 16;
-           *e++ = tmp >> 8;
-           *e++ = tmp & 0xff;
-    }
+       if (RequestedIP) {
+               int tmp = ntohl (RequestedIP);
 
+               *e++ = 50;      /* Requested IP */
+               *e++ = 4;
+               *e++ = tmp >> 24;
+               *e++ = tmp >> 16;
+               *e++ = tmp >> 8;
+               *e++ = tmp & 0xff;
+       }
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SEND_HOSTNAME)
-    if ( (hostname = getenv("hostname")) ) {
-           int hostnamelen = strlen(hostname);
-           *e++ = 12;        /* Hostname */
-           *e++ = hostnamelen;
-           memcpy(e,hostname,hostnamelen);
-           e += hostnamelen;
-    }
+       if ((hostname = getenv ("hostname"))) {
+               int hostnamelen = strlen (hostname);
+
+               *e++ = 12;      /* Hostname */
+               *e++ = hostnamelen;
+               memcpy (e, hostname, hostnamelen);
+               e += hostnamelen;
+       }
 #endif
 
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
-    if ((x = dhcp_vendorex_prep (e)))
-       return x - start ;
+       if ((x = dhcp_vendorex_prep (e)))
+               return x - start;
 #endif
 
-    *e++ = 55;         /* Parameter Request List */
-    cnt  = e++;                /* Pointer to count of requested items */
-    *cnt = 0;
+       *e++ = 55;              /* Parameter Request List */
+        cnt = e++;             /* Pointer to count of requested items */
+       *cnt = 0;
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SUBNETMASK)
-    *e++ = 1;          /* Subnet Mask */
-    *cnt += 1;
+       *e++  = 1;              /* Subnet Mask */
+       *cnt += 1;
 #endif
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_GATEWAY)
-    *e++ = 3;          /* Router Option */
-    *cnt += 1;
+       *e++  = 3;              /* Router Option */
+       *cnt += 1;
 #endif
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS)
-    *e++ = 6;          /* DNS Server(s) */
-    *cnt += 1;
+       *e++  = 6;              /* DNS Server(s) */
+       *cnt += 1;
 #endif
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_HOSTNAME)
-    *e++ = 12;         /* Hostname */
-    *cnt += 1;
+       *e++  = 12;             /* Hostname */
+       *cnt += 1;
 #endif
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTFILESIZE)
-    *e++ = 13;         /* Boot File Size */
-    *cnt += 1;
+       *e++  = 13;             /* Boot File Size */
+       *cnt += 1;
 #endif
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTPATH)
-    *e++ = 17;         /* Boot path */
-    *cnt += 1;
+       *e++  = 17;             /* Boot path */
+       *cnt += 1;
 #endif
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NISDOMAIN)
-    *e++ = 40;         /* NIS Domain name request */
-    *cnt += 1;
+       *e++  = 40;             /* NIS Domain name request */
+       *cnt += 1;
 #endif
-    *e++ = 255;                /* End of the list */
+       *e++  = 255;            /* End of the list */
 
-    /* Pad to minimal length */
+       /* Pad to minimal length */
 #ifdef CONFIG_DHCP_MIN_EXT_LEN
-    while ((e - start) <= CONFIG_DHCP_MIN_EXT_LEN)
-       *e++ = 0;
+       while ((e - start) <= CONFIG_DHCP_MIN_EXT_LEN)
+               *e++ = 0;
 #endif
 
-    return e - start ;
+       return e - start;
 }
 
 #else  /* CFG_CMD_DHCP */
 /*
  *     Warning: no field size check - change CONFIG_BOOTP_MASK at your own risk!
  */
-static int BootpExtended (u8 *e)
+static int BootpExtended (u8 * e)
 {
-    u8 *start = e ;
+       u8 *start = e;
 
-    *e++ =  99;                /* RFC1048 Magic Cookie */
-    *e++ = 130;
-    *e++ =  83;
-    *e++ =  99;
+       *e++ = 99;              /* RFC1048 Magic Cookie */
+       *e++ = 130;
+       *e++ = 83;
+       *e++ = 99;
 
 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
-    *e++ = 53;         /* DHCP Message Type */
-    *e++ = 1;
-    *e++ = DHCP_DISCOVER;
-
-    *e++ = 57;         /* Maximum DHCP Message Size */
-    *e++ = 2;
-    *e++ = (576-312+OPT_SIZE) >> 16;
-    *e++ = (576-312+OPT_SIZE) & 0xff;
-#endif /* CFG_CMD_DHCP */
+       *e++ = 53;              /* DHCP Message Type */
+       *e++ = 1;
+       *e++ = DHCP_DISCOVER;
+
+       *e++ = 57;              /* Maximum DHCP Message Size */
+       *e++ = 2;
+       *e++ = (576 - 312 + OPT_SIZE) >> 16;
+       *e++ = (576 - 312 + OPT_SIZE) & 0xff;
+#endif /* CFG_CMD_DHCP */
 
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SUBNETMASK)
-    *e++ =  1;         /* Subnet mask request */
-    *e++ =  4;
-     e  +=  4;
+       *e++ = 1;               /* Subnet mask request */
+       *e++ = 4;
+       e   += 4;
 #endif
 
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_GATEWAY)
-    *e++ =  3;         /* Default gateway request */
-    *e++ =  4;
-     e  +=  4;
+       *e++ = 3;               /* Default gateway request */
+       *e++ = 4;
+       e   += 4;
 #endif
 
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS)
-    *e++ =  6;         /* Domain Name Server */
-    *e++ =  4;
-     e  +=  4;
+       *e++ = 6;               /* Domain Name Server */
+       *e++ = 4;
+       e   += 4;
 #endif
 
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_HOSTNAME)
-    *e++ = 12;         /* Host name request */
-    *e++ = 32;
-     e  += 32;
+       *e++ = 12;              /* Host name request */
+       *e++ = 32;
+       e   += 32;
 #endif
 
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTFILESIZE)
-    *e++ = 13;         /* Boot file size */
-    *e++ =  2;
-     e  +=  2;
+       *e++ = 13;              /* Boot file size */
+       *e++ = 2;
+       e   += 2;
 #endif
 
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTPATH)
-    *e++ = 17;         /* Boot path */
-    *e++ = 32;
-     e  += 32;
+       *e++ = 17;              /* Boot path */
+       *e++ = 32;
+       e   += 32;
 #endif
 
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NISDOMAIN)
-    *e++ = 40;         /* NIS Domain name request */
-    *e++ = 32;
-     e  += 32;
+       *e++ = 40;              /* NIS Domain name request */
+       *e++ = 32;
+       e   += 32;
 #endif
 
-    *e++ = 255;                /* End of the list */
+       *e++ = 255;             /* End of the list */
 
-    return e - start ;
+       return e - start;
 }
 #endif /* CFG_CMD_DHCP */
 
@@ -678,7 +679,7 @@ BootpRequest (void)
                | ((ulong)NetOurEther[4] << 8)
                | (ulong)NetOurEther[5];
        BootpID += get_timer(0);
-       BootpID  = htonl(BootpID);
+       BootpID  = htonl(BootpID);
        NetCopyLong(&bp->bp_id, &BootpID);
 
        /*
@@ -700,64 +701,59 @@ BootpRequest (void)
 }
 
 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
-static void DhcpOptionsProcess(uchar *popt)
+static void DhcpOptionsProcess (uchar * popt)
 {
        uchar *end = popt + BOOTP_HDR_SIZE;
        int oplen, size;
 
-       while ( popt < end && *popt != 0xff ) {
+       while (popt < end && *popt != 0xff) {
                oplen = *(popt + 1);
-               switch(*popt) {
-                       case  1:
-                               NetCopyIP(&NetOurSubnetMask, (popt+2));
-                               break;
-                       case  3:
-                               NetCopyIP(&NetOurGatewayIP, (popt+2));
-                               break;
-                       case  6:
-                               NetCopyIP(&NetOurDNSIP, (popt+2));
+               switch (*popt) {
+               case 1:
+                       NetCopyIP (&NetOurSubnetMask, (popt + 2));
+                       break;
+               case 3:
+                       NetCopyIP (&NetOurGatewayIP, (popt + 2));
+                       break;
+               case 6:
+                       NetCopyIP (&NetOurDNSIP, (popt + 2));
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2)
-                               if ( *(popt+1) > 4 ) {
-                                       NetCopyIP(&NetOurDNS2IP, (popt+2+4));
-                               }
+                       if (*(popt + 1) > 4) {
+                               NetCopyIP (&NetOurDNS2IP, (popt + 2 + 4));
+                       }
 #endif
-                               break;
-                       case 12:
-                               size = truncate_sz ("Host Name",
-                                                   sizeof(NetOurHostName),
-                                                   oplen);
-                               memcpy(&NetOurHostName, popt+2, size);
-                               NetOurHostName[size] = 0 ;
-                               break;
-                       case 15:                /* Ignore Domain Name Option */
-                               break;
-                       case 17:
-                               size = truncate_sz ("Root Path",
-                                                   sizeof(NetOurRootPath),
-                                                   oplen);
-                               memcpy(&NetOurRootPath, popt+2, size);
-                               NetOurRootPath[size] = 0 ;
-                               break;
-                       case 51:
-                               NetCopyLong (&dhcp_leasetime, (ulong *)(popt + 2));
-                               break;
-                       case 53:                /* Ignore Message Type Option */
-                               break;
-                       case 54:
-                               NetCopyIP(&NetDHCPServerIP, (popt+2));
-                               break;
-                       case 58:                /* Ignore Renewal Time Option */
-                               break;
-                       case 59:                /* Ignore Rebinding Time Option */
-                               break;
-                       default:
+                       break;
+               case 12:
+                       size = truncate_sz ("Host Name", sizeof (NetOurHostName), oplen);
+                       memcpy (&NetOurHostName, popt + 2, size);
+                       NetOurHostName[size] = 0;
+                       break;
+               case 15:        /* Ignore Domain Name Option */
+                       break;
+               case 17:
+                       size = truncate_sz ("Root Path", sizeof (NetOurRootPath), oplen);
+                       memcpy (&NetOurRootPath, popt + 2, size);
+                       NetOurRootPath[size] = 0;
+                       break;
+               case 51:
+                       NetCopyLong (&dhcp_leasetime, (ulong *) (popt + 2));
+                       break;
+               case 53:        /* Ignore Message Type Option */
+                       break;
+               case 54:
+                       NetCopyIP (&NetDHCPServerIP, (popt + 2));
+                       break;
+               case 58:        /* Ignore Renewal Time Option */
+                       break;
+               case 59:        /* Ignore Rebinding Time Option */
+                       break;
+               default:
 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
-                           if (dhcp_vendorex_proc(popt))
+                       if (dhcp_vendorex_proc (popt))
                                break;
 #endif
-                               printf("*** Unhandled DHCP Option in OFFER/ACK: %d\n",
-                                       *popt);
-                               break;
+                       printf ("*** Unhandled DHCP Option in OFFER/ACK: %d\n", *popt);
+                       break;
                }
                popt += oplen + 2;      /* Process next option */
        }
@@ -837,7 +833,7 @@ DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
        debug ("DHCPHandler: got packet: (src=%d, dst=%d, len=%d) state: %d\n",
                src, dest, len, dhcp_state);
 
-       if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
+       if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
                return;
 
        debug ("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state: %d\n",
@@ -864,7 +860,7 @@ DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
                        if (NetReadLong((ulong*)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
                                DhcpOptionsProcess(&bp->bp_vend[4]);
 
-                       BootpCopyNetParams(bp); /* Store net params from reply */
+                       BootpCopyNetParams(bp); /* Store net params from reply */
 
                        NetSetTimeout(TIMEOUT * CFG_HZ, BootpTimeout);
                        DhcpSendRequestPkt(bp);
@@ -882,7 +878,7 @@ DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
 
                        if (NetReadLong((ulong*)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
                                DhcpOptionsProcess(&bp->bp_vend[4]);
-                       BootpCopyNetParams(bp); /* Store net params from reply */
+                       BootpCopyNetParams(bp); /* Store net params from reply */
                        dhcp_state = BOUND;
                        printf("DHCP client bound to address ");
                        print_IPaddr(NetOurIP);