]> git.sur5r.net Git - u-boot/commitdiff
drivers/usb: regorganisation
authorJean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Fri, 3 Apr 2009 10:46:58 +0000 (12:46 +0200)
committerRemy Bohmer <linux@bohmer.net>
Mon, 6 Apr 2009 18:40:46 +0000 (20:40 +0200)
move to linux usb driver organisation

as following

drivers/usb/gadget
drivers/usb/host
drivers/usb/musb

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Signed-off-by: Remy Bohmer <linux@bohmer.net>
71 files changed:
Makefile
drivers/serial/usbtty.c
drivers/serial/usbtty.h
drivers/usb/Makefile [deleted file]
drivers/usb/atmel_usb.c [deleted file]
drivers/usb/davinci_usb.c [deleted file]
drivers/usb/davinci_usb.h [deleted file]
drivers/usb/gadget/Makefile [new file with mode: 0644]
drivers/usb/gadget/core.c [new file with mode: 0644]
drivers/usb/gadget/ep0.c [new file with mode: 0644]
drivers/usb/gadget/ep0.h [new file with mode: 0644]
drivers/usb/gadget/mpc8xx_udc.c [new file with mode: 0644]
drivers/usb/gadget/omap1510_udc.c [new file with mode: 0644]
drivers/usb/host/Makefile [new file with mode: 0644]
drivers/usb/host/ehci-core.h [new file with mode: 0644]
drivers/usb/host/ehci-fsl.c [new file with mode: 0644]
drivers/usb/host/ehci-fsl.h [new file with mode: 0644]
drivers/usb/host/ehci-hcd.c [new file with mode: 0644]
drivers/usb/host/ehci-ixp4xx.c [new file with mode: 0644]
drivers/usb/host/ehci-pci.c [new file with mode: 0644]
drivers/usb/host/ehci-vct.c [new file with mode: 0644]
drivers/usb/host/ehci.h [new file with mode: 0644]
drivers/usb/host/isp116x-hcd.c [new file with mode: 0644]
drivers/usb/host/isp116x.h [new file with mode: 0644]
drivers/usb/host/ohci-at91.c [new file with mode: 0644]
drivers/usb/host/ohci-hcd.c [new file with mode: 0644]
drivers/usb/host/ohci.h [new file with mode: 0644]
drivers/usb/host/r8a66597-hcd.c [new file with mode: 0644]
drivers/usb/host/r8a66597.h [new file with mode: 0644]
drivers/usb/host/s3c64xx-hcd.c [new file with mode: 0644]
drivers/usb/host/sl811-hcd.c [new file with mode: 0644]
drivers/usb/host/sl811.h [new file with mode: 0644]
drivers/usb/isp116x-hcd.c [deleted file]
drivers/usb/isp116x.h [deleted file]
drivers/usb/musb/Makefile [new file with mode: 0644]
drivers/usb/musb/davinci.c [new file with mode: 0644]
drivers/usb/musb/davinci.h [new file with mode: 0644]
drivers/usb/musb/musb_core.c [new file with mode: 0644]
drivers/usb/musb/musb_core.h [new file with mode: 0644]
drivers/usb/musb/musb_hcd.c [new file with mode: 0644]
drivers/usb/musb/musb_hcd.h [new file with mode: 0644]
drivers/usb/musb_core.c [deleted file]
drivers/usb/musb_core.h [deleted file]
drivers/usb/musb_hcd.c [deleted file]
drivers/usb/musb_hcd.h [deleted file]
drivers/usb/r8a66597-hcd.c [deleted file]
drivers/usb/r8a66597.h [deleted file]
drivers/usb/s3c64xx_usb.c [deleted file]
drivers/usb/sl811.h [deleted file]
drivers/usb/sl811_usb.c [deleted file]
drivers/usb/usb_ehci.h [deleted file]
drivers/usb/usb_ehci_core.c [deleted file]
drivers/usb/usb_ehci_core.h [deleted file]
drivers/usb/usb_ehci_fsl.c [deleted file]
drivers/usb/usb_ehci_fsl.h [deleted file]
drivers/usb/usb_ehci_ixp.c [deleted file]
drivers/usb/usb_ehci_pci.c [deleted file]
drivers/usb/usb_ehci_vct.c [deleted file]
drivers/usb/usb_ohci.c [deleted file]
drivers/usb/usb_ohci.h [deleted file]
drivers/usb/usbdcore.c [deleted file]
drivers/usb/usbdcore_ep0.c [deleted file]
drivers/usb/usbdcore_mpc8xx.c [deleted file]
drivers/usb/usbdcore_omap1510.c [deleted file]
include/usb/mpc8xx_udc.h [new file with mode: 0644]
include/usb/omap1510_udc.h [new file with mode: 0644]
include/usbdcore.h [deleted file]
include/usbdcore_ep0.h [deleted file]
include/usbdcore_mpc8xx.h [deleted file]
include/usbdcore_omap1510.h [deleted file]
include/usbdevice.h [new file with mode: 0644]

index 49b83c0c4906371a7ff15d63ba2c8fcbc47935cb..e91c051f5e6f0b2091366acb3a32218badf6f1c9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -263,7 +263,9 @@ endif
 LIBS += drivers/rtc/librtc.a
 LIBS += drivers/serial/libserial.a
 LIBS += drivers/twserial/libtws.a
-LIBS += drivers/usb/libusb.a
+LIBS += drivers/usb/gadget/libusb_gadget.a
+LIBS += drivers/usb/host/libusb_host.a
+LIBS += drivers/usb/musb/libusb_musb.a
 LIBS += drivers/video/libvideo.a
 LIBS += drivers/watchdog/libwatchdog.a
 LIBS += common/libcommon.a
index d8b13879176491c7ede5eb46e10d7a18f5174a5b..f711d0b18b1a967877698d271bd5a4fff915fab6 100644 (file)
@@ -94,7 +94,7 @@ static char serial_number[16];
  * Descriptors, Strings, Local variables.
  */
 
-/* defined and used by usbdcore_ep0.c */
+/* defined and used by gadget/ep0.c */
 extern struct usb_string_descriptor **usb_strings;
 
 /* Indicies, References */
index ecefde549208abfaf7e05b7cea4b141b3402e7e0..77db972b8765294088e35674036fc2dc330b912e 100644 (file)
 #ifndef __USB_TTY_H__
 #define __USB_TTY_H__
 
-#include <usbdcore.h>
+#include <usbdevice.h>
 #if defined(CONFIG_PPC)
-#include <usbdcore_mpc8xx.h>
+#include <usb/mpc8xx_udc.h>
 #elif defined(CONFIG_ARM)
-#include <usbdcore_omap1510.h>
+#include <usb/omap1510_udc.h>
 #endif
 
 #include <version_autogenerated.h>
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
deleted file mode 100644 (file)
index 5523cbd..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#
-# (C) Copyright 2000-2007
-# 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    := $(obj)libusb.a
-
-# core
-COBJS-y += usbdcore.o
-COBJS-$(CONFIG_USB_OHCI_NEW) += usb_ohci.o
-COBJS-$(CONFIG_USB_EHCI) += usb_ehci_core.o
-
-# host
-COBJS-$(CONFIG_USB_ATMEL) += atmel_usb.o
-COBJS-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
-COBJS-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
-COBJS-$(CONFIG_USB_S3C64XX) += s3c64xx_usb.o
-COBJS-$(CONFIG_USB_SL811HS) += sl811_usb.o
-COBJS-$(CONFIG_USB_EHCI_FSL) += usb_ehci_fsl.o
-COBJS-$(CONFIG_USB_EHCI_PCI) += usb_ehci_pci.o
-COBJS-$(CONFIG_USB_EHCI_IXP4XX) += usb_ehci_ixp.o
-COBJS-$(CONFIG_MUSB_HCD) += musb_hcd.o musb_core.o
-COBJS-$(CONFIG_USB_DAVINCI) += davinci_usb.o
-COBJS-$(CONFIG_USB_EHCI_VCT) += usb_ehci_vct.o
-
-# device
-ifdef CONFIG_USB_DEVICE
-COBJS-y += usbdcore_ep0.o
-COBJS-$(CONFIG_OMAP1510) += usbdcore_omap1510.o
-COBJS-$(CONFIG_OMAP1610) += usbdcore_omap1510.o
-COBJS-$(CONFIG_MPC885_FAMILY) += usbdcore_mpc8xx.o
-endif
-
-COBJS  := $(COBJS-y)
-SRCS   := $(COBJS:.o=.c)
-OBJS   := $(addprefix $(obj),$(COBJS))
-
-all:   $(LIB)
-
-$(LIB):        $(obj).depend $(OBJS)
-       $(AR) $(ARFLAGS) $@ $(OBJS)
-
-#########################################################################
-
-# defines $(obj).depend target
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
diff --git a/drivers/usb/atmel_usb.c b/drivers/usb/atmel_usb.c
deleted file mode 100644 (file)
index 7c44ad0..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * (C) Copyright 2006
- * DENX Software Engineering <mk@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>
-
-#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT)
-
-#include <asm/arch/hardware.h>
-#include <asm/arch/io.h>
-#include <asm/arch/at91_pmc.h>
-
-int usb_cpu_init(void)
-{
-
-#if defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \
-    defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91SAM9G20)
-       /* Enable PLLB */
-       at91_sys_write(AT91_CKGR_PLLBR, CONFIG_SYS_AT91_PLLB);
-       while ((at91_sys_read(AT91_PMC_SR) & AT91_PMC_LOCKB) != AT91_PMC_LOCKB)
-               ;
-#endif
-
-       /* Enable USB host clock. */
-       at91_sys_write(AT91_PMC_PCER, 1 << AT91_ID_UHP);
-#ifdef CONFIG_AT91SAM9261
-       at91_sys_write(AT91_PMC_SCER, AT91_PMC_UHP | AT91_PMC_HCK0);
-#else
-       at91_sys_write(AT91_PMC_SCER, AT91_PMC_UHP);
-#endif
-
-       return 0;
-}
-
-int usb_cpu_stop(void)
-{
-       /* Disable USB host clock. */
-       at91_sys_write(AT91_PMC_PCDR, 1 << AT91_ID_UHP);
-#ifdef CONFIG_AT91SAM9261
-       at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP | AT91_PMC_HCK0);
-#else
-       at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP);
-#endif
-
-#if defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \
-    defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91SAM9G20)
-       /* Disable PLLB */
-       at91_sys_write(AT91_CKGR_PLLBR, 0);
-       while ((at91_sys_read(AT91_PMC_SR) & AT91_PMC_LOCKB) != 0)
-               ;
-#endif
-
-       return 0;
-}
-
-int usb_cpu_init_fail(void)
-{
-       return usb_cpu_stop();
-}
-
-#endif /* defined(CONFIG_USB_OHCI) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) */
diff --git a/drivers/usb/davinci_usb.c b/drivers/usb/davinci_usb.c
deleted file mode 100644 (file)
index e66f660..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * TI's Davinci platform specific USB wrapper functions.
- *
- * Copyright (c) 2008 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
- *
- * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include "davinci_usb.h"
-
-/* MUSB platform configuration */
-struct musb_config musb_cfg = {
-       (struct musb_regs *)MENTOR_USB0_BASE,
-       DAVINCI_USB_TIMEOUT,
-       0
-};
-
-/* MUSB module register overlay */
-struct davinci_usb_regs *dregs;
-
-/*
- * Enable the USB phy
- */
-static u8 phy_on(void)
-{
-       u32 timeout;
-
-       /* Wait until the USB phy is turned on */
-       writel(USBPHY_SESNDEN | USBPHY_VBDTCTEN, USBPHY_CTL_PADDR);
-       timeout = musb_cfg.timeout;
-       while (timeout--)
-               if (readl(USBPHY_CTL_PADDR) & USBPHY_PHYCLKGD)
-                       return 1;
-
-       /* USB phy was not turned on */
-       return 0;
-}
-
-/*
- * Disable the USB phy
- */
-static void phy_off(void)
-{
-       /* powerdown the on-chip PHY and its oscillator */
-       writel(USBPHY_OSCPDWN | USBPHY_PHYPDWN, USBPHY_CTL_PADDR);
-}
-
-/*
- * This function performs Davinci platform specific initialization for usb0.
- */
-int musb_platform_init(void)
-{
-       u32  revision;
-
-       /* enable USB VBUS */
-       enable_vbus();
-
-       /* start the on-chip USB phy and its pll */
-       if (!phy_on())
-               return -1;
-
-       /* reset the controller */
-       dregs = (struct davinci_usb_regs *)DAVINCI_USB0_BASE;
-       writel(1, &dregs->ctrlr);
-       udelay(5000);
-
-       /* Returns zero if e.g. not clocked */
-       revision = readl(&dregs->version);
-       if (!revision)
-               return -1;
-
-       /* Disable all interrupts */
-       writel(DAVINCI_USB_USBINT_MASK | DAVINCI_USB_RXINT_MASK |
-                       DAVINCI_USB_TXINT_MASK , &dregs->intmsksetr);
-       return 0;
-}
-
-/*
- * This function performs Davinci platform specific deinitialization for usb0.
- */
-void musb_platform_deinit(void)
-{
-       /* Turn of the phy */
-       phy_off();
-
-       /* flush any interrupts */
-       writel(DAVINCI_USB_USBINT_MASK | DAVINCI_USB_TXINT_MASK |
-                       DAVINCI_USB_RXINT_MASK , &dregs->intclrr);
-}
diff --git a/drivers/usb/davinci_usb.h b/drivers/usb/davinci_usb.h
deleted file mode 100644 (file)
index f6751bf..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * TI's Davinci platform specific USB wrapper functions.
- *
- * Copyright (c) 2008 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
- *
- * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
- */
-
-#ifndef __DAVINCI_USB_H__
-#define __DAVINCI_USB_H__
-
-#include <asm/arch/hardware.h>
-#include "musb_core.h"
-
-/* Base address of DAVINCI usb0 wrapper */
-#define DAVINCI_USB0_BASE 0x01C64000
-
-/* Base address of DAVINCI musb core */
-#define MENTOR_USB0_BASE (DAVINCI_USB0_BASE+0x400)
-
-/*
- * Davinci platform USB wrapper register overlay. Note: Only the required
- * registers are included in this structure. It can be expanded as required.
- */
-struct davinci_usb_regs {
-       u32     version;
-       u32     ctrlr;
-       u32     reserved[0x20];
-       u32     intclrr;
-       u32     intmskr;
-       u32     intmsksetr;
-};
-
-#define DAVINCI_USB_TX_ENDPTS_MASK     0x1f /* ep0 + 4 tx */
-#define DAVINCI_USB_RX_ENDPTS_MASK     0x1e /* 4 rx */
-#define DAVINCI_USB_USBINT_SHIFT       16
-#define DAVINCI_USB_TXINT_SHIFT        0
-#define DAVINCI_USB_RXINT_SHIFT        8
-#define DAVINCI_INTR_DRVVBUS           0x0100
-
-#define DAVINCI_USB_USBINT_MASK        0x01ff0000      /* 8 Mentor, DRVVBUS */
-#define DAVINCI_USB_TXINT_MASK \
-               (DAVINCI_USB_TX_ENDPTS_MASK << DAVINCI_USB_TXINT_SHIFT)
-#define DAVINCI_USB_RXINT_MASK \
-               (DAVINCI_USB_RX_ENDPTS_MASK << DAVINCI_USB_RXINT_SHIFT)
-#define MGC_BUSCTL_OFFSET(_bEnd, _bOffset) \
-               (0x80 + (8*(_bEnd)) + (_bOffset))
-
-/* Integrated highspeed/otg PHY */
-#define USBPHY_CTL_PADDR       (DAVINCI_SYSTEM_MODULE_BASE + 0x34)
-#define USBPHY_PHYCLKGD        (1 << 8)
-#define USBPHY_SESNDEN         (1 << 7)        /* v(sess_end) comparator */
-#define USBPHY_VBDTCTEN        (1 << 6)        /* v(bus) comparator */
-#define USBPHY_PHYPLLON        (1 << 4)        /* override pll suspend */
-#define USBPHY_CLKO1SEL        (1 << 3)
-#define USBPHY_OSCPDWN         (1 << 2)
-#define USBPHY_PHYPDWN         (1 << 0)
-
-/* Timeout for Davinci USB module */
-#define DAVINCI_USB_TIMEOUT 0x3FFFFFF
-
-/* IO Expander I2C address and VBUS enable mask */
-#define IOEXP_I2C_ADDR 0x3A
-#define IOEXP_VBUSEN_MASK 1
-
-/* extern functions */
-extern void lpsc_on(unsigned int id);
-extern int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len);
-extern int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len);
-extern void enable_vbus(void);
-#endif /* __DAVINCI_USB_H__ */
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
new file mode 100644 (file)
index 0000000..251724f
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# (C) Copyright 2000-2007
+# 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    := $(obj)libusb_gadget.a
+
+ifdef CONFIG_USB_DEVICE
+COBJS-y += core.o
+COBJS-y += ep0.o
+COBJS-$(CONFIG_OMAP1510) += omap1510_udc.o
+COBJS-$(CONFIG_OMAP1610) += omap1510_udc.o
+COBJS-$(CONFIG_MPC885_FAMILY) += mpc8xx_udc.o
+endif
+
+COBJS  := $(COBJS-y)
+SRCS   := $(COBJS:.o=.c)
+OBJS   := $(addprefix $(obj),$(COBJS))
+
+all:   $(LIB)
+
+$(LIB):        $(obj).depend $(OBJS)
+       $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/usb/gadget/core.c b/drivers/usb/gadget/core.c
new file mode 100644 (file)
index 0000000..67b6681
--- /dev/null
@@ -0,0 +1,683 @@
+/*
+ * (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 <usbdevice.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)
+{
+       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(%zu) 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/usb/gadget/ep0.c b/drivers/usb/gadget/ep0.c
new file mode 100644 (file)
index 0000000..2b4ec44
--- /dev/null
@@ -0,0 +1,597 @@
+/*
+ * (C) Copyright 2003
+ * Gerry Hamel, geh@ti.com, Texas Instruments
+ *
+ * (C) Copyright 2006
+ * Bryan O'Donoghue, deckard@CodeHermit.ie
+ *
+ * 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
+ *
+ * As alluded to above, a simple callback cdc_recv_setup has been implemented
+ * in the usb_device data structure to facilicate passing
+ * Common Device Class packets to a function driver.
+ *
+ * XXX
+ */
+
+#include <common.h>
+#include <usbdevice.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 = (char*)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.
+ */
+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;
+       }
+       length = max_length;
+
+       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 = (char*)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;
+
+               }
+               dbg_ep0(3, "copied device configuration, actual_length: 0x%x", urb->actual_length);
+               break;
+
+       case USB_DESCRIPTOR_TYPE_CONFIGURATION:
+               {
+                       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;
+                       }
+                       dbg_ep0(0, "attempt to copy %d bytes to urb\n",cpu_to_le16(configuration_descriptor->wTotalLength));
+                       copy_config (urb, configuration_descriptor,
+
+                                       cpu_to_le16(configuration_descriptor->wTotalLength),
+                                    max);
+               }
+
+               break;
+
+       case USB_DESCRIPTOR_TYPE_STRING:
+               {
+                       struct usb_string_descriptor *string_descriptor;
+                       if (!(string_descriptor = usbd_get_string (index))) {
+                               serial_printf("Invalid string index %d\n", index);
+                               return -1;
+                       }
+                       dbg_ep0(3, "string_descriptor: %p length %d", string_descriptor, string_descriptor->bLength);
+                       copy_config (urb, string_descriptor, string_descriptor->bLength, max);
+               }
+               break;
+       case USB_DESCRIPTOR_TYPE_INTERFACE:
+       serial_printf("USB_DESCRIPTOR_TYPE_INTERFACE - error not implemented\n");
+               return -1;
+       case USB_DESCRIPTOR_TYPE_ENDPOINT:
+               serial_printf("USB_DESCRIPTOR_TYPE_ENDPOINT - error not implemented\n");
+               return -1;
+       case USB_DESCRIPTOR_TYPE_HID:
+               {
+                       serial_printf("USB_DESCRIPTOR_TYPE_HID - error not implemented\n");
+                       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:
+               {
+                       serial_printf("USB_DESCRIPTOR_TYPE_REPORT - error not implemented\n");
+                       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;
+       case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
+               {
+                       /* If a USB device supports both a full speed and low speed operation
+                        * we must send a Device_Qualifier descriptor here
+                        */
+                       return -1;
+               }
+       default:
+               return -1;
+       }
+
+
+       dbg_ep0 (1, "urb: buffer: %p buffer_length: %2d actual_length: %2d tx_packetSize: %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) {
+               if(device->device_state <= STATE_CONFIGURED){
+                       /*      Attempt to handle a CDC specific request if we are
+                        *      in the configured state.
+                        */
+                       return device->cdc_recv_setup(request,urb);
+               }
+               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:
+                       serial_printf("get config %d\n", device->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); */
+
+                       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 */
+                       device->configuration = le16_to_cpu(request->wValue) & 0xff;
+
+                       /* 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;
+}
diff --git a/drivers/usb/gadget/ep0.h b/drivers/usb/gadget/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/drivers/usb/gadget/mpc8xx_udc.c b/drivers/usb/gadget/mpc8xx_udc.c
new file mode 100644 (file)
index 0000000..da3fbba
--- /dev/null
@@ -0,0 +1,1399 @@
+/*
+ * Copyright (C) 2006 by Bryan O'Donoghue, CodeHermit
+ * bodonoghue@CodeHermit.ie
+ *
+ * References
+ * DasUBoot/drivers/usb/gadget/omap1510_udc.c, for design and implementation
+ * ideas.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * Notes :
+ * 1.  #define __SIMULATE_ERROR__ to inject a CRC error into every 2nd TX
+ *             packet to force the USB re-transmit protocol.
+ *
+ * 2.  #define __DEBUG_UDC__ to switch on debug tracing to serial console
+ *     be careful that tracing doesn't create Hiesen-bugs with respect to
+ *     response timeouts to control requests.
+ *
+ * 3.  This driver should be able to support any higher level driver that
+ *     that wants to do either of the two standard UDC implementations
+ *     Control-Bulk-Interrupt or  Bulk-IN/Bulk-Out standards. Hence
+ *     gserial and cdc_acm should work with this code.
+ *
+ * 4.  NAK events never actually get raised at all, the documentation
+ *     is just wrong !
+ *
+ * 5.  For some reason, cbd_datlen is *always* +2 the value it should be.
+ *     this means that having an RX cbd of 16 bytes is not possible, since
+ *     the same size is reported for 14 bytes received as 16 bytes received
+ *     until we can find out why this happens, RX cbds must be limited to 8
+ *     bytes. TODO: check errata for this behaviour.
+ *
+ * 6.  Right now this code doesn't support properly powering up with the USB
+ *     cable attached to the USB host my development board the Adder87x doesn't
+ *     have a pull-up fitted to allow this, so it is necessary to power the
+ *     board and *then* attached the USB cable to the host. However somebody
+ *     with a different design in their board may be able to keep the cable
+ *     constantly connected and simply enable/disable a pull-up  re
+ *     figure 31.1 in MPC885RM.pdf instead of having to power up the board and
+ *     then attach the cable !
+ *
+ */
+#include <common.h>
+#include <config.h>
+#include <commproc.h>
+#include <usbdevice.h>
+#include <usb/mpc8xx_udc.h>
+
+#include "ep0.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define ERR(fmt, args...)\
+       serial_printf("ERROR : [%s] %s:%d: "fmt,\
+                               __FILE__,__FUNCTION__,__LINE__, ##args)
+#ifdef __DEBUG_UDC__
+#define DBG(fmt,args...)\
+               serial_printf("[%s] %s:%d: "fmt,\
+                               __FILE__,__FUNCTION__,__LINE__, ##args)
+#else
+#define DBG(fmt,args...)
+#endif
+
+/* Static Data */
+#ifdef __SIMULATE_ERROR__
+static char err_poison_test = 0;
+#endif
+static struct mpc8xx_ep ep_ref[MAX_ENDPOINTS];
+static u32 address_base = STATE_NOT_READY;
+static mpc8xx_udc_state_t udc_state = 0;
+static struct usb_device_instance *udc_device = 0;
+static volatile usb_epb_t *endpoints[MAX_ENDPOINTS];
+static volatile cbd_t *tx_cbd[TX_RING_SIZE];
+static volatile cbd_t *rx_cbd[RX_RING_SIZE];
+static volatile immap_t *immr = 0;
+static volatile cpm8xx_t *cp = 0;
+static volatile usb_pram_t *usb_paramp = 0;
+static volatile usb_t *usbp = 0;
+static int rx_ct = 0;
+static int tx_ct = 0;
+
+/* Static Function Declarations */
+static void mpc8xx_udc_state_transition_up (usb_device_state_t initial,
+                                           usb_device_state_t final);
+static void mpc8xx_udc_state_transition_down (usb_device_state_t initial,
+                                             usb_device_state_t final);
+static void mpc8xx_udc_stall (unsigned int ep);
+static void mpc8xx_udc_flush_tx_fifo (int epid);
+static void mpc8xx_udc_flush_rx_fifo (void);
+static void mpc8xx_udc_clear_rxbd (volatile cbd_t * rx_cbdp);
+static void mpc8xx_udc_init_tx (struct usb_endpoint_instance *epi,
+                               struct urb *tx_urb);
+static void mpc8xx_udc_dump_request (struct usb_device_request *request);
+static void mpc8xx_udc_clock_init (volatile immap_t * immr,
+                                  volatile cpm8xx_t * cp);
+static int mpc8xx_udc_ep_tx (struct usb_endpoint_instance *epi);
+static int mpc8xx_udc_epn_rx (unsigned int epid, volatile cbd_t * rx_cbdp);
+static void mpc8xx_udc_ep0_rx (volatile cbd_t * rx_cbdp);
+static void mpc8xx_udc_cbd_init (void);
+static void mpc8xx_udc_endpoint_init (void);
+static void mpc8xx_udc_cbd_attach (int ep, uchar tx_size, uchar rx_size);
+static u32 mpc8xx_udc_alloc (u32 data_size, u32 alignment);
+static int mpc8xx_udc_ep0_rx_setup (volatile cbd_t * rx_cbdp);
+static void mpc8xx_udc_set_nak (unsigned int ep);
+static short mpc8xx_udc_handle_txerr (void);
+static void mpc8xx_udc_advance_rx (volatile cbd_t ** rx_cbdp, int epid);
+
+/******************************************************************************
+                              Global Linkage
+ *****************************************************************************/
+
+/* udc_init
+ *
+ * Do initial bus gluing
+ */
+int udc_init (void)
+{
+       /* Init various pointers */
+       immr = (immap_t *) CONFIG_SYS_IMMR;
+       cp = (cpm8xx_t *) & (immr->im_cpm);
+       usb_paramp = (usb_pram_t *) & (cp->cp_dparam[PROFF_USB]);
+       usbp = (usb_t *) & (cp->cp_scc[0]);
+
+       memset (ep_ref, 0x00, (sizeof (struct mpc8xx_ep) * MAX_ENDPOINTS));
+
+       udc_device = 0;
+       udc_state = STATE_NOT_READY;
+
+       usbp->usmod = 0x00;
+       usbp->uscom = 0;
+
+       /* Set USB Frame #0, Respond at Address & Get a clock source  */
+       usbp->usaddr = 0x00;
+       mpc8xx_udc_clock_init (immr, cp);
+
+       /* PA15, PA14 as perhiperal USBRXD and USBOE */
+       immr->im_ioport.iop_padir &= ~0x0003;
+       immr->im_ioport.iop_papar |= 0x0003;
+
+       /* PC11/PC10 as peripheral USBRXP USBRXN */
+       immr->im_ioport.iop_pcso |= 0x0030;
+
+       /* PC7/PC6 as perhiperal USBTXP and USBTXN */
+       immr->im_ioport.iop_pcdir |= 0x0300;
+       immr->im_ioport.iop_pcpar |= 0x0300;
+
+       /* Set the base address */
+       address_base = (u32) (cp->cp_dpmem + CPM_USB_BASE);
+
+       /* Initialise endpoints and circular buffers */
+       mpc8xx_udc_endpoint_init ();
+       mpc8xx_udc_cbd_init ();
+
+       /* Assign allocated Dual Port Endpoint descriptors */
+       usb_paramp->ep0ptr = (u32) endpoints[0];
+       usb_paramp->ep1ptr = (u32) endpoints[1];
+       usb_paramp->ep2ptr = (u32) endpoints[2];
+       usb_paramp->ep3ptr = (u32) endpoints[3];
+       usb_paramp->frame_n = 0;
+
+       DBG ("ep0ptr=0x%08x ep1ptr=0x%08x ep2ptr=0x%08x ep3ptr=0x%08x\n",
+            usb_paramp->ep0ptr, usb_paramp->ep1ptr, usb_paramp->ep2ptr,
+            usb_paramp->ep3ptr);
+
+       return 0;
+}
+
+/* udc_irq
+ *
+ * Poll for whatever events may have occured
+ */
+void udc_irq (void)
+{
+       int epid = 0;
+       volatile cbd_t *rx_cbdp = 0;
+       volatile cbd_t *rx_cbdp_base = 0;
+
+       if (udc_state != STATE_READY) {
+               return;
+       }
+
+       if (usbp->usber & USB_E_BSY) {
+               /* This shouldn't happen. If it does then it's a bug ! */
+               usbp->usber |= USB_E_BSY;
+               mpc8xx_udc_flush_rx_fifo ();
+       }
+
+       /* Scan all RX/Bidirectional Endpoints for RX data. */
+       for (epid = 0; epid < MAX_ENDPOINTS; epid++) {
+               if (!ep_ref[epid].prx) {
+                       continue;
+               }
+               rx_cbdp = rx_cbdp_base = ep_ref[epid].prx;
+
+               do {
+                       if (!(rx_cbdp->cbd_sc & RX_BD_E)) {
+
+                               if (rx_cbdp->cbd_sc & 0x1F) {
+                                       /* Corrupt data discard it.
+                                        * Controller has NAK'd this packet.
+                                        */
+                                       mpc8xx_udc_clear_rxbd (rx_cbdp);
+
+                               } else {
+                                       if (!epid) {
+                                               mpc8xx_udc_ep0_rx (rx_cbdp);
+
+                                       } else {
+                                               /* Process data */
+                                               mpc8xx_udc_set_nak (epid);
+                                               mpc8xx_udc_epn_rx (epid, rx_cbdp);
+                                               mpc8xx_udc_clear_rxbd (rx_cbdp);
+                                       }
+                               }
+
+                               /* Advance RX CBD pointer */
+                               mpc8xx_udc_advance_rx (&rx_cbdp, epid);
+                               ep_ref[epid].prx = rx_cbdp;
+                       } else {
+                               /* Advance RX CBD pointer */
+                               mpc8xx_udc_advance_rx (&rx_cbdp, epid);
+                       }
+
+               } while (rx_cbdp != rx_cbdp_base);
+       }
+
+       /* Handle TX events as appropiate, the correct place to do this is
+        * in a tx routine. Perhaps TX on epn was pre-empted by ep0
+        */
+
+       if (usbp->usber & USB_E_TXB) {
+               usbp->usber |= USB_E_TXB;
+       }
+
+       if (usbp->usber & (USB_TX_ERRMASK)) {
+               mpc8xx_udc_handle_txerr ();
+       }
+
+       /* Switch to the default state, respond at the default address */
+       if (usbp->usber & USB_E_RESET) {
+               usbp->usber |= USB_E_RESET;
+               usbp->usaddr = 0x00;
+               udc_device->device_state = STATE_DEFAULT;
+       }
+
+       /* if(usbp->usber&USB_E_IDLE){
+          We could suspend here !
+          usbp->usber|=USB_E_IDLE;
+          DBG("idle state change\n");
+          }
+          if(usbp->usbs){
+          We could resume here when IDLE is deasserted !
+          Not worth doing, so long as we are self powered though.
+          }
+       */
+
+       return;
+}
+
+/* udc_endpoint_write
+ *
+ * Write some data to an endpoint
+ */
+int udc_endpoint_write (struct usb_endpoint_instance *epi)
+{
+       int ep = 0;
+       short epid = 1, unnak = 0, ret = 0;
+
+       if (udc_state != STATE_READY) {
+               ERR ("invalid udc_state != STATE_READY!\n");
+               return -1;
+       }
+
+       if (!udc_device || !epi) {
+               return -1;
+       }
+
+       if (udc_device->device_state != STATE_CONFIGURED) {
+               return -1;
+       }
+
+       ep = epi->endpoint_address & 0x03;
+       if (ep >= MAX_ENDPOINTS) {
+               return -1;
+       }
+
+       /* Set NAK for all RX endpoints during TX */
+       for (epid = 1; epid < MAX_ENDPOINTS; epid++) {
+
+               /* Don't set NAK on DATA IN/CONTROL endpoints */
+               if (ep_ref[epid].sc & USB_DIR_IN) {
+                       continue;
+               }
+
+               if (!(usbp->usep[epid] & (USEP_THS_NAK | USEP_RHS_NAK))) {
+                       unnak |= 1 << epid;
+               }
+
+               mpc8xx_udc_set_nak (epid);
+       }
+
+       mpc8xx_udc_init_tx (&udc_device->bus->endpoint_array[ep],
+                           epi->tx_urb);
+       ret = mpc8xx_udc_ep_tx (&udc_device->bus->endpoint_array[ep]);
+
+       /* Remove temporary NAK */
+       for (epid = 1; epid < MAX_ENDPOINTS; epid++) {
+               if (unnak & (1 << epid)) {
+                       udc_unset_nak (epid);
+               }
+       }
+
+       return ret;
+}
+
+/* mpc8xx_udc_assign_urb
+ *
+ * Associate a given urb to an endpoint TX or RX transmit/receive buffers
+ */
+static int mpc8xx_udc_assign_urb (int ep, char direction)
+{
+       struct usb_endpoint_instance *epi = 0;
+
+       if (ep >= MAX_ENDPOINTS) {
+               goto err;
+       }
+       epi = &udc_device->bus->endpoint_array[ep];
+       if (!epi) {
+               goto err;
+       }
+
+       if (!ep_ref[ep].urb) {
+               ep_ref[ep].urb = usbd_alloc_urb (udc_device, udc_device->bus->endpoint_array);
+               if (!ep_ref[ep].urb) {
+                       goto err;
+               }
+       } else {
+               ep_ref[ep].urb->actual_length = 0;
+       }
+
+       switch (direction) {
+       case USB_DIR_IN:
+               epi->tx_urb = ep_ref[ep].urb;
+               break;
+       case USB_DIR_OUT:
+               epi->rcv_urb = ep_ref[ep].urb;
+               break;
+       default:
+               goto err;
+       }
+       return 0;
+
+      err:
+       udc_state = STATE_ERROR;
+       return -1;
+}
+
+/* udc_setup_ep
+ *
+ * Associate U-Boot software endpoints to mpc8xx endpoint parameter ram
+ * Isochronous endpoints aren't yet supported!
+ */
+void udc_setup_ep (struct usb_device_instance *device, unsigned int ep,
+                  struct usb_endpoint_instance *epi)
+{
+       uchar direction = 0;
+       int ep_attrib = 0;
+
+       if (epi && (ep < MAX_ENDPOINTS)) {
+
+               if (ep == 0) {
+                       if (epi->rcv_attributes != USB_ENDPOINT_XFER_CONTROL
+                           || epi->tx_attributes !=
+                           USB_ENDPOINT_XFER_CONTROL) {
+
+                               /* ep0 must be a control endpoint */
+                               udc_state = STATE_ERROR;
+                               return;
+
+                       }
+                       if (!(ep_ref[ep].sc & EP_ATTACHED)) {
+                               mpc8xx_udc_cbd_attach (ep, epi->tx_packetSize,
+                                                      epi->rcv_packetSize);
+                       }
+                       usbp->usep[ep] = 0x0000;
+                       return;
+               }
+
+               if ((epi->endpoint_address & USB_ENDPOINT_DIR_MASK)
+                   == USB_DIR_IN) {
+
+                       direction = 1;
+                       ep_attrib = epi->tx_attributes;
+                       epi->rcv_packetSize = 0;
+                       ep_ref[ep].sc |= USB_DIR_IN;
+               } else {
+
+                       direction = 0;
+                       ep_attrib = epi->rcv_attributes;
+                       epi->tx_packetSize = 0;
+                       ep_ref[ep].sc &= ~USB_DIR_IN;
+               }
+
+               if (mpc8xx_udc_assign_urb (ep, epi->endpoint_address
+                                          & USB_ENDPOINT_DIR_MASK)) {
+                       return;
+               }
+
+               switch (ep_attrib) {
+               case USB_ENDPOINT_XFER_CONTROL:
+                       if (!(ep_ref[ep].sc & EP_ATTACHED)) {
+                               mpc8xx_udc_cbd_attach (ep,
+                                                      epi->tx_packetSize,
+                                                      epi->rcv_packetSize);
+                       }
+                       usbp->usep[ep] = ep << 12;
+                       epi->rcv_urb = epi->tx_urb = ep_ref[ep].urb;
+
+                       break;
+               case USB_ENDPOINT_XFER_BULK:
+               case USB_ENDPOINT_XFER_INT:
+                       if (!(ep_ref[ep].sc & EP_ATTACHED)) {
+                               if (direction) {
+                                       mpc8xx_udc_cbd_attach (ep,
+                                                              epi->tx_packetSize,
+                                                              0);
+                               } else {
+                                       mpc8xx_udc_cbd_attach (ep,
+                                                              0,
+                                                              epi->rcv_packetSize);
+                               }
+                       }
+                       usbp->usep[ep] = (ep << 12) | ((ep_attrib) << 8);
+
+                       break;
+               case USB_ENDPOINT_XFER_ISOC:
+               default:
+                       serial_printf ("Error endpoint attrib %d>3\n", ep_attrib);
+                       udc_state = STATE_ERROR;
+                       break;
+               }
+       }
+
+}
+
+/* udc_connect
+ *
+ * Move state, switch on the USB
+ */
+void udc_connect (void)
+{
+       /* Enable pull-up resistor on D+
+        * TODO: fit a pull-up resistor to drive SE0 for > 2.5us
+        */
+
+       if (udc_state != STATE_ERROR) {
+               udc_state = STATE_READY;
+               usbp->usmod |= USMOD_EN;
+       }
+}
+
+/* udc_disconnect
+ *
+ * Disconnect is not used but, is included for completeness
+ */
+void udc_disconnect (void)
+{
+       /* Disable pull-up resistor on D-
+        * TODO: fix a pullup resistor to control this
+        */
+
+       if (udc_state != STATE_ERROR) {
+               udc_state = STATE_NOT_READY;
+       }
+       usbp->usmod &= ~USMOD_EN;
+}
+
+/* udc_enable
+ *
+ * Grab an EP0 URB, register interest in a subset of USB events
+ */
+void udc_enable (struct usb_device_instance *device)
+{
+       if (udc_state == STATE_ERROR) {
+               return;
+       }
+
+       udc_device = device;
+
+       if (!ep_ref[0].urb) {
+               ep_ref[0].urb = usbd_alloc_urb (device, device->bus->endpoint_array);
+       }
+
+       /* Register interest in all events except SOF, enable transceiver */
+       usbp->usber = 0x03FF;
+       usbp->usbmr = 0x02F7;
+
+       return;
+}
+
+/* udc_disable
+ *
+ * disable the currently hooked device
+ */
+void udc_disable (void)
+{
+       int i = 0;
+
+       if (udc_state == STATE_ERROR) {
+               DBG ("Won't disable UDC. udc_state==STATE_ERROR !\n");
+               return;
+       }
+
+       udc_device = 0;
+
+       for (; i < MAX_ENDPOINTS; i++) {
+               if (ep_ref[i].urb) {
+                       usbd_dealloc_urb (ep_ref[i].urb);
+                       ep_ref[i].urb = 0;
+               }
+       }
+
+       usbp->usbmr = 0x00;
+       usbp->usmod = ~USMOD_EN;
+       udc_state = STATE_NOT_READY;
+}
+
+/* udc_startup_events
+ *
+ * Enable the specified device
+ */
+void udc_startup_events (struct usb_device_instance *device)
+{
+       udc_enable (device);
+       if (udc_state == STATE_READY) {
+               usbd_device_event_irq (device, DEVICE_CREATE, 0);
+       }
+}
+
+/* udc_set_nak
+ *
+ * Allow upper layers to signal lower layers should not accept more RX data
+ *
+ */
+void udc_set_nak (int epid)
+{
+       if (epid) {
+               mpc8xx_udc_set_nak (epid);
+       }
+}
+
+/* udc_unset_nak
+ *
+ * Suspend sending of NAK tokens for DATA OUT tokens on a given endpoint.
+ * Switch off NAKing on this endpoint to accept more data output from host.
+ *
+ */
+void udc_unset_nak (int epid)
+{
+       if (epid > MAX_ENDPOINTS) {
+               return;
+       }
+
+       if (usbp->usep[epid] & (USEP_THS_NAK | USEP_RHS_NAK)) {
+               usbp->usep[epid] &= ~(USEP_THS_NAK | USEP_RHS_NAK);
+               __asm__ ("eieio");
+       }
+}
+
+/******************************************************************************
+                             Static Linkage
+******************************************************************************/
+
+/* 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.
+ *
+ */
+
+static void mpc8xx_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 mpc8xx_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;
+               }
+       }
+}
+
+/* mpc8xx_udc_stall
+ *
+ * Force returning of STALL tokens on the given endpoint. Protocol or function
+ * STALL conditions are permissable here
+ */
+static void mpc8xx_udc_stall (unsigned int ep)
+{
+       usbp->usep[ep] |= STALL_BITMASK;
+}
+
+/* mpc8xx_udc_set_nak
+ *
+ * Force returning of NAK responses for the given endpoint as a kind of very
+ * simple flow control
+ */
+static void mpc8xx_udc_set_nak (unsigned int ep)
+{
+       usbp->usep[ep] |= NAK_BITMASK;
+       __asm__ ("eieio");
+}
+
+/* mpc8xx_udc_handle_txerr
+ *
+ * Handle errors relevant to TX. Return a status code to allow calling
+ * indicative of what if anything happened
+ */
+static short mpc8xx_udc_handle_txerr ()
+{
+       short ep = 0, ret = 0;
+
+       for (; ep < TX_RING_SIZE; ep++) {
+               if (usbp->usber & (0x10 << ep)) {
+
+                       /* Timeout or underrun */
+                       if (tx_cbd[ep]->cbd_sc & 0x06) {
+                               ret = 1;
+                               mpc8xx_udc_flush_tx_fifo (ep);
+
+                       } else {
+                               if (usbp->usep[ep] & STALL_BITMASK) {
+                                       if (!ep) {
+                                               usbp->usep[ep] &= ~STALL_BITMASK;
+                                       }
+                               }       /* else NAK */
+                       }
+                       usbp->usber |= (0x10 << ep);
+               }
+       }
+       return ret;
+}
+
+/* mpc8xx_udc_advance_rx
+ *
+ * Advance cbd rx
+ */
+static void mpc8xx_udc_advance_rx (volatile cbd_t ** rx_cbdp, int epid)
+{
+       if ((*rx_cbdp)->cbd_sc & RX_BD_W) {
+               *rx_cbdp = (volatile cbd_t *) (endpoints[epid]->rbase + CONFIG_SYS_IMMR);
+
+       } else {
+               (*rx_cbdp)++;
+       }
+}
+
+
+/* mpc8xx_udc_flush_tx_fifo
+ *
+ * Flush a given TX fifo. Assumes one tx cbd per endpoint
+ */
+static void mpc8xx_udc_flush_tx_fifo (int epid)
+{
+       volatile cbd_t *tx_cbdp = 0;
+
+       if (epid > MAX_ENDPOINTS) {
+               return;
+       }
+
+       /* TX stop */
+       immr->im_cpm.cp_cpcr = ((epid << 2) | 0x1D01);
+       __asm__ ("eieio");
+       while (immr->im_cpm.cp_cpcr & 0x01);
+
+       usbp->uscom = 0x40 | 0;
+
+       /* reset ring */
+       tx_cbdp = (cbd_t *) (endpoints[epid]->tbptr + CONFIG_SYS_IMMR);
+       tx_cbdp->cbd_sc = (TX_BD_I | TX_BD_W);
+
+
+       endpoints[epid]->tptr = endpoints[epid]->tbase;
+       endpoints[epid]->tstate = 0x00;
+       endpoints[epid]->tbcnt = 0x00;
+
+       /* TX start */
+       immr->im_cpm.cp_cpcr = ((epid << 2) | 0x2D01);
+       __asm__ ("eieio");
+       while (immr->im_cpm.cp_cpcr & 0x01);
+
+       return;
+}
+
+/* mpc8xx_udc_flush_rx_fifo
+ *
+ * For the sake of completeness of the namespace, it seems like
+ * a good-design-decision (tm) to include mpc8xx_udc_flush_rx_fifo();
+ * If RX_BD_E is true => a driver bug either here or in an upper layer
+ * not polling frequently enough. If RX_BD_E is true we have told the host
+ * we have accepted data but, the CPM found it had no-where to put that data
+ * which needless to say would be a bad thing.
+ */
+static void mpc8xx_udc_flush_rx_fifo ()
+{
+       int i = 0;
+
+       for (i = 0; i < RX_RING_SIZE; i++) {
+               if (!(rx_cbd[i]->cbd_sc & RX_BD_E)) {
+                       ERR ("buf %p used rx data len = 0x%x sc=0x%x!\n",
+                            rx_cbd[i], rx_cbd[i]->cbd_datlen,
+                            rx_cbd[i]->cbd_sc);
+
+               }
+       }
+       ERR ("BUG : Input over-run\n");
+}
+
+/* mpc8xx_udc_clear_rxbd
+ *
+ * Release control of RX CBD to CP.
+ */
+static void mpc8xx_udc_clear_rxbd (volatile cbd_t * rx_cbdp)
+{
+       rx_cbdp->cbd_datlen = 0x0000;
+       rx_cbdp->cbd_sc = ((rx_cbdp->cbd_sc & RX_BD_W) | (RX_BD_E | RX_BD_I));
+       __asm__ ("eieio");
+}
+
+/* mpc8xx_udc_tx_irq
+ *
+ * Parse for tx timeout, control RX or USB reset/busy conditions
+ * Return -1 on timeout, -2 on fatal error, else return zero
+ */
+static int mpc8xx_udc_tx_irq (int ep)
+{
+       int i = 0;
+
+       if (usbp->usber & (USB_TX_ERRMASK)) {
+               if (mpc8xx_udc_handle_txerr ()) {
+                       /* Timeout, controlling function must retry send */
+                       return -1;
+               }
+       }
+
+       if (usbp->usber & (USB_E_RESET | USB_E_BSY)) {
+               /* Fatal, abandon TX transaction */
+               return -2;
+       }
+
+       if (usbp->usber & USB_E_RXB) {
+               for (i = 0; i < RX_RING_SIZE; i++) {
+                       if (!(rx_cbd[i]->cbd_sc & RX_BD_E)) {
+                               if ((rx_cbd[i] == ep_ref[0].prx) || ep) {
+                                       return -2;
+                               }
+                       }
+               }
+       }
+
+       return 0;
+}
+
+/* mpc8xx_udc_ep_tx
+ *
+ * Transmit in a re-entrant fashion outbound USB packets.
+ * Implement retry/timeout mechanism described in USB specification
+ * Toggle DATA0/DATA1 pids as necessary
+ * Introduces non-standard tx_retry. The USB standard has no scope for slave
+ * devices to give up TX, however tx_retry stops us getting stuck in an endless
+ * TX loop.
+ */
+static int mpc8xx_udc_ep_tx (struct usb_endpoint_instance *epi)
+{
+       struct urb *urb = epi->tx_urb;
+       volatile cbd_t *tx_cbdp = 0;
+       unsigned int ep = 0, pkt_len = 0, x = 0, tx_retry = 0;
+       int ret = 0;
+
+       if (!epi || (epi->endpoint_address & 0x03) >= MAX_ENDPOINTS || !urb) {
+               return -1;
+       }
+
+       ep = epi->endpoint_address & 0x03;
+       tx_cbdp = (cbd_t *) (endpoints[ep]->tbptr + CONFIG_SYS_IMMR);
+
+       if (tx_cbdp->cbd_sc & TX_BD_R || usbp->usber & USB_E_TXB) {
+               mpc8xx_udc_flush_tx_fifo (ep);
+               usbp->usber |= USB_E_TXB;
+       };
+
+       while (tx_retry++ < 100) {
+               ret = mpc8xx_udc_tx_irq (ep);
+               if (ret == -1) {
+                       /* ignore timeout here */
+               } else if (ret == -2) {
+                       /* Abandon TX */
+                       mpc8xx_udc_flush_tx_fifo (ep);
+                       return -1;
+               }
+
+               tx_cbdp = (cbd_t *) (endpoints[ep]->tbptr + CONFIG_SYS_IMMR);
+               while (tx_cbdp->cbd_sc & TX_BD_R) {
+               };
+               tx_cbdp->cbd_sc = (tx_cbdp->cbd_sc & TX_BD_W);
+
+               pkt_len = urb->actual_length - epi->sent;
+
+               if (pkt_len > epi->tx_packetSize || pkt_len > EP_MAX_PKT) {
+                       pkt_len = MIN (epi->tx_packetSize, EP_MAX_PKT);
+               }
+
+               for (x = 0; x < pkt_len; x++) {
+                       *((unsigned char *) (tx_cbdp->cbd_bufaddr + x)) =
+                               urb->buffer[epi->sent + x];
+               }
+               tx_cbdp->cbd_datlen = pkt_len;
+               tx_cbdp->cbd_sc |= (CBD_TX_BITMASK | ep_ref[ep].pid);
+               __asm__ ("eieio");
+
+#ifdef __SIMULATE_ERROR__
+               if (++err_poison_test == 2) {
+                       err_poison_test = 0;
+                       tx_cbdp->cbd_sc &= ~TX_BD_TC;
+               }
+#endif
+
+               usbp->uscom = (USCOM_STR | ep);
+
+               while (!(usbp->usber & USB_E_TXB)) {
+                       ret = mpc8xx_udc_tx_irq (ep);
+                       if (ret == -1) {
+                               /* TX timeout */
+                               break;
+                       } else if (ret == -2) {
+                               if (usbp->usber & USB_E_TXB) {
+                                       usbp->usber |= USB_E_TXB;
+                               }
+                               mpc8xx_udc_flush_tx_fifo (ep);
+                               return -1;
+                       }
+               };
+
+               if (usbp->usber & USB_E_TXB) {
+                       usbp->usber |= USB_E_TXB;
+               }
+
+               /* ACK must be present <= 18bit times from TX */
+               if (ret == -1) {
+                       continue;
+               }
+
+               /* TX ACK : USB 2.0 8.7.2, Toggle PID, Advance TX */
+               epi->sent += pkt_len;
+               epi->last = MIN (urb->actual_length - epi->sent, epi->tx_packetSize);
+               TOGGLE_TX_PID (ep_ref[ep].pid);
+
+               if (epi->sent >= epi->tx_urb->actual_length) {
+
+                       epi->tx_urb->actual_length = 0;
+                       epi->sent = 0;
+
+                       if (ep_ref[ep].sc & EP_SEND_ZLP) {
+                               ep_ref[ep].sc &= ~EP_SEND_ZLP;
+                       } else {
+                               return 0;
+                       }
+               }
+       }
+
+       ERR ("TX fail, endpoint 0x%x tx bytes 0x%x/0x%x\n", ep, epi->sent,
+            epi->tx_urb->actual_length);
+
+       return -1;
+}
+
+/* mpc8xx_udc_dump_request
+ *
+ * Dump a control request to console
+ */
+static void mpc8xx_udc_dump_request (struct usb_device_request *request)
+{
+       DBG ("bmRequestType:%02x bRequest:%02x wValue:%04x "
+            "wIndex:%04x wLength:%04x ?\n",
+            request->bmRequestType,
+            request->bRequest,
+            request->wValue, request->wIndex, request->wLength);
+
+       return;
+}
+
+/* mpc8xx_udc_ep0_rx_setup
+ *
+ * Decode received ep0 SETUP packet. return non-zero on error
+ */
+static int mpc8xx_udc_ep0_rx_setup (volatile cbd_t * rx_cbdp)
+{
+       unsigned int x = 0;
+       struct urb *purb = ep_ref[0].urb;
+       struct usb_endpoint_instance *epi =
+               &udc_device->bus->endpoint_array[0];
+
+       for (; x < rx_cbdp->cbd_datlen; x++) {
+               *(((unsigned char *) &ep_ref[0].urb->device_request) + x) =
+                       *((unsigned char *) (rx_cbdp->cbd_bufaddr + x));
+       }
+
+       mpc8xx_udc_clear_rxbd (rx_cbdp);
+
+       if (ep0_recv_setup (purb)) {
+               mpc8xx_udc_dump_request (&purb->device_request);
+               return -1;
+       }
+
+       if ((purb->device_request.bmRequestType & USB_REQ_DIRECTION_MASK)
+           == USB_REQ_HOST2DEVICE) {
+
+               switch (purb->device_request.bRequest) {
+               case USB_REQ_SET_ADDRESS:
+                       /* Send the Status OUT ZLP */
+                       ep_ref[0].pid = TX_BD_PID_DATA1;
+                       purb->actual_length = 0;
+                       mpc8xx_udc_init_tx (epi, purb);
+                       mpc8xx_udc_ep_tx (epi);
+
+                       /* Move to the addressed state */
+                       usbp->usaddr = udc_device->address;
+                       mpc8xx_udc_state_transition_up (udc_device->device_state,
+                                                       STATE_ADDRESSED);
+                       return 0;
+
+               case USB_REQ_SET_CONFIGURATION:
+                       if (!purb->device_request.wValue) {
+                               /* Respond at default address */
+                               usbp->usaddr = 0x00;
+                               mpc8xx_udc_state_transition_down (udc_device->device_state,
+                                                                 STATE_ADDRESSED);
+                       } else {
+                               /* TODO: Support multiple configurations */
+                               mpc8xx_udc_state_transition_up (udc_device->device_state,
+                                                               STATE_CONFIGURED);
+                               for (x = 1; x < MAX_ENDPOINTS; x++) {
+                                       if ((udc_device->bus->endpoint_array[x].endpoint_address & USB_ENDPOINT_DIR_MASK)
+                                           == USB_DIR_IN) {
+                                               ep_ref[x].pid = TX_BD_PID_DATA0;
+                                       } else {
+                                               ep_ref[x].pid = RX_BD_PID_DATA0;
+                                       }
+                                       /* Set configuration must unstall endpoints */
+                                       usbp->usep[x] &= ~STALL_BITMASK;
+                               }
+                       }
+                       break;
+               default:
+                       /* CDC/Vendor specific */
+                       break;
+               }
+
+               /* Send ZLP as ACK in Status OUT phase */
+               ep_ref[0].pid = TX_BD_PID_DATA1;
+               purb->actual_length = 0;
+               mpc8xx_udc_init_tx (epi, purb);
+               mpc8xx_udc_ep_tx (epi);
+
+       } else {
+
+               if (purb->actual_length) {
+                       ep_ref[0].pid = TX_BD_PID_DATA1;
+                       mpc8xx_udc_init_tx (epi, purb);
+
+                       if (!(purb->actual_length % EP0_MAX_PACKET_SIZE)) {
+                               ep_ref[0].sc |= EP_SEND_ZLP;
+                       }
+
+                       if (purb->device_request.wValue ==
+                           USB_DESCRIPTOR_TYPE_DEVICE) {
+                               if (le16_to_cpu (purb->device_request.wLength)
+                                   > purb->actual_length) {
+                                       /* Send EP0_MAX_PACKET_SIZE bytes
+                                        * unless correct size requested.
+                                        */
+                                       if (purb->actual_length > epi->tx_packetSize) {
+                                               purb->actual_length = epi->tx_packetSize;
+                                       }
+                               }
+                       }
+                       mpc8xx_udc_ep_tx (epi);
+
+               } else {
+                       /* Corrupt SETUP packet? */
+                       ERR ("Zero length data or SETUP with DATA-IN phase ?\n");
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+/* mpc8xx_udc_init_tx
+ *
+ * Setup some basic parameters for a TX transaction
+ */
+static void mpc8xx_udc_init_tx (struct usb_endpoint_instance *epi,
+                               struct urb *tx_urb)
+{
+       epi->sent = 0;
+       epi->last = 0;
+       epi->tx_urb = tx_urb;
+}
+
+/* mpc8xx_udc_ep0_rx
+ *
+ * Receive ep0/control USB data. Parse and possibly send a response.
+ */
+static void mpc8xx_udc_ep0_rx (volatile cbd_t * rx_cbdp)
+{
+       if (rx_cbdp->cbd_sc & RX_BD_PID_SETUP) {
+
+               /* Unconditionally accept SETUP packets */
+               if (mpc8xx_udc_ep0_rx_setup (rx_cbdp)) {
+                       mpc8xx_udc_stall (0);
+               }
+
+       } else {
+
+               mpc8xx_udc_clear_rxbd (rx_cbdp);
+
+               if ((rx_cbdp->cbd_datlen - 2)) {
+                       /* SETUP with a DATA phase
+                        * outside of SETUP packet.
+                        * Reply with STALL.
+                        */
+                       mpc8xx_udc_stall (0);
+               }
+       }
+}
+
+/* mpc8xx_udc_epn_rx
+ *
+ * Receive some data from cbd into USB system urb data abstraction
+ * Upper layers should NAK if there is insufficient RX data space
+ */
+static int mpc8xx_udc_epn_rx (unsigned int epid, volatile cbd_t * rx_cbdp)
+{
+       struct usb_endpoint_instance *epi = 0;
+       struct urb *urb = 0;
+       unsigned int x = 0;
+
+       if (epid >= MAX_ENDPOINTS || !rx_cbdp->cbd_datlen) {
+               return 0;
+       }
+
+       /* USB 2.0 PDF section 8.6.4
+        * Discard data with invalid PID it is a resend.
+        */
+       if (ep_ref[epid].pid != (rx_cbdp->cbd_sc & 0xC0)) {
+               return 1;
+       }
+       TOGGLE_RX_PID (ep_ref[epid].pid);
+
+       epi = &udc_device->bus->endpoint_array[epid];
+       urb = epi->rcv_urb;
+
+       for (; x < (rx_cbdp->cbd_datlen - 2); x++) {
+               *((unsigned char *) (urb->buffer + urb->actual_length + x)) =
+                       *((unsigned char *) (rx_cbdp->cbd_bufaddr + x));
+       }
+
+       if (x) {
+               usbd_rcv_complete (epi, x, 0);
+               if (ep_ref[epid].urb->status == RECV_ERROR) {
+                       DBG ("RX error unset NAK\n");
+                       udc_unset_nak (epid);
+               }
+       }
+       return x;
+}
+
+/* mpc8xx_udc_clock_init
+ *
+ * Obtain a clock reference for Full Speed Signaling
+ */
+static void mpc8xx_udc_clock_init (volatile immap_t * immr,
+                                  volatile cpm8xx_t * cp)
+{
+
+#if defined(CONFIG_SYS_USB_EXTC_CLK)
+
+       /* This has been tested with a 48MHz crystal on CLK6 */
+       switch (CONFIG_SYS_USB_EXTC_CLK) {
+       case 1:
+               immr->im_ioport.iop_papar |= 0x0100;
+               immr->im_ioport.iop_padir &= ~0x0100;
+               cp->cp_sicr |= 0x24;
+               break;
+       case 2:
+               immr->im_ioport.iop_papar |= 0x0200;
+               immr->im_ioport.iop_padir &= ~0x0200;
+               cp->cp_sicr |= 0x2D;
+               break;
+       case 3:
+               immr->im_ioport.iop_papar |= 0x0400;
+               immr->im_ioport.iop_padir &= ~0x0400;
+               cp->cp_sicr |= 0x36;
+               break;
+       case 4:
+               immr->im_ioport.iop_papar |= 0x0800;
+               immr->im_ioport.iop_padir &= ~0x0800;
+               cp->cp_sicr |= 0x3F;
+               break;
+       default:
+               udc_state = STATE_ERROR;
+               break;
+       }
+
+#elif defined(CONFIG_SYS_USB_BRGCLK)
+
+       /* This has been tested with brgclk == 50MHz */
+       int divisor = 0;
+
+       if (gd->cpu_clk < 48000000L) {
+               ERR ("brgclk is too slow for full-speed USB!\n");
+               udc_state = STATE_ERROR;
+               return;
+       }
+
+       /* Assume the brgclk is 'good enough', we want !(gd->cpu_clk%48MHz)
+        * but, can /probably/ live with close-ish alternative rates.
+        */
+       divisor = (gd->cpu_clk / 48000000L) - 1;
+       cp->cp_sicr &= ~0x0000003F;
+
+       switch (CONFIG_SYS_USB_BRGCLK) {
+       case 1:
+               cp->cp_brgc1 |= (divisor | CPM_BRG_EN);
+               cp->cp_sicr &= ~0x2F;
+               break;
+       case 2:
+               cp->cp_brgc2 |= (divisor | CPM_BRG_EN);
+               cp->cp_sicr |= 0x00000009;
+               break;
+       case 3:
+               cp->cp_brgc3 |= (divisor | CPM_BRG_EN);
+               cp->cp_sicr |= 0x00000012;
+               break;
+       case 4:
+               cp->cp_brgc4 = (divisor | CPM_BRG_EN);
+               cp->cp_sicr |= 0x0000001B;
+               break;
+       default:
+               udc_state = STATE_ERROR;
+               break;
+       }
+
+#else
+#error "CONFIG_SYS_USB_EXTC_CLK or CONFIG_SYS_USB_BRGCLK must be defined"
+#endif
+
+}
+
+/* mpc8xx_udc_cbd_attach
+ *
+ * attach a cbd to and endpoint
+ */
+static void mpc8xx_udc_cbd_attach (int ep, uchar tx_size, uchar rx_size)
+{
+
+       if (!tx_cbd[ep] || !rx_cbd[ep] || ep >= MAX_ENDPOINTS) {
+               udc_state = STATE_ERROR;
+               return;
+       }
+
+       if (tx_size > USB_MAX_PKT || rx_size > USB_MAX_PKT ||
+           (!tx_size && !rx_size)) {
+               udc_state = STATE_ERROR;
+               return;
+       }
+
+       /* Attach CBD to appropiate Parameter RAM Endpoint data structure */
+       if (rx_size) {
+               endpoints[ep]->rbase = (u32) rx_cbd[rx_ct];
+               endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct];
+               rx_ct++;
+
+               if (!ep) {
+
+                       endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct];
+                       rx_cbd[rx_ct]->cbd_sc |= RX_BD_W;
+                       rx_ct++;
+
+               } else {
+                       rx_ct += 2;
+                       endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct];
+                       rx_cbd[rx_ct]->cbd_sc |= RX_BD_W;
+                       rx_ct++;
+               }
+
+               /* Where we expect to RX data on this endpoint */
+               ep_ref[ep].prx = rx_cbd[rx_ct - 1];
+       } else {
+
+               ep_ref[ep].prx = 0;
+               endpoints[ep]->rbase = 0;
+               endpoints[ep]->rbptr = 0;
+       }
+
+       if (tx_size) {
+               endpoints[ep]->tbase = (u32) tx_cbd[tx_ct];
+               endpoints[ep]->tbptr = (u32) tx_cbd[tx_ct];
+               tx_ct++;
+       } else {
+               endpoints[ep]->tbase = 0;
+               endpoints[ep]->tbptr = 0;
+       }
+
+       endpoints[ep]->tstate = 0;
+       endpoints[ep]->tbcnt = 0;
+       endpoints[ep]->mrblr = EP_MAX_PKT;
+       endpoints[ep]->rfcr = 0x18;
+       endpoints[ep]->tfcr = 0x18;
+       ep_ref[ep].sc |= EP_ATTACHED;
+
+       DBG ("ep %d rbase 0x%08x rbptr 0x%08x tbase 0x%08x tbptr 0x%08x prx = %p\n",
+               ep, endpoints[ep]->rbase, endpoints[ep]->rbptr,
+               endpoints[ep]->tbase, endpoints[ep]->tbptr,
+               ep_ref[ep].prx);
+
+       return;
+}
+
+/* mpc8xx_udc_cbd_init
+ *
+ * Allocate space for a cbd and allocate TX/RX data space
+ */
+static void mpc8xx_udc_cbd_init (void)
+{
+       int i = 0;
+
+       for (; i < TX_RING_SIZE; i++) {
+               tx_cbd[i] = (cbd_t *)
+                       mpc8xx_udc_alloc (sizeof (cbd_t), sizeof (int));
+       }
+
+       for (i = 0; i < RX_RING_SIZE; i++) {
+               rx_cbd[i] = (cbd_t *)
+                       mpc8xx_udc_alloc (sizeof (cbd_t), sizeof (int));
+       }
+
+       for (i = 0; i < TX_RING_SIZE; i++) {
+               tx_cbd[i]->cbd_bufaddr =
+                       mpc8xx_udc_alloc (EP_MAX_PKT, sizeof (int));
+
+               tx_cbd[i]->cbd_sc = (TX_BD_I | TX_BD_W);
+               tx_cbd[i]->cbd_datlen = 0x0000;
+       }
+
+
+       for (i = 0; i < RX_RING_SIZE; i++) {
+               rx_cbd[i]->cbd_bufaddr =
+                       mpc8xx_udc_alloc (EP_MAX_PKT, sizeof (int));
+               rx_cbd[i]->cbd_sc = (RX_BD_I | RX_BD_E);
+               rx_cbd[i]->cbd_datlen = 0x0000;
+
+       }
+
+       return;
+}
+
+/* mpc8xx_udc_endpoint_init
+ *
+ * Attach an endpoint to some dpram
+ */
+static void mpc8xx_udc_endpoint_init (void)
+{
+       int i = 0;
+
+       for (; i < MAX_ENDPOINTS; i++) {
+               endpoints[i] = (usb_epb_t *)
+                       mpc8xx_udc_alloc (sizeof (usb_epb_t), 32);
+       }
+}
+
+/* mpc8xx_udc_alloc
+ *
+ * Grab the address of some dpram
+ */
+static u32 mpc8xx_udc_alloc (u32 data_size, u32 alignment)
+{
+       u32 retaddr = address_base;
+
+       while (retaddr % alignment) {
+               retaddr++;
+       }
+       address_base += data_size;
+
+       return retaddr;
+}
diff --git a/drivers/usb/gadget/omap1510_udc.c b/drivers/usb/gadget/omap1510_udc.c
new file mode 100644 (file)
index 0000000..90f7907
--- /dev/null
@@ -0,0 +1,1567 @@
+/*
+ * (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>
+#include <asm/io.h>
+#ifdef CONFIG_OMAP_SX1
+#include <i2c.h>
+#endif
+#include <usbdevice.h>
+#include <usb/omap1510_udc.h>
+
+#include "ep0.h"
+
+
+#define UDC_INIT_MDELAY                     80 /* Device settle delay */
+#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. */
+int 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);
+       }
+
+       return 0;
+}
+
+/* Start to initialize h/w stuff */
+int udc_init (void)
+{
+       u16 udc_rev;
+       uchar value;
+       ulong gpio;
+       int i;
+
+       /* Let the device settle down before we start */
+       for (i = 0; i < UDC_INIT_MDELAY; i++) udelay(1000);
+
+       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);
+
+#ifdef CONFIG_OMAP1510
+       /* This code was originally implemented for OMAP1510 and
+        * therefore is only applicable for OMAP1510 boards. For
+        * OMAP5912 or OMAP16xx the register APLL_CTRL does not
+        * exist and DPLL_CTRL is already configured.
+        */
+
+       /* Set and check APLL */
+       outw (0x0008, APLL_CTRL);
+       UDCREG (APLL_CTRL);
+       /* Set and check DPLL */
+       outw (0x2210, DPLL_CTRL);
+       UDCREG (DPLL_CTRL);
+#endif
+       /* Set and check SOFT
+        * The below line of code has been changed to perform a
+        * read-modify-write instead of a simple write for
+        * configuring the SOFT_REQ register. This allows the code
+        * to be compatible with OMAP5912 and OMAP16xx devices
+        */
+       outw ((1 << 4) | (1 << 3) | 1 | (inw(SOFT_REQ)), SOFT_REQ);
+
+       /* Short delay to wait for DPLL */
+       udelay (1000);
+
+       /* Print banner with device revision */
+       udc_rev = inw (UDC_REV) & 0xff;
+#ifdef CONFIG_OMAP1510
+       printf ("USB:   TI OMAP1510 USB function module rev %d.%d\n",
+               udc_rev >> 4, udc_rev & 0xf);
+#endif
+
+#ifdef CONFIG_OMAP1610
+       printf ("USB:   TI OMAP5912 USB function module rev %d.%d\n",
+               udc_rev >> 4, udc_rev & 0xf);
+#endif
+
+#ifdef CONFIG_OMAP_SX1
+       i2c_read (0x32, 0x04, 1, &value, 1);
+       value |= 0x04;
+       i2c_write (0x32, 0x04, 1, &value, 1);
+
+       i2c_read (0x32, 0x03, 1, &value, 1);
+       value |= 0x01;
+       i2c_write (0x32, 0x03, 1, &value, 1);
+
+       gpio = inl(GPIO_PIN_CONTROL_REG);
+       gpio |=  0x0002; /* A_IRDA_OFF */
+       gpio |=  0x0800; /* A_SWITCH   */
+       gpio |=  0x8000; /* A_USB_ON   */
+       outl (gpio, GPIO_PIN_CONTROL_REG);
+
+       gpio = inl(GPIO_DIR_CONTROL_REG);
+       gpio &= ~0x0002; /* A_IRDA_OFF */
+       gpio &= ~0x0800; /* A_SWITCH   */
+       gpio &= ~0x8000; /* A_USB_ON   */
+       outl (gpio, GPIO_DIR_CONTROL_REG);
+
+       gpio = inl(GPIO_DATA_OUTPUT_REG);
+       gpio |=  0x0002; /* A_IRDA_OFF */
+       gpio &= ~0x0800; /* A_SWITCH   */
+       gpio &= ~0x8000; /* A_USB_ON   */
+       outl (gpio, GPIO_DATA_OUTPUT_REG);
+#endif
+
+       /* 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);
+}
+
+/**
+ * udc_irq - do pseudo interrupts
+ */
+void udc_irq(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 ();
+       }
+}
+
+/* Flow control */
+void udc_set_nak(int epid)
+{
+       /* TODO: implement this functionality in omap1510 */
+}
+
+void udc_unset_nak (int epid)
+{
+       /* TODO: implement this functionality in omap1510 */
+}
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
new file mode 100644 (file)
index 0000000..ec1d689
--- /dev/null
@@ -0,0 +1,59 @@
+#
+# (C) Copyright 2000-2007
+# 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    := $(obj)libusb_host.a
+
+# ohci
+COBJS-$(CONFIG_USB_OHCI_NEW) += ohci-hcd.o
+COBJS-$(CONFIG_USB_ATMEL) += ohci-at91.o
+COBJS-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
+COBJS-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
+COBJS-$(CONFIG_USB_S3C64XX) += s3c64xx-hcd.o
+COBJS-$(CONFIG_USB_SL811HS) += sl811-hcd.o
+
+# echi
+COBJS-$(CONFIG_USB_EHCI) += ehci-hcd.o
+COBJS-$(CONFIG_USB_EHCI_FSL) += ehci-fsl.o
+COBJS-$(CONFIG_USB_EHCI_IXP4XX) += ehci-ixp.o
+COBJS-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o
+COBJS-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o
+
+COBJS  := $(COBJS-y)
+SRCS   := $(COBJS:.o=.c)
+OBJS   := $(addprefix $(obj),$(COBJS))
+
+all:   $(LIB)
+
+$(LIB):        $(obj).depend $(OBJS)
+       $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/usb/host/ehci-core.h b/drivers/usb/host/ehci-core.h
new file mode 100644 (file)
index 0000000..39e5c5e
--- /dev/null
@@ -0,0 +1,29 @@
+/*-
+ * Copyright (c) 2007-2008, Juniper Networks, Inc.
+ * Copyright (c) 2008, Excito Elektronik i SkÃ¥ne AB
+ * All rights reserved.
+ *
+ * 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 version 2 of
+ * the License.
+ *
+ * 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_EHCI_CORE_H
+#define USB_EHCI_CORE_H
+
+extern int rootdev;
+extern struct ehci_hccr *hccr;
+extern volatile struct ehci_hcor *hcor;
+
+#endif
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
new file mode 100644 (file)
index 0000000..86ee1d5
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * (C) Copyright 2008, Excito Elektronik i Sk=E5ne AB
+ *
+ * Author: Tor Krill tor@excito.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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <usb.h>
+#include <mpc83xx.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+
+#include "ehci.h"
+#include "ehci-fsl.h"
+#include "ehci-core.h"
+
+/*
+ * Create the appropriate control structures to manage
+ * a new EHCI host controller.
+ *
+ * Excerpts from linux ehci fsl driver.
+ */
+int ehci_hcd_init(void)
+{
+       volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+       uint32_t addr, temp;
+
+       addr = (uint32_t)&(im->usb[0]);
+       hccr = (struct ehci_hccr *)(addr + FSL_SKIP_PCI);
+       hcor = (struct ehci_hcor *)((uint32_t) hccr +
+                       HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+       /* Configure clock */
+       clrsetbits_be32(&(im->clk.sccr), MPC83XX_SCCR_USB_MASK,
+                       MPC83XX_SCCR_USB_DRCM_11);
+
+       /* Confgure interface. */
+       temp = in_be32((void *)(addr + FSL_SOC_USB_CTRL));
+       out_be32((void *)(addr + FSL_SOC_USB_CTRL), temp
+                | REFSEL_16MHZ | UTMI_PHY_EN);
+
+       /* Wait for clock to stabilize */
+       do {
+               temp = in_be32((void *)(addr + FSL_SOC_USB_CTRL));
+               udelay(1000);
+       } while (!(temp & PHY_CLK_VALID));
+
+       /* Set to Host mode */
+       temp = in_le32((void *)(addr + FSL_SOC_USB_USBMODE));
+       out_le32((void *)(addr + FSL_SOC_USB_USBMODE), temp | CM_HOST);
+
+       out_be32((void *)(addr + FSL_SOC_USB_SNOOP1), SNOOP_SIZE_2GB);
+       out_be32((void *)(addr + FSL_SOC_USB_SNOOP2),
+                0x80000000 | SNOOP_SIZE_2GB);
+
+       /* Init phy */
+       /* TODO: handle different phys? */
+       out_le32(&(hcor->or_portsc[0]), PORT_PTS_UTMI);
+
+       /* Enable interface. */
+       temp = in_be32((void *)(addr + FSL_SOC_USB_CTRL));
+       out_be32((void *)(addr + FSL_SOC_USB_CTRL), temp | USB_EN);
+
+       out_be32((void *)(addr + FSL_SOC_USB_PRICTRL), 0x0000000c);
+       out_be32((void *)(addr + FSL_SOC_USB_AGECNTTHRSH), 0x00000040);
+       out_be32((void *)(addr + FSL_SOC_USB_SICTRL), 0x00000001);
+
+       /* Enable interface. */
+       temp = in_be32((void *)(addr + FSL_SOC_USB_CTRL));
+       out_be32((void *)(addr + FSL_SOC_USB_CTRL), temp | USB_EN);
+
+       temp = in_le32((void *)(addr + FSL_SOC_USB_USBMODE));
+
+       return 0;
+}
+
+/*
+ * Destroy the appropriate control structures corresponding
+ * the the EHCI host controller.
+ */
+int ehci_hcd_stop(void)
+{
+       return 0;
+}
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
new file mode 100644 (file)
index 0000000..c429af1
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2005 freescale semiconductor
+ * Copyright (c) 2005 MontaVista Software
+ * Copyright (c) 2008 Excito Elektronik i Sk=E5ne AB
+ *
+ * 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 _EHCI_FSL_H
+#define _EHCI_FSL_H
+
+/* Global offsets */
+#define FSL_SKIP_PCI           0x100
+
+/* offsets for the non-ehci registers in the FSL SOC USB controller */
+#define FSL_SOC_USB_ULPIVP     0x170
+#define FSL_SOC_USB_PORTSC1    0x184
+#define PORT_PTS_MSK           (3 << 30)
+#define PORT_PTS_UTMI          (0 << 30)
+#define PORT_PTS_ULPI          (2 << 30)
+#define PORT_PTS_SERIAL                (3 << 30)
+#define PORT_PTS_PTW           (1 << 28)
+
+/* USBMODE Register bits */
+#define CM_IDLE                        (0 << 0)
+#define CM_RESERVED            (1 << 0)
+#define CM_DEVICE              (2 << 0)
+#define CM_HOST                        (3 << 0)
+#define USBMODE_RESERVED_2     (0 << 2)
+#define SLOM                   (1 << 3)
+#define SDIS                   (1 << 4)
+
+/* CONTROL Register bits */
+#define ULPI_INT_EN            (1 << 0)
+#define WU_INT_EN              (1 << 1)
+#define USB_EN                 (1 << 2)
+#define LSF_EN                 (1 << 3)
+#define KEEP_OTG_ON            (1 << 4)
+#define OTG_PORT               (1 << 5)
+#define REFSEL_12MHZ           (0 << 6)
+#define REFSEL_16MHZ           (1 << 6)
+#define REFSEL_48MHZ           (2 << 6)
+#define PLL_RESET              (1 << 8)
+#define UTMI_PHY_EN            (1 << 9)
+#define PHY_CLK_SEL_UTMI       (0 << 10)
+#define PHY_CLK_SEL_ULPI       (1 << 10)
+#define CLKIN_SEL_USB_CLK      (0 << 11)
+#define CLKIN_SEL_USB_CLK2     (1 << 11)
+#define CLKIN_SEL_SYS_CLK      (2 << 11)
+#define CLKIN_SEL_SYS_CLK2     (3 << 11)
+#define RESERVED_18            (0 << 13)
+#define RESERVED_17            (0 << 14)
+#define RESERVED_16            (0 << 15)
+#define WU_INT                 (1 << 16)
+#define PHY_CLK_VALID          (1 << 17)
+
+#define FSL_SOC_USB_PORTSC2    0x188
+#define FSL_SOC_USB_USBMODE    0x1a8
+#define FSL_SOC_USB_SNOOP1     0x400   /* NOTE: big-endian */
+#define FSL_SOC_USB_SNOOP2     0x404   /* NOTE: big-endian */
+#define FSL_SOC_USB_AGECNTTHRSH        0x408   /* NOTE: big-endian */
+#define FSL_SOC_USB_PRICTRL    0x40c   /* NOTE: big-endian */
+#define FSL_SOC_USB_SICTRL     0x410   /* NOTE: big-endian */
+#define FSL_SOC_USB_CTRL       0x500   /* NOTE: big-endian */
+#define SNOOP_SIZE_2GB         0x1e
+
+/* System Clock Control Register */
+#define MPC83XX_SCCR_USB_MASK          0x00f00000
+#define MPC83XX_SCCR_USB_DRCM_11       0x00300000
+#define MPC83XX_SCCR_USB_DRCM_01       0x00100000
+#define MPC83XX_SCCR_USB_DRCM_10       0x00200000
+
+#endif /* _EHCI_FSL_H */
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
new file mode 100644 (file)
index 0000000..bbd547b
--- /dev/null
@@ -0,0 +1,883 @@
+/*-
+ * Copyright (c) 2007-2008, Juniper Networks, Inc.
+ * Copyright (c) 2008, Excito Elektronik i SkÃ¥ne AB
+ * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it>
+ *
+ * All rights reserved.
+ *
+ * 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 version 2 of
+ * the License.
+ *
+ * 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 <asm/byteorder.h>
+#include <usb.h>
+#include <asm/io.h>
+#include <malloc.h>
+
+#include "ehci.h"
+
+int rootdev;
+struct ehci_hccr *hccr;        /* R/O registers, not need for volatile */
+volatile struct ehci_hcor *hcor;
+
+static uint16_t portreset;
+static struct QH qh_list __attribute__((aligned(32)));
+
+static struct descriptor {
+       struct usb_hub_descriptor hub;
+       struct usb_device_descriptor device;
+       struct usb_linux_config_descriptor config;
+       struct usb_linux_interface_descriptor interface;
+       struct usb_endpoint_descriptor endpoint;
+}  __attribute__ ((packed)) descriptor = {
+       {
+               0x8,            /* bDescLength */
+               0x29,           /* bDescriptorType: hub descriptor */
+               2,              /* bNrPorts -- runtime modified */
+               0,              /* wHubCharacteristics */
+               0xff,           /* bPwrOn2PwrGood */
+               0,              /* bHubCntrCurrent */
+               {},             /* Device removable */
+               {}              /* at most 7 ports! XXX */
+       },
+       {
+               0x12,           /* bLength */
+               1,              /* bDescriptorType: UDESC_DEVICE */
+               0x0002,         /* bcdUSB: v2.0 */
+               9,              /* bDeviceClass: UDCLASS_HUB */
+               0,              /* bDeviceSubClass: UDSUBCLASS_HUB */
+               1,              /* bDeviceProtocol: UDPROTO_HSHUBSTT */
+               64,             /* bMaxPacketSize: 64 bytes */
+               0x0000,         /* idVendor */
+               0x0000,         /* idProduct */
+               0x0001,         /* bcdDevice */
+               1,              /* iManufacturer */
+               2,              /* iProduct */
+               0,              /* iSerialNumber */
+               1               /* bNumConfigurations: 1 */
+       },
+       {
+               0x9,
+               2,              /* bDescriptorType: UDESC_CONFIG */
+               cpu_to_le16(0x19),
+               1,              /* bNumInterface */
+               1,              /* bConfigurationValue */
+               0,              /* iConfiguration */
+               0x40,           /* bmAttributes: UC_SELF_POWER */
+               0               /* bMaxPower */
+       },
+       {
+               0x9,            /* bLength */
+               4,              /* bDescriptorType: UDESC_INTERFACE */
+               0,              /* bInterfaceNumber */
+               0,              /* bAlternateSetting */
+               1,              /* bNumEndpoints */
+               9,              /* bInterfaceClass: UICLASS_HUB */
+               0,              /* bInterfaceSubClass: UISUBCLASS_HUB */
+               0,              /* bInterfaceProtocol: UIPROTO_HSHUBSTT */
+               0               /* iInterface */
+       },
+       {
+               0x7,            /* bLength */
+               5,              /* bDescriptorType: UDESC_ENDPOINT */
+               0x81,           /* bEndpointAddress:
+                                * UE_DIR_IN | EHCI_INTR_ENDPT
+                                */
+               3,              /* bmAttributes: UE_INTERRUPT */
+               8, 0,           /* wMaxPacketSize */
+               255             /* bInterval */
+       },
+};
+
+#if defined(CONFIG_EHCI_IS_TDI)
+#define ehci_is_TDI()  (1)
+#else
+#define ehci_is_TDI()  (0)
+#endif
+
+#if defined(CONFIG_EHCI_DCACHE)
+/*
+ * Routines to handle (flush/invalidate) the dcache for the QH and qTD
+ * structures and data buffers. This is needed on platforms using this
+ * EHCI support with dcache enabled.
+ */
+static void flush_invalidate(u32 addr, int size, int flush)
+{
+       if (flush)
+               flush_dcache_range(addr, addr + size);
+       else
+               invalidate_dcache_range(addr, addr + size);
+}
+
+static void cache_qtd(struct qTD *qtd, int flush)
+{
+       u32 *ptr = (u32 *)qtd->qt_buffer[0];
+       int len = (qtd->qt_token & 0x7fff0000) >> 16;
+
+       flush_invalidate((u32)qtd, sizeof(struct qTD), flush);
+       if (ptr && len)
+               flush_invalidate((u32)ptr, len, flush);
+}
+
+
+static inline struct QH *qh_addr(struct QH *qh)
+{
+       return (struct QH *)((u32)qh & 0xffffffe0);
+}
+
+static void cache_qh(struct QH *qh, int flush)
+{
+       struct qTD *qtd;
+       struct qTD *next;
+       static struct qTD *first_qtd;
+
+       /*
+        * Walk the QH list and flush/invalidate all entries
+        */
+       while (1) {
+               flush_invalidate((u32)qh_addr(qh), sizeof(struct QH), flush);
+               if ((u32)qh & QH_LINK_TYPE_QH)
+                       break;
+               qh = qh_addr(qh);
+               qh = (struct QH *)qh->qh_link;
+       }
+       qh = qh_addr(qh);
+
+       /*
+        * Save first qTD pointer, needed for invalidating pass on this QH
+        */
+       if (flush)
+               first_qtd = qtd = (struct qTD *)(*(u32 *)&qh->qh_overlay &
+                                                0xffffffe0);
+       else
+               qtd = first_qtd;
+
+       /*
+        * Walk the qTD list and flush/invalidate all entries
+        */
+       while (1) {
+               if (qtd == NULL)
+                       break;
+               cache_qtd(qtd, flush);
+               next = (struct qTD *)((u32)qtd->qt_next & 0xffffffe0);
+               if (next == qtd)
+                       break;
+               qtd = next;
+       }
+}
+
+static inline void ehci_flush_dcache(struct QH *qh)
+{
+       cache_qh(qh, 1);
+}
+
+static inline void ehci_invalidate_dcache(struct QH *qh)
+{
+       cache_qh(qh, 0);
+}
+#else /* CONFIG_EHCI_DCACHE */
+/*
+ *
+ */
+static inline void ehci_flush_dcache(struct QH *qh)
+{
+}
+
+static inline void ehci_invalidate_dcache(struct QH *qh)
+{
+}
+#endif /* CONFIG_EHCI_DCACHE */
+
+static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec)
+{
+       uint32_t result;
+       do {
+               result = ehci_readl(ptr);
+               if (result == ~(uint32_t)0)
+                       return -1;
+               result &= mask;
+               if (result == done)
+                       return 0;
+               udelay(1);
+               usec--;
+       } while (usec > 0);
+       return -1;
+}
+
+static void ehci_free(void *p, size_t sz)
+{
+
+}
+
+static int ehci_reset(void)
+{
+       uint32_t cmd;
+       uint32_t tmp;
+       uint32_t *reg_ptr;
+       int ret = 0;
+
+       cmd = ehci_readl(&hcor->or_usbcmd);
+       cmd |= CMD_RESET;
+       ehci_writel(&hcor->or_usbcmd, cmd);
+       ret = handshake((uint32_t *)&hcor->or_usbcmd, CMD_RESET, 0, 250 * 1000);
+       if (ret < 0) {
+               printf("EHCI fail to reset\n");
+               goto out;
+       }
+
+       if (ehci_is_TDI()) {
+               reg_ptr = (uint32_t *)((u8 *)hcor + USBMODE);
+               tmp = ehci_readl(reg_ptr);
+               tmp |= USBMODE_CM_HC;
+#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN)
+               tmp |= USBMODE_BE;
+#endif
+               ehci_writel(reg_ptr, tmp);
+       }
+out:
+       return ret;
+}
+
+static void *ehci_alloc(size_t sz, size_t align)
+{
+       static struct QH qh __attribute__((aligned(32)));
+       static struct qTD td[3] __attribute__((aligned (32)));
+       static int ntds;
+       void *p;
+
+       switch (sz) {
+       case sizeof(struct QH):
+               p = &qh;
+               ntds = 0;
+               break;
+       case sizeof(struct qTD):
+               if (ntds == 3) {
+                       debug("out of TDs\n");
+                       return NULL;
+               }
+               p = &td[ntds];
+               ntds++;
+               break;
+       default:
+               debug("unknown allocation size\n");
+               return NULL;
+       }
+
+       memset(p, sz, 0);
+       return p;
+}
+
+static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
+{
+       uint32_t addr, delta, next;
+       int idx;
+
+       addr = (uint32_t) buf;
+       idx = 0;
+       while (idx < 5) {
+               td->qt_buffer[idx] = cpu_to_hc32(addr);
+               next = (addr + 4096) & ~4095;
+               delta = next - addr;
+               if (delta >= sz)
+                       break;
+               sz -= delta;
+               addr = next;
+               idx++;
+       }
+
+       if (idx == 5) {
+               debug("out of buffer pointers (%u bytes left)\n", sz);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int
+ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
+                  int length, struct devrequest *req)
+{
+       struct QH *qh;
+       struct qTD *td;
+       volatile struct qTD *vtd;
+       unsigned long ts;
+       uint32_t *tdp;
+       uint32_t endpt, token, usbsts;
+       uint32_t c, toggle;
+       uint32_t cmd;
+       int ret = 0;
+
+       debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe,
+             buffer, length, req);
+       if (req != NULL)
+               debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n",
+                     req->request, req->request,
+                     req->requesttype, req->requesttype,
+                     le16_to_cpu(req->value), le16_to_cpu(req->value),
+                     le16_to_cpu(req->index));
+
+       qh = ehci_alloc(sizeof(struct QH), 32);
+       if (qh == NULL) {
+               debug("unable to allocate QH\n");
+               return -1;
+       }
+       qh->qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH);
+       c = (usb_pipespeed(pipe) != USB_SPEED_HIGH &&
+            usb_pipeendpoint(pipe) == 0) ? 1 : 0;
+       endpt = (8 << 28) |
+           (c << 27) |
+           (usb_maxpacket(dev, pipe) << 16) |
+           (0 << 15) |
+           (1 << 14) |
+           (usb_pipespeed(pipe) << 12) |
+           (usb_pipeendpoint(pipe) << 8) |
+           (0 << 7) | (usb_pipedevice(pipe) << 0);
+       qh->qh_endpt1 = cpu_to_hc32(endpt);
+       endpt = (1 << 30) |
+           (dev->portnr << 23) |
+           (dev->parent->devnum << 16) | (0 << 8) | (0 << 0);
+       qh->qh_endpt2 = cpu_to_hc32(endpt);
+       qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
+       qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+
+       td = NULL;
+       tdp = &qh->qh_overlay.qt_next;
+
+       toggle =
+           usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
+
+       if (req != NULL) {
+               td = ehci_alloc(sizeof(struct qTD), 32);
+               if (td == NULL) {
+                       debug("unable to allocate SETUP td\n");
+                       goto fail;
+               }
+               td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
+               td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+               token = (0 << 31) |
+                   (sizeof(*req) << 16) |
+                   (0 << 15) | (0 << 12) | (3 << 10) | (2 << 8) | (0x80 << 0);
+               td->qt_token = cpu_to_hc32(token);
+               if (ehci_td_buffer(td, req, sizeof(*req)) != 0) {
+                       debug("unable construct SETUP td\n");
+                       ehci_free(td, sizeof(*td));
+                       goto fail;
+               }
+               *tdp = cpu_to_hc32((uint32_t) td);
+               tdp = &td->qt_next;
+               toggle = 1;
+       }
+
+       if (length > 0 || req == NULL) {
+               td = ehci_alloc(sizeof(struct qTD), 32);
+               if (td == NULL) {
+                       debug("unable to allocate DATA td\n");
+                       goto fail;
+               }
+               td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
+               td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+               token = (toggle << 31) |
+                   (length << 16) |
+                   ((req == NULL ? 1 : 0) << 15) |
+                   (0 << 12) |
+                   (3 << 10) |
+                   ((usb_pipein(pipe) ? 1 : 0) << 8) | (0x80 << 0);
+               td->qt_token = cpu_to_hc32(token);
+               if (ehci_td_buffer(td, buffer, length) != 0) {
+                       debug("unable construct DATA td\n");
+                       ehci_free(td, sizeof(*td));
+                       goto fail;
+               }
+               *tdp = cpu_to_hc32((uint32_t) td);
+               tdp = &td->qt_next;
+       }
+
+       if (req != NULL) {
+               td = ehci_alloc(sizeof(struct qTD), 32);
+               if (td == NULL) {
+                       debug("unable to allocate ACK td\n");
+                       goto fail;
+               }
+               td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
+               td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+               token = (toggle << 31) |
+                   (0 << 16) |
+                   (1 << 15) |
+                   (0 << 12) |
+                   (3 << 10) |
+                   ((usb_pipein(pipe) ? 0 : 1) << 8) | (0x80 << 0);
+               td->qt_token = cpu_to_hc32(token);
+               *tdp = cpu_to_hc32((uint32_t) td);
+               tdp = &td->qt_next;
+       }
+
+       qh_list.qh_link = cpu_to_hc32((uint32_t) qh | QH_LINK_TYPE_QH);
+
+       /* Flush dcache */
+       ehci_flush_dcache(&qh_list);
+
+       usbsts = ehci_readl(&hcor->or_usbsts);
+       ehci_writel(&hcor->or_usbsts, (usbsts & 0x3f));
+
+       /* Enable async. schedule. */
+       cmd = ehci_readl(&hcor->or_usbcmd);
+       cmd |= CMD_ASE;
+       ehci_writel(&hcor->or_usbcmd, cmd);
+
+       ret = handshake((uint32_t *)&hcor->or_usbsts, STD_ASS, STD_ASS,
+                       100 * 1000);
+       if (ret < 0) {
+               printf("EHCI fail timeout STD_ASS set\n");
+               goto fail;
+       }
+
+       /* Wait for TDs to be processed. */
+       ts = get_timer(0);
+       vtd = td;
+       do {
+               /* Invalidate dcache */
+               ehci_invalidate_dcache(&qh_list);
+               token = hc32_to_cpu(vtd->qt_token);
+               if (!(token & 0x80))
+                       break;
+       } while (get_timer(ts) < CONFIG_SYS_HZ);
+
+       /* Disable async schedule. */
+       cmd = ehci_readl(&hcor->or_usbcmd);
+       cmd &= ~CMD_ASE;
+       ehci_writel(&hcor->or_usbcmd, cmd);
+
+       ret = handshake((uint32_t *)&hcor->or_usbsts, STD_ASS, 0,
+                       100 * 1000);
+       if (ret < 0) {
+               printf("EHCI fail timeout STD_ASS reset\n");
+               goto fail;
+       }
+
+       qh_list.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH);
+
+       token = hc32_to_cpu(qh->qh_overlay.qt_token);
+       if (!(token & 0x80)) {
+               debug("TOKEN=%#x\n", token);
+               switch (token & 0xfc) {
+               case 0:
+                       toggle = token >> 31;
+                       usb_settoggle(dev, usb_pipeendpoint(pipe),
+                                      usb_pipeout(pipe), toggle);
+                       dev->status = 0;
+                       break;
+               case 0x40:
+                       dev->status = USB_ST_STALLED;
+                       break;
+               case 0xa0:
+               case 0x20:
+                       dev->status = USB_ST_BUF_ERR;
+                       break;
+               case 0x50:
+               case 0x10:
+                       dev->status = USB_ST_BABBLE_DET;
+                       break;
+               default:
+                       dev->status = USB_ST_CRC_ERR;
+                       break;
+               }
+               dev->act_len = length - ((token >> 16) & 0x7fff);
+       } else {
+               dev->act_len = 0;
+               debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n",
+                     dev->devnum, ehci_readl(&hcor->or_usbsts),
+                     ehci_readl(&hcor->or_portsc[0]),
+                     ehci_readl(&hcor->or_portsc[1]));
+       }
+
+       return (dev->status != USB_ST_NOT_PROC) ? 0 : -1;
+
+fail:
+       td = (void *)hc32_to_cpu(qh->qh_overlay.qt_next);
+       while (td != (void *)QT_NEXT_TERMINATE) {
+               qh->qh_overlay.qt_next = td->qt_next;
+               ehci_free(td, sizeof(*td));
+               td = (void *)hc32_to_cpu(qh->qh_overlay.qt_next);
+       }
+       ehci_free(qh, sizeof(*qh));
+       return -1;
+}
+
+static inline int min3(int a, int b, int c)
+{
+
+       if (b < a)
+               a = b;
+       if (c < a)
+               a = c;
+       return a;
+}
+
+int
+ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
+                int length, struct devrequest *req)
+{
+       uint8_t tmpbuf[4];
+       u16 typeReq;
+       void *srcptr = NULL;
+       int len, srclen;
+       uint32_t reg;
+       uint32_t *status_reg;
+
+       if (le16_to_cpu(req->index) >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) {
+               printf("The request port(%d) is not configured\n",
+                       le16_to_cpu(req->index) - 1);
+               return -1;
+       }
+       status_reg = (uint32_t *)&hcor->or_portsc[
+                                               le16_to_cpu(req->index) - 1];
+       srclen = 0;
+
+       debug("req=%u (%#x), type=%u (%#x), value=%u, index=%u\n",
+             req->request, req->request,
+             req->requesttype, req->requesttype,
+             le16_to_cpu(req->value), le16_to_cpu(req->index));
+
+       typeReq = req->request << 8 | req->requesttype;
+
+       switch (le16_to_cpu(typeReq)) {
+       case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
+               switch (le16_to_cpu(req->value) >> 8) {
+               case USB_DT_DEVICE:
+                       debug("USB_DT_DEVICE request\n");
+                       srcptr = &descriptor.device;
+                       srclen = 0x12;
+                       break;
+               case USB_DT_CONFIG:
+                       debug("USB_DT_CONFIG config\n");
+                       srcptr = &descriptor.config;
+                       srclen = 0x19;
+                       break;
+               case USB_DT_STRING:
+                       debug("USB_DT_STRING config\n");
+                       switch (le16_to_cpu(req->value) & 0xff) {
+                       case 0: /* Language */
+                               srcptr = "\4\3\1\0";
+                               srclen = 4;
+                               break;
+                       case 1: /* Vendor */
+                               srcptr = "\16\3u\0-\0b\0o\0o\0t\0";
+                               srclen = 14;
+                               break;
+                       case 2: /* Product */
+                               srcptr = "\52\3E\0H\0C\0I\0 "
+                                        "\0H\0o\0s\0t\0 "
+                                        "\0C\0o\0n\0t\0r\0o\0l\0l\0e\0r\0";
+                               srclen = 42;
+                               break;
+                       default:
+                               debug("unknown value DT_STRING %x\n",
+                                       le16_to_cpu(req->value));
+                               goto unknown;
+                       }
+                       break;
+               default:
+                       debug("unknown value %x\n", le16_to_cpu(req->value));
+                       goto unknown;
+               }
+               break;
+       case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8):
+               switch (le16_to_cpu(req->value) >> 8) {
+               case USB_DT_HUB:
+                       debug("USB_DT_HUB config\n");
+                       srcptr = &descriptor.hub;
+                       srclen = 0x8;
+                       break;
+               default:
+                       debug("unknown value %x\n", le16_to_cpu(req->value));
+                       goto unknown;
+               }
+               break;
+       case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8):
+               debug("USB_REQ_SET_ADDRESS\n");
+               rootdev = le16_to_cpu(req->value);
+               break;
+       case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
+               debug("USB_REQ_SET_CONFIGURATION\n");
+               /* Nothing to do */
+               break;
+       case USB_REQ_GET_STATUS | ((USB_DIR_IN | USB_RT_HUB) << 8):
+               tmpbuf[0] = 1;  /* USB_STATUS_SELFPOWERED */
+               tmpbuf[1] = 0;
+               srcptr = tmpbuf;
+               srclen = 2;
+               break;
+       case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8):
+               memset(tmpbuf, 0, 4);
+               reg = ehci_readl(status_reg);
+               if (reg & EHCI_PS_CS)
+                       tmpbuf[0] |= USB_PORT_STAT_CONNECTION;
+               if (reg & EHCI_PS_PE)
+                       tmpbuf[0] |= USB_PORT_STAT_ENABLE;
+               if (reg & EHCI_PS_SUSP)
+                       tmpbuf[0] |= USB_PORT_STAT_SUSPEND;
+               if (reg & EHCI_PS_OCA)
+                       tmpbuf[0] |= USB_PORT_STAT_OVERCURRENT;
+               if (reg & EHCI_PS_PR &&
+                   (portreset & (1 << le16_to_cpu(req->index)))) {
+                       int ret;
+                       /* force reset to complete */
+                       reg = reg & ~(EHCI_PS_PR | EHCI_PS_CLEAR);
+                       ehci_writel(status_reg, reg);
+                       ret = handshake(status_reg, EHCI_PS_PR, 0, 2 * 1000);
+                       if (!ret)
+                               tmpbuf[0] |= USB_PORT_STAT_RESET;
+                       else
+                               printf("port(%d) reset error\n",
+                                       le16_to_cpu(req->index) - 1);
+               }
+               if (reg & EHCI_PS_PP)
+                       tmpbuf[1] |= USB_PORT_STAT_POWER >> 8;
+
+               if (ehci_is_TDI()) {
+                       switch ((reg >> 26) & 3) {
+                       case 0:
+                               break;
+                       case 1:
+                               tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8;
+                               break;
+                       case 2:
+                       default:
+                               tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
+                               break;
+                       }
+               } else {
+                       tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
+               }
+
+               if (reg & EHCI_PS_CSC)
+                       tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION;
+               if (reg & EHCI_PS_PEC)
+                       tmpbuf[2] |= USB_PORT_STAT_C_ENABLE;
+               if (reg & EHCI_PS_OCC)
+                       tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT;
+               if (portreset & (1 << le16_to_cpu(req->index)))
+                       tmpbuf[2] |= USB_PORT_STAT_C_RESET;
+
+               srcptr = tmpbuf;
+               srclen = 4;
+               break;
+       case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
+               reg = ehci_readl(status_reg);
+               reg &= ~EHCI_PS_CLEAR;
+               switch (le16_to_cpu(req->value)) {
+               case USB_PORT_FEAT_ENABLE:
+                       reg |= EHCI_PS_PE;
+                       ehci_writel(status_reg, reg);
+                       break;
+               case USB_PORT_FEAT_POWER:
+                       if (HCS_PPC(ehci_readl(&hccr->cr_hcsparams))) {
+                               reg |= EHCI_PS_PP;
+                               ehci_writel(status_reg, reg);
+                       }
+                       break;
+               case USB_PORT_FEAT_RESET:
+                       if ((reg & (EHCI_PS_PE | EHCI_PS_CS)) == EHCI_PS_CS &&
+                           !ehci_is_TDI() &&
+                           EHCI_PS_IS_LOWSPEED(reg)) {
+                               /* Low speed device, give up ownership. */
+                               debug("port %d low speed --> companion\n",
+                                     req->index - 1);
+                               reg |= EHCI_PS_PO;
+                               ehci_writel(status_reg, reg);
+                               break;
+                       } else {
+                               reg |= EHCI_PS_PR;
+                               reg &= ~EHCI_PS_PE;
+                               ehci_writel(status_reg, reg);
+                               /*
+                                * caller must wait, then call GetPortStatus
+                                * usb 2.0 specification say 50 ms resets on
+                                * root
+                                */
+                               wait_ms(50);
+                               portreset |= 1 << le16_to_cpu(req->index);
+                       }
+                       break;
+               default:
+                       debug("unknown feature %x\n", le16_to_cpu(req->value));
+                       goto unknown;
+               }
+               /* unblock posted writes */
+               ehci_readl(&hcor->or_usbcmd);
+               break;
+       case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
+               reg = ehci_readl(status_reg);
+               switch (le16_to_cpu(req->value)) {
+               case USB_PORT_FEAT_ENABLE:
+                       reg &= ~EHCI_PS_PE;
+                       break;
+               case USB_PORT_FEAT_C_ENABLE:
+                       reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_PE;
+                       break;
+               case USB_PORT_FEAT_POWER:
+                       if (HCS_PPC(ehci_readl(&hccr->cr_hcsparams)))
+                               reg = reg & ~(EHCI_PS_CLEAR | EHCI_PS_PP);
+               case USB_PORT_FEAT_C_CONNECTION:
+                       reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_CSC;
+                       break;
+               case USB_PORT_FEAT_OVER_CURRENT:
+                       reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_OCC;
+                       break;
+               case USB_PORT_FEAT_C_RESET:
+                       portreset &= ~(1 << le16_to_cpu(req->index));
+                       break;
+               default:
+                       debug("unknown feature %x\n", le16_to_cpu(req->value));
+                       goto unknown;
+               }
+               ehci_writel(status_reg, reg);
+               /* unblock posted write */
+               ehci_readl(&hcor->or_usbcmd);
+               break;
+       default:
+               debug("Unknown request\n");
+               goto unknown;
+       }
+
+       wait_ms(1);
+       len = min3(srclen, le16_to_cpu(req->length), length);
+       if (srcptr != NULL && len > 0)
+               memcpy(buffer, srcptr, len);
+       else
+               debug("Len is 0\n");
+
+       dev->act_len = len;
+       dev->status = 0;
+       return 0;
+
+unknown:
+       debug("requesttype=%x, request=%x, value=%x, index=%x, length=%x\n",
+             req->requesttype, req->request, le16_to_cpu(req->value),
+             le16_to_cpu(req->index), le16_to_cpu(req->length));
+
+       dev->act_len = 0;
+       dev->status = USB_ST_STALLED;
+       return -1;
+}
+
+int usb_lowlevel_stop(void)
+{
+       return ehci_hcd_stop();
+}
+
+int usb_lowlevel_init(void)
+{
+       uint32_t reg;
+       uint32_t cmd;
+
+       if (ehci_hcd_init() != 0)
+               return -1;
+
+       /* EHCI spec section 4.1 */
+       if (ehci_reset() != 0)
+               return -1;
+
+#if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET)
+       if (ehci_hcd_init() != 0)
+               return -1;
+#endif
+
+       /* Set head of reclaim list */
+       memset(&qh_list, 0, sizeof(qh_list));
+       qh_list.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH);
+       qh_list.qh_endpt1 = cpu_to_hc32((1 << 15) | (USB_SPEED_HIGH << 12));
+       qh_list.qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE);
+       qh_list.qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
+       qh_list.qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+       qh_list.qh_overlay.qt_token = cpu_to_hc32(0x40);
+
+       /* Set async. queue head pointer. */
+       ehci_writel(&hcor->or_asynclistaddr, (uint32_t)&qh_list);
+
+       reg = ehci_readl(&hccr->cr_hcsparams);
+       descriptor.hub.bNbrPorts = HCS_N_PORTS(reg);
+       printf("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts);
+       /* Port Indicators */
+       if (HCS_INDICATOR(reg))
+               descriptor.hub.wHubCharacteristics |= 0x80;
+       /* Port Power Control */
+       if (HCS_PPC(reg))
+               descriptor.hub.wHubCharacteristics |= 0x01;
+
+       /* Start the host controller. */
+       cmd = ehci_readl(&hcor->or_usbcmd);
+       /*
+        * Philips, Intel, and maybe others need CMD_RUN before the
+        * root hub will detect new devices (why?); NEC doesn't
+        */
+       cmd &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
+       cmd |= CMD_RUN;
+       ehci_writel(&hcor->or_usbcmd, cmd);
+
+       /* take control over the ports */
+       cmd = ehci_readl(&hcor->or_configflag);
+       cmd |= FLAG_CF;
+       ehci_writel(&hcor->or_configflag, cmd);
+       /* unblock posted write */
+       cmd = ehci_readl(&hcor->or_usbcmd);
+       wait_ms(5);
+       reg = HC_VERSION(ehci_readl(&hccr->cr_capbase));
+       printf("USB EHCI %x.%02x\n", reg >> 8, reg & 0xff);
+
+       rootdev = 0;
+
+       return 0;
+}
+
+int
+submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+               int length)
+{
+
+       if (usb_pipetype(pipe) != PIPE_BULK) {
+               debug("non-bulk pipe (type=%lu)", usb_pipetype(pipe));
+               return -1;
+       }
+       return ehci_submit_async(dev, pipe, buffer, length, NULL);
+}
+
+int
+submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                  int length, struct devrequest *setup)
+{
+
+       if (usb_pipetype(pipe) != PIPE_CONTROL) {
+               debug("non-control pipe (type=%lu)", usb_pipetype(pipe));
+               return -1;
+       }
+
+       if (usb_pipedevice(pipe) == rootdev) {
+               if (rootdev == 0)
+                       dev->speed = USB_SPEED_HIGH;
+               return ehci_submit_root(dev, pipe, buffer, length, setup);
+       }
+       return ehci_submit_async(dev, pipe, buffer, length, setup);
+}
+
+int
+submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+              int length, int interval)
+{
+
+       debug("dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d",
+             dev, pipe, buffer, length, interval);
+       return -1;
+}
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
new file mode 100644 (file)
index 0000000..b8f15ae
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * (C) Copyright 2008, Michael Trimarchi <trimarchimichael@yahoo.it>
+ *
+ * Author: Michael Trimarchi <trimarchimichael@yahoo.it>
+ * This code is based on ehci freescale driver
+ *
+ * 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 <usb.h>
+
+#include "ehci.h"
+#include "ehci-core.h"
+/*
+ * Create the appropriate control structures to manage
+ * a new EHCI host controller.
+ */
+int ehci_hcd_init(void)
+{
+       hccr = (struct ehci_hccr *)(0xcd000100);
+       hcor = (struct ehci_hcor *)((uint32_t) hccr
+                       + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+       printf("IXP4XX init hccr %x and hcor %x hc_length %d\n",
+               (uint32_t)hccr, (uint32_t)hcor,
+               (uint32_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+       return 0;
+}
+
+/*
+ * Destroy the appropriate control structures corresponding
+ * the the EHCI host controller.
+ */
+int ehci_hcd_stop(void)
+{
+       return 0;
+}
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
new file mode 100644 (file)
index 0000000..441b1a2
--- /dev/null
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 2007-2008, Juniper Networks, Inc.
+ * All rights reserved.
+ *
+ * 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 version 2 of
+ * the License.
+ *
+ * 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 <pci.h>
+#include <usb.h>
+
+#include "ehci.h"
+#include "ehci-core.h"
+
+#ifdef CONFIG_PCI_EHCI_DEVICE
+static struct pci_device_id ehci_pci_ids[] = {
+       /* Please add supported PCI EHCI controller ids here */
+       {0, 0}
+};
+#endif
+
+/*
+ * Create the appropriate control structures to manage
+ * a new EHCI host controller.
+ */
+int ehci_hcd_init(void)
+{
+       pci_dev_t pdev;
+       uint32_t addr;
+
+       pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVICE);
+       if (pdev == -1) {
+               printf("EHCI host controller not found\n");
+               return -1;
+       }
+
+       pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &addr);
+       hccr = (struct ehci_hccr *)addr;
+       hcor = (struct ehci_hcor *)((uint32_t) hccr +
+                       HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+       return 0;
+}
+
+/*
+ * Destroy the appropriate control structures corresponding
+ * the the EHCI host controller.
+ */
+int ehci_hcd_stop(void)
+{
+       return 0;
+}
diff --git a/drivers/usb/host/ehci-vct.c b/drivers/usb/host/ehci-vct.c
new file mode 100644 (file)
index 0000000..3063dd1
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * (C) Copyright 2009 Stefan Roese <sr@denx.de>, DENX Software Engineering
+ *
+ * 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 <usb.h>
+
+#include "ehci.h"
+#include "ehci-core.h"
+
+int vct_ehci_hcd_init(u32 *hccr, u32 *hcor);
+
+/*
+ * Create the appropriate control structures to manage
+ * a new EHCI host controller.
+ */
+int ehci_hcd_init(void)
+{
+       int ret;
+       u32 vct_hccr;
+       u32 vct_hcor;
+
+       /*
+        * Init VCT specific stuff
+        */
+       ret = vct_ehci_hcd_init(&vct_hccr, &vct_hcor);
+       if (ret)
+               return ret;
+
+       hccr = (struct ehci_hccr *)vct_hccr;
+       hcor = (struct ehci_hcor *)vct_hcor;
+
+       return 0;
+}
+
+/*
+ * Destroy the appropriate control structures corresponding
+ * the the EHCI host controller.
+ */
+int ehci_hcd_stop(void)
+{
+       return 0;
+}
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
new file mode 100644 (file)
index 0000000..b3c1d5d
--- /dev/null
@@ -0,0 +1,194 @@
+/*-
+ * Copyright (c) 2007-2008, Juniper Networks, Inc.
+ * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it>
+ * All rights reserved.
+ *
+ * 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 version 2 of
+ * the License.
+ *
+ * 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_EHCI_H
+#define USB_EHCI_H
+
+#if !defined(CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS)
+#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS     2
+#endif
+
+/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */
+#define DeviceRequest \
+       ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE) << 8)
+
+#define DeviceOutRequest \
+       ((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE) << 8)
+
+#define InterfaceRequest \
+       ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
+
+#define EndpointRequest \
+       ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
+
+#define EndpointOutRequest \
+       ((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
+
+/*
+ * Register Space.
+ */
+struct ehci_hccr {
+       uint32_t cr_capbase;
+#define HC_LENGTH(p)           (((p) >> 0) & 0x00ff)
+#define HC_VERSION(p)          (((p) >> 16) & 0xffff)
+       uint32_t cr_hcsparams;
+#define HCS_PPC(p)             ((p) & (1 << 4))
+#define HCS_INDICATOR(p)       ((p) & (1 << 16)) /* Port indicators */
+#define HCS_N_PORTS(p)         (((p) >> 0) & 0xf)
+       uint32_t cr_hccparams;
+       uint8_t cr_hcsp_portrt[8];
+} __attribute__ ((packed));
+
+struct ehci_hcor {
+       uint32_t or_usbcmd;
+#define CMD_PARK       (1 << 11)               /* enable "park" */
+#define CMD_PARK_CNT(c)        (((c) >> 8) & 3)        /* how many transfers to park */
+#define CMD_ASE                (1 << 5)                /* async schedule enable */
+#define CMD_LRESET     (1 << 7)                /* partial reset */
+#define CMD_IAAD       (1 << 5)                /* "doorbell" interrupt */
+#define CMD_PSE                (1 << 4)                /* periodic schedule enable */
+#define CMD_RESET      (1 << 1)                /* reset HC not bus */
+#define CMD_RUN                (1 << 0)                /* start/stop HC */
+       uint32_t or_usbsts;
+#define        STD_ASS         (1 << 15)
+#define STS_HALT       (1 << 12)
+       uint32_t or_usbintr;
+       uint32_t or_frindex;
+       uint32_t or_ctrldssegment;
+       uint32_t or_periodiclistbase;
+       uint32_t or_asynclistaddr;
+       uint32_t _reserved_[9];
+       uint32_t or_configflag;
+#define FLAG_CF                (1 << 0)        /* true:  we'll support "high speed" */
+       uint32_t or_portsc[CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS];
+       uint32_t or_systune;
+} __attribute__ ((packed));
+
+#define USBMODE                0x68            /* USB Device mode */
+#define USBMODE_SDIS   (1 << 3)        /* Stream disable */
+#define USBMODE_BE     (1 << 2)        /* BE/LE endiannes select */
+#define USBMODE_CM_HC  (3 << 0)        /* host controller mode */
+#define USBMODE_CM_IDLE        (0 << 0)        /* idle state */
+
+/* Interface descriptor */
+struct usb_linux_interface_descriptor {
+       unsigned char   bLength;
+       unsigned char   bDescriptorType;
+       unsigned char   bInterfaceNumber;
+       unsigned char   bAlternateSetting;
+       unsigned char   bNumEndpoints;
+       unsigned char   bInterfaceClass;
+       unsigned char   bInterfaceSubClass;
+       unsigned char   bInterfaceProtocol;
+       unsigned char   iInterface;
+} __attribute__ ((packed));
+
+/* Configuration descriptor information.. */
+struct usb_linux_config_descriptor {
+       unsigned char   bLength;
+       unsigned char   bDescriptorType;
+       unsigned short  wTotalLength;
+       unsigned char   bNumInterfaces;
+       unsigned char   bConfigurationValue;
+       unsigned char   iConfiguration;
+       unsigned char   bmAttributes;
+       unsigned char   MaxPower;
+} __attribute__ ((packed));
+
+#if defined CONFIG_EHCI_DESC_BIG_ENDIAN
+#define        ehci_readl(x)           (*((volatile u32 *)(x)))
+#define ehci_writel(a, b)      (*((volatile u32 *)(a)) = ((volatile u32)b))
+#else
+#define ehci_readl(x)          cpu_to_le32((*((volatile u32 *)(x))))
+#define ehci_writel(a, b)      (*((volatile u32 *)(a)) = \
+                                       cpu_to_le32(((volatile u32)b)))
+#endif
+
+#if defined CONFIG_EHCI_MMIO_BIG_ENDIAN
+#define hc32_to_cpu(x)         be32_to_cpu((x))
+#define cpu_to_hc32(x)         cpu_to_be32((x))
+#else
+#define hc32_to_cpu(x)         le32_to_cpu((x))
+#define cpu_to_hc32(x)         cpu_to_le32((x))
+#endif
+
+#define EHCI_PS_WKOC_E         (1 << 22)       /* RW wake on over current */
+#define EHCI_PS_WKDSCNNT_E     (1 << 21)       /* RW wake on disconnect */
+#define EHCI_PS_WKCNNT_E       (1 << 20)       /* RW wake on connect */
+#define EHCI_PS_PO             (1 << 13)       /* RW port owner */
+#define EHCI_PS_PP             (1 << 12)       /* RW,RO port power */
+#define EHCI_PS_LS             (3 << 10)       /* RO line status */
+#define EHCI_PS_PR             (1 << 8)        /* RW port reset */
+#define EHCI_PS_SUSP           (1 << 7)        /* RW suspend */
+#define EHCI_PS_FPR            (1 << 6)        /* RW force port resume */
+#define EHCI_PS_OCC            (1 << 5)        /* RWC over current change */
+#define EHCI_PS_OCA            (1 << 4)        /* RO over current active */
+#define EHCI_PS_PEC            (1 << 3)        /* RWC port enable change */
+#define EHCI_PS_PE             (1 << 2)        /* RW port enable */
+#define EHCI_PS_CSC            (1 << 1)        /* RWC connect status change */
+#define EHCI_PS_CS             (1 << 0)        /* RO connect status */
+#define EHCI_PS_CLEAR          (EHCI_PS_OCC | EHCI_PS_PEC | EHCI_PS_CSC)
+
+#define EHCI_PS_IS_LOWSPEED(x) (((x) & EHCI_PS_LS) == (1 << 10))
+
+/*
+ * Schedule Interface Space.
+ *
+ * IMPORTANT: Software must ensure that no interface data structure
+ * reachable by the EHCI host controller spans a 4K page boundary!
+ *
+ * Periodic transfers (i.e. isochronous and interrupt transfers) are
+ * not supported.
+ */
+
+/* Queue Element Transfer Descriptor (qTD). */
+struct qTD {
+       uint32_t qt_next;
+#define        QT_NEXT_TERMINATE       1
+       uint32_t qt_altnext;
+       uint32_t qt_token;
+       uint32_t qt_buffer[5];
+};
+
+/* Queue Head (QH). */
+struct QH {
+       uint32_t qh_link;
+#define        QH_LINK_TERMINATE       1
+#define        QH_LINK_TYPE_ITD        0
+#define        QH_LINK_TYPE_QH         2
+#define        QH_LINK_TYPE_SITD       4
+#define        QH_LINK_TYPE_FSTN       6
+       uint32_t qh_endpt1;
+       uint32_t qh_endpt2;
+       uint32_t qh_curtd;
+       struct qTD qh_overlay;
+       /*
+        * Add dummy fill value to make the size of this struct
+        * aligned to 32 bytes
+        */
+       uint8_t fill[16];
+};
+
+/* Low level init functions */
+int ehci_hcd_init(void);
+int ehci_hcd_stop(void);
+
+#endif /* USB_EHCI_H */
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
new file mode 100644 (file)
index 0000000..348e404
--- /dev/null
@@ -0,0 +1,1441 @@
+/*
+ * ISP116x HCD (Host Controller Driver) for u-boot.
+ *
+ * Copyright (C) 2006-2007 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2006-2007 Eurotech S.p.A. <info@eurotech.it>
+ *
+ * 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
+ *
+ *
+ * Derived in part from the SL811 HCD driver "u-boot/drivers/usb/sl811_usb.c"
+ * (original copyright message follows):
+ *
+ *    (C) Copyright 2004
+ *    Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ *    This code is based on linux driver for sl811hs chip, source at
+ *    drivers/usb/host/sl811.c:
+ *
+ *    SL811 Host Controller Interface driver for USB.
+ *
+ *    Copyright (c) 2003/06, Courage Co., Ltd.
+ *
+ *    Based on:
+ *         1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap,
+ *           Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber,
+ *           Adam Richter, Gregory P. Smith;
+ *         2.Original SL811 driver (hc_sl811.o) by Pei Liu <pbl@cypress.com>
+ *         3.Rewrited as sl811.o by Yin Aihua <yinah:couragetech.com.cn>
+ *
+ *    [[GNU/GPL disclaimer]]
+ *
+ * and in part from AU1x00 OHCI HCD driver "u-boot/cpu/mips/au1x00_usb_ohci.c"
+ * (original copyright message follows):
+ *
+ *    URB OHCI HCD (Host Controller Driver) for USB on the AU1x00.
+ *
+ *    (C) Copyright 2003
+ *    Gary Jennejohn, DENX Software Engineering <gj@denx.de>
+ *
+ *    [[GNU/GPL disclaimer]]
+ *
+ *    Note: Part of this code has been derived from linux
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <usb.h>
+#include <malloc.h>
+#include <linux/list.h>
+
+/*
+ * ISP116x chips require certain delays between accesses to its
+ * registers. The following timing options exist.
+ *
+ * 1. Configure your memory controller (the best)
+ * 2. Use ndelay (easiest, poorest). For that, enable the following macro.
+ *
+ * Value is in microseconds.
+ */
+#ifdef ISP116X_HCD_USE_UDELAY
+#define UDELAY         1
+#endif
+
+/*
+ * On some (slowly?) machines an extra delay after data packing into
+ * controller's FIFOs is required, * otherwise you may get the following
+ * error:
+ *
+ *   uboot> usb start
+ *   (Re)start USB...
+ *   USB:   scanning bus for devices... isp116x: isp116x_submit_job: CTL:TIMEOUT
+ *   isp116x: isp116x_submit_job: ****** FIFO not ready! ******
+ *
+ *         USB device not responding, giving up (status=4)
+ *         isp116x: isp116x_submit_job: ****** FIFO not empty! ******
+ *         isp116x: isp116x_submit_job: ****** FIFO not empty! ******
+ *         isp116x: isp116x_submit_job: ****** FIFO not empty! ******
+ *         3 USB Device(s) found
+ *                scanning bus for storage devices... 0 Storage Device(s) found
+ *
+ * Value is in milliseconds.
+ */
+#ifdef ISP116X_HCD_USE_EXTRA_DELAY
+#define EXTRA_DELAY    2
+#endif
+
+/*
+ * Enable the following defines if you wish enable debugging messages.
+ */
+#undef DEBUG                   /* enable debugging messages */
+#undef TRACE                   /* enable tracing code */
+#undef VERBOSE                 /* verbose debugging messages */
+
+#include "isp116x.h"
+
+#define DRIVER_VERSION "08 Jan 2007"
+static const char hcd_name[] = "isp116x-hcd";
+
+struct isp116x isp116x_dev;
+struct isp116x_platform_data isp116x_board;
+static int got_rhsc;           /* root hub status change */
+struct usb_device *devgone;    /* device which was disconnected */
+static int rh_devnum;          /* address of Root Hub endpoint */
+
+/* ------------------------------------------------------------------------- */
+
+#define ALIGN(x,a)     (((x)+(a)-1UL)&~((a)-1UL))
+#define min_t(type,x,y)        \
+       ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; })
+
+/* ------------------------------------------------------------------------- */
+
+static int isp116x_reset(struct isp116x *isp116x);
+
+/* --- Debugging functions ------------------------------------------------- */
+
+#define isp116x_show_reg(d, r) {                               \
+       if ((r) < 0x20) {                                       \
+               DBG("%-12s[%02x]: %08x", #r,                    \
+                       r, isp116x_read_reg32(d, r));           \
+       } else {                                                \
+               DBG("%-12s[%02x]:     %04x", #r,                \
+                       r, isp116x_read_reg16(d, r));           \
+       }                                                       \
+}
+
+#define isp116x_show_regs(d) {                                 \
+       isp116x_show_reg(d, HCREVISION);                        \
+       isp116x_show_reg(d, HCCONTROL);                         \
+       isp116x_show_reg(d, HCCMDSTAT);                         \
+       isp116x_show_reg(d, HCINTSTAT);                         \
+       isp116x_show_reg(d, HCINTENB);                          \
+       isp116x_show_reg(d, HCFMINTVL);                         \
+       isp116x_show_reg(d, HCFMREM);                           \
+       isp116x_show_reg(d, HCFMNUM);                           \
+       isp116x_show_reg(d, HCLSTHRESH);                        \
+       isp116x_show_reg(d, HCRHDESCA);                         \
+       isp116x_show_reg(d, HCRHDESCB);                         \
+       isp116x_show_reg(d, HCRHSTATUS);                        \
+       isp116x_show_reg(d, HCRHPORT1);                         \
+       isp116x_show_reg(d, HCRHPORT2);                         \
+       isp116x_show_reg(d, HCHWCFG);                           \
+       isp116x_show_reg(d, HCDMACFG);                          \
+       isp116x_show_reg(d, HCXFERCTR);                         \
+       isp116x_show_reg(d, HCuPINT);                           \
+       isp116x_show_reg(d, HCuPINTENB);                        \
+       isp116x_show_reg(d, HCCHIPID);                          \
+       isp116x_show_reg(d, HCSCRATCH);                         \
+       isp116x_show_reg(d, HCITLBUFLEN);                       \
+       isp116x_show_reg(d, HCATLBUFLEN);                       \
+       isp116x_show_reg(d, HCBUFSTAT);                         \
+       isp116x_show_reg(d, HCRDITL0LEN);                       \
+       isp116x_show_reg(d, HCRDITL1LEN);                       \
+}
+
+#if defined(TRACE)
+
+static int isp116x_get_current_frame_number(struct usb_device *usb_dev)
+{
+       struct isp116x *isp116x = &isp116x_dev;
+
+       return isp116x_read_reg32(isp116x, HCFMNUM);
+}
+
+static void dump_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                    int len, char *str)
+{
+#if defined(VERBOSE)
+       int i;
+#endif
+
+       DBG("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d stat:%#lx",
+           str,
+           isp116x_get_current_frame_number(dev),
+           usb_pipedevice(pipe),
+           usb_pipeendpoint(pipe),
+           usb_pipeout(pipe) ? 'O' : 'I',
+           usb_pipetype(pipe) < 2 ?
+           (usb_pipeint(pipe) ?
+            "INTR" : "ISOC") :
+           (usb_pipecontrol(pipe) ? "CTRL" : "BULK"), len, dev->status);
+#if defined(VERBOSE)
+       if (len > 0 && buffer) {
+               printf(__FILE__ ": data(%d):", len);
+               for (i = 0; i < 16 && i < len; i++)
+                       printf(" %02x", ((__u8 *) buffer)[i]);
+               printf("%s\n", i < len ? "..." : "");
+       }
+#endif
+}
+
+#define PTD_DIR_STR(ptd)  ({char __c;          \
+       switch(PTD_GET_DIR(ptd)){               \
+       case 0:  __c = 's'; break;              \
+       case 1:  __c = 'o'; break;              \
+       default: __c = 'i'; break;              \
+       }; __c;})
+
+/*
+  Dump PTD info. The code documents the format
+  perfectly, right :)
+*/
+static inline void dump_ptd(struct ptd *ptd)
+{
+#if defined(VERBOSE)
+       int k;
+#endif
+
+       DBG("PTD(ext) : cc:%x %d%c%d %d,%d,%d t:%x %x%x%x",
+           PTD_GET_CC(ptd),
+           PTD_GET_FA(ptd), PTD_DIR_STR(ptd), PTD_GET_EP(ptd),
+           PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd),
+           PTD_GET_TOGGLE(ptd),
+           PTD_GET_ACTIVE(ptd), PTD_GET_SPD(ptd), PTD_GET_LAST(ptd));
+#if defined(VERBOSE)
+       printf("isp116x: %s: PTD(byte): ", __FUNCTION__);
+       for (k = 0; k < sizeof(struct ptd); ++k)
+               printf("%02x ", ((u8 *) ptd)[k]);
+       printf("\n");
+#endif
+}
+
+static inline void dump_ptd_data(struct ptd *ptd, u8 * buf, int type)
+{
+#if defined(VERBOSE)
+       int k;
+
+       if (type == 0 /* 0ut data */ ) {
+               printf("isp116x: %s: out data: ", __FUNCTION__);
+               for (k = 0; k < PTD_GET_LEN(ptd); ++k)
+                       printf("%02x ", ((u8 *) buf)[k]);
+               printf("\n");
+       }
+       if (type == 1 /* 1n data */ ) {
+               printf("isp116x: %s: in data: ", __FUNCTION__);
+               for (k = 0; k < PTD_GET_COUNT(ptd); ++k)
+                       printf("%02x ", ((u8 *) buf)[k]);
+               printf("\n");
+       }
+
+       if (PTD_GET_LAST(ptd))
+               DBG("--- last PTD ---");
+#endif
+}
+
+#else
+
+#define dump_msg(dev, pipe, buffer, len, str)                  do { } while (0)
+#define dump_pkt(dev, pipe, buffer, len, setup, str, small)    do {} while (0)
+
+#define dump_ptd(ptd)                  do {} while (0)
+#define dump_ptd_data(ptd, buf, type)  do {} while (0)
+
+#endif
+
+/* --- Virtual Root Hub ---------------------------------------------------- */
+
+/* Device descriptor */
+static __u8 root_hub_dev_des[] = {
+       0x12,                   /*  __u8  bLength; */
+       0x01,                   /*  __u8  bDescriptorType; Device */
+       0x10,                   /*  __u16 bcdUSB; v1.1 */
+       0x01,
+       0x09,                   /*  __u8  bDeviceClass; HUB_CLASSCODE */
+       0x00,                   /*  __u8  bDeviceSubClass; */
+       0x00,                   /*  __u8  bDeviceProtocol; */
+       0x08,                   /*  __u8  bMaxPacketSize0; 8 Bytes */
+       0x00,                   /*  __u16 idVendor; */
+       0x00,
+       0x00,                   /*  __u16 idProduct; */
+       0x00,
+       0x00,                   /*  __u16 bcdDevice; */
+       0x00,
+       0x00,                   /*  __u8  iManufacturer; */
+       0x01,                   /*  __u8  iProduct; */
+       0x00,                   /*  __u8  iSerialNumber; */
+       0x01                    /*  __u8  bNumConfigurations; */
+};
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] = {
+       0x09,                   /*  __u8  bLength; */
+       0x02,                   /*  __u8  bDescriptorType; Configuration */
+       0x19,                   /*  __u16 wTotalLength; */
+       0x00,
+       0x01,                   /*  __u8  bNumInterfaces; */
+       0x01,                   /*  __u8  bConfigurationValue; */
+       0x00,                   /*  __u8  iConfiguration; */
+       0x40,                   /*  __u8  bmAttributes;
+                                  Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
+       0x00,                   /*  __u8  MaxPower; */
+
+       /* interface */
+       0x09,                   /*  __u8  if_bLength; */
+       0x04,                   /*  __u8  if_bDescriptorType; Interface */
+       0x00,                   /*  __u8  if_bInterfaceNumber; */
+       0x00,                   /*  __u8  if_bAlternateSetting; */
+       0x01,                   /*  __u8  if_bNumEndpoints; */
+       0x09,                   /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
+       0x00,                   /*  __u8  if_bInterfaceSubClass; */
+       0x00,                   /*  __u8  if_bInterfaceProtocol; */
+       0x00,                   /*  __u8  if_iInterface; */
+
+       /* endpoint */
+       0x07,                   /*  __u8  ep_bLength; */
+       0x05,                   /*  __u8  ep_bDescriptorType; Endpoint */
+       0x81,                   /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
+       0x03,                   /*  __u8  ep_bmAttributes; Interrupt */
+       0x00,                   /*  __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
+       0x02,
+       0xff                    /*  __u8  ep_bInterval; 255 ms */
+};
+
+static unsigned char root_hub_str_index0[] = {
+       0x04,                   /*  __u8  bLength; */
+       0x03,                   /*  __u8  bDescriptorType; String-descriptor */
+       0x09,                   /*  __u8  lang ID */
+       0x04,                   /*  __u8  lang ID */
+};
+
+static unsigned char root_hub_str_index1[] = {
+       0x22,                   /*  __u8  bLength; */
+       0x03,                   /*  __u8  bDescriptorType; String-descriptor */
+       'I',                    /*  __u8  Unicode */
+       0,                      /*  __u8  Unicode */
+       'S',                    /*  __u8  Unicode */
+       0,                      /*  __u8  Unicode */
+       'P',                    /*  __u8  Unicode */
+       0,                      /*  __u8  Unicode */
+       '1',                    /*  __u8  Unicode */
+       0,                      /*  __u8  Unicode */
+       '1',                    /*  __u8  Unicode */
+       0,                      /*  __u8  Unicode */
+       '6',                    /*  __u8  Unicode */
+       0,                      /*  __u8  Unicode */
+       'x',                    /*  __u8  Unicode */
+       0,                      /*  __u8  Unicode */
+       ' ',                    /*  __u8  Unicode */
+       0,                      /*  __u8  Unicode */
+       'R',                    /*  __u8  Unicode */
+       0,                      /*  __u8  Unicode */
+       'o',                    /*  __u8  Unicode */
+       0,                      /*  __u8  Unicode */
+       'o',                    /*  __u8  Unicode */
+       0,                      /*  __u8  Unicode */
+       't',                    /*  __u8  Unicode */
+       0,                      /*  __u8  Unicode */
+       ' ',                    /*  __u8  Unicode */
+       0,                      /*  __u8  Unicode */
+       'H',                    /*  __u8  Unicode */
+       0,                      /*  __u8  Unicode */
+       'u',                    /*  __u8  Unicode */
+       0,                      /*  __u8  Unicode */
+       'b',                    /*  __u8  Unicode */
+       0,                      /*  __u8  Unicode */
+};
+
+/*
+ * Hub class-specific descriptor is constructed dynamically
+ */
+
+/* --- Virtual root hub management functions ------------------------------- */
+
+static int rh_check_port_status(struct isp116x *isp116x)
+{
+       u32 temp, ndp, i;
+       int res;
+
+       res = -1;
+       temp = isp116x_read_reg32(isp116x, HCRHSTATUS);
+       ndp = (temp & RH_A_NDP);
+       for (i = 0; i < ndp; i++) {
+               temp = isp116x_read_reg32(isp116x, HCRHPORT1 + i);
+               /* check for a device disconnect */
+               if (((temp & (RH_PS_PESC | RH_PS_CSC)) ==
+                    (RH_PS_PESC | RH_PS_CSC)) && ((temp & RH_PS_CCS) == 0)) {
+                       res = i;
+                       break;
+               }
+       }
+       return res;
+}
+
+/* --- HC management functions --------------------------------------------- */
+
+/* Write len bytes to fifo, pad till 32-bit boundary
+ */
+static void write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, int len)
+{
+       u8 *dp = (u8 *) buf;
+       u16 *dp2 = (u16 *) buf;
+       u16 w;
+       int quot = len % 4;
+
+       if ((unsigned long)dp2 & 1) {
+               /* not aligned */
+               for (; len > 1; len -= 2) {
+                       w = *dp++;
+                       w |= *dp++ << 8;
+                       isp116x_raw_write_data16(isp116x, w);
+               }
+               if (len)
+                       isp116x_write_data16(isp116x, (u16) * dp);
+       } else {
+               /* aligned */
+               for (; len > 1; len -= 2)
+                       isp116x_raw_write_data16(isp116x, *dp2++);
+               if (len)
+                       isp116x_write_data16(isp116x, 0xff & *((u8 *) dp2));
+       }
+       if (quot == 1 || quot == 2)
+               isp116x_raw_write_data16(isp116x, 0);
+}
+
+/* Read len bytes from fifo and then read till 32-bit boundary
+ */
+static void read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, int len)
+{
+       u8 *dp = (u8 *) buf;
+       u16 *dp2 = (u16 *) buf;
+       u16 w;
+       int quot = len % 4;
+
+       if ((unsigned long)dp2 & 1) {
+               /* not aligned */
+               for (; len > 1; len -= 2) {
+                       w = isp116x_raw_read_data16(isp116x);
+                       *dp++ = w & 0xff;
+                       *dp++ = (w >> 8) & 0xff;
+               }
+               if (len)
+                       *dp = 0xff & isp116x_read_data16(isp116x);
+       } else {
+               /* aligned */
+               for (; len > 1; len -= 2)
+                       *dp2++ = isp116x_raw_read_data16(isp116x);
+               if (len)
+                       *(u8 *) dp2 = 0xff & isp116x_read_data16(isp116x);
+       }
+       if (quot == 1 || quot == 2)
+               isp116x_raw_read_data16(isp116x);
+}
+
+/* Write PTD's and data for scheduled transfers into the fifo ram.
+ * Fifo must be empty and ready */
+static void pack_fifo(struct isp116x *isp116x, struct usb_device *dev,
+                     unsigned long pipe, struct ptd *ptd, int n, void *data,
+                     int len)
+{
+       int buflen = n * sizeof(struct ptd) + len;
+       int i, done;
+
+       DBG("--- pack buffer %p - %d bytes (fifo %d) ---", data, len, buflen);
+
+       isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT);
+       isp116x_write_reg16(isp116x, HCXFERCTR, buflen);
+       isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET);
+
+       done = 0;
+       for (i = 0; i < n; i++) {
+               DBG("i=%d - done=%d - len=%d", i, done, PTD_GET_LEN(&ptd[i]));
+
+               dump_ptd(&ptd[i]);
+               isp116x_write_data16(isp116x, ptd[i].count);
+               isp116x_write_data16(isp116x, ptd[i].mps);
+               isp116x_write_data16(isp116x, ptd[i].len);
+               isp116x_write_data16(isp116x, ptd[i].faddr);
+
+               dump_ptd_data(&ptd[i], (__u8 *) data + done, 0);
+               write_ptddata_to_fifo(isp116x,
+                                     (__u8 *) data + done,
+                                     PTD_GET_LEN(&ptd[i]));
+
+               done += PTD_GET_LEN(&ptd[i]);
+       }
+}
+
+/* Read the processed PTD's and data from fifo ram back to URBs' buffers.
+ * Fifo must be full and done */
+static int unpack_fifo(struct isp116x *isp116x, struct usb_device *dev,
+                      unsigned long pipe, struct ptd *ptd, int n, void *data,
+                      int len)
+{
+       int buflen = n * sizeof(struct ptd) + len;
+       int i, done, cc, ret;
+
+       isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT);
+       isp116x_write_reg16(isp116x, HCXFERCTR, buflen);
+       isp116x_write_addr(isp116x, HCATLPORT);
+
+       ret = TD_CC_NOERROR;
+       done = 0;
+       for (i = 0; i < n; i++) {
+               DBG("i=%d - done=%d - len=%d", i, done, PTD_GET_LEN(&ptd[i]));
+
+               ptd[i].count = isp116x_read_data16(isp116x);
+               ptd[i].mps = isp116x_read_data16(isp116x);
+               ptd[i].len = isp116x_read_data16(isp116x);
+               ptd[i].faddr = isp116x_read_data16(isp116x);
+               dump_ptd(&ptd[i]);
+
+               read_ptddata_from_fifo(isp116x,
+                                      (__u8 *) data + done,
+                                      PTD_GET_LEN(&ptd[i]));
+               dump_ptd_data(&ptd[i], (__u8 *) data + done, 1);
+
+               done += PTD_GET_LEN(&ptd[i]);
+
+               cc = PTD_GET_CC(&ptd[i]);
+
+               /* Data underrun means basically that we had more buffer space than
+                * the function had data. It is perfectly normal but upper levels have
+                * to know how much we actually transferred.
+                */
+               if (cc == TD_NOTACCESSED ||
+                               (cc != TD_CC_NOERROR && (ret == TD_CC_NOERROR || ret == TD_DATAUNDERRUN)))
+                       ret = cc;
+       }
+
+       DBG("--- unpack buffer %p - %d bytes (fifo %d) ---", data, len, buflen);
+
+       return ret;
+}
+
+/* Interrupt handling
+ */
+static int isp116x_interrupt(struct isp116x *isp116x)
+{
+       u16 irqstat;
+       u32 intstat;
+       int ret = 0;
+
+       isp116x_write_reg16(isp116x, HCuPINTENB, 0);
+       irqstat = isp116x_read_reg16(isp116x, HCuPINT);
+       isp116x_write_reg16(isp116x, HCuPINT, irqstat);
+       DBG(">>>>>> irqstat %x <<<<<<", irqstat);
+
+       if (irqstat & HCuPINT_ATL) {
+               DBG(">>>>>> HCuPINT_ATL <<<<<<");
+               udelay(500);
+               ret = 1;
+       }
+
+       if (irqstat & HCuPINT_OPR) {
+               intstat = isp116x_read_reg32(isp116x, HCINTSTAT);
+               isp116x_write_reg32(isp116x, HCINTSTAT, intstat);
+               DBG(">>>>>> HCuPINT_OPR %x <<<<<<", intstat);
+
+               if (intstat & HCINT_UE) {
+                       ERR("unrecoverable error, controller disabled");
+
+                       /* FIXME: be optimistic, hope that bug won't repeat
+                        * often. Make some non-interrupt context restart the
+                        * controller. Count and limit the retries though;
+                        * either hardware or software errors can go forever...
+                        */
+                       isp116x_reset(isp116x);
+                       ret = -1;
+                       return -1;
+               }
+
+               if (intstat & HCINT_RHSC) {
+                       got_rhsc = 1;
+                       ret = 1;
+                       /* When root hub or any of its ports is going
+                          to come out of suspend, it may take more
+                          than 10ms for status bits to stabilize. */
+                       wait_ms(20);
+               }
+
+               if (intstat & HCINT_SO) {
+                       ERR("schedule overrun");
+                       ret = -1;
+               }
+
+               irqstat &= ~HCuPINT_OPR;
+       }
+
+       return ret;
+}
+
+/* With one PTD we can transfer almost 1K in one go;
+ * HC does the splitting into endpoint digestible transactions
+ */
+struct ptd ptd[1];
+
+static inline int max_transfer_len(struct usb_device *dev, unsigned long pipe)
+{
+       unsigned mpck = usb_maxpacket(dev, pipe);
+
+       /* One PTD can transfer 1023 bytes but try to always
+        * transfer multiples of endpoint buffer size
+        */
+       return 1023 / mpck * mpck;
+}
+
+/* Do an USB transfer
+ */
+static int isp116x_submit_job(struct usb_device *dev, unsigned long pipe,
+                             int dir, void *buffer, int len)
+{
+       struct isp116x *isp116x = &isp116x_dev;
+       int type = usb_pipetype(pipe);
+       int epnum = usb_pipeendpoint(pipe);
+       int max = usb_maxpacket(dev, pipe);
+       int dir_out = usb_pipeout(pipe);
+       int speed_low = usb_pipeslow(pipe);
+       int i, done = 0, stat, timeout, cc;
+
+       /* 500 frames or 0.5s timeout when function is busy and NAKs transactions for a while */
+       int retries = 500;
+
+       DBG("------------------------------------------------");
+       dump_msg(dev, pipe, buffer, len, "SUBMIT");
+       DBG("------------------------------------------------");
+
+       if (len >= 1024) {
+               ERR("Too big job");
+               dev->status = USB_ST_CRC_ERR;
+               return -1;
+       }
+
+       if (isp116x->disabled) {
+               ERR("EPIPE");
+               dev->status = USB_ST_CRC_ERR;
+               return -1;
+       }
+
+       /* device pulled? Shortcut the action. */
+       if (devgone == dev) {
+               ERR("ENODEV");
+               dev->status = USB_ST_CRC_ERR;
+               return USB_ST_CRC_ERR;
+       }
+
+       if (!max) {
+               ERR("pipesize for pipe %lx is zero", pipe);
+               dev->status = USB_ST_CRC_ERR;
+               return -1;
+       }
+
+       if (type == PIPE_ISOCHRONOUS) {
+               ERR("isochronous transfers not supported");
+               dev->status = USB_ST_CRC_ERR;
+               return -1;
+       }
+
+       /* FIFO not empty? */
+       if (isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_FULL) {
+               ERR("****** FIFO not empty! ******");
+               dev->status = USB_ST_BUF_ERR;
+               return -1;
+       }
+
+      retry:
+       isp116x_write_reg32(isp116x, HCINTSTAT, 0xff);
+
+       /* Prepare the PTD data */
+       ptd->count = PTD_CC_MSK | PTD_ACTIVE_MSK |
+               PTD_TOGGLE(usb_gettoggle(dev, epnum, dir_out));
+       ptd->mps = PTD_MPS(max) | PTD_SPD(speed_low) | PTD_EP(epnum) | PTD_LAST_MSK;
+       ptd->len = PTD_LEN(len) | PTD_DIR(dir);
+       ptd->faddr = PTD_FA(usb_pipedevice(pipe));
+
+retry_same:
+       /* Pack data into FIFO ram */
+       pack_fifo(isp116x, dev, pipe, ptd, 1, buffer, len);
+#ifdef EXTRA_DELAY
+       wait_ms(EXTRA_DELAY);
+#endif
+
+       /* Start the data transfer */
+
+       /* Allow more time for a BULK device to react - some are slow */
+       if (usb_pipebulk(pipe))
+               timeout = 5000;
+       else
+               timeout = 100;
+
+       /* Wait for it to complete */
+       for (;;) {
+               /* Check whether the controller is done */
+               stat = isp116x_interrupt(isp116x);
+
+               if (stat < 0) {
+                       dev->status = USB_ST_CRC_ERR;
+                       break;
+               }
+               if (stat > 0)
+                       break;
+
+               /* Check the timeout */
+               if (--timeout)
+                       udelay(1);
+               else {
+                       ERR("CTL:TIMEOUT ");
+                       stat = USB_ST_CRC_ERR;
+                       break;
+               }
+       }
+
+       /* We got an Root Hub Status Change interrupt */
+       if (got_rhsc) {
+               isp116x_show_regs(isp116x);
+
+               got_rhsc = 0;
+
+               /* Abuse timeout */
+               timeout = rh_check_port_status(isp116x);
+               if (timeout >= 0) {
+                       /*
+                        * FIXME! NOTE! AAAARGH!
+                        * This is potentially dangerous because it assumes
+                        * that only one device is ever plugged in!
+                        */
+                       devgone = dev;
+               }
+       }
+
+       /* Ok, now we can read transfer status */
+
+       /* FIFO not ready? */
+       if (!(isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_DONE)) {
+               ERR("****** FIFO not ready! ******");
+               dev->status = USB_ST_BUF_ERR;
+               return -1;
+       }
+
+       /* Unpack data from FIFO ram */
+       cc = unpack_fifo(isp116x, dev, pipe, ptd, 1, buffer, len);
+
+       i = PTD_GET_COUNT(ptd);
+       done += i;
+       buffer += i;
+       len -= i;
+
+       /* There was some kind of real problem; Prepare the PTD again
+        * and retry from the failed transaction on
+        */
+       if (cc && cc != TD_NOTACCESSED && cc != TD_DATAUNDERRUN) {
+               if (retries >= 100) {
+                       retries -= 100;
+                       /* The chip will have toggled the toggle bit for the failed
+                        * transaction too. We have to toggle it back.
+                        */
+                       usb_settoggle(dev, epnum, dir_out, !PTD_GET_TOGGLE(ptd));
+                       goto retry;
+               }
+       }
+       /* "Normal" errors; TD_NOTACCESSED would mean in effect that the function have NAKed
+        * the transactions from the first on for the whole frame. It may be busy and we retry
+        * with the same PTD. PTD_ACTIVE (and not TD_NOTACCESSED) would mean that some of the
+        * PTD didn't make it because the function was busy or the frame ended before the PTD
+        * finished. We prepare the rest of the data and try again.
+        */
+       else if (cc == TD_NOTACCESSED || PTD_GET_ACTIVE(ptd) || (cc != TD_DATAUNDERRUN && PTD_GET_COUNT(ptd) < PTD_GET_LEN(ptd))) {
+               if (retries) {
+                       --retries;
+                       if (cc == TD_NOTACCESSED && PTD_GET_ACTIVE(ptd) && !PTD_GET_COUNT(ptd)) goto retry_same;
+                       usb_settoggle(dev, epnum, dir_out, PTD_GET_TOGGLE(ptd));
+                       goto retry;
+               }
+       }
+
+       if (cc != TD_CC_NOERROR && cc != TD_DATAUNDERRUN) {
+               DBG("****** completition code error %x ******", cc);
+               switch (cc) {
+               case TD_CC_BITSTUFFING:
+                       dev->status = USB_ST_BIT_ERR;
+                       break;
+               case TD_CC_STALL:
+                       dev->status = USB_ST_STALLED;
+                       break;
+               case TD_BUFFEROVERRUN:
+               case TD_BUFFERUNDERRUN:
+                       dev->status = USB_ST_BUF_ERR;
+                       break;
+               default:
+                       dev->status = USB_ST_CRC_ERR;
+               }
+               return -cc;
+       }
+       else usb_settoggle(dev, epnum, dir_out, PTD_GET_TOGGLE(ptd));
+
+       dump_msg(dev, pipe, buffer, len, "SUBMIT(ret)");
+
+       dev->status = 0;
+       return done;
+}
+
+/* Adapted from au1x00_usb_ohci.c
+ */
+static int isp116x_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
+                                void *buffer, int transfer_len,
+                                struct devrequest *cmd)
+{
+       struct isp116x *isp116x = &isp116x_dev;
+       u32 tmp = 0;
+
+       int leni = transfer_len;
+       int len = 0;
+       int stat = 0;
+       u32 datab[4];
+       u8 *data_buf = (u8 *) datab;
+       u16 bmRType_bReq;
+       u16 wValue;
+       u16 wIndex;
+       u16 wLength;
+
+       if (usb_pipeint(pipe)) {
+               INFO("Root-Hub submit IRQ: NOT implemented");
+               return 0;
+       }
+
+       bmRType_bReq = cmd->requesttype | (cmd->request << 8);
+       wValue = swap_16(cmd->value);
+       wIndex = swap_16(cmd->index);
+       wLength = swap_16(cmd->length);
+
+       DBG("--- HUB ----------------------------------------");
+       DBG("submit rh urb, req=%x val=%#x index=%#x len=%d",
+           bmRType_bReq, wValue, wIndex, wLength);
+       dump_msg(dev, pipe, buffer, transfer_len, "RH");
+       DBG("------------------------------------------------");
+
+       switch (bmRType_bReq) {
+       case RH_GET_STATUS:
+               DBG("RH_GET_STATUS");
+
+               *(__u16 *) data_buf = swap_16(1);
+               len = 2;
+               break;
+
+       case RH_GET_STATUS | RH_INTERFACE:
+               DBG("RH_GET_STATUS | RH_INTERFACE");
+
+               *(__u16 *) data_buf = swap_16(0);
+               len = 2;
+               break;
+
+       case RH_GET_STATUS | RH_ENDPOINT:
+               DBG("RH_GET_STATUS | RH_ENDPOINT");
+
+               *(__u16 *) data_buf = swap_16(0);
+               len = 2;
+               break;
+
+       case RH_GET_STATUS | RH_CLASS:
+               DBG("RH_GET_STATUS | RH_CLASS");
+
+               tmp = isp116x_read_reg32(isp116x, HCRHSTATUS);
+
+               *(__u32 *) data_buf = swap_32(tmp & ~(RH_HS_CRWE | RH_HS_DRWE));
+               len = 4;
+               break;
+
+       case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+               DBG("RH_GET_STATUS | RH_OTHER | RH_CLASS");
+
+               tmp = isp116x_read_reg32(isp116x, HCRHPORT1 + wIndex - 1);
+               *(__u32 *) data_buf = swap_32(tmp);
+               isp116x_show_regs(isp116x);
+               len = 4;
+               break;
+
+       case RH_CLEAR_FEATURE | RH_ENDPOINT:
+               DBG("RH_CLEAR_FEATURE | RH_ENDPOINT");
+
+               switch (wValue) {
+               case RH_ENDPOINT_STALL:
+                       DBG("C_HUB_ENDPOINT_STALL");
+                       len = 0;
+                       break;
+               }
+               break;
+
+       case RH_CLEAR_FEATURE | RH_CLASS:
+               DBG("RH_CLEAR_FEATURE | RH_CLASS");
+
+               switch (wValue) {
+               case RH_C_HUB_LOCAL_POWER:
+                       DBG("C_HUB_LOCAL_POWER");
+                       len = 0;
+                       break;
+
+               case RH_C_HUB_OVER_CURRENT:
+                       DBG("C_HUB_OVER_CURRENT");
+                       isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_OCIC);
+                       len = 0;
+                       break;
+               }
+               break;
+
+       case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+               DBG("RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS");
+
+               switch (wValue) {
+               case RH_PORT_ENABLE:
+                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+                                           RH_PS_CCS);
+                       len = 0;
+                       break;
+
+               case RH_PORT_SUSPEND:
+                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+                                           RH_PS_POCI);
+                       len = 0;
+                       break;
+
+               case RH_PORT_POWER:
+                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+                                           RH_PS_LSDA);
+                       len = 0;
+                       break;
+
+               case RH_C_PORT_CONNECTION:
+                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+                                           RH_PS_CSC);
+                       len = 0;
+                       break;
+
+               case RH_C_PORT_ENABLE:
+                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+                                           RH_PS_PESC);
+                       len = 0;
+                       break;
+
+               case RH_C_PORT_SUSPEND:
+                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+                                           RH_PS_PSSC);
+                       len = 0;
+                       break;
+
+               case RH_C_PORT_OVER_CURRENT:
+                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+                                           RH_PS_POCI);
+                       len = 0;
+                       break;
+
+               case RH_C_PORT_RESET:
+                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+                                           RH_PS_PRSC);
+                       len = 0;
+                       break;
+
+               default:
+                       ERR("invalid wValue");
+                       stat = USB_ST_STALLED;
+               }
+
+               isp116x_show_regs(isp116x);
+
+               break;
+
+       case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+               DBG("RH_SET_FEATURE | RH_OTHER | RH_CLASS");
+
+               switch (wValue) {
+               case RH_PORT_SUSPEND:
+                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+                                           RH_PS_PSS);
+                       len = 0;
+                       break;
+
+               case RH_PORT_RESET:
+                       /* Spin until any current reset finishes */
+                       while (1) {
+                               tmp =
+                                   isp116x_read_reg32(isp116x,
+                                                      HCRHPORT1 + wIndex - 1);
+                               if (!(tmp & RH_PS_PRS))
+                                       break;
+                               wait_ms(1);
+                       }
+                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+                                           RH_PS_PRS);
+                       wait_ms(10);
+
+                       len = 0;
+                       break;
+
+               case RH_PORT_POWER:
+                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+                                           RH_PS_PPS);
+                       len = 0;
+                       break;
+
+               case RH_PORT_ENABLE:
+                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+                                           RH_PS_PES);
+                       len = 0;
+                       break;
+
+               default:
+                       ERR("invalid wValue");
+                       stat = USB_ST_STALLED;
+               }
+
+               isp116x_show_regs(isp116x);
+
+               break;
+
+       case RH_SET_ADDRESS:
+               DBG("RH_SET_ADDRESS");
+
+               rh_devnum = wValue;
+               len = 0;
+               break;
+
+       case RH_GET_DESCRIPTOR:
+               DBG("RH_GET_DESCRIPTOR: %x, %d", wValue, wLength);
+
+               switch (wValue) {
+               case (USB_DT_DEVICE << 8):      /* device descriptor */
+                       len = min_t(unsigned int,
+                                   leni, min_t(unsigned int,
+                                               sizeof(root_hub_dev_des),
+                                               wLength));
+                       data_buf = root_hub_dev_des;
+                       break;
+
+               case (USB_DT_CONFIG << 8):      /* configuration descriptor */
+                       len = min_t(unsigned int,
+                                   leni, min_t(unsigned int,
+                                               sizeof(root_hub_config_des),
+                                               wLength));
+                       data_buf = root_hub_config_des;
+                       break;
+
+               case ((USB_DT_STRING << 8) | 0x00):     /* string 0 descriptors */
+                       len = min_t(unsigned int,
+                                   leni, min_t(unsigned int,
+                                               sizeof(root_hub_str_index0),
+                                               wLength));
+                       data_buf = root_hub_str_index0;
+                       break;
+
+               case ((USB_DT_STRING << 8) | 0x01):     /* string 1 descriptors */
+                       len = min_t(unsigned int,
+                                   leni, min_t(unsigned int,
+                                               sizeof(root_hub_str_index1),
+                                               wLength));
+                       data_buf = root_hub_str_index1;
+                       break;
+
+               default:
+                       ERR("invalid wValue");
+                       stat = USB_ST_STALLED;
+               }
+
+               break;
+
+       case RH_GET_DESCRIPTOR | RH_CLASS:
+               DBG("RH_GET_DESCRIPTOR | RH_CLASS");
+
+               tmp = isp116x_read_reg32(isp116x, HCRHDESCA);
+
+               data_buf[0] = 0x09;     /* min length; */
+               data_buf[1] = 0x29;
+               data_buf[2] = tmp & RH_A_NDP;
+               data_buf[3] = 0;
+               if (tmp & RH_A_PSM)     /* per-port power switching? */
+                       data_buf[3] |= 0x01;
+               if (tmp & RH_A_NOCP)    /* no overcurrent reporting? */
+                       data_buf[3] |= 0x10;
+               else if (tmp & RH_A_OCPM)       /* per-port overcurrent rep? */
+                       data_buf[3] |= 0x08;
+
+               /* Corresponds to data_buf[4-7] */
+               datab[1] = 0;
+               data_buf[5] = (tmp & RH_A_POTPGT) >> 24;
+
+               tmp = isp116x_read_reg32(isp116x, HCRHDESCB);
+
+               data_buf[7] = tmp & RH_B_DR;
+               if (data_buf[2] < 7)
+                       data_buf[8] = 0xff;
+               else {
+                       data_buf[0] += 2;
+                       data_buf[8] = (tmp & RH_B_DR) >> 8;
+                       data_buf[10] = data_buf[9] = 0xff;
+               }
+
+               len = min_t(unsigned int, leni,
+                           min_t(unsigned int, data_buf[0], wLength));
+               break;
+
+       case RH_GET_CONFIGURATION:
+               DBG("RH_GET_CONFIGURATION");
+
+               *(__u8 *) data_buf = 0x01;
+               len = 1;
+               break;
+
+       case RH_SET_CONFIGURATION:
+               DBG("RH_SET_CONFIGURATION");
+
+               isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPSC);
+               len = 0;
+               break;
+
+       default:
+               ERR("*** *** *** unsupported root hub command *** *** ***");
+               stat = USB_ST_STALLED;
+       }
+
+       len = min_t(int, len, leni);
+       if (buffer != data_buf)
+               memcpy(buffer, data_buf, len);
+
+       dev->act_len = len;
+       dev->status = stat;
+       DBG("dev act_len %d, status %d", dev->act_len, dev->status);
+
+       dump_msg(dev, pipe, buffer, transfer_len, "RH(ret)");
+
+       return stat;
+}
+
+/* --- Transfer functions -------------------------------------------------- */
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                  int len, int interval)
+{
+       DBG("dev=%p pipe=%#lx buf=%p size=%d int=%d",
+           dev, pipe, buffer, len, interval);
+
+       return -1;
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                      int len, struct devrequest *setup)
+{
+       int devnum = usb_pipedevice(pipe);
+       int epnum = usb_pipeendpoint(pipe);
+       int max = max_transfer_len(dev, pipe);
+       int dir_in = usb_pipein(pipe);
+       int done, ret;
+
+       /* Control message is for the HUB? */
+       if (devnum == rh_devnum)
+               return isp116x_submit_rh_msg(dev, pipe, buffer, len, setup);
+
+       /* Ok, no HUB message so send the message to the device */
+
+       /* Setup phase */
+       DBG("--- SETUP PHASE --------------------------------");
+       usb_settoggle(dev, epnum, 1, 0);
+       ret = isp116x_submit_job(dev, pipe,
+                                PTD_DIR_SETUP,
+                                setup, sizeof(struct devrequest));
+       if (ret < 0) {
+               DBG("control setup phase error (ret = %d", ret);
+               return -1;
+       }
+
+       /* Data phase */
+       DBG("--- DATA PHASE ---------------------------------");
+       done = 0;
+       usb_settoggle(dev, epnum, !dir_in, 1);
+       while (done < len) {
+               ret = isp116x_submit_job(dev, pipe,
+                                        dir_in ? PTD_DIR_IN : PTD_DIR_OUT,
+                                        (__u8 *) buffer + done,
+                                        max > len - done ? len - done : max);
+               if (ret < 0) {
+                       DBG("control data phase error (ret = %d)", ret);
+                       return -1;
+               }
+               done += ret;
+
+               if (dir_in && ret < max)        /* short packet */
+                       break;
+       }
+
+       /* Status phase */
+       DBG("--- STATUS PHASE -------------------------------");
+       usb_settoggle(dev, epnum, !dir_in, 1);
+       ret = isp116x_submit_job(dev, pipe,
+                                !dir_in ? PTD_DIR_IN : PTD_DIR_OUT, NULL, 0);
+       if (ret < 0) {
+               DBG("control status phase error (ret = %d", ret);
+               return -1;
+       }
+
+       dev->act_len = done;
+
+       dump_msg(dev, pipe, buffer, len, "DEV(ret)");
+
+       return done;
+}
+
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                   int len)
+{
+       int dir_out = usb_pipeout(pipe);
+       int max = max_transfer_len(dev, pipe);
+       int done, ret;
+
+       DBG("--- BULK ---------------------------------------");
+       DBG("dev=%ld pipe=%ld buf=%p size=%d dir_out=%d",
+           usb_pipedevice(pipe), usb_pipeendpoint(pipe), buffer, len, dir_out);
+
+       done = 0;
+       while (done < len) {
+               ret = isp116x_submit_job(dev, pipe,
+                                        !dir_out ? PTD_DIR_IN : PTD_DIR_OUT,
+                                        (__u8 *) buffer + done,
+                                        max > len - done ? len - done : max);
+               if (ret < 0) {
+                       DBG("error on bulk message (ret = %d)", ret);
+                       return -1;
+               }
+
+               done += ret;
+
+               if (!dir_out && ret < max)      /* short packet */
+                       break;
+       }
+
+       dev->act_len = done;
+
+       return 0;
+}
+
+/* --- Basic functions ----------------------------------------------------- */
+
+static int isp116x_sw_reset(struct isp116x *isp116x)
+{
+       int retries = 15;
+       int ret = 0;
+
+       DBG("");
+
+       isp116x->disabled = 1;
+
+       isp116x_write_reg16(isp116x, HCSWRES, HCSWRES_MAGIC);
+       isp116x_write_reg32(isp116x, HCCMDSTAT, HCCMDSTAT_HCR);
+       while (--retries) {
+               /* It usually resets within 1 ms */
+               wait_ms(1);
+               if (!(isp116x_read_reg32(isp116x, HCCMDSTAT) & HCCMDSTAT_HCR))
+                       break;
+       }
+       if (!retries) {
+               ERR("software reset timeout");
+               ret = -1;
+       }
+       return ret;
+}
+
+static int isp116x_reset(struct isp116x *isp116x)
+{
+       unsigned long t;
+       u16 clkrdy = 0;
+       int ret, timeout = 15 /* ms */ ;
+
+       DBG("");
+
+       ret = isp116x_sw_reset(isp116x);
+       if (ret)
+               return ret;
+
+       for (t = 0; t < timeout; t++) {
+               clkrdy = isp116x_read_reg16(isp116x, HCuPINT) & HCuPINT_CLKRDY;
+               if (clkrdy)
+                       break;
+               wait_ms(1);
+       }
+       if (!clkrdy) {
+               ERR("clock not ready after %dms", timeout);
+               /* After sw_reset the clock won't report to be ready, if
+                  H_WAKEUP pin is high. */
+               ERR("please make sure that the H_WAKEUP pin is pulled low!");
+               ret = -1;
+       }
+       return ret;
+}
+
+static void isp116x_stop(struct isp116x *isp116x)
+{
+       u32 val;
+
+       DBG("");
+
+       isp116x_write_reg16(isp116x, HCuPINTENB, 0);
+
+       /* Switch off ports' power, some devices don't come up
+          after next 'start' without this */
+       val = isp116x_read_reg32(isp116x, HCRHDESCA);
+       val &= ~(RH_A_NPS | RH_A_PSM);
+       isp116x_write_reg32(isp116x, HCRHDESCA, val);
+       isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS);
+
+       isp116x_sw_reset(isp116x);
+}
+
+/*
+ *  Configure the chip. The chip must be successfully reset by now.
+ */
+static int isp116x_start(struct isp116x *isp116x)
+{
+       struct isp116x_platform_data *board = isp116x->board;
+       u32 val;
+
+       DBG("");
+
+       /* Clear interrupt status and disable all interrupt sources */
+       isp116x_write_reg16(isp116x, HCuPINT, 0xff);
+       isp116x_write_reg16(isp116x, HCuPINTENB, 0);
+
+       isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE);
+       isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE);
+
+       /* Hardware configuration */
+       val = HCHWCFG_DBWIDTH(1);
+       if (board->sel15Kres)
+               val |= HCHWCFG_15KRSEL;
+       /* Remote wakeup won't work without working clock */
+       if (board->remote_wakeup_enable)
+               val |= HCHWCFG_CLKNOTSTOP;
+       if (board->oc_enable)
+               val |= HCHWCFG_ANALOG_OC;
+       isp116x_write_reg16(isp116x, HCHWCFG, val);
+
+       /* --- Root hub configuration */
+       val = (25 << 24) & RH_A_POTPGT;
+       /* AN10003_1.pdf recommends RH_A_NPS (no power switching) to
+          be always set. Yet, instead, we request individual port
+          power switching. */
+       val |= RH_A_PSM;
+       /* Report overcurrent per port */
+       val |= RH_A_OCPM;
+       isp116x_write_reg32(isp116x, HCRHDESCA, val);
+       isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA);
+
+       val = RH_B_PPCM;
+       isp116x_write_reg32(isp116x, HCRHDESCB, val);
+       isp116x->rhdescb = isp116x_read_reg32(isp116x, HCRHDESCB);
+
+       val = 0;
+       if (board->remote_wakeup_enable)
+               val |= RH_HS_DRWE;
+       isp116x_write_reg32(isp116x, HCRHSTATUS, val);
+       isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS);
+
+       isp116x_write_reg32(isp116x, HCFMINTVL, 0x27782edf);
+
+       /* Go operational */
+       val = HCCONTROL_USB_OPER;
+       if (board->remote_wakeup_enable)
+               val |= HCCONTROL_RWE;
+       isp116x_write_reg32(isp116x, HCCONTROL, val);
+
+       /* Disable ports to avoid race in device enumeration */
+       isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS);
+       isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS);
+
+       isp116x_show_regs(isp116x);
+
+       isp116x->disabled = 0;
+
+       return 0;
+}
+
+/* --- Init functions ------------------------------------------------------ */
+
+int isp116x_check_id(struct isp116x *isp116x)
+{
+       int val;
+
+       val = isp116x_read_reg16(isp116x, HCCHIPID);
+       if ((val & HCCHIPID_MASK) != HCCHIPID_MAGIC) {
+               ERR("invalid chip ID %04x", val);
+               return -1;
+       }
+
+       return 0;
+}
+
+int usb_lowlevel_init(void)
+{
+       struct isp116x *isp116x = &isp116x_dev;
+
+       DBG("");
+
+       got_rhsc = rh_devnum = 0;
+
+       /* Init device registers addr */
+       isp116x->addr_reg = (u16 *) ISP116X_HCD_ADDR;
+       isp116x->data_reg = (u16 *) ISP116X_HCD_DATA;
+
+       /* Setup specific board settings */
+#ifdef ISP116X_HCD_SEL15kRES
+       isp116x_board.sel15Kres = 1;
+#endif
+#ifdef ISP116X_HCD_OC_ENABLE
+       isp116x_board.oc_enable = 1;
+#endif
+#ifdef ISP116X_HCD_REMOTE_WAKEUP_ENABLE
+       isp116x_board.remote_wakeup_enable = 1;
+#endif
+       isp116x->board = &isp116x_board;
+
+       /* Try to get ISP116x silicon chip ID */
+       if (isp116x_check_id(isp116x) < 0)
+               return -1;
+
+       isp116x->disabled = 1;
+       isp116x->sleeping = 0;
+
+       isp116x_reset(isp116x);
+       isp116x_start(isp116x);
+
+       return 0;
+}
+
+int usb_lowlevel_stop(void)
+{
+       struct isp116x *isp116x = &isp116x_dev;
+
+       DBG("");
+
+       if (!isp116x->disabled)
+               isp116x_stop(isp116x);
+
+       return 0;
+}
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h
new file mode 100644 (file)
index 0000000..a3ce3b5
--- /dev/null
@@ -0,0 +1,489 @@
+/*
+ * ISP116x register declarations and HCD data structures
+ *
+ * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
+ * Copyright (C) 2005 Olav Kongas <ok@artecdesign.ee>
+ * Portions:
+ * Copyright (C) 2004 Lothar Wassmann
+ * Copyright (C) 2004 Psion Teklogix
+ * Copyright (C) 2004 David Brownell
+ *
+ * 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
+ */
+
+#ifdef DEBUG
+#define DBG(fmt, args...)      \
+               printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args)
+#else
+#define DBG(fmt, args...)      do {} while (0)
+#endif
+
+#ifdef VERBOSE
+#    define VDBG               DBG
+#else
+#    define VDBG(fmt, args...) do {} while (0)
+#endif
+
+#define ERR(fmt, args...)      \
+               printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args)
+#define WARN(fmt, args...)     \
+               printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args)
+#define INFO(fmt, args...)     \
+               printf("isp116x: " fmt "\n" , ## args)
+
+/* ------------------------------------------------------------------------- */
+
+/* us of 1ms frame */
+#define  MAX_LOAD_LIMIT                850
+
+/* Full speed: max # of bytes to transfer for a single urb
+   at a time must be < 1024 && must be multiple of 64.
+   832 allows transfering 4kiB within 5 frames. */
+#define MAX_TRANSFER_SIZE_FULLSPEED    832
+
+/* Low speed: there is no reason to schedule in very big
+   chunks; often the requested long transfers are for
+   string descriptors containing short strings. */
+#define MAX_TRANSFER_SIZE_LOWSPEED     64
+
+/* Bytetime (us), a rough indication of how much time it
+   would take to transfer a byte of useful data over USB */
+#define BYTE_TIME_FULLSPEED    1
+#define BYTE_TIME_LOWSPEED     20
+
+/* Buffer sizes */
+#define ISP116x_BUF_SIZE       4096
+#define ISP116x_ITL_BUFSIZE    0
+#define ISP116x_ATL_BUFSIZE    ((ISP116x_BUF_SIZE) - 2*(ISP116x_ITL_BUFSIZE))
+
+#define ISP116x_WRITE_OFFSET   0x80
+
+/* --- ISP116x registers/bits ---------------------------------------------- */
+
+#define        HCREVISION      0x00
+#define        HCCONTROL       0x01
+#define                HCCONTROL_HCFS  (3 << 6)        /* host controller
+                                                  functional state */
+#define                HCCONTROL_USB_RESET     (0 << 6)
+#define                HCCONTROL_USB_RESUME    (1 << 6)
+#define                HCCONTROL_USB_OPER      (2 << 6)
+#define                HCCONTROL_USB_SUSPEND   (3 << 6)
+#define                HCCONTROL_RWC   (1 << 9)        /* remote wakeup connected */
+#define                HCCONTROL_RWE   (1 << 10)       /* remote wakeup enable */
+#define        HCCMDSTAT       0x02
+#define                HCCMDSTAT_HCR   (1 << 0)        /* host controller reset */
+#define                HCCMDSTAT_SOC   (3 << 16)       /* scheduling overrun count */
+#define        HCINTSTAT       0x03
+#define                HCINT_SO        (1 << 0)        /* scheduling overrun */
+#define                HCINT_WDH       (1 << 1)        /* writeback of done_head */
+#define                HCINT_SF        (1 << 2)        /* start frame */
+#define                HCINT_RD        (1 << 3)        /* resume detect */
+#define                HCINT_UE        (1 << 4)        /* unrecoverable error */
+#define                HCINT_FNO       (1 << 5)        /* frame number overflow */
+#define                HCINT_RHSC      (1 << 6)        /* root hub status change */
+#define                HCINT_OC        (1 << 30)       /* ownership change */
+#define                HCINT_MIE       (1 << 31)       /* master interrupt enable */
+#define        HCINTENB        0x04
+#define        HCINTDIS        0x05
+#define        HCFMINTVL       0x0d
+#define        HCFMREM         0x0e
+#define        HCFMNUM         0x0f
+#define        HCLSTHRESH      0x11
+#define        HCRHDESCA       0x12
+#define                RH_A_NDP        (0x3 << 0)      /* # downstream ports */
+#define                RH_A_PSM        (1 << 8)        /* power switching mode */
+#define                RH_A_NPS        (1 << 9)        /* no power switching */
+#define                RH_A_DT         (1 << 10)       /* device type (mbz) */
+#define                RH_A_OCPM       (1 << 11)       /* overcurrent protection
+                                                  mode */
+#define                RH_A_NOCP       (1 << 12)       /* no overcurrent protection */
+#define                RH_A_POTPGT     (0xff << 24)    /* power on -> power good
+                                                  time */
+#define        HCRHDESCB       0x13
+#define                RH_B_DR         (0xffff << 0)   /* device removable flags */
+#define                RH_B_PPCM       (0xffff << 16)  /* port power control mask */
+#define        HCRHSTATUS      0x14
+#define                RH_HS_LPS       (1 << 0)        /* local power status */
+#define                RH_HS_OCI       (1 << 1)        /* over current indicator */
+#define                RH_HS_DRWE      (1 << 15)       /* device remote wakeup
+                                                  enable */
+#define                RH_HS_LPSC      (1 << 16)       /* local power status change */
+#define                RH_HS_OCIC      (1 << 17)       /* over current indicator
+                                                  change */
+#define                RH_HS_CRWE      (1 << 31)       /* clear remote wakeup
+                                                  enable */
+#define        HCRHPORT1       0x15
+#define                RH_PS_CCS       (1 << 0)        /* current connect status */
+#define                RH_PS_PES       (1 << 1)        /* port enable status */
+#define                RH_PS_PSS       (1 << 2)        /* port suspend status */
+#define                RH_PS_POCI      (1 << 3)        /* port over current
+                                                  indicator */
+#define                RH_PS_PRS       (1 << 4)        /* port reset status */
+#define                RH_PS_PPS       (1 << 8)        /* port power status */
+#define                RH_PS_LSDA      (1 << 9)        /* low speed device attached */
+#define                RH_PS_CSC       (1 << 16)       /* connect status change */
+#define                RH_PS_PESC      (1 << 17)       /* port enable status change */
+#define                RH_PS_PSSC      (1 << 18)       /* port suspend status
+                                                  change */
+#define                RH_PS_OCIC      (1 << 19)       /* over current indicator
+                                                  change */
+#define                RH_PS_PRSC      (1 << 20)       /* port reset status change */
+#define                HCRHPORT_CLRMASK        (0x1f << 16)
+#define        HCRHPORT2       0x16
+#define        HCHWCFG         0x20
+#define                HCHWCFG_15KRSEL         (1 << 12)
+#define                HCHWCFG_CLKNOTSTOP      (1 << 11)
+#define                HCHWCFG_ANALOG_OC       (1 << 10)
+#define                HCHWCFG_DACK_MODE       (1 << 8)
+#define                HCHWCFG_EOT_POL         (1 << 7)
+#define                HCHWCFG_DACK_POL        (1 << 6)
+#define                HCHWCFG_DREQ_POL        (1 << 5)
+#define                HCHWCFG_DBWIDTH_MASK    (0x03 << 3)
+#define                HCHWCFG_DBWIDTH(n)      (((n) << 3) & HCHWCFG_DBWIDTH_MASK)
+#define                HCHWCFG_INT_POL         (1 << 2)
+#define                HCHWCFG_INT_TRIGGER     (1 << 1)
+#define                HCHWCFG_INT_ENABLE      (1 << 0)
+#define        HCDMACFG        0x21
+#define                HCDMACFG_BURST_LEN_MASK (0x03 << 5)
+#define                HCDMACFG_BURST_LEN(n)   (((n) << 5) & HCDMACFG_BURST_LEN_MASK)
+#define                HCDMACFG_BURST_LEN_1    HCDMACFG_BURST_LEN(0)
+#define                HCDMACFG_BURST_LEN_4    HCDMACFG_BURST_LEN(1)
+#define                HCDMACFG_BURST_LEN_8    HCDMACFG_BURST_LEN(2)
+#define                HCDMACFG_DMA_ENABLE     (1 << 4)
+#define                HCDMACFG_BUF_TYPE_MASK  (0x07 << 1)
+#define                HCDMACFG_CTR_SEL        (1 << 2)
+#define                HCDMACFG_ITLATL_SEL     (1 << 1)
+#define                HCDMACFG_DMA_RW_SELECT  (1 << 0)
+#define        HCXFERCTR       0x22
+#define        HCuPINT         0x24
+#define                HCuPINT_SOF             (1 << 0)
+#define                HCuPINT_ATL             (1 << 1)
+#define                HCuPINT_AIIEOT          (1 << 2)
+#define                HCuPINT_OPR             (1 << 4)
+#define                HCuPINT_SUSP            (1 << 5)
+#define                HCuPINT_CLKRDY          (1 << 6)
+#define        HCuPINTENB      0x25
+#define        HCCHIPID        0x27
+#define                HCCHIPID_MASK           0xff00
+#define                HCCHIPID_MAGIC          0x6100
+#define        HCSCRATCH       0x28
+#define        HCSWRES         0x29
+#define                HCSWRES_MAGIC           0x00f6
+#define        HCITLBUFLEN     0x2a
+#define        HCATLBUFLEN     0x2b
+#define        HCBUFSTAT       0x2c
+#define                HCBUFSTAT_ITL0_FULL     (1 << 0)
+#define                HCBUFSTAT_ITL1_FULL     (1 << 1)
+#define                HCBUFSTAT_ATL_FULL      (1 << 2)
+#define                HCBUFSTAT_ITL0_DONE     (1 << 3)
+#define                HCBUFSTAT_ITL1_DONE     (1 << 4)
+#define                HCBUFSTAT_ATL_DONE      (1 << 5)
+#define        HCRDITL0LEN     0x2d
+#define        HCRDITL1LEN     0x2e
+#define        HCITLPORT       0x40
+#define        HCATLPORT       0x41
+
+/* PTD accessor macros. */
+#define PTD_GET_COUNT(p)       (((p)->count & PTD_COUNT_MSK) >> 0)
+#define PTD_COUNT(v)           (((v) << 0) & PTD_COUNT_MSK)
+#define PTD_GET_TOGGLE(p)      (((p)->count & PTD_TOGGLE_MSK) >> 10)
+#define PTD_TOGGLE(v)          (((v) << 10) & PTD_TOGGLE_MSK)
+#define PTD_GET_ACTIVE(p)      (((p)->count & PTD_ACTIVE_MSK) >> 11)
+#define PTD_ACTIVE(v)          (((v) << 11) & PTD_ACTIVE_MSK)
+#define PTD_GET_CC(p)          (((p)->count & PTD_CC_MSK) >> 12)
+#define PTD_CC(v)              (((v) << 12) & PTD_CC_MSK)
+#define PTD_GET_MPS(p)         (((p)->mps & PTD_MPS_MSK) >> 0)
+#define PTD_MPS(v)             (((v) << 0) & PTD_MPS_MSK)
+#define PTD_GET_SPD(p)         (((p)->mps & PTD_SPD_MSK) >> 10)
+#define PTD_SPD(v)             (((v) << 10) & PTD_SPD_MSK)
+#define PTD_GET_LAST(p)                (((p)->mps & PTD_LAST_MSK) >> 11)
+#define PTD_LAST(v)            (((v) << 11) & PTD_LAST_MSK)
+#define PTD_GET_EP(p)          (((p)->mps & PTD_EP_MSK) >> 12)
+#define PTD_EP(v)              (((v) << 12) & PTD_EP_MSK)
+#define PTD_GET_LEN(p)         (((p)->len & PTD_LEN_MSK) >> 0)
+#define PTD_LEN(v)             (((v) << 0) & PTD_LEN_MSK)
+#define PTD_GET_DIR(p)         (((p)->len & PTD_DIR_MSK) >> 10)
+#define PTD_DIR(v)             (((v) << 10) & PTD_DIR_MSK)
+#define PTD_GET_B5_5(p)                (((p)->len & PTD_B5_5_MSK) >> 13)
+#define PTD_B5_5(v)            (((v) << 13) & PTD_B5_5_MSK)
+#define PTD_GET_FA(p)          (((p)->faddr & PTD_FA_MSK) >> 0)
+#define PTD_FA(v)              (((v) << 0) & PTD_FA_MSK)
+#define PTD_GET_FMT(p)         (((p)->faddr & PTD_FMT_MSK) >> 7)
+#define PTD_FMT(v)             (((v) << 7) & PTD_FMT_MSK)
+
+/*  Hardware transfer status codes -- CC from ptd->count */
+#define TD_CC_NOERROR      0x00
+#define TD_CC_CRC          0x01
+#define TD_CC_BITSTUFFING  0x02
+#define TD_CC_DATATOGGLEM  0x03
+#define TD_CC_STALL        0x04
+#define TD_DEVNOTRESP      0x05
+#define TD_PIDCHECKFAIL    0x06
+#define TD_UNEXPECTEDPID   0x07
+#define TD_DATAOVERRUN     0x08
+#define TD_DATAUNDERRUN    0x09
+    /* 0x0A, 0x0B reserved for hardware */
+#define TD_BUFFEROVERRUN   0x0C
+#define TD_BUFFERUNDERRUN  0x0D
+    /* 0x0E, 0x0F reserved for HCD */
+#define TD_NOTACCESSED     0x0F
+
+/* ------------------------------------------------------------------------- */
+
+#define        LOG2_PERIODIC_SIZE      5       /* arbitrary; this matches OHCI */
+#define        PERIODIC_SIZE           (1 << LOG2_PERIODIC_SIZE)
+
+/* Philips transfer descriptor */
+struct ptd {
+       u16 count;
+#define        PTD_COUNT_MSK   (0x3ff << 0)
+#define        PTD_TOGGLE_MSK  (1 << 10)
+#define        PTD_ACTIVE_MSK  (1 << 11)
+#define        PTD_CC_MSK      (0xf << 12)
+       u16 mps;
+#define        PTD_MPS_MSK     (0x3ff << 0)
+#define        PTD_SPD_MSK     (1 << 10)
+#define        PTD_LAST_MSK    (1 << 11)
+#define        PTD_EP_MSK      (0xf << 12)
+       u16 len;
+#define        PTD_LEN_MSK     (0x3ff << 0)
+#define        PTD_DIR_MSK     (3 << 10)
+#define        PTD_DIR_SETUP   (0)
+#define        PTD_DIR_OUT     (1)
+#define        PTD_DIR_IN      (2)
+#define        PTD_B5_5_MSK    (1 << 13)
+       u16 faddr;
+#define        PTD_FA_MSK      (0x7f << 0)
+#define        PTD_FMT_MSK     (1 << 7)
+} __attribute__ ((packed, aligned(2)));
+
+struct isp116x_ep {
+       struct usb_device *udev;
+       struct ptd ptd;
+
+       u8 maxpacket;
+       u8 epnum;
+       u8 nextpid;
+
+       u16 length;             /* of current packet */
+       unsigned char *data;    /* to databuf */
+
+       u16 error_count;
+};
+
+/* URB struct */
+#define N_URB_TD               48
+#define URB_DEL                        1
+typedef struct {
+       struct isp116x_ep *ed;
+       void *transfer_buffer;  /* (in) associated data buffer */
+       int actual_length;      /* (return) actual transfer length */
+       unsigned long pipe;     /* (in) pipe information */
+#if 0
+       int state;
+#endif
+} urb_priv_t;
+
+struct isp116x_platform_data {
+       /* Enable internal resistors on downstream ports */
+       unsigned sel15Kres:1;
+       /* On-chip overcurrent detection */
+       unsigned oc_enable:1;
+       /* Enable wakeup by devices on usb bus (e.g. wakeup
+          by attachment/detachment or by device activity
+          such as moving a mouse). When chosen, this option
+          prevents stopping internal clock, increasing
+          thereby power consumption in suspended state. */
+       unsigned remote_wakeup_enable:1;
+};
+
+struct isp116x {
+       u16 *addr_reg;
+       u16 *data_reg;
+
+       struct isp116x_platform_data *board;
+
+       struct dentry *dentry;
+       unsigned long stat1, stat2, stat4, stat8, stat16;
+
+       /* Status flags */
+       unsigned disabled:1;
+       unsigned sleeping:1;
+
+       /* Root hub registers */
+       u32 rhdesca;
+       u32 rhdescb;
+       u32 rhstatus;
+       u32 rhport[2];
+
+       /* Schedule for the current frame */
+       struct isp116x_ep *atl_active;
+       int atl_buflen;
+       int atl_bufshrt;
+       int atl_last_dir;
+       int atl_finishing;
+};
+
+/* ------------------------------------------------- */
+
+/* Inter-io delay (ns). The chip is picky about access timings; it
+ * expects at least:
+ * 150ns delay between consecutive accesses to DATA_REG,
+ * 300ns delay between access to ADDR_REG and DATA_REG
+ * OE, WE MUST NOT be changed during these intervals
+ */
+#if defined(UDELAY)
+#define        isp116x_delay(h,d)      udelay(d)
+#else
+#define        isp116x_delay(h,d)      do {} while (0)
+#endif
+
+static inline void isp116x_write_addr(struct isp116x *isp116x, unsigned reg)
+{
+       writew(reg & 0xff, isp116x->addr_reg);
+       isp116x_delay(isp116x, UDELAY);
+}
+
+static inline void isp116x_write_data16(struct isp116x *isp116x, u16 val)
+{
+       writew(val, isp116x->data_reg);
+       isp116x_delay(isp116x, UDELAY);
+}
+
+static inline void isp116x_raw_write_data16(struct isp116x *isp116x, u16 val)
+{
+       __raw_writew(val, isp116x->data_reg);
+       isp116x_delay(isp116x, UDELAY);
+}
+
+static inline u16 isp116x_read_data16(struct isp116x *isp116x)
+{
+       u16 val;
+
+       val = readw(isp116x->data_reg);
+       isp116x_delay(isp116x, UDELAY);
+       return val;
+}
+
+static inline u16 isp116x_raw_read_data16(struct isp116x *isp116x)
+{
+       u16 val;
+
+       val = __raw_readw(isp116x->data_reg);
+       isp116x_delay(isp116x, UDELAY);
+       return val;
+}
+
+static inline void isp116x_write_data32(struct isp116x *isp116x, u32 val)
+{
+       writew(val & 0xffff, isp116x->data_reg);
+       isp116x_delay(isp116x, UDELAY);
+       writew(val >> 16, isp116x->data_reg);
+       isp116x_delay(isp116x, UDELAY);
+}
+
+static inline u32 isp116x_read_data32(struct isp116x *isp116x)
+{
+       u32 val;
+
+       val = (u32) readw(isp116x->data_reg);
+       isp116x_delay(isp116x, UDELAY);
+       val |= ((u32) readw(isp116x->data_reg)) << 16;
+       isp116x_delay(isp116x, UDELAY);
+       return val;
+}
+
+/* Let's keep register access functions out of line. Hint:
+   we wait at least 150 ns at every access.
+*/
+static u16 isp116x_read_reg16(struct isp116x *isp116x, unsigned reg)
+{
+       isp116x_write_addr(isp116x, reg);
+       return isp116x_read_data16(isp116x);
+}
+
+static u32 isp116x_read_reg32(struct isp116x *isp116x, unsigned reg)
+{
+       isp116x_write_addr(isp116x, reg);
+       return isp116x_read_data32(isp116x);
+}
+
+static void isp116x_write_reg16(struct isp116x *isp116x, unsigned reg,
+                               unsigned val)
+{
+       isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET);
+       isp116x_write_data16(isp116x, (u16) (val & 0xffff));
+}
+
+static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg,
+                               unsigned val)
+{
+       isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET);
+       isp116x_write_data32(isp116x, (u32) val);
+}
+
+/* --- USB HUB constants (not OHCI-specific; see hub.h) -------------------- */
+
+/* destination of request */
+#define RH_INTERFACE               0x01
+#define RH_ENDPOINT                0x02
+#define RH_OTHER                   0x03
+
+#define RH_CLASS                   0x20
+#define RH_VENDOR                  0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS           0x0080
+#define RH_CLEAR_FEATURE        0x0100
+#define RH_SET_FEATURE          0x0300
+#define RH_SET_ADDRESS          0x0500
+#define RH_GET_DESCRIPTOR       0x0680
+#define RH_SET_DESCRIPTOR       0x0700
+#define RH_GET_CONFIGURATION    0x0880
+#define RH_SET_CONFIGURATION    0x0900
+#define RH_GET_STATE            0x0280
+#define RH_GET_INTERFACE        0x0A80
+#define RH_SET_INTERFACE        0x0B00
+#define RH_SYNC_FRAME           0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP               0x2000
+
+/* Hub port features */
+#define RH_PORT_CONNECTION         0x00
+#define RH_PORT_ENABLE             0x01
+#define RH_PORT_SUSPEND            0x02
+#define RH_PORT_OVER_CURRENT       0x03
+#define RH_PORT_RESET              0x04
+#define RH_PORT_POWER              0x08
+#define RH_PORT_LOW_SPEED          0x09
+
+#define RH_C_PORT_CONNECTION       0x10
+#define RH_C_PORT_ENABLE           0x11
+#define RH_C_PORT_SUSPEND          0x12
+#define RH_C_PORT_OVER_CURRENT     0x13
+#define RH_C_PORT_RESET            0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER       0x00
+#define RH_C_HUB_OVER_CURRENT      0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP    0x00
+#define RH_ENDPOINT_STALL          0x01
+
+#define RH_ACK                     0x01
+#define RH_REQ_ERR                 -1
+#define RH_NACK                    0x00
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
new file mode 100644 (file)
index 0000000..7c44ad0
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * (C) Copyright 2006
+ * DENX Software Engineering <mk@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>
+
+#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT)
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/io.h>
+#include <asm/arch/at91_pmc.h>
+
+int usb_cpu_init(void)
+{
+
+#if defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \
+    defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91SAM9G20)
+       /* Enable PLLB */
+       at91_sys_write(AT91_CKGR_PLLBR, CONFIG_SYS_AT91_PLLB);
+       while ((at91_sys_read(AT91_PMC_SR) & AT91_PMC_LOCKB) != AT91_PMC_LOCKB)
+               ;
+#endif
+
+       /* Enable USB host clock. */
+       at91_sys_write(AT91_PMC_PCER, 1 << AT91_ID_UHP);
+#ifdef CONFIG_AT91SAM9261
+       at91_sys_write(AT91_PMC_SCER, AT91_PMC_UHP | AT91_PMC_HCK0);
+#else
+       at91_sys_write(AT91_PMC_SCER, AT91_PMC_UHP);
+#endif
+
+       return 0;
+}
+
+int usb_cpu_stop(void)
+{
+       /* Disable USB host clock. */
+       at91_sys_write(AT91_PMC_PCDR, 1 << AT91_ID_UHP);
+#ifdef CONFIG_AT91SAM9261
+       at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP | AT91_PMC_HCK0);
+#else
+       at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP);
+#endif
+
+#if defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \
+    defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91SAM9G20)
+       /* Disable PLLB */
+       at91_sys_write(AT91_CKGR_PLLBR, 0);
+       while ((at91_sys_read(AT91_PMC_SR) & AT91_PMC_LOCKB) != 0)
+               ;
+#endif
+
+       return 0;
+}
+
+int usb_cpu_init_fail(void)
+{
+       return usb_cpu_stop();
+}
+
+#endif /* defined(CONFIG_USB_OHCI) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) */
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
new file mode 100644 (file)
index 0000000..e2f289e
--- /dev/null
@@ -0,0 +1,2016 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB on the AT91RM9200 and PCI bus.
+ *
+ * Interrupt support is added. Now, it has been tested
+ * on ULI1575 chip and works well with USB keyboard.
+ *
+ * (C) Copyright 2007
+ * Zhang Wei, Freescale Semiconductor, Inc. <wei.zhang@freescale.com>
+ *
+ * (C) Copyright 2003
+ * Gary Jennejohn, DENX Software Engineering <gj@denx.de>
+ *
+ * Note: Much of this code has been derived from Linux 2.4
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell
+ *
+ * Modified for the MP2USB by (C) Copyright 2005 Eric Benard
+ * ebenard@eukrea.com - based on s3c24x0's driver
+ *
+ * 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
+ *
+ */
+/*
+ * IMPORTANT NOTES
+ * 1 - Read doc/README.generic_usb_ohci
+ * 2 - this driver is intended for use with USB Mass Storage Devices
+ *     (BBB) and USB keyboard. There is NO support for Isochronous pipes!
+ * 2 - when running on a PQFP208 AT91RM9200, define CONFIG_AT91C_PQFP_UHPBUG
+ *     to activate workaround for bug #41 or this driver will NOT work!
+ */
+
+#include <common.h>
+#include <asm/byteorder.h>
+
+#if defined(CONFIG_PCI_OHCI)
+# include <pci.h>
+#if !defined(CONFIG_PCI_OHCI_DEVNO)
+#define CONFIG_PCI_OHCI_DEVNO  0
+#endif
+#endif
+
+#include <malloc.h>
+#include <usb.h>
+
+#include "ohci.h"
+
+#ifdef CONFIG_AT91RM9200
+#include <asm/arch/hardware.h> /* needed for AT91_USB_HOST_BASE */
+#endif
+
+#if defined(CONFIG_ARM920T) || \
+    defined(CONFIG_S3C2400) || \
+    defined(CONFIG_S3C2410) || \
+    defined(CONFIG_S3C6400) || \
+    defined(CONFIG_440EP) || \
+    defined(CONFIG_PCI_OHCI) || \
+    defined(CONFIG_MPC5200) || \
+    defined(CONFIG_SYS_OHCI_USE_NPS)
+# define OHCI_USE_NPS          /* force NoPowerSwitching mode */
+#endif
+
+#undef OHCI_VERBOSE_DEBUG      /* not always helpful */
+#undef DEBUG
+#undef SHOW_INFO
+#undef OHCI_FILL_TRACE
+
+/* For initializing controller (mask in an HCFS mode too) */
+#define OHCI_CONTROL_INIT \
+       (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
+
+/*
+ * e.g. PCI controllers need this
+ */
+#ifdef CONFIG_SYS_OHCI_SWAP_REG_ACCESS
+# define readl(a) __swap_32(*((volatile u32 *)(a)))
+# define writel(a, b) (*((volatile u32 *)(b)) = __swap_32((volatile u32)a))
+#else
+# define readl(a) (*((volatile u32 *)(a)))
+# define writel(a, b) (*((volatile u32 *)(b)) = ((volatile u32)a))
+#endif /* CONFIG_SYS_OHCI_SWAP_REG_ACCESS */
+
+#define min_t(type, x, y) \
+                   ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+
+#ifdef CONFIG_PCI_OHCI
+static struct pci_device_id ohci_pci_ids[] = {
+       {0x10b9, 0x5237},       /* ULI1575 PCI OHCI module ids */
+       {0x1033, 0x0035},       /* NEC PCI OHCI module ids */
+       {0x1131, 0x1561},       /* Philips 1561 PCI OHCI module ids */
+       /* Please add supported PCI OHCI controller ids here */
+       {0, 0}
+};
+#endif
+
+#ifdef CONFIG_PCI_EHCI_DEVNO
+static struct pci_device_id ehci_pci_ids[] = {
+       {0x1131, 0x1562},       /* Philips 1562 PCI EHCI module ids */
+       /* Please add supported PCI EHCI controller ids here */
+       {0, 0}
+};
+#endif
+
+#ifdef DEBUG
+#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg)
+#else
+#define dbg(format, arg...) do {} while (0)
+#endif /* DEBUG */
+#define err(format, arg...) printf("ERROR: " format "\n", ## arg)
+#ifdef SHOW_INFO
+#define info(format, arg...) printf("INFO: " format "\n", ## arg)
+#else
+#define info(format, arg...) do {} while (0)
+#endif
+
+#ifdef CONFIG_SYS_OHCI_BE_CONTROLLER
+# define m16_swap(x) cpu_to_be16(x)
+# define m32_swap(x) cpu_to_be32(x)
+#else
+# define m16_swap(x) cpu_to_le16(x)
+# define m32_swap(x) cpu_to_le32(x)
+#endif /* CONFIG_SYS_OHCI_BE_CONTROLLER */
+
+/* global ohci_t */
+static ohci_t gohci;
+/* this must be aligned to a 256 byte boundary */
+struct ohci_hcca ghcca[1];
+/* a pointer to the aligned storage */
+struct ohci_hcca *phcca;
+/* this allocates EDs for all possible endpoints */
+struct ohci_device ohci_dev;
+/* device which was disconnected */
+struct usb_device *devgone;
+
+static inline u32 roothub_a(struct ohci *hc)
+       { return readl(&hc->regs->roothub.a); }
+static inline u32 roothub_b(struct ohci *hc)
+       { return readl(&hc->regs->roothub.b); }
+static inline u32 roothub_status(struct ohci *hc)
+       { return readl(&hc->regs->roothub.status); }
+static inline u32 roothub_portstatus(struct ohci *hc, int i)
+       { return readl(&hc->regs->roothub.portstatus[i]); }
+
+/* forward declaration */
+static int hc_interrupt(void);
+static void td_submit_job(struct usb_device *dev, unsigned long pipe,
+                         void *buffer, int transfer_len,
+                         struct devrequest *setup, urb_priv_t *urb,
+                         int interval);
+
+/*-------------------------------------------------------------------------*
+ * URB support functions
+ *-------------------------------------------------------------------------*/
+
+/* free HCD-private data associated with this URB */
+
+static void urb_free_priv(urb_priv_t *urb)
+{
+       int             i;
+       int             last;
+       struct td       *td;
+
+       last = urb->length - 1;
+       if (last >= 0) {
+               for (i = 0; i <= last; i++) {
+                       td = urb->td[i];
+                       if (td) {
+                               td->usb_dev = NULL;
+                               urb->td[i] = NULL;
+                       }
+               }
+       }
+       free(urb);
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+static int sohci_get_current_frame_number(struct usb_device *dev);
+
+/* debug| print the main components of an URB
+ * small: 0) header + data packets 1) just header */
+
+static void pkt_print(urb_priv_t *purb, struct usb_device *dev,
+                     unsigned long pipe, void *buffer, int transfer_len,
+                     struct devrequest *setup, char *str, int small)
+{
+       dbg("%s URB:[%4x] dev:%2lu,ep:%2lu-%c,type:%s,len:%d/%d stat:%#lx",
+                       str,
+                       sohci_get_current_frame_number(dev),
+                       usb_pipedevice(pipe),
+                       usb_pipeendpoint(pipe),
+                       usb_pipeout(pipe)? 'O': 'I',
+                       usb_pipetype(pipe) < 2 ? \
+                               (usb_pipeint(pipe)? "INTR": "ISOC"): \
+                               (usb_pipecontrol(pipe)? "CTRL": "BULK"),
+                       (purb ? purb->actual_length : 0),
+                       transfer_len, dev->status);
+#ifdef OHCI_VERBOSE_DEBUG
+       if (!small) {
+               int i, len;
+
+               if (usb_pipecontrol(pipe)) {
+                       printf(__FILE__ ": cmd(8):");
+                       for (i = 0; i < 8 ; i++)
+                               printf(" %02x", ((__u8 *) setup) [i]);
+                       printf("\n");
+               }
+               if (transfer_len > 0 && buffer) {
+                       printf(__FILE__ ": data(%d/%d):",
+                               (purb ? purb->actual_length : 0),
+                               transfer_len);
+                       len = usb_pipeout(pipe)? transfer_len:
+                                       (purb ? purb->actual_length : 0);
+                       for (i = 0; i < 16 && i < len; i++)
+                               printf(" %02x", ((__u8 *) buffer) [i]);
+                       printf("%s\n", i < len? "...": "");
+               }
+       }
+#endif
+}
+
+/* just for debugging; prints non-empty branches of the int ed tree
+ * inclusive iso eds */
+void ep_print_int_eds(ohci_t *ohci, char *str)
+{
+       int i, j;
+        __u32 *ed_p;
+       for (i = 0; i < 32; i++) {
+               j = 5;
+               ed_p = &(ohci->hcca->int_table [i]);
+               if (*ed_p == 0)
+                   continue;
+               printf(__FILE__ ": %s branch int %2d(%2x):", str, i, i);
+               while (*ed_p != 0 && j--) {
+                       ed_t *ed = (ed_t *)m32_swap(ed_p);
+                       printf(" ed: %4x;", ed->hwINFO);
+                       ed_p = &ed->hwNextED;
+               }
+               printf("\n");
+       }
+}
+
+static void ohci_dump_intr_mask(char *label, __u32 mask)
+{
+       dbg("%s: 0x%08x%s%s%s%s%s%s%s%s%s",
+               label,
+               mask,
+               (mask & OHCI_INTR_MIE) ? " MIE" : "",
+               (mask & OHCI_INTR_OC) ? " OC" : "",
+               (mask & OHCI_INTR_RHSC) ? " RHSC" : "",
+               (mask & OHCI_INTR_FNO) ? " FNO" : "",
+               (mask & OHCI_INTR_UE) ? " UE" : "",
+               (mask & OHCI_INTR_RD) ? " RD" : "",
+               (mask & OHCI_INTR_SF) ? " SF" : "",
+               (mask & OHCI_INTR_WDH) ? " WDH" : "",
+               (mask & OHCI_INTR_SO) ? " SO" : ""
+               );
+}
+
+static void maybe_print_eds(char *label, __u32 value)
+{
+       ed_t *edp = (ed_t *)value;
+
+       if (value) {
+               dbg("%s %08x", label, value);
+               dbg("%08x", edp->hwINFO);
+               dbg("%08x", edp->hwTailP);
+               dbg("%08x", edp->hwHeadP);
+               dbg("%08x", edp->hwNextED);
+       }
+}
+
+static char *hcfs2string(int state)
+{
+       switch (state) {
+       case OHCI_USB_RESET:    return "reset";
+       case OHCI_USB_RESUME:   return "resume";
+       case OHCI_USB_OPER:     return "operational";
+       case OHCI_USB_SUSPEND:  return "suspend";
+       }
+       return "?";
+}
+
+/* dump control and status registers */
+static void ohci_dump_status(ohci_t *controller)
+{
+       struct ohci_regs        *regs = controller->regs;
+       __u32                   temp;
+
+       temp = readl(&regs->revision) & 0xff;
+       if (temp != 0x10)
+               dbg("spec %d.%d", (temp >> 4), (temp & 0x0f));
+
+       temp = readl(&regs->control);
+       dbg("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp,
+               (temp & OHCI_CTRL_RWE) ? " RWE" : "",
+               (temp & OHCI_CTRL_RWC) ? " RWC" : "",
+               (temp & OHCI_CTRL_IR) ? " IR" : "",
+               hcfs2string(temp & OHCI_CTRL_HCFS),
+               (temp & OHCI_CTRL_BLE) ? " BLE" : "",
+               (temp & OHCI_CTRL_CLE) ? " CLE" : "",
+               (temp & OHCI_CTRL_IE) ? " IE" : "",
+               (temp & OHCI_CTRL_PLE) ? " PLE" : "",
+               temp & OHCI_CTRL_CBSR
+               );
+
+       temp = readl(&regs->cmdstatus);
+       dbg("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp,
+               (temp & OHCI_SOC) >> 16,
+               (temp & OHCI_OCR) ? " OCR" : "",
+               (temp & OHCI_BLF) ? " BLF" : "",
+               (temp & OHCI_CLF) ? " CLF" : "",
+               (temp & OHCI_HCR) ? " HCR" : ""
+               );
+
+       ohci_dump_intr_mask("intrstatus", readl(&regs->intrstatus));
+       ohci_dump_intr_mask("intrenable", readl(&regs->intrenable));
+
+       maybe_print_eds("ed_periodcurrent", readl(&regs->ed_periodcurrent));
+
+       maybe_print_eds("ed_controlhead", readl(&regs->ed_controlhead));
+       maybe_print_eds("ed_controlcurrent", readl(&regs->ed_controlcurrent));
+
+       maybe_print_eds("ed_bulkhead", readl(&regs->ed_bulkhead));
+       maybe_print_eds("ed_bulkcurrent", readl(&regs->ed_bulkcurrent));
+
+       maybe_print_eds("donehead", readl(&regs->donehead));
+}
+
+static void ohci_dump_roothub(ohci_t *controller, int verbose)
+{
+       __u32                   temp, ndp, i;
+
+       temp = roothub_a(controller);
+       ndp = (temp & RH_A_NDP);
+#ifdef CONFIG_AT91C_PQFP_UHPBUG
+       ndp = (ndp == 2) ? 1:0;
+#endif
+       if (verbose) {
+               dbg("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp,
+                       ((temp & RH_A_POTPGT) >> 24) & 0xff,
+                       (temp & RH_A_NOCP) ? " NOCP" : "",
+                       (temp & RH_A_OCPM) ? " OCPM" : "",
+                       (temp & RH_A_DT) ? " DT" : "",
+                       (temp & RH_A_NPS) ? " NPS" : "",
+                       (temp & RH_A_PSM) ? " PSM" : "",
+                       ndp
+                       );
+               temp = roothub_b(controller);
+               dbg("roothub.b: %08x PPCM=%04x DR=%04x",
+                       temp,
+                       (temp & RH_B_PPCM) >> 16,
+                       (temp & RH_B_DR)
+                       );
+               temp = roothub_status(controller);
+               dbg("roothub.status: %08x%s%s%s%s%s%s",
+                       temp,
+                       (temp & RH_HS_CRWE) ? " CRWE" : "",
+                       (temp & RH_HS_OCIC) ? " OCIC" : "",
+                       (temp & RH_HS_LPSC) ? " LPSC" : "",
+                       (temp & RH_HS_DRWE) ? " DRWE" : "",
+                       (temp & RH_HS_OCI) ? " OCI" : "",
+                       (temp & RH_HS_LPS) ? " LPS" : ""
+                       );
+       }
+
+       for (i = 0; i < ndp; i++) {
+               temp = roothub_portstatus(controller, i);
+               dbg("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s",
+                       i,
+                       temp,
+                       (temp & RH_PS_PRSC) ? " PRSC" : "",
+                       (temp & RH_PS_OCIC) ? " OCIC" : "",
+                       (temp & RH_PS_PSSC) ? " PSSC" : "",
+                       (temp & RH_PS_PESC) ? " PESC" : "",
+                       (temp & RH_PS_CSC) ? " CSC" : "",
+
+                       (temp & RH_PS_LSDA) ? " LSDA" : "",
+                       (temp & RH_PS_PPS) ? " PPS" : "",
+                       (temp & RH_PS_PRS) ? " PRS" : "",
+                       (temp & RH_PS_POCI) ? " POCI" : "",
+                       (temp & RH_PS_PSS) ? " PSS" : "",
+
+                       (temp & RH_PS_PES) ? " PES" : "",
+                       (temp & RH_PS_CCS) ? " CCS" : ""
+                       );
+       }
+}
+
+static void ohci_dump(ohci_t *controller, int verbose)
+{
+       dbg("OHCI controller usb-%s state", controller->slot_name);
+
+       /* dumps some of the state we know about */
+       ohci_dump_status(controller);
+       if (verbose)
+               ep_print_int_eds(controller, "hcca");
+       dbg("hcca frame #%04x", controller->hcca->frame_no);
+       ohci_dump_roothub(controller, 1);
+}
+#endif /* DEBUG */
+
+/*-------------------------------------------------------------------------*
+ * Interface functions (URB)
+ *-------------------------------------------------------------------------*/
+
+/* get a transfer request */
+
+int sohci_submit_job(urb_priv_t *urb, struct devrequest *setup)
+{
+       ohci_t *ohci;
+       ed_t *ed;
+       urb_priv_t *purb_priv = urb;
+       int i, size = 0;
+       struct usb_device *dev = urb->dev;
+       unsigned long pipe = urb->pipe;
+       void *buffer = urb->transfer_buffer;
+       int transfer_len = urb->transfer_buffer_length;
+       int interval = urb->interval;
+
+       ohci = &gohci;
+
+       /* when controller's hung, permit only roothub cleanup attempts
+        * such as powering down ports */
+       if (ohci->disabled) {
+               err("sohci_submit_job: EPIPE");
+               return -1;
+       }
+
+       /* we're about to begin a new transaction here so mark the
+        * URB unfinished */
+       urb->finished = 0;
+
+       /* every endpoint has a ed, locate and fill it */
+       ed = ep_add_ed(dev, pipe, interval, 1);
+       if (!ed) {
+               err("sohci_submit_job: ENOMEM");
+               return -1;
+       }
+
+       /* for the private part of the URB we need the number of TDs (size) */
+       switch (usb_pipetype(pipe)) {
+       case PIPE_BULK: /* one TD for every 4096 Byte */
+               size = (transfer_len - 1) / 4096 + 1;
+               break;
+       case PIPE_CONTROL:/* 1 TD for setup, 1 for ACK and 1 for every 4096 B */
+               size = (transfer_len == 0)? 2:
+                                       (transfer_len - 1) / 4096 + 3;
+               break;
+       case PIPE_INTERRUPT: /* 1 TD */
+               size = 1;
+               break;
+       }
+
+       ed->purb = urb;
+
+       if (size >= (N_URB_TD - 1)) {
+               err("need %d TDs, only have %d", size, N_URB_TD);
+               return -1;
+       }
+       purb_priv->pipe = pipe;
+
+       /* fill the private part of the URB */
+       purb_priv->length = size;
+       purb_priv->ed = ed;
+       purb_priv->actual_length = 0;
+
+       /* allocate the TDs */
+       /* note that td[0] was allocated in ep_add_ed */
+       for (i = 0; i < size; i++) {
+               purb_priv->td[i] = td_alloc(dev);
+               if (!purb_priv->td[i]) {
+                       purb_priv->length = i;
+                       urb_free_priv(purb_priv);
+                       err("sohci_submit_job: ENOMEM");
+                       return -1;
+               }
+       }
+
+       if (ed->state == ED_NEW || (ed->state & ED_DEL)) {
+               urb_free_priv(purb_priv);
+               err("sohci_submit_job: EINVAL");
+               return -1;
+       }
+
+       /* link the ed into a chain if is not already */
+       if (ed->state != ED_OPER)
+               ep_link(ohci, ed);
+
+       /* fill the TDs and link it to the ed */
+       td_submit_job(dev, pipe, buffer, transfer_len,
+                     setup, purb_priv, interval);
+
+       return 0;
+}
+
+static inline int sohci_return_job(struct ohci *hc, urb_priv_t *urb)
+{
+       struct ohci_regs *regs = hc->regs;
+
+       switch (usb_pipetype(urb->pipe)) {
+       case PIPE_INTERRUPT:
+               /* implicitly requeued */
+               if (urb->dev->irq_handle &&
+                               (urb->dev->irq_act_len = urb->actual_length)) {
+                       writel(OHCI_INTR_WDH, &regs->intrenable);
+                       readl(&regs->intrenable); /* PCI posting flush */
+                       urb->dev->irq_handle(urb->dev);
+                       writel(OHCI_INTR_WDH, &regs->intrdisable);
+                       readl(&regs->intrdisable); /* PCI posting flush */
+               }
+               urb->actual_length = 0;
+               td_submit_job(
+                               urb->dev,
+                               urb->pipe,
+                               urb->transfer_buffer,
+                               urb->transfer_buffer_length,
+                               NULL,
+                               urb,
+                               urb->interval);
+               break;
+       case PIPE_CONTROL:
+       case PIPE_BULK:
+               break;
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+/* tell us the current USB frame number */
+
+static int sohci_get_current_frame_number(struct usb_device *usb_dev)
+{
+       ohci_t *ohci = &gohci;
+
+       return m16_swap(ohci->hcca->frame_no);
+}
+#endif
+
+/*-------------------------------------------------------------------------*
+ * ED handling functions
+ *-------------------------------------------------------------------------*/
+
+/* search for the right branch to insert an interrupt ed into the int tree
+ * do some load ballancing;
+ * returns the branch and
+ * sets the interval to interval = 2^integer (ld (interval)) */
+
+static int ep_int_ballance(ohci_t *ohci, int interval, int load)
+{
+       int i, branch = 0;
+
+       /* search for the least loaded interrupt endpoint
+        * branch of all 32 branches
+        */
+       for (i = 0; i < 32; i++)
+               if (ohci->ohci_int_load [branch] > ohci->ohci_int_load [i])
+                       branch = i;
+
+       branch = branch % interval;
+       for (i = branch; i < 32; i += interval)
+               ohci->ohci_int_load [i] += load;
+
+       return branch;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*  2^int( ld (inter)) */
+
+static int ep_2_n_interval(int inter)
+{
+       int i;
+       for (i = 0; ((inter >> i) > 1) && (i < 5); i++);
+       return 1 << i;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* the int tree is a binary tree
+ * in order to process it sequentially the indexes of the branches have to
+ * be mapped the mapping reverses the bits of a word of num_bits length */
+static int ep_rev(int num_bits, int word)
+{
+       int i, wout = 0;
+
+       for (i = 0; i < num_bits; i++)
+               wout |= (((word >> i) & 1) << (num_bits - i - 1));
+       return wout;
+}
+
+/*-------------------------------------------------------------------------*
+ * ED handling functions
+ *-------------------------------------------------------------------------*/
+
+/* link an ed into one of the HC chains */
+
+static int ep_link(ohci_t *ohci, ed_t *edi)
+{
+       volatile ed_t *ed = edi;
+       int int_branch;
+       int i;
+       int inter;
+       int interval;
+       int load;
+       __u32 *ed_p;
+
+       ed->state = ED_OPER;
+       ed->int_interval = 0;
+
+       switch (ed->type) {
+       case PIPE_CONTROL:
+               ed->hwNextED = 0;
+               if (ohci->ed_controltail == NULL)
+                       writel(ed, &ohci->regs->ed_controlhead);
+               else
+                       ohci->ed_controltail->hwNextED =
+                                                  m32_swap((unsigned long)ed);
+
+               ed->ed_prev = ohci->ed_controltail;
+               if (!ohci->ed_controltail && !ohci->ed_rm_list[0] &&
+                       !ohci->ed_rm_list[1] && !ohci->sleeping) {
+                       ohci->hc_control |= OHCI_CTRL_CLE;
+                       writel(ohci->hc_control, &ohci->regs->control);
+               }
+               ohci->ed_controltail = edi;
+               break;
+
+       case PIPE_BULK:
+               ed->hwNextED = 0;
+               if (ohci->ed_bulktail == NULL)
+                       writel(ed, &ohci->regs->ed_bulkhead);
+               else
+                       ohci->ed_bulktail->hwNextED =
+                                                  m32_swap((unsigned long)ed);
+
+               ed->ed_prev = ohci->ed_bulktail;
+               if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] &&
+                       !ohci->ed_rm_list[1] && !ohci->sleeping) {
+                       ohci->hc_control |= OHCI_CTRL_BLE;
+                       writel(ohci->hc_control, &ohci->regs->control);
+               }
+               ohci->ed_bulktail = edi;
+               break;
+
+       case PIPE_INTERRUPT:
+               load = ed->int_load;
+               interval = ep_2_n_interval(ed->int_period);
+               ed->int_interval = interval;
+               int_branch = ep_int_ballance(ohci, interval, load);
+               ed->int_branch = int_branch;
+
+               for (i = 0; i < ep_rev(6, interval); i += inter) {
+                       inter = 1;
+                       for (ed_p = &(ohci->hcca->int_table[\
+                                               ep_rev(5, i) + int_branch]);
+                               (*ed_p != 0) &&
+                               (((ed_t *)ed_p)->int_interval >= interval);
+                               ed_p = &(((ed_t *)ed_p)->hwNextED))
+                                       inter = ep_rev(6,
+                                                ((ed_t *)ed_p)->int_interval);
+                       ed->hwNextED = *ed_p;
+                       *ed_p = m32_swap((unsigned long)ed);
+               }
+               break;
+       }
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* scan the periodic table to find and unlink this ED */
+static void periodic_unlink(struct ohci *ohci, volatile struct ed *ed,
+                           unsigned index, unsigned period)
+{
+       for (; index < NUM_INTS; index += period) {
+               __u32   *ed_p = &ohci->hcca->int_table [index];
+
+               /* ED might have been unlinked through another path */
+               while (*ed_p != 0) {
+                       if (((struct ed *)
+                                       m32_swap((unsigned long)ed_p)) == ed) {
+                               *ed_p = ed->hwNextED;
+                               break;
+                       }
+                       ed_p = &(((struct ed *)
+                                    m32_swap((unsigned long)ed_p))->hwNextED);
+               }
+       }
+}
+
+/* unlink an ed from one of the HC chains.
+ * just the link to the ed is unlinked.
+ * the link from the ed still points to another operational ed or 0
+ * so the HC can eventually finish the processing of the unlinked ed */
+
+static int ep_unlink(ohci_t *ohci, ed_t *edi)
+{
+       volatile ed_t *ed = edi;
+       int i;
+
+       ed->hwINFO |= m32_swap(OHCI_ED_SKIP);
+
+       switch (ed->type) {
+       case PIPE_CONTROL:
+               if (ed->ed_prev == NULL) {
+                       if (!ed->hwNextED) {
+                               ohci->hc_control &= ~OHCI_CTRL_CLE;
+                               writel(ohci->hc_control, &ohci->regs->control);
+                       }
+                       writel(m32_swap(*((__u32 *)&ed->hwNextED)),
+                               &ohci->regs->ed_controlhead);
+               } else {
+                       ed->ed_prev->hwNextED = ed->hwNextED;
+               }
+               if (ohci->ed_controltail == ed) {
+                       ohci->ed_controltail = ed->ed_prev;
+               } else {
+                       ((ed_t *)m32_swap(
+                           *((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev;
+               }
+               break;
+
+       case PIPE_BULK:
+               if (ed->ed_prev == NULL) {
+                       if (!ed->hwNextED) {
+                               ohci->hc_control &= ~OHCI_CTRL_BLE;
+                               writel(ohci->hc_control, &ohci->regs->control);
+                       }
+                       writel(m32_swap(*((__u32 *)&ed->hwNextED)),
+                              &ohci->regs->ed_bulkhead);
+               } else {
+                       ed->ed_prev->hwNextED = ed->hwNextED;
+               }
+               if (ohci->ed_bulktail == ed) {
+                       ohci->ed_bulktail = ed->ed_prev;
+               } else {
+                       ((ed_t *)m32_swap(
+                            *((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev;
+               }
+               break;
+
+       case PIPE_INTERRUPT:
+               periodic_unlink(ohci, ed, 0, 1);
+               for (i = ed->int_branch; i < 32; i += ed->int_interval)
+                   ohci->ohci_int_load[i] -= ed->int_load;
+               break;
+       }
+       ed->state = ED_UNLINK;
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* add/reinit an endpoint; this should be done once at the
+ * usb_set_configuration command, but the USB stack is a little bit
+ * stateless so we do it at every transaction if the state of the ed
+ * is ED_NEW then a dummy td is added and the state is changed to
+ * ED_UNLINK in all other cases the state is left unchanged the ed
+ * info fields are setted anyway even though most of them should not
+ * change
+ */
+static ed_t *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe,
+                       int interval, int load)
+{
+       td_t *td;
+       ed_t *ed_ret;
+       volatile ed_t *ed;
+
+       ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint(pipe) << 1) |
+                       (usb_pipecontrol(pipe)? 0: usb_pipeout(pipe))];
+
+       if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) {
+               err("ep_add_ed: pending delete");
+               /* pending delete request */
+               return NULL;
+       }
+
+       if (ed->state == ED_NEW) {
+               /* dummy td; end of td list for ed */
+               td = td_alloc(usb_dev);
+               ed->hwTailP = m32_swap((unsigned long)td);
+               ed->hwHeadP = ed->hwTailP;
+               ed->state = ED_UNLINK;
+               ed->type = usb_pipetype(pipe);
+               ohci_dev.ed_cnt++;
+       }
+
+       ed->hwINFO = m32_swap(usb_pipedevice(pipe)
+                       | usb_pipeendpoint(pipe) << 7
+                       | (usb_pipeisoc(pipe)? 0x8000: 0)
+                       | (usb_pipecontrol(pipe)? 0: \
+                                          (usb_pipeout(pipe)? 0x800: 0x1000))
+                       | usb_pipeslow(pipe) << 13
+                       | usb_maxpacket(usb_dev, pipe) << 16);
+
+       if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) {
+               ed->int_period = interval;
+               ed->int_load = load;
+       }
+
+       return ed_ret;
+}
+
+/*-------------------------------------------------------------------------*
+ * TD handling functions
+ *-------------------------------------------------------------------------*/
+
+/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
+
+static void td_fill(ohci_t *ohci, unsigned int info,
+       void *data, int len,
+       struct usb_device *dev, int index, urb_priv_t *urb_priv)
+{
+       volatile td_t  *td, *td_pt;
+#ifdef OHCI_FILL_TRACE
+       int i;
+#endif
+
+       if (index > urb_priv->length) {
+               err("index > length");
+               return;
+       }
+       /* use this td as the next dummy */
+       td_pt = urb_priv->td [index];
+       td_pt->hwNextTD = 0;
+
+       /* fill the old dummy TD */
+       td = urb_priv->td [index] =
+                            (td_t *)(m32_swap(urb_priv->ed->hwTailP) & ~0xf);
+
+       td->ed = urb_priv->ed;
+       td->next_dl_td = NULL;
+       td->index = index;
+       td->data = (__u32)data;
+#ifdef OHCI_FILL_TRACE
+       if (usb_pipebulk(urb_priv->pipe) && usb_pipeout(urb_priv->pipe)) {
+               for (i = 0; i < len; i++)
+               printf("td->data[%d] %#2x ", i, ((unsigned char *)td->data)[i]);
+               printf("\n");
+       }
+#endif
+       if (!len)
+               data = 0;
+
+       td->hwINFO = m32_swap(info);
+       td->hwCBP = m32_swap((unsigned long)data);
+       if (data)
+               td->hwBE = m32_swap((unsigned long)(data + len - 1));
+       else
+               td->hwBE = 0;
+
+       td->hwNextTD = m32_swap((unsigned long)td_pt);
+
+       /* append to queue */
+       td->ed->hwTailP = td->hwNextTD;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* prepare all TDs of a transfer */
+
+static void td_submit_job(struct usb_device *dev, unsigned long pipe,
+                         void *buffer, int transfer_len,
+                         struct devrequest *setup, urb_priv_t *urb,
+                         int interval)
+{
+       ohci_t *ohci = &gohci;
+       int data_len = transfer_len;
+       void *data;
+       int cnt = 0;
+       __u32 info = 0;
+       unsigned int toggle = 0;
+
+       /* OHCI handles the DATA-toggles itself, we just use the USB-toggle
+        * bits for reseting */
+       if (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) {
+               toggle = TD_T_TOGGLE;
+       } else {
+               toggle = TD_T_DATA0;
+               usb_settoggle(dev, usb_pipeendpoint(pipe),
+                               usb_pipeout(pipe), 1);
+       }
+       urb->td_cnt = 0;
+       if (data_len)
+               data = buffer;
+       else
+               data = 0;
+
+       switch (usb_pipetype(pipe)) {
+       case PIPE_BULK:
+               info = usb_pipeout(pipe)?
+                       TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ;
+               while (data_len > 4096) {
+                       td_fill(ohci, info | (cnt? TD_T_TOGGLE:toggle),
+                               data, 4096, dev, cnt, urb);
+                       data += 4096; data_len -= 4096; cnt++;
+               }
+               info = usb_pipeout(pipe)?
+                       TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ;
+               td_fill(ohci, info | (cnt? TD_T_TOGGLE:toggle), data,
+                       data_len, dev, cnt, urb);
+               cnt++;
+
+               if (!ohci->sleeping) {
+                       /* start bulk list */
+                       writel(OHCI_BLF, &ohci->regs->cmdstatus);
+               }
+               break;
+
+       case PIPE_CONTROL:
+               /* Setup phase */
+               info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
+               td_fill(ohci, info, setup, 8, dev, cnt++, urb);
+
+               /* Optional Data phase */
+               if (data_len > 0) {
+                       info = usb_pipeout(pipe)?
+                               TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 :
+                               TD_CC | TD_R | TD_DP_IN | TD_T_DATA1;
+                       /* NOTE:  mishandles transfers >8K, some >4K */
+                       td_fill(ohci, info, data, data_len, dev, cnt++, urb);
+               }
+
+               /* Status phase */
+               info = usb_pipeout(pipe)?
+                       TD_CC | TD_DP_IN | TD_T_DATA1:
+                       TD_CC | TD_DP_OUT | TD_T_DATA1;
+               td_fill(ohci, info, data, 0, dev, cnt++, urb);
+
+               if (!ohci->sleeping) {
+                       /* start Control list */
+                       writel(OHCI_CLF, &ohci->regs->cmdstatus);
+               }
+               break;
+
+       case PIPE_INTERRUPT:
+               info = usb_pipeout(urb->pipe)?
+                       TD_CC | TD_DP_OUT | toggle:
+                       TD_CC | TD_R | TD_DP_IN | toggle;
+               td_fill(ohci, info, data, data_len, dev, cnt++, urb);
+               break;
+       }
+       if (urb->length != cnt)
+               dbg("TD LENGTH %d != CNT %d", urb->length, cnt);
+}
+
+/*-------------------------------------------------------------------------*
+ * Done List handling functions
+ *-------------------------------------------------------------------------*/
+
+/* calculate the transfer length and update the urb */
+
+static void dl_transfer_length(td_t *td)
+{
+       __u32 tdINFO, tdBE, tdCBP;
+       urb_priv_t *lurb_priv = td->ed->purb;
+
+       tdINFO = m32_swap(td->hwINFO);
+       tdBE   = m32_swap(td->hwBE);
+       tdCBP  = m32_swap(td->hwCBP);
+
+       if (!(usb_pipecontrol(lurb_priv->pipe) &&
+           ((td->index == 0) || (td->index == lurb_priv->length - 1)))) {
+               if (tdBE != 0) {
+                       if (td->hwCBP == 0)
+                               lurb_priv->actual_length += tdBE - td->data + 1;
+                       else
+                               lurb_priv->actual_length += tdCBP - td->data;
+               }
+       }
+}
+
+/*-------------------------------------------------------------------------*/
+static void check_status(td_t *td_list)
+{
+       urb_priv_t *lurb_priv = td_list->ed->purb;
+       int        urb_len    = lurb_priv->length;
+       __u32      *phwHeadP  = &td_list->ed->hwHeadP;
+       int        cc;
+
+       cc = TD_CC_GET(m32_swap(td_list->hwINFO));
+       if (cc) {
+               err(" USB-error: %s (%x)", cc_to_string[cc], cc);
+
+               if (*phwHeadP & m32_swap(0x1)) {
+                       if (lurb_priv &&
+                           ((td_list->index + 1) < urb_len)) {
+                               *phwHeadP =
+                                       (lurb_priv->td[urb_len - 1]->hwNextTD &\
+                                                       m32_swap(0xfffffff0)) |
+                                                  (*phwHeadP & m32_swap(0x2));
+
+                               lurb_priv->td_cnt += urb_len -
+                                                    td_list->index - 1;
+                       } else
+                               *phwHeadP &= m32_swap(0xfffffff2);
+               }
+#ifdef CONFIG_MPC5200
+               td_list->hwNextTD = 0;
+#endif
+       }
+}
+
+/* replies to the request have to be on a FIFO basis so
+ * we reverse the reversed done-list */
+static td_t *dl_reverse_done_list(ohci_t *ohci)
+{
+       __u32 td_list_hc;
+       td_t *td_rev = NULL;
+       td_t *td_list = NULL;
+
+       td_list_hc = m32_swap(ohci->hcca->done_head) & 0xfffffff0;
+       ohci->hcca->done_head = 0;
+
+       while (td_list_hc) {
+               td_list = (td_t *)td_list_hc;
+               check_status(td_list);
+               td_list->next_dl_td = td_rev;
+               td_rev = td_list;
+               td_list_hc = m32_swap(td_list->hwNextTD) & 0xfffffff0;
+       }
+       return td_list;
+}
+
+/*-------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------*/
+
+static void finish_urb(ohci_t *ohci, urb_priv_t *urb, int status)
+{
+       if ((status & (ED_OPER | ED_UNLINK)) && (urb->state != URB_DEL))
+               urb->finished = sohci_return_job(ohci, urb);
+       else
+               dbg("finish_urb: strange.., ED state %x, \n", status);
+}
+
+/*
+ * Used to take back a TD from the host controller. This would normally be
+ * called from within dl_done_list, however it may be called directly if the
+ * HC no longer sees the TD and it has not appeared on the donelist (after
+ * two frames).  This bug has been observed on ZF Micro systems.
+ */
+static int takeback_td(ohci_t *ohci, td_t *td_list)
+{
+       ed_t *ed;
+       int cc;
+       int stat = 0;
+       /* urb_t *urb; */
+       urb_priv_t *lurb_priv;
+       __u32 tdINFO, edHeadP, edTailP;
+
+       tdINFO = m32_swap(td_list->hwINFO);
+
+       ed = td_list->ed;
+       lurb_priv = ed->purb;
+
+       dl_transfer_length(td_list);
+
+       lurb_priv->td_cnt++;
+
+       /* error code of transfer */
+       cc = TD_CC_GET(tdINFO);
+       if (cc) {
+               err("USB-error: %s (%x)", cc_to_string[cc], cc);
+               stat = cc_to_error[cc];
+       }
+
+       /* see if this done list makes for all TD's of current URB,
+       * and mark the URB finished if so */
+       if (lurb_priv->td_cnt == lurb_priv->length)
+               finish_urb(ohci, lurb_priv, ed->state);
+
+       dbg("dl_done_list: processing TD %x, len %x\n",
+               lurb_priv->td_cnt, lurb_priv->length);
+
+       if (ed->state != ED_NEW && (!usb_pipeint(lurb_priv->pipe))) {
+               edHeadP = m32_swap(ed->hwHeadP) & 0xfffffff0;
+               edTailP = m32_swap(ed->hwTailP);
+
+               /* unlink eds if they are not busy */
+               if ((edHeadP == edTailP) && (ed->state == ED_OPER))
+                       ep_unlink(ohci, ed);
+       }
+       return stat;
+}
+
+static int dl_done_list(ohci_t *ohci)
+{
+       int stat = 0;
+       td_t    *td_list = dl_reverse_done_list(ohci);
+
+       while (td_list) {
+               td_t    *td_next = td_list->next_dl_td;
+               stat = takeback_td(ohci, td_list);
+               td_list = td_next;
+       }
+       return stat;
+}
+
+/*-------------------------------------------------------------------------*
+ * Virtual Root Hub
+ *-------------------------------------------------------------------------*/
+
+/* Device descriptor */
+static __u8 root_hub_dev_des[] =
+{
+       0x12,       /*  __u8  bLength; */
+       0x01,       /*  __u8  bDescriptorType; Device */
+       0x10,       /*  __u16 bcdUSB; v1.1 */
+       0x01,
+       0x09,       /*  __u8  bDeviceClass; HUB_CLASSCODE */
+       0x00,       /*  __u8  bDeviceSubClass; */
+       0x00,       /*  __u8  bDeviceProtocol; */
+       0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
+       0x00,       /*  __u16 idVendor; */
+       0x00,
+       0x00,       /*  __u16 idProduct; */
+       0x00,
+       0x00,       /*  __u16 bcdDevice; */
+       0x00,
+       0x00,       /*  __u8  iManufacturer; */
+       0x01,       /*  __u8  iProduct; */
+       0x00,       /*  __u8  iSerialNumber; */
+       0x01        /*  __u8  bNumConfigurations; */
+};
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] =
+{
+       0x09,       /*  __u8  bLength; */
+       0x02,       /*  __u8  bDescriptorType; Configuration */
+       0x19,       /*  __u16 wTotalLength; */
+       0x00,
+       0x01,       /*  __u8  bNumInterfaces; */
+       0x01,       /*  __u8  bConfigurationValue; */
+       0x00,       /*  __u8  iConfiguration; */
+       0x40,       /*  __u8  bmAttributes;
+        Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
+       0x00,       /*  __u8  MaxPower; */
+
+       /* interface */
+       0x09,       /*  __u8  if_bLength; */
+       0x04,       /*  __u8  if_bDescriptorType; Interface */
+       0x00,       /*  __u8  if_bInterfaceNumber; */
+       0x00,       /*  __u8  if_bAlternateSetting; */
+       0x01,       /*  __u8  if_bNumEndpoints; */
+       0x09,       /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
+       0x00,       /*  __u8  if_bInterfaceSubClass; */
+       0x00,       /*  __u8  if_bInterfaceProtocol; */
+       0x00,       /*  __u8  if_iInterface; */
+
+       /* endpoint */
+       0x07,       /*  __u8  ep_bLength; */
+       0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
+       0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
+       0x03,       /*  __u8  ep_bmAttributes; Interrupt */
+       0x02,       /*  __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
+       0x00,
+       0xff        /*  __u8  ep_bInterval; 255 ms */
+};
+
+static unsigned char root_hub_str_index0[] =
+{
+       0x04,                   /*  __u8  bLength; */
+       0x03,                   /*  __u8  bDescriptorType; String-descriptor */
+       0x09,                   /*  __u8  lang ID */
+       0x04,                   /*  __u8  lang ID */
+};
+
+static unsigned char root_hub_str_index1[] =
+{
+       28,                     /*  __u8  bLength; */
+       0x03,                   /*  __u8  bDescriptorType; String-descriptor */
+       'O',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'H',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'C',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'I',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       ' ',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'R',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'o',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'o',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       't',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       ' ',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'H',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'u',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'b',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+};
+
+/* Hub class-specific descriptor is constructed dynamically */
+
+/*-------------------------------------------------------------------------*/
+
+#define OK(x)                  len = (x); break
+#ifdef DEBUG
+#define WR_RH_STAT(x)          {info("WR:status %#8x", (x)); writel((x), \
+                                               &gohci.regs->roothub.status); }
+#define WR_RH_PORTSTAT(x)      {info("WR:portstatus[%d] %#8x", wIndex-1, \
+               (x)); writel((x), &gohci.regs->roothub.portstatus[wIndex-1]); }
+#else
+#define WR_RH_STAT(x)          writel((x), &gohci.regs->roothub.status)
+#define WR_RH_PORTSTAT(x)      writel((x), \
+                                   &gohci.regs->roothub.portstatus[wIndex-1])
+#endif
+#define RD_RH_STAT             roothub_status(&gohci)
+#define RD_RH_PORTSTAT         roothub_portstatus(&gohci, wIndex-1)
+
+/* request to virtual root hub */
+
+int rh_check_port_status(ohci_t *controller)
+{
+       __u32 temp, ndp, i;
+       int res;
+
+       res = -1;
+       temp = roothub_a(controller);
+       ndp = (temp & RH_A_NDP);
+#ifdef CONFIG_AT91C_PQFP_UHPBUG
+       ndp = (ndp == 2) ? 1:0;
+#endif
+       for (i = 0; i < ndp; i++) {
+               temp = roothub_portstatus(controller, i);
+               /* check for a device disconnect */
+               if (((temp & (RH_PS_PESC | RH_PS_CSC)) ==
+                       (RH_PS_PESC | RH_PS_CSC)) &&
+                       ((temp & RH_PS_CCS) == 0)) {
+                       res = i;
+                       break;
+               }
+       }
+       return res;
+}
+
+static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
+               void *buffer, int transfer_len, struct devrequest *cmd)
+{
+       void *data = buffer;
+       int leni = transfer_len;
+       int len = 0;
+       int stat = 0;
+       __u32 datab[4];
+       __u8 *data_buf = (__u8 *)datab;
+       __u16 bmRType_bReq;
+       __u16 wValue;
+       __u16 wIndex;
+       __u16 wLength;
+
+#ifdef DEBUG
+pkt_print(NULL, dev, pipe, buffer, transfer_len,
+         cmd, "SUB(rh)", usb_pipein(pipe));
+#else
+       wait_ms(1);
+#endif
+       if (usb_pipeint(pipe)) {
+               info("Root-Hub submit IRQ: NOT implemented");
+               return 0;
+       }
+
+       bmRType_bReq  = cmd->requesttype | (cmd->request << 8);
+       wValue        = le16_to_cpu(cmd->value);
+       wIndex        = le16_to_cpu(cmd->index);
+       wLength       = le16_to_cpu(cmd->length);
+
+       info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x",
+               dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength);
+
+       switch (bmRType_bReq) {
+       /* Request Destination:
+          without flags: Device,
+          RH_INTERFACE: interface,
+          RH_ENDPOINT: endpoint,
+          RH_CLASS means HUB here,
+          RH_OTHER | RH_CLASS  almost ever means HUB_PORT here
+       */
+
+       case RH_GET_STATUS:
+               *(__u16 *) data_buf = cpu_to_le16(1);
+               OK(2);
+       case RH_GET_STATUS | RH_INTERFACE:
+               *(__u16 *) data_buf = cpu_to_le16(0);
+               OK(2);
+       case RH_GET_STATUS | RH_ENDPOINT:
+               *(__u16 *) data_buf = cpu_to_le16(0);
+               OK(2);
+       case RH_GET_STATUS | RH_CLASS:
+               *(__u32 *) data_buf = cpu_to_le32(
+                               RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE));
+               OK(4);
+       case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+               *(__u32 *) data_buf = cpu_to_le32(RD_RH_PORTSTAT);
+               OK(4);
+
+       case RH_CLEAR_FEATURE | RH_ENDPOINT:
+               switch (wValue) {
+               case (RH_ENDPOINT_STALL):
+                       OK(0);
+               }
+               break;
+
+       case RH_CLEAR_FEATURE | RH_CLASS:
+               switch (wValue) {
+               case RH_C_HUB_LOCAL_POWER:
+                       OK(0);
+               case (RH_C_HUB_OVER_CURRENT):
+                       WR_RH_STAT(RH_HS_OCIC);
+                       OK(0);
+               }
+               break;
+
+       case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+               switch (wValue) {
+               case (RH_PORT_ENABLE):        WR_RH_PORTSTAT(RH_PS_CCS);  OK(0);
+               case (RH_PORT_SUSPEND):       WR_RH_PORTSTAT(RH_PS_POCI); OK(0);
+               case (RH_PORT_POWER):         WR_RH_PORTSTAT(RH_PS_LSDA); OK(0);
+               case (RH_C_PORT_CONNECTION):  WR_RH_PORTSTAT(RH_PS_CSC);  OK(0);
+               case (RH_C_PORT_ENABLE):      WR_RH_PORTSTAT(RH_PS_PESC); OK(0);
+               case (RH_C_PORT_SUSPEND):     WR_RH_PORTSTAT(RH_PS_PSSC); OK(0);
+               case (RH_C_PORT_OVER_CURRENT):WR_RH_PORTSTAT(RH_PS_OCIC); OK(0);
+               case (RH_C_PORT_RESET):       WR_RH_PORTSTAT(RH_PS_PRSC); OK(0);
+               }
+               break;
+
+       case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+               switch (wValue) {
+               case (RH_PORT_SUSPEND):
+                       WR_RH_PORTSTAT(RH_PS_PSS);  OK(0);
+               case (RH_PORT_RESET): /* BUG IN HUP CODE *********/
+                       if (RD_RH_PORTSTAT & RH_PS_CCS)
+                               WR_RH_PORTSTAT(RH_PS_PRS);
+                       OK(0);
+               case (RH_PORT_POWER):
+                       WR_RH_PORTSTAT(RH_PS_PPS);
+                       wait_ms(100);
+                       OK(0);
+               case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/
+                       if (RD_RH_PORTSTAT & RH_PS_CCS)
+                               WR_RH_PORTSTAT(RH_PS_PES);
+                       OK(0);
+               }
+               break;
+
+       case RH_SET_ADDRESS:
+               gohci.rh.devnum = wValue;
+               OK(0);
+
+       case RH_GET_DESCRIPTOR:
+               switch ((wValue & 0xff00) >> 8) {
+               case (0x01): /* device descriptor */
+                       len = min_t(unsigned int,
+                                       leni,
+                                       min_t(unsigned int,
+                                       sizeof(root_hub_dev_des),
+                                       wLength));
+                       data_buf = root_hub_dev_des; OK(len);
+               case (0x02): /* configuration descriptor */
+                       len = min_t(unsigned int,
+                                       leni,
+                                       min_t(unsigned int,
+                                       sizeof(root_hub_config_des),
+                                       wLength));
+                       data_buf = root_hub_config_des; OK(len);
+               case (0x03): /* string descriptors */
+                       if (wValue == 0x0300) {
+                               len = min_t(unsigned int,
+                                               leni,
+                                               min_t(unsigned int,
+                                               sizeof(root_hub_str_index0),
+                                               wLength));
+                               data_buf = root_hub_str_index0;
+                               OK(len);
+                       }
+                       if (wValue == 0x0301) {
+                               len = min_t(unsigned int,
+                                               leni,
+                                               min_t(unsigned int,
+                                               sizeof(root_hub_str_index1),
+                                               wLength));
+                               data_buf = root_hub_str_index1;
+                               OK(len);
+               }
+               default:
+                       stat = USB_ST_STALLED;
+               }
+               break;
+
+       case RH_GET_DESCRIPTOR | RH_CLASS:
+       {
+               __u32 temp = roothub_a(&gohci);
+
+               data_buf [0] = 9;               /* min length; */
+               data_buf [1] = 0x29;
+               data_buf [2] = temp & RH_A_NDP;
+#ifdef CONFIG_AT91C_PQFP_UHPBUG
+               data_buf [2] = (data_buf [2] == 2) ? 1:0;
+#endif
+               data_buf [3] = 0;
+               if (temp & RH_A_PSM)    /* per-port power switching? */
+                       data_buf [3] |= 0x1;
+               if (temp & RH_A_NOCP)   /* no overcurrent reporting? */
+                       data_buf [3] |= 0x10;
+               else if (temp & RH_A_OCPM)/* per-port overcurrent reporting? */
+                       data_buf [3] |= 0x8;
+
+               /* corresponds to data_buf[4-7] */
+               datab [1] = 0;
+               data_buf [5] = (temp & RH_A_POTPGT) >> 24;
+               temp = roothub_b(&gohci);
+               data_buf [7] = temp & RH_B_DR;
+               if (data_buf [2] < 7) {
+                       data_buf [8] = 0xff;
+               } else {
+                       data_buf [0] += 2;
+                       data_buf [8] = (temp & RH_B_DR) >> 8;
+                       data_buf [10] = data_buf [9] = 0xff;
+               }
+
+               len = min_t(unsigned int, leni,
+                           min_t(unsigned int, data_buf [0], wLength));
+               OK(len);
+       }
+
+       case RH_GET_CONFIGURATION:      *(__u8 *) data_buf = 0x01; OK(1);
+
+       case RH_SET_CONFIGURATION:      WR_RH_STAT(0x10000); OK(0);
+
+       default:
+               dbg("unsupported root hub command");
+               stat = USB_ST_STALLED;
+       }
+
+#ifdef DEBUG
+       ohci_dump_roothub(&gohci, 1);
+#else
+       wait_ms(1);
+#endif
+
+       len = min_t(int, len, leni);
+       if (data != data_buf)
+           memcpy(data, data_buf, len);
+       dev->act_len = len;
+       dev->status = stat;
+
+#ifdef DEBUG
+       pkt_print(NULL, dev, pipe, buffer,
+                 transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/);
+#else
+       wait_ms(1);
+#endif
+
+       return stat;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* common code for handling submit messages - used for all but root hub */
+/* accesses. */
+int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+               int transfer_len, struct devrequest *setup, int interval)
+{
+       int stat = 0;
+       int maxsize = usb_maxpacket(dev, pipe);
+       int timeout;
+       urb_priv_t *urb;
+
+       urb = malloc(sizeof(urb_priv_t));
+       memset(urb, 0, sizeof(urb_priv_t));
+
+       urb->dev = dev;
+       urb->pipe = pipe;
+       urb->transfer_buffer = buffer;
+       urb->transfer_buffer_length = transfer_len;
+       urb->interval = interval;
+
+       /* device pulled? Shortcut the action. */
+       if (devgone == dev) {
+               dev->status = USB_ST_CRC_ERR;
+               return 0;
+       }
+
+#ifdef DEBUG
+       urb->actual_length = 0;
+       pkt_print(urb, dev, pipe, buffer, transfer_len,
+                 setup, "SUB", usb_pipein(pipe));
+#else
+       wait_ms(1);
+#endif
+       if (!maxsize) {
+               err("submit_common_message: pipesize for pipe %lx is zero",
+                       pipe);
+               return -1;
+       }
+
+       if (sohci_submit_job(urb, setup) < 0) {
+               err("sohci_submit_job failed");
+               return -1;
+       }
+
+#if 0
+       wait_ms(10);
+       /* ohci_dump_status(&gohci); */
+#endif
+
+       /* allow more time for a BULK device to react - some are slow */
+#define BULK_TO         5000   /* timeout in milliseconds */
+       if (usb_pipebulk(pipe))
+               timeout = BULK_TO;
+       else
+               timeout = 100;
+
+       /* wait for it to complete */
+       for (;;) {
+               /* check whether the controller is done */
+               stat = hc_interrupt();
+               if (stat < 0) {
+                       stat = USB_ST_CRC_ERR;
+                       break;
+               }
+
+               /* NOTE: since we are not interrupt driven in U-Boot and always
+                * handle only one URB at a time, we cannot assume the
+                * transaction finished on the first successful return from
+                * hc_interrupt().. unless the flag for current URB is set,
+                * meaning that all TD's to/from device got actually
+                * transferred and processed. If the current URB is not
+                * finished we need to re-iterate this loop so as
+                * hc_interrupt() gets called again as there needs to be some
+                * more TD's to process still */
+               if ((stat >= 0) && (stat != 0xff) && (urb->finished)) {
+                       /* 0xff is returned for an SF-interrupt */
+                       break;
+               }
+
+               if (--timeout) {
+                       wait_ms(1);
+                       if (!urb->finished)
+                               dbg("*");
+
+               } else {
+                       err("CTL:TIMEOUT ");
+                       dbg("submit_common_msg: TO status %x\n", stat);
+                       urb->finished = 1;
+                       stat = USB_ST_CRC_ERR;
+                       break;
+               }
+       }
+
+       dev->status = stat;
+       dev->act_len = transfer_len;
+
+#ifdef DEBUG
+       pkt_print(urb, dev, pipe, buffer, transfer_len,
+                 setup, "RET(ctlr)", usb_pipein(pipe));
+#else
+       wait_ms(1);
+#endif
+
+       /* free TDs in urb_priv */
+       if (!usb_pipeint(pipe))
+               urb_free_priv(urb);
+       return 0;
+}
+
+/* submit routines called from usb.c */
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+               int transfer_len)
+{
+       info("submit_bulk_msg");
+       return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0);
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+               int transfer_len, struct devrequest *setup)
+{
+       int maxsize = usb_maxpacket(dev, pipe);
+
+       info("submit_control_msg");
+#ifdef DEBUG
+       pkt_print(NULL, dev, pipe, buffer, transfer_len,
+                 setup, "SUB", usb_pipein(pipe));
+#else
+       wait_ms(1);
+#endif
+       if (!maxsize) {
+               err("submit_control_message: pipesize for pipe %lx is zero",
+                       pipe);
+               return -1;
+       }
+       if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) {
+               gohci.rh.dev = dev;
+               /* root hub - redirect */
+               return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len,
+                       setup);
+       }
+
+       return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0);
+}
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+               int transfer_len, int interval)
+{
+       info("submit_int_msg");
+       return submit_common_msg(dev, pipe, buffer, transfer_len, NULL,
+                       interval);
+}
+
+/*-------------------------------------------------------------------------*
+ * HC functions
+ *-------------------------------------------------------------------------*/
+
+/* reset the HC and BUS */
+
+static int hc_reset(ohci_t *ohci)
+{
+#ifdef CONFIG_PCI_EHCI_DEVNO
+       pci_dev_t pdev;
+#endif
+       int timeout = 30;
+       int smm_timeout = 50; /* 0,5 sec */
+
+       dbg("%s\n", __FUNCTION__);
+
+#ifdef CONFIG_PCI_EHCI_DEVNO
+       /*
+        *  Some multi-function controllers (e.g. ISP1562) allow root hub
+        * resetting via EHCI registers only.
+        */
+       pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVNO);
+       if (pdev != -1) {
+               u32 base;
+               int timeout = 1000;
+
+               pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &base);
+               writel(readl(base + EHCI_USBCMD_OFF) | EHCI_USBCMD_HCRESET,
+                       base + EHCI_USBCMD_OFF);
+
+               while (readl(base + EHCI_USBCMD_OFF) & EHCI_USBCMD_HCRESET) {
+                       if (timeout-- <= 0) {
+                               printf("USB RootHub reset timed out!");
+                               break;
+                       }
+                       udelay(1);
+               }
+       } else
+               printf("No EHCI func at %d index!\n", CONFIG_PCI_EHCI_DEVNO);
+#endif
+       if (readl(&ohci->regs->control) & OHCI_CTRL_IR) {
+               /* SMM owns the HC */
+               writel(OHCI_OCR, &ohci->regs->cmdstatus);/* request ownership */
+               info("USB HC TakeOver from SMM");
+               while (readl(&ohci->regs->control) & OHCI_CTRL_IR) {
+                       wait_ms(10);
+                       if (--smm_timeout == 0) {
+                               err("USB HC TakeOver failed!");
+                               return -1;
+                       }
+               }
+       }
+
+       /* Disable HC interrupts */
+       writel(OHCI_INTR_MIE, &ohci->regs->intrdisable);
+
+       dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;\n",
+               ohci->slot_name,
+               readl(&ohci->regs->control));
+
+       /* Reset USB (needed by some controllers) */
+       ohci->hc_control = 0;
+       writel(ohci->hc_control, &ohci->regs->control);
+
+       /* HC Reset requires max 10 us delay */
+       writel(OHCI_HCR,  &ohci->regs->cmdstatus);
+       while ((readl(&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
+               if (--timeout == 0) {
+                       err("USB HC reset timed out!");
+                       return -1;
+               }
+               udelay(1);
+       }
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Start an OHCI controller, set the BUS operational
+ * enable interrupts
+ * connect the virtual root hub */
+
+static int hc_start(ohci_t *ohci)
+{
+       __u32 mask;
+       unsigned int fminterval;
+
+       ohci->disabled = 1;
+
+       /* Tell the controller where the control and bulk lists are
+        * The lists are empty now. */
+
+       writel(0, &ohci->regs->ed_controlhead);
+       writel(0, &ohci->regs->ed_bulkhead);
+
+       writel((__u32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */
+
+       fminterval = 0x2edf;
+       writel((fminterval * 9) / 10, &ohci->regs->periodicstart);
+       fminterval |= ((((fminterval - 210) * 6) / 7) << 16);
+       writel(fminterval, &ohci->regs->fminterval);
+       writel(0x628, &ohci->regs->lsthresh);
+
+       /* start controller operations */
+       ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
+       ohci->disabled = 0;
+       writel(ohci->hc_control, &ohci->regs->control);
+
+       /* disable all interrupts */
+       mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD |
+                       OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC |
+                       OHCI_INTR_OC | OHCI_INTR_MIE);
+       writel(mask, &ohci->regs->intrdisable);
+       /* clear all interrupts */
+       mask &= ~OHCI_INTR_MIE;
+       writel(mask, &ohci->regs->intrstatus);
+       /* Choose the interrupts we care about now  - but w/o MIE */
+       mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO;
+       writel(mask, &ohci->regs->intrenable);
+
+#ifdef OHCI_USE_NPS
+       /* required for AMD-756 and some Mac platforms */
+       writel((roothub_a(ohci) | RH_A_NPS) & ~RH_A_PSM,
+               &ohci->regs->roothub.a);
+       writel(RH_HS_LPSC, &ohci->regs->roothub.status);
+#endif /* OHCI_USE_NPS */
+
+#define mdelay(n) ({unsigned long msec = (n); while (msec--) udelay(1000); })
+       /* POTPGT delay is bits 24-31, in 2 ms units. */
+       mdelay((roothub_a(ohci) >> 23) & 0x1fe);
+
+       /* connect the virtual root hub */
+       ohci->rh.devnum = 0;
+
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Poll USB interrupt. */
+void usb_event_poll(void)
+{
+       hc_interrupt();
+}
+
+/* an interrupt happens */
+
+static int hc_interrupt(void)
+{
+       ohci_t *ohci = &gohci;
+       struct ohci_regs *regs = ohci->regs;
+       int ints;
+       int stat = -1;
+
+       if ((ohci->hcca->done_head != 0) &&
+                               !(m32_swap(ohci->hcca->done_head) & 0x01)) {
+               ints =  OHCI_INTR_WDH;
+       } else {
+               ints = readl(&regs->intrstatus);
+               if (ints == ~(u32)0) {
+                       ohci->disabled++;
+                       err("%s device removed!", ohci->slot_name);
+                       return -1;
+               } else {
+                       ints &= readl(&regs->intrenable);
+                       if (ints == 0) {
+                               dbg("hc_interrupt: returning..\n");
+                               return 0xff;
+                       }
+               }
+       }
+
+       /* dbg("Interrupt: %x frame: %x", ints,
+                                       le16_to_cpu(ohci->hcca->frame_no)); */
+
+       if (ints & OHCI_INTR_RHSC)
+               stat = 0xff;
+
+       if (ints & OHCI_INTR_UE) {
+               ohci->disabled++;
+               err("OHCI Unrecoverable Error, controller usb-%s disabled",
+                       ohci->slot_name);
+               /* e.g. due to PCI Master/Target Abort */
+
+#ifdef DEBUG
+               ohci_dump(ohci, 1);
+#else
+               wait_ms(1);
+#endif
+               /* FIXME: be optimistic, hope that bug won't repeat often. */
+               /* Make some non-interrupt context restart the controller. */
+               /* Count and limit the retries though; either hardware or */
+               /* software errors can go forever... */
+               hc_reset(ohci);
+               return -1;
+       }
+
+       if (ints & OHCI_INTR_WDH) {
+               wait_ms(1);
+               writel(OHCI_INTR_WDH, &regs->intrdisable);
+               (void)readl(&regs->intrdisable); /* flush */
+               stat = dl_done_list(&gohci);
+               writel(OHCI_INTR_WDH, &regs->intrenable);
+               (void)readl(&regs->intrdisable); /* flush */
+       }
+
+       if (ints & OHCI_INTR_SO) {
+               dbg("USB Schedule overrun\n");
+               writel(OHCI_INTR_SO, &regs->intrenable);
+               stat = -1;
+       }
+
+       /* FIXME:  this assumes SOF (1/ms) interrupts don't get lost... */
+       if (ints & OHCI_INTR_SF) {
+               unsigned int frame = m16_swap(ohci->hcca->frame_no) & 1;
+               wait_ms(1);
+               writel(OHCI_INTR_SF, &regs->intrdisable);
+               if (ohci->ed_rm_list[frame] != NULL)
+                       writel(OHCI_INTR_SF, &regs->intrenable);
+               stat = 0xff;
+       }
+
+       writel(ints, &regs->intrstatus);
+       return stat;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+
+/* De-allocate all resources.. */
+
+static void hc_release_ohci(ohci_t *ohci)
+{
+       dbg("USB HC release ohci usb-%s", ohci->slot_name);
+
+       if (!ohci->disabled)
+               hc_reset(ohci);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * low level initalisation routine, called from usb.c
+ */
+static char ohci_inited = 0;
+
+int usb_lowlevel_init(void)
+{
+#ifdef CONFIG_PCI_OHCI
+       pci_dev_t pdev;
+#endif
+
+#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT
+       /* cpu dependant init */
+       if (usb_cpu_init())
+               return -1;
+#endif
+
+#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT
+       /*  board dependant init */
+       if (usb_board_init())
+               return -1;
+#endif
+       memset(&gohci, 0, sizeof(ohci_t));
+
+       /* align the storage */
+       if ((__u32)&ghcca[0] & 0xff) {
+               err("HCCA not aligned!!");
+               return -1;
+       }
+       phcca = &ghcca[0];
+       info("aligned ghcca %p", phcca);
+       memset(&ohci_dev, 0, sizeof(struct ohci_device));
+       if ((__u32)&ohci_dev.ed[0] & 0x7) {
+               err("EDs not aligned!!");
+               return -1;
+       }
+       memset(gtd, 0, sizeof(td_t) * (NUM_TD + 1));
+       if ((__u32)gtd & 0x7) {
+               err("TDs not aligned!!");
+               return -1;
+       }
+       ptd = gtd;
+       gohci.hcca = phcca;
+       memset(phcca, 0, sizeof(struct ohci_hcca));
+
+       gohci.disabled = 1;
+       gohci.sleeping = 0;
+       gohci.irq = -1;
+#ifdef CONFIG_PCI_OHCI
+       pdev = pci_find_devices(ohci_pci_ids, CONFIG_PCI_OHCI_DEVNO);
+
+       if (pdev != -1) {
+               u16 vid, did;
+               u32 base;
+               pci_read_config_word(pdev, PCI_VENDOR_ID, &vid);
+               pci_read_config_word(pdev, PCI_DEVICE_ID, &did);
+               printf("OHCI pci controller (%04x, %04x) found @(%d:%d:%d)\n",
+                               vid, did, (pdev >> 16) & 0xff,
+                               (pdev >> 11) & 0x1f, (pdev >> 8) & 0x7);
+               pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &base);
+               printf("OHCI regs address 0x%08x\n", base);
+               gohci.regs = (struct ohci_regs *)base;
+       } else
+               return -1;
+#else
+       gohci.regs = (struct ohci_regs *)CONFIG_SYS_USB_OHCI_REGS_BASE;
+#endif
+
+       gohci.flags = 0;
+       gohci.slot_name = CONFIG_SYS_USB_OHCI_SLOT_NAME;
+
+       if (hc_reset (&gohci) < 0) {
+               hc_release_ohci (&gohci);
+               err ("can't reset usb-%s", gohci.slot_name);
+#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT
+               /* board dependant cleanup */
+               usb_board_init_fail();
+#endif
+
+#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT
+               /* cpu dependant cleanup */
+               usb_cpu_init_fail();
+#endif
+               return -1;
+       }
+
+       if (hc_start(&gohci) < 0) {
+               err("can't start usb-%s", gohci.slot_name);
+               hc_release_ohci(&gohci);
+               /* Initialization failed */
+#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT
+               /* board dependant cleanup */
+               usb_board_stop();
+#endif
+
+#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT
+               /* cpu dependant cleanup */
+               usb_cpu_stop();
+#endif
+               return -1;
+       }
+
+#ifdef DEBUG
+       ohci_dump(&gohci, 1);
+#else
+       wait_ms(1);
+#endif
+       ohci_inited = 1;
+       return 0;
+}
+
+int usb_lowlevel_stop(void)
+{
+       /* this gets called really early - before the controller has */
+       /* even been initialized! */
+       if (!ohci_inited)
+               return 0;
+       /* TODO release any interrupts, etc. */
+       /* call hc_release_ohci() here ? */
+       hc_reset(&gohci);
+
+#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT
+       /* board dependant cleanup */
+       if (usb_board_stop())
+               return -1;
+#endif
+
+#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT
+       /* cpu dependant cleanup */
+       if (usb_cpu_stop())
+               return -1;
+#endif
+       /* This driver is no longer initialised. It needs a new low-level
+        * init (board/cpu) before it can be used again. */
+       ohci_inited = 0;
+       return 0;
+}
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
new file mode 100644 (file)
index 0000000..a547337
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
+ *
+ * usb-ohci.h
+ */
+
+/* functions for doing board or CPU specific setup/cleanup */
+extern int usb_board_init(void);
+extern int usb_board_stop(void);
+extern int usb_board_init_fail(void);
+
+extern int usb_cpu_init(void);
+extern int usb_cpu_stop(void);
+extern int usb_cpu_init_fail(void);
+
+
+static int cc_to_error[16] = {
+
+/* mapping of the OHCI CC status to error codes */
+       /* No  Error  */               0,
+       /* CRC Error  */               USB_ST_CRC_ERR,
+       /* Bit Stuff  */               USB_ST_BIT_ERR,
+       /* Data Togg  */               USB_ST_CRC_ERR,
+       /* Stall      */               USB_ST_STALLED,
+       /* DevNotResp */               -1,
+       /* PIDCheck   */               USB_ST_BIT_ERR,
+       /* UnExpPID   */               USB_ST_BIT_ERR,
+       /* DataOver   */               USB_ST_BUF_ERR,
+       /* DataUnder  */               USB_ST_BUF_ERR,
+       /* reservd    */               -1,
+       /* reservd    */               -1,
+       /* BufferOver */               USB_ST_BUF_ERR,
+       /* BuffUnder  */               USB_ST_BUF_ERR,
+       /* Not Access */               -1,
+       /* Not Access */               -1
+};
+
+static const char *cc_to_string[16] = {
+       "No Error",
+       "CRC: Last data packet from endpoint contained a CRC error.",
+       "BITSTUFFING: Last data packet from endpoint contained a bit " \
+                    "stuffing violation",
+       "DATATOGGLEMISMATCH: Last packet from endpoint had data toggle PID\n" \
+                    "that did not match the expected value.",
+       "STALL: TD was moved to the Done Queue because the endpoint returned" \
+                    " a STALL PID",
+       "DEVICENOTRESPONDING: Device did not respond to token (IN) or did\n" \
+                    "not provide a handshake (OUT)",
+       "PIDCHECKFAILURE: Check bits on PID from endpoint failed on data PID\n"\
+                    "(IN) or handshake (OUT)",
+       "UNEXPECTEDPID: Receive PID was not valid when encountered or PID\n" \
+                    "value is not defined.",
+       "DATAOVERRUN: The amount of data returned by the endpoint exceeded\n" \
+                    "either the size of the maximum data packet allowed\n" \
+                    "from the endpoint (found in MaximumPacketSize field\n" \
+                    "of ED) or the remaining buffer size.",
+       "DATAUNDERRUN: The endpoint returned less than MaximumPacketSize\n" \
+                    "and that amount was not sufficient to fill the\n" \
+                    "specified buffer",
+       "reserved1",
+       "reserved2",
+       "BUFFEROVERRUN: During an IN, HC received data from endpoint faster\n" \
+                    "than it could be written to system memory",
+       "BUFFERUNDERRUN: During an OUT, HC could not retrieve data from\n" \
+                    "system memory fast enough to keep up with data USB " \
+                    "data rate.",
+       "NOT ACCESSED: This code is set by software before the TD is placed" \
+                    "on a list to be processed by the HC.(1)",
+       "NOT ACCESSED: This code is set by software before the TD is placed" \
+                    "on a list to be processed by the HC.(2)",
+};
+
+/* ED States */
+
+#define ED_NEW         0x00
+#define ED_UNLINK      0x01
+#define ED_OPER                0x02
+#define ED_DEL         0x04
+#define ED_URB_DEL     0x08
+
+/* usb_ohci_ed */
+struct ed {
+       __u32 hwINFO;
+       __u32 hwTailP;
+       __u32 hwHeadP;
+       __u32 hwNextED;
+
+       struct ed *ed_prev;
+       __u8 int_period;
+       __u8 int_branch;
+       __u8 int_load;
+       __u8 int_interval;
+       __u8 state;
+       __u8 type;
+       __u16 last_iso;
+       struct ed *ed_rm_list;
+
+       struct usb_device *usb_dev;
+       void *purb;
+       __u32 unused[2];
+} __attribute((aligned(16)));
+typedef struct ed ed_t;
+
+
+/* TD info field */
+#define TD_CC      0xf0000000
+#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
+#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
+#define TD_EC      0x0C000000
+#define TD_T       0x03000000
+#define TD_T_DATA0  0x02000000
+#define TD_T_DATA1  0x03000000
+#define TD_T_TOGGLE 0x00000000
+#define TD_R       0x00040000
+#define TD_DI      0x00E00000
+#define TD_DI_SET(X) (((X) & 0x07)<< 21)
+#define TD_DP      0x00180000
+#define TD_DP_SETUP 0x00000000
+#define TD_DP_IN    0x00100000
+#define TD_DP_OUT   0x00080000
+
+#define TD_ISO     0x00010000
+#define TD_DEL     0x00020000
+
+/* CC Codes */
+#define TD_CC_NOERROR     0x00
+#define TD_CC_CRC         0x01
+#define TD_CC_BITSTUFFING  0x02
+#define TD_CC_DATATOGGLEM  0x03
+#define TD_CC_STALL       0x04
+#define TD_DEVNOTRESP     0x05
+#define TD_PIDCHECKFAIL           0x06
+#define TD_UNEXPECTEDPID   0x07
+#define TD_DATAOVERRUN    0x08
+#define TD_DATAUNDERRUN           0x09
+#define TD_BUFFEROVERRUN   0x0C
+#define TD_BUFFERUNDERRUN  0x0D
+#define TD_NOTACCESSED    0x0F
+
+
+#define MAXPSW 1
+
+struct td {
+       __u32 hwINFO;
+       __u32 hwCBP;            /* Current Buffer Pointer */
+       __u32 hwNextTD;         /* Next TD Pointer */
+       __u32 hwBE;             /* Memory Buffer End Pointer */
+
+/* #ifndef CONFIG_MPC5200 /\* this seems wrong *\/ */
+       __u16 hwPSW[MAXPSW];
+/* #endif */
+       __u8 unused;
+       __u8 index;
+       struct ed *ed;
+       struct td *next_dl_td;
+       struct usb_device *usb_dev;
+       int transfer_len;
+       __u32 data;
+
+       __u32 unused2[2];
+} __attribute((aligned(32)));
+typedef struct td td_t;
+
+#define OHCI_ED_SKIP   (1 << 14)
+
+/*
+ * The HCCA (Host Controller Communications Area) is a 256 byte
+ * structure defined in the OHCI spec. that the host controller is
+ * told the base address of.  It must be 256-byte aligned.
+ */
+
+#define NUM_INTS 32    /* part of the OHCI standard */
+struct ohci_hcca {
+       __u32   int_table[NUM_INTS];    /* Interrupt ED table */
+#if defined(CONFIG_MPC5200)
+       __u16   pad1;                   /* set to 0 on each frame_no change */
+       __u16   frame_no;               /* current frame number */
+#else
+       __u16   frame_no;               /* current frame number */
+       __u16   pad1;                   /* set to 0 on each frame_no change */
+#endif
+       __u32   done_head;              /* info returned for an interrupt */
+       u8              reserved_for_hc[116];
+} __attribute((aligned(256)));
+
+
+/*
+ * Maximum number of root hub ports.
+ */
+#ifndef CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS
+# error "CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS undefined!"
+#endif
+
+/*
+ * This is the structure of the OHCI controller's memory mapped I/O
+ * region.  This is Memory Mapped I/O. You must use the readl() and
+ * writel() macros defined in asm/io.h to access these!!
+ */
+struct ohci_regs {
+       /* control and status registers */
+       __u32   revision;
+       __u32   control;
+       __u32   cmdstatus;
+       __u32   intrstatus;
+       __u32   intrenable;
+       __u32   intrdisable;
+       /* memory pointers */
+       __u32   hcca;
+       __u32   ed_periodcurrent;
+       __u32   ed_controlhead;
+       __u32   ed_controlcurrent;
+       __u32   ed_bulkhead;
+       __u32   ed_bulkcurrent;
+       __u32   donehead;
+       /* frame counters */
+       __u32   fminterval;
+       __u32   fmremaining;
+       __u32   fmnumber;
+       __u32   periodicstart;
+       __u32   lsthresh;
+       /* Root hub ports */
+       struct  ohci_roothub_regs {
+               __u32   a;
+               __u32   b;
+               __u32   status;
+               __u32   portstatus[CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS];
+       } roothub;
+} __attribute((aligned(32)));
+
+/* Some EHCI controls */
+#define EHCI_USBCMD_OFF                0x20
+#define EHCI_USBCMD_HCRESET    (1 << 1)
+
+/* OHCI CONTROL AND STATUS REGISTER MASKS */
+
+/*
+ * HcControl (control) register masks
+ */
+#define OHCI_CTRL_CBSR (3 << 0)        /* control/bulk service ratio */
+#define OHCI_CTRL_PLE  (1 << 2)        /* periodic list enable */
+#define OHCI_CTRL_IE   (1 << 3)        /* isochronous enable */
+#define OHCI_CTRL_CLE  (1 << 4)        /* control list enable */
+#define OHCI_CTRL_BLE  (1 << 5)        /* bulk list enable */
+#define OHCI_CTRL_HCFS (3 << 6)        /* host controller functional state */
+#define OHCI_CTRL_IR   (1 << 8)        /* interrupt routing */
+#define OHCI_CTRL_RWC  (1 << 9)        /* remote wakeup connected */
+#define OHCI_CTRL_RWE  (1 << 10)       /* remote wakeup enable */
+
+/* pre-shifted values for HCFS */
+#      define OHCI_USB_RESET   (0 << 6)
+#      define OHCI_USB_RESUME  (1 << 6)
+#      define OHCI_USB_OPER    (2 << 6)
+#      define OHCI_USB_SUSPEND (3 << 6)
+
+/*
+ * HcCommandStatus (cmdstatus) register masks
+ */
+#define OHCI_HCR       (1 << 0)        /* host controller reset */
+#define OHCI_CLF       (1 << 1)        /* control list filled */
+#define OHCI_BLF       (1 << 2)        /* bulk list filled */
+#define OHCI_OCR       (1 << 3)        /* ownership change request */
+#define OHCI_SOC       (3 << 16)       /* scheduling overrun count */
+
+/*
+ * masks used with interrupt registers:
+ * HcInterruptStatus (intrstatus)
+ * HcInterruptEnable (intrenable)
+ * HcInterruptDisable (intrdisable)
+ */
+#define OHCI_INTR_SO   (1 << 0)        /* scheduling overrun */
+#define OHCI_INTR_WDH  (1 << 1)        /* writeback of done_head */
+#define OHCI_INTR_SF   (1 << 2)        /* start frame */
+#define OHCI_INTR_RD   (1 << 3)        /* resume detect */
+#define OHCI_INTR_UE   (1 << 4)        /* unrecoverable error */
+#define OHCI_INTR_FNO  (1 << 5)        /* frame number overflow */
+#define OHCI_INTR_RHSC (1 << 6)        /* root hub status change */
+#define OHCI_INTR_OC   (1 << 30)       /* ownership change */
+#define OHCI_INTR_MIE  (1 << 31)       /* master interrupt enable */
+
+
+/* Virtual Root HUB */
+struct virt_root_hub {
+       int devnum; /* Address of Root Hub endpoint */
+       void *dev;  /* was urb */
+       void *int_addr;
+       int send;
+       int interval;
+};
+
+/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */
+
+/* destination of request */
+#define RH_INTERFACE              0x01
+#define RH_ENDPOINT               0x02
+#define RH_OTHER                  0x03
+
+#define RH_CLASS                  0x20
+#define RH_VENDOR                 0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS          0x0080
+#define RH_CLEAR_FEATURE       0x0100
+#define RH_SET_FEATURE         0x0300
+#define RH_SET_ADDRESS         0x0500
+#define RH_GET_DESCRIPTOR      0x0680
+#define RH_SET_DESCRIPTOR      0x0700
+#define RH_GET_CONFIGURATION   0x0880
+#define RH_SET_CONFIGURATION   0x0900
+#define RH_GET_STATE           0x0280
+#define RH_GET_INTERFACE       0x0A80
+#define RH_SET_INTERFACE       0x0B00
+#define RH_SYNC_FRAME          0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP              0x2000
+
+
+/* Hub port features */
+#define RH_PORT_CONNECTION        0x00
+#define RH_PORT_ENABLE            0x01
+#define RH_PORT_SUSPEND                   0x02
+#define RH_PORT_OVER_CURRENT      0x03
+#define RH_PORT_RESET             0x04
+#define RH_PORT_POWER             0x08
+#define RH_PORT_LOW_SPEED         0x09
+
+#define RH_C_PORT_CONNECTION      0x10
+#define RH_C_PORT_ENABLE          0x11
+#define RH_C_PORT_SUSPEND         0x12
+#define RH_C_PORT_OVER_CURRENT    0x13
+#define RH_C_PORT_RESET                   0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER      0x00
+#define RH_C_HUB_OVER_CURRENT     0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP           0x00
+#define RH_ENDPOINT_STALL         0x01
+
+#define RH_ACK                    0x01
+#define RH_REQ_ERR                -1
+#define RH_NACK                           0x00
+
+
+/* OHCI ROOT HUB REGISTER MASKS */
+
+/* roothub.portstatus [i] bits */
+#define RH_PS_CCS           0x00000001         /* current connect status */
+#define RH_PS_PES           0x00000002         /* port enable status*/
+#define RH_PS_PSS           0x00000004         /* port suspend status */
+#define RH_PS_POCI          0x00000008         /* port over current indicator */
+#define RH_PS_PRS           0x00000010         /* port reset status */
+#define RH_PS_PPS           0x00000100         /* port power status */
+#define RH_PS_LSDA          0x00000200         /* low speed device attached */
+#define RH_PS_CSC           0x00010000         /* connect status change */
+#define RH_PS_PESC          0x00020000         /* port enable status change */
+#define RH_PS_PSSC          0x00040000         /* port suspend status change */
+#define RH_PS_OCIC          0x00080000         /* over current indicator change */
+#define RH_PS_PRSC          0x00100000         /* port reset status change */
+
+/* roothub.status bits */
+#define RH_HS_LPS           0x00000001         /* local power status */
+#define RH_HS_OCI           0x00000002         /* over current indicator */
+#define RH_HS_DRWE          0x00008000         /* device remote wakeup enable */
+#define RH_HS_LPSC          0x00010000         /* local power status change */
+#define RH_HS_OCIC          0x00020000         /* over current indicator change */
+#define RH_HS_CRWE          0x80000000         /* clear remote wakeup enable */
+
+/* roothub.b masks */
+#define RH_B_DR                0x0000ffff              /* device removable flags */
+#define RH_B_PPCM      0xffff0000              /* port power control mask */
+
+/* roothub.a masks */
+#define RH_A_NDP       (0xff << 0)             /* number of downstream ports */
+#define RH_A_PSM       (1 << 8)                /* power switching mode */
+#define RH_A_NPS       (1 << 9)                /* no power switching */
+#define RH_A_DT                (1 << 10)               /* device type (mbz) */
+#define RH_A_OCPM      (1 << 11)               /* over current protection mode */
+#define RH_A_NOCP      (1 << 12)               /* no over current protection */
+#define RH_A_POTPGT    (0xff << 24)            /* power on to power good time */
+
+/* urb */
+#define N_URB_TD 48
+typedef struct
+{
+       ed_t *ed;
+       __u16 length;   /* number of tds associated with this request */
+       __u16 td_cnt;   /* number of tds already serviced */
+       struct usb_device *dev;
+       int   state;
+       unsigned long pipe;
+       void *transfer_buffer;
+       int transfer_buffer_length;
+       int interval;
+       int actual_length;
+       int finished;
+       td_t *td[N_URB_TD];     /* list pointer to all corresponding TDs associated with this request */
+} urb_priv_t;
+#define URB_DEL 1
+
+/*
+ * This is the full ohci controller description
+ *
+ * Note how the "proper" USB information is just
+ * a subset of what the full implementation needs. (Linus)
+ */
+
+
+typedef struct ohci {
+       struct ohci_hcca *hcca;         /* hcca */
+       /*dma_addr_t hcca_dma;*/
+
+       int irq;
+       int disabled;                   /* e.g. got a UE, we're hung */
+       int sleeping;
+       unsigned long flags;            /* for HC bugs */
+
+       struct ohci_regs *regs; /* OHCI controller's memory */
+
+       int ohci_int_load[32];   /* load of the 32 Interrupt Chains (for load balancing)*/
+       ed_t *ed_rm_list[2];     /* lists of all endpoints to be removed */
+       ed_t *ed_bulktail;       /* last endpoint of bulk list */
+       ed_t *ed_controltail;    /* last endpoint of control list */
+       int intrstatus;
+       __u32 hc_control;               /* copy of the hc control reg */
+       struct usb_device *dev[32];
+       struct virt_root_hub rh;
+
+       const char      *slot_name;
+} ohci_t;
+
+#define NUM_EDS 8              /* num of preallocated endpoint descriptors */
+
+struct ohci_device {
+       ed_t    ed[NUM_EDS];
+       int ed_cnt;
+};
+
+/* hcd */
+/* endpoint */
+static int ep_link(ohci_t * ohci, ed_t * ed);
+static int ep_unlink(ohci_t * ohci, ed_t * ed);
+static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned long pipe,
+               int interval, int load);
+
+/*-------------------------------------------------------------------------*/
+
+/* we need more TDs than EDs */
+#define NUM_TD 64
+
+/* +1 so we can align the storage */
+td_t gtd[NUM_TD+1];
+/* pointers to aligned storage */
+td_t *ptd;
+
+/* TDs ... */
+static inline struct td *
+td_alloc (struct usb_device *usb_dev)
+{
+       int i;
+       struct td       *td;
+
+       td = NULL;
+       for (i = 0; i < NUM_TD; i++)
+       {
+               if (ptd[i].usb_dev == NULL)
+               {
+                       td = &ptd[i];
+                       td->usb_dev = usb_dev;
+                       break;
+               }
+       }
+
+       return td;
+}
+
+static inline void
+ed_free (struct ed *ed)
+{
+       ed->usb_dev = NULL;
+}
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
new file mode 100644 (file)
index 0000000..db611b6
--- /dev/null
@@ -0,0 +1,945 @@
+/*
+ * R8A66597 HCD (Host Controller Driver) for u-boot
+ *
+ * Copyright (C) 2008  Yoshihiro Shimoda <shimoda.yoshihiro@renesas.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; version 2 of the License.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <common.h>
+#include <usb.h>
+#include <asm/io.h>
+
+#include "r8a66597.h"
+
+#ifdef R8A66597_DEBUG
+#define R8A66597_DPRINT                printf
+#else
+#define R8A66597_DPRINT(...)
+#endif
+
+static const char hcd_name[] = "r8a66597_hcd";
+static unsigned short clock = CONFIG_R8A66597_XTAL;
+static unsigned short vif = CONFIG_R8A66597_LDRV;
+static unsigned short endian = CONFIG_R8A66597_ENDIAN;
+static struct r8a66597 gr8a66597;
+
+static void get_hub_data(struct usb_device *dev, u16 *hub_devnum, u16 *hubport)
+{
+       int i;
+
+       *hub_devnum = 0;
+       *hubport = 0;
+
+       /* check a device connected to root_hub */
+       if ((dev->parent && dev->parent->devnum == 1) ||
+           (dev->devnum == 1))
+               return;
+
+       for (i = 0; i < USB_MAXCHILDREN; i++) {
+               if (dev->parent->children[i] == dev) {
+                       *hub_devnum = (u8)dev->parent->devnum;
+                       *hubport = i;
+                       return;
+               }
+       }
+
+       printf("get_hub_data error.\n");
+}
+
+static void set_devadd(struct r8a66597 *r8a66597, u8 r8a66597_address,
+                       struct usb_device *dev, int port)
+{
+       u16 val, usbspd, upphub, hubport;
+       unsigned long devadd_reg = get_devadd_addr(r8a66597_address);
+
+       get_hub_data(dev, &upphub, &hubport);
+       usbspd = r8a66597->speed;
+       val = (upphub << 11) | (hubport << 8) | (usbspd << 6) | (port & 0x0001);
+       r8a66597_write(r8a66597, val, devadd_reg);
+}
+
+static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
+{
+       u16 tmp;
+       int i = 0;
+
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+       do {
+               r8a66597_write(r8a66597, SCKE, SYSCFG0);
+               tmp = r8a66597_read(r8a66597, SYSCFG0);
+               if (i++ > 1000) {
+                       printf("register access fail.\n");
+                       return -1;
+               }
+       } while ((tmp & SCKE) != SCKE);
+       r8a66597_write(r8a66597, 0x04, 0x02);
+#else
+       do {
+               r8a66597_write(r8a66597, USBE, SYSCFG0);
+               tmp = r8a66597_read(r8a66597, SYSCFG0);
+               if (i++ > 1000) {
+                       printf("register access fail.\n");
+                       return -1;
+               }
+       } while ((tmp & USBE) != USBE);
+       r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+       r8a66597_mdfy(r8a66597, clock, XTAL, SYSCFG0);
+
+       i = 0;
+       r8a66597_bset(r8a66597, XCKE, SYSCFG0);
+       do {
+               udelay(1000);
+               tmp = r8a66597_read(r8a66597, SYSCFG0);
+               if (i++ > 500) {
+                       printf("register access fail.\n");
+                       return -1;
+               }
+       } while ((tmp & SCKE) != SCKE);
+#endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
+
+       return 0;
+}
+
+static void r8a66597_clock_disable(struct r8a66597 *r8a66597)
+{
+       r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
+       udelay(1);
+#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+       r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
+       r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
+       r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+#endif
+}
+
+static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port)
+{
+       u16 val;
+
+       val = port ? DRPD : DCFM | DRPD;
+       r8a66597_bset(r8a66597, val, get_syscfg_reg(port));
+       r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
+
+       r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, get_dmacfg_reg(port));
+}
+
+static void r8a66597_disable_port(struct r8a66597 *r8a66597, int port)
+{
+       u16 val, tmp;
+
+       r8a66597_write(r8a66597, 0, get_intenb_reg(port));
+       r8a66597_write(r8a66597, 0, get_intsts_reg(port));
+
+       r8a66597_port_power(r8a66597, port, 0);
+
+       do {
+               tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS;
+               udelay(640);
+       } while (tmp == EDGESTS);
+
+       val = port ? DRPD : DCFM | DRPD;
+       r8a66597_bclr(r8a66597, val, get_syscfg_reg(port));
+       r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));
+}
+
+static int enable_controller(struct r8a66597 *r8a66597)
+{
+       int ret, port;
+
+       ret = r8a66597_clock_enable(r8a66597);
+       if (ret < 0)
+               return ret;
+
+       r8a66597_bset(r8a66597, vif & LDRV, PINCFG);
+       r8a66597_bset(r8a66597, USBE, SYSCFG0);
+
+       r8a66597_bset(r8a66597, INTL, SOFCFG);
+       r8a66597_write(r8a66597, 0, INTENB0);
+       r8a66597_write(r8a66597, 0, INTENB1);
+       r8a66597_write(r8a66597, 0, INTENB2);
+
+       r8a66597_bset(r8a66597, endian & BIGEND, CFIFOSEL);
+       r8a66597_bset(r8a66597, endian & BIGEND, D0FIFOSEL);
+       r8a66597_bset(r8a66597, endian & BIGEND, D1FIFOSEL);
+       r8a66597_bset(r8a66597, TRNENSEL, SOFCFG);
+
+       for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
+               r8a66597_enable_port(r8a66597, port);
+
+       return 0;
+}
+
+static void disable_controller(struct r8a66597 *r8a66597)
+{
+       int i;
+
+       if (!(r8a66597_read(r8a66597, SYSCFG0) & USBE))
+               return;
+
+       r8a66597_write(r8a66597, 0, INTENB0);
+       r8a66597_write(r8a66597, 0, INTSTS0);
+
+       r8a66597_write(r8a66597, 0, D0FIFOSEL);
+       r8a66597_write(r8a66597, 0, D1FIFOSEL);
+       r8a66597_write(r8a66597, 0, DCPCFG);
+       r8a66597_write(r8a66597, 0x40, DCPMAXP);
+       r8a66597_write(r8a66597, 0, DCPCTR);
+
+       for (i = 0; i <= 10; i++)
+               r8a66597_write(r8a66597, 0, get_devadd_addr(i));
+       for (i = 1; i <= 5; i++) {
+               r8a66597_write(r8a66597, 0, get_pipetre_addr(i));
+               r8a66597_write(r8a66597, 0, get_pipetrn_addr(i));
+       }
+       for (i = 1; i < R8A66597_MAX_NUM_PIPE; i++) {
+               r8a66597_write(r8a66597, 0, get_pipectr_addr(i));
+               r8a66597_write(r8a66597, i, PIPESEL);
+               r8a66597_write(r8a66597, 0, PIPECFG);
+               r8a66597_write(r8a66597, 0, PIPEBUF);
+               r8a66597_write(r8a66597, 0, PIPEMAXP);
+               r8a66597_write(r8a66597, 0, PIPEPERI);
+       }
+
+       for (i = 0; i < R8A66597_MAX_ROOT_HUB; i++)
+               r8a66597_disable_port(r8a66597, i);
+
+       r8a66597_clock_disable(r8a66597);
+}
+
+static void r8a66597_reg_wait(struct r8a66597 *r8a66597, unsigned long reg,
+                             u16 mask, u16 loop)
+{
+       u16 tmp;
+       int i = 0;
+
+       do {
+               tmp = r8a66597_read(r8a66597, reg);
+               if (i++ > 1000000) {
+                       printf("register%lx, loop %x is timeout\n", reg, loop);
+                       break;
+               }
+       } while ((tmp & mask) != loop);
+}
+
+static void pipe_buffer_setting(struct r8a66597 *r8a66597,
+                               struct usb_device *dev, unsigned long pipe)
+{
+       u16 val = 0;
+       u16 pipenum, bufnum, maxpacket;
+
+       if (usb_pipein(pipe)) {
+               pipenum = BULK_IN_PIPENUM;
+               bufnum = BULK_IN_BUFNUM;
+               maxpacket = dev->epmaxpacketin[usb_pipeendpoint(pipe)];
+       } else {
+               pipenum = BULK_OUT_PIPENUM;
+               bufnum = BULK_OUT_BUFNUM;
+               maxpacket = dev->epmaxpacketout[usb_pipeendpoint(pipe)];
+       }
+
+       if (r8a66597->pipe_config & (1 << pipenum))
+               return;
+       r8a66597->pipe_config |= (1 << pipenum);
+
+       r8a66597_bset(r8a66597, ACLRM, get_pipectr_addr(pipenum));
+       r8a66597_bclr(r8a66597, ACLRM, get_pipectr_addr(pipenum));
+       r8a66597_write(r8a66597, pipenum, PIPESEL);
+
+       /* FIXME: This driver support bulk transfer only. */
+       if (!usb_pipein(pipe))
+               val |= R8A66597_DIR;
+       else
+               val |= R8A66597_SHTNAK;
+       val |= R8A66597_BULK | R8A66597_DBLB | usb_pipeendpoint(pipe);
+       r8a66597_write(r8a66597, val, PIPECFG);
+
+       r8a66597_write(r8a66597, (8 << 10) | bufnum, PIPEBUF);
+       r8a66597_write(r8a66597, make_devsel(usb_pipedevice(pipe)) |
+                                maxpacket, PIPEMAXP);
+       r8a66597_write(r8a66597, 0, PIPEPERI);
+       r8a66597_write(r8a66597, SQCLR, get_pipectr_addr(pipenum));
+}
+
+static int send_setup_packet(struct r8a66597 *r8a66597, struct usb_device *dev,
+                            struct devrequest *setup)
+{
+       int i;
+       unsigned short *p = (unsigned short *)setup;
+       unsigned long setup_addr = USBREQ;
+       u16 intsts1;
+       int timeout = 3000;
+       u16 devsel = setup->request == USB_REQ_SET_ADDRESS ? 0 : dev->devnum;
+
+       r8a66597_write(r8a66597, make_devsel(devsel) |
+                                (8 << dev->maxpacketsize), DCPMAXP);
+       r8a66597_write(r8a66597, ~(SIGN | SACK), INTSTS1);
+
+       for (i = 0; i < 4; i++) {
+               r8a66597_write(r8a66597, le16_to_cpu(p[i]), setup_addr);
+               setup_addr += 2;
+       }
+       r8a66597_write(r8a66597, ~0x0001, BRDYSTS);
+       r8a66597_write(r8a66597, SUREQ, DCPCTR);
+
+       while (1) {
+               intsts1 = r8a66597_read(r8a66597, INTSTS1);
+               if (intsts1 & SACK)
+                       break;
+               if (intsts1 & SIGN) {
+                       printf("setup packet send error\n");
+                       return -1;
+               }
+               if (timeout-- < 0) {
+                       printf("setup packet timeout\n");
+                       return -1;
+               }
+               udelay(500);
+       }
+
+       return 0;
+}
+
+static int send_bulk_packet(struct r8a66597 *r8a66597, struct usb_device *dev,
+                           unsigned long pipe, void *buffer, int transfer_len)
+{
+       u16 tmp, bufsize;
+       u16 *buf;
+       size_t size;
+
+       R8A66597_DPRINT("%s\n", __func__);
+
+       r8a66597_mdfy(r8a66597, MBW | BULK_OUT_PIPENUM,
+                       MBW | CURPIPE, CFIFOSEL);
+       r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, BULK_OUT_PIPENUM);
+       tmp = r8a66597_read(r8a66597, CFIFOCTR);
+       if ((tmp & FRDY) == 0) {
+               printf("%s FRDY is not set (%x)\n", __func__, tmp);
+               return -1;
+       }
+
+       /* prepare parameters */
+       bufsize = dev->epmaxpacketout[usb_pipeendpoint(pipe)];
+       buf = (u16 *)(buffer + dev->act_len);
+       size = min((int)bufsize, transfer_len - dev->act_len);
+
+       /* write fifo */
+       r8a66597_write(r8a66597, ~(1 << BULK_OUT_PIPENUM), BEMPSTS);
+       if (buffer) {
+               r8a66597_write_fifo(r8a66597, CFIFO, buf, size);
+               r8a66597_write(r8a66597, BVAL, CFIFOCTR);
+       }
+
+       /* update parameters */
+       dev->act_len += size;
+
+       r8a66597_mdfy(r8a66597, PID_BUF, PID,
+                       get_pipectr_addr(BULK_OUT_PIPENUM));
+
+       while (!(r8a66597_read(r8a66597, BEMPSTS) & (1 << BULK_OUT_PIPENUM)))
+               if (ctrlc())
+                       return -1;
+       r8a66597_write(r8a66597, ~(1 << BULK_OUT_PIPENUM), BEMPSTS);
+
+       if (dev->act_len >= transfer_len)
+               r8a66597_mdfy(r8a66597, PID_NAK, PID,
+                               get_pipectr_addr(BULK_OUT_PIPENUM));
+
+       return 0;
+}
+
+static int receive_bulk_packet(struct r8a66597 *r8a66597,
+                              struct usb_device *dev,
+                              unsigned long pipe,
+                              void *buffer, int transfer_len)
+{
+       u16 tmp;
+       u16 *buf;
+       const u16 pipenum = BULK_IN_PIPENUM;
+       int rcv_len;
+       int maxpacket = dev->epmaxpacketin[usb_pipeendpoint(pipe)];
+
+       R8A66597_DPRINT("%s\n", __func__);
+
+       /* prepare */
+       if (dev->act_len == 0) {
+               r8a66597_mdfy(r8a66597, PID_NAK, PID,
+                               get_pipectr_addr(pipenum));
+               r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS);
+
+               r8a66597_write(r8a66597, TRCLR, get_pipetre_addr(pipenum));
+               r8a66597_write(r8a66597,
+                               (transfer_len + maxpacket - 1) / maxpacket,
+                               get_pipetrn_addr(pipenum));
+               r8a66597_bset(r8a66597, TRENB, get_pipetre_addr(pipenum));
+
+               r8a66597_mdfy(r8a66597, PID_BUF, PID,
+                               get_pipectr_addr(pipenum));
+       }
+
+       r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL);
+       r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, pipenum);
+
+       while (!(r8a66597_read(r8a66597, BRDYSTS) & (1 << pipenum)))
+               if (ctrlc())
+                       return -1;
+       r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS);
+
+       tmp = r8a66597_read(r8a66597, CFIFOCTR);
+       if ((tmp & FRDY) == 0) {
+               printf("%s FRDY is not set. (%x)\n", __func__, tmp);
+               return -1;
+       }
+
+       buf = (u16 *)(buffer + dev->act_len);
+       rcv_len = tmp & DTLN;
+       dev->act_len += rcv_len;
+
+       if (buffer) {
+               if (rcv_len == 0)
+                       r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+               else
+                       r8a66597_read_fifo(r8a66597, CFIFO, buf, rcv_len);
+       }
+
+       return 0;
+}
+
+static int receive_control_packet(struct r8a66597 *r8a66597,
+                                 struct usb_device *dev,
+                                 void *buffer, int transfer_len)
+{
+       u16 tmp;
+       int rcv_len;
+
+       /* FIXME: limit transfer size : 64byte or less */
+
+       r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
+       r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL);
+       r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+       r8a66597_bset(r8a66597, SQSET, DCPCTR);
+       r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+       r8a66597_mdfy(r8a66597, PID_BUF, PID, DCPCTR);
+
+       while (!(r8a66597_read(r8a66597, BRDYSTS) & 0x0001))
+               if (ctrlc())
+                       return -1;
+       r8a66597_write(r8a66597, ~0x0001, BRDYSTS);
+
+       r8a66597_mdfy(r8a66597, MBW, MBW | CURPIPE, CFIFOSEL);
+       r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+
+       tmp = r8a66597_read(r8a66597, CFIFOCTR);
+       if ((tmp & FRDY) == 0) {
+               printf("%s FRDY is not set. (%x)\n", __func__, tmp);
+               return -1;
+       }
+
+       rcv_len = tmp & DTLN;
+       dev->act_len += rcv_len;
+
+       r8a66597_mdfy(r8a66597, PID_NAK, PID, DCPCTR);
+
+       if (buffer) {
+               if (rcv_len == 0)
+                       r8a66597_write(r8a66597, BCLR, DCPCTR);
+               else
+                       r8a66597_read_fifo(r8a66597, CFIFO, buffer, rcv_len);
+       }
+
+       return 0;
+}
+
+static int send_status_packet(struct r8a66597 *r8a66597,
+                              unsigned long pipe)
+{
+       r8a66597_bset(r8a66597, SQSET, DCPCTR);
+       r8a66597_mdfy(r8a66597, PID_NAK, PID, DCPCTR);
+
+       if (usb_pipein(pipe)) {
+               r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG);
+               r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL);
+               r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+               r8a66597_write(r8a66597, ~BEMP0, BEMPSTS);
+               r8a66597_write(r8a66597, BCLR | BVAL, CFIFOCTR);
+       } else {
+               r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
+               r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL);
+               r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+               r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+       }
+       r8a66597_mdfy(r8a66597, PID_BUF, PID, DCPCTR);
+
+       while (!(r8a66597_read(r8a66597, BEMPSTS) & 0x0001))
+               if (ctrlc())
+                       return -1;
+
+       return 0;
+}
+
+static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port)
+{
+       int count = R8A66597_MAX_SAMPLING;
+       unsigned short syssts, old_syssts;
+
+       R8A66597_DPRINT("%s\n", __func__);
+
+       old_syssts = r8a66597_read(r8a66597, get_syssts_reg(port) & LNST);
+       while (count > 0) {
+               wait_ms(R8A66597_RH_POLL_TIME);
+
+               syssts = r8a66597_read(r8a66597, get_syssts_reg(port) & LNST);
+               if (syssts == old_syssts) {
+                       count--;
+               } else {
+                       count = R8A66597_MAX_SAMPLING;
+                       old_syssts = syssts;
+               }
+       }
+}
+
+static void r8a66597_bus_reset(struct r8a66597 *r8a66597, int port)
+{
+       wait_ms(10);
+       r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT, get_dvstctr_reg(port));
+       wait_ms(50);
+       r8a66597_mdfy(r8a66597, UACT, USBRST | UACT, get_dvstctr_reg(port));
+       wait_ms(50);
+}
+
+static int check_usb_device_connecting(struct r8a66597 *r8a66597)
+{
+       int timeout = 10000;    /* 100usec * 10000 = 1sec */
+       int i;
+
+       for (i = 0; i < 5; i++) {
+               /* check a usb cable connect */
+               while (!(r8a66597_read(r8a66597, INTSTS1) & ATTCH)) {
+                       if (timeout-- < 0) {
+                               printf("%s timeout.\n", __func__);
+                               return -1;
+                       }
+                       udelay(100);
+               }
+
+               /* check a data line */
+               r8a66597_check_syssts(r8a66597, 0);
+
+               r8a66597_bus_reset(r8a66597, 0);
+               r8a66597->speed = get_rh_usb_speed(r8a66597, 0);
+
+               if (!(r8a66597_read(r8a66597, INTSTS1) & DTCH)) {
+                       r8a66597->port_change = USB_PORT_STAT_C_CONNECTION;
+                       r8a66597->port_status = USB_PORT_STAT_CONNECTION |
+                                               USB_PORT_STAT_ENABLE;
+                       return 0;       /* success */
+               }
+
+               R8A66597_DPRINT("USB device has detached. retry = %d\n", i);
+               r8a66597_write(r8a66597, ~DTCH, INTSTS1);
+       }
+
+       return -1;      /* fail */
+}
+
+/* based on usb_ohci.c */
+#define min_t(type, x, y) \
+               ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; })
+/*-------------------------------------------------------------------------*
+ * Virtual Root Hub
+ *-------------------------------------------------------------------------*/
+
+/* Device descriptor */
+static __u8 root_hub_dev_des[] =
+{
+       0x12,       /*  __u8  bLength; */
+       0x01,       /*  __u8  bDescriptorType; Device */
+       0x10,       /*  __u16 bcdUSB; v1.1 */
+       0x01,
+       0x09,       /*  __u8  bDeviceClass; HUB_CLASSCODE */
+       0x00,       /*  __u8  bDeviceSubClass; */
+       0x00,       /*  __u8  bDeviceProtocol; */
+       0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
+       0x00,       /*  __u16 idVendor; */
+       0x00,
+       0x00,       /*  __u16 idProduct; */
+       0x00,
+       0x00,       /*  __u16 bcdDevice; */
+       0x00,
+       0x00,       /*  __u8  iManufacturer; */
+       0x01,       /*  __u8  iProduct; */
+       0x00,       /*  __u8  iSerialNumber; */
+       0x01        /*  __u8  bNumConfigurations; */
+};
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] =
+{
+       0x09,       /*  __u8  bLength; */
+       0x02,       /*  __u8  bDescriptorType; Configuration */
+       0x19,       /*  __u16 wTotalLength; */
+       0x00,
+       0x01,       /*  __u8  bNumInterfaces; */
+       0x01,       /*  __u8  bConfigurationValue; */
+       0x00,       /*  __u8  iConfiguration; */
+       0x40,       /*  __u8  bmAttributes; */
+
+       0x00,       /*  __u8  MaxPower; */
+
+       /* interface */
+       0x09,       /*  __u8  if_bLength; */
+       0x04,       /*  __u8  if_bDescriptorType; Interface */
+       0x00,       /*  __u8  if_bInterfaceNumber; */
+       0x00,       /*  __u8  if_bAlternateSetting; */
+       0x01,       /*  __u8  if_bNumEndpoints; */
+       0x09,       /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
+       0x00,       /*  __u8  if_bInterfaceSubClass; */
+       0x00,       /*  __u8  if_bInterfaceProtocol; */
+       0x00,       /*  __u8  if_iInterface; */
+
+       /* endpoint */
+       0x07,       /*  __u8  ep_bLength; */
+       0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
+       0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
+       0x03,       /*  __u8  ep_bmAttributes; Interrupt */
+       0x02,       /*  __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
+       0x00,
+       0xff        /*  __u8  ep_bInterval; 255 ms */
+};
+
+static unsigned char root_hub_str_index0[] =
+{
+       0x04,                   /*  __u8  bLength; */
+       0x03,                   /*  __u8  bDescriptorType; String-descriptor */
+       0x09,                   /*  __u8  lang ID */
+       0x04,                   /*  __u8  lang ID */
+};
+
+static unsigned char root_hub_str_index1[] =
+{
+       34,                     /*  __u8  bLength; */
+       0x03,                   /*  __u8  bDescriptorType; String-descriptor */
+       'R',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       '8',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'A',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       '6',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       '6',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       '5',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       '9',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       '7',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       ' ',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'R',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'o',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'o',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       't',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'H',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'u',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'b',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+};
+
+static int r8a66597_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
+                       void *buffer, int transfer_len, struct devrequest *cmd)
+{
+       struct r8a66597 *r8a66597 = &gr8a66597;
+       int leni = transfer_len;
+       int len = 0;
+       int stat = 0;
+       __u16 bmRType_bReq;
+       __u16 wValue;
+       __u16 wIndex;
+       __u16 wLength;
+       unsigned char data[32];
+
+       R8A66597_DPRINT("%s\n", __func__);
+
+       if (usb_pipeint(pipe)) {
+               printf("Root-Hub submit IRQ: NOT implemented");
+               return 0;
+       }
+
+       bmRType_bReq  = cmd->requesttype | (cmd->request << 8);
+       wValue        = cpu_to_le16 (cmd->value);
+       wIndex        = cpu_to_le16 (cmd->index);
+       wLength       = cpu_to_le16 (cmd->length);
+
+       switch (bmRType_bReq) {
+       case RH_GET_STATUS:
+               *(__u16 *)buffer = cpu_to_le16(1);
+               len = 2;
+               break;
+       case RH_GET_STATUS | RH_INTERFACE:
+               *(__u16 *)buffer = cpu_to_le16(0);
+               len = 2;
+               break;
+       case RH_GET_STATUS | RH_ENDPOINT:
+               *(__u16 *)buffer = cpu_to_le16(0);
+               len = 2;
+               break;
+       case RH_GET_STATUS | RH_CLASS:
+               *(__u32 *)buffer = cpu_to_le32(0);
+               len = 4;
+               break;
+       case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+               *(__u32 *)buffer = cpu_to_le32(r8a66597->port_status |
+                                               (r8a66597->port_change << 16));
+               len = 4;
+               break;
+       case RH_CLEAR_FEATURE | RH_ENDPOINT:
+       case RH_CLEAR_FEATURE | RH_CLASS:
+               break;
+
+       case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+               switch (wValue) {
+               case RH_C_PORT_CONNECTION:
+                       r8a66597->port_change &= ~USB_PORT_STAT_C_CONNECTION;
+                       break;
+               }
+               break;
+
+       case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+               switch (wValue) {
+               case (RH_PORT_SUSPEND):
+                       break;
+               case (RH_PORT_RESET):
+                       r8a66597_bus_reset(r8a66597, 0);
+                       break;
+               case (RH_PORT_POWER):
+                       break;
+               case (RH_PORT_ENABLE):
+                       break;
+               }
+               break;
+       case RH_SET_ADDRESS:
+               gr8a66597.rh_devnum = wValue;
+               break;
+       case RH_GET_DESCRIPTOR:
+               switch ((wValue & 0xff00) >> 8) {
+               case (0x01): /* device descriptor */
+                       len = min_t(unsigned int,
+                                 leni,
+                                 min_t(unsigned int,
+                                     sizeof(root_hub_dev_des),
+                                     wLength));
+                       memcpy(buffer, root_hub_dev_des, len);
+                       break;
+               case (0x02): /* configuration descriptor */
+                       len = min_t(unsigned int,
+                                 leni,
+                                 min_t(unsigned int,
+                                     sizeof(root_hub_config_des),
+                                     wLength));
+                       memcpy(buffer, root_hub_config_des, len);
+                       break;
+               case (0x03): /* string descriptors */
+                       if (wValue == 0x0300) {
+                               len = min_t(unsigned int,
+                                         leni,
+                                         min_t(unsigned int,
+                                             sizeof(root_hub_str_index0),
+                                             wLength));
+                               memcpy(buffer, root_hub_str_index0, len);
+                       }
+                       if (wValue == 0x0301) {
+                               len = min_t(unsigned int,
+                                         leni,
+                                         min_t(unsigned int,
+                                             sizeof(root_hub_str_index1),
+                                             wLength));
+                               memcpy(buffer, root_hub_str_index1, len);
+                       }
+                       break;
+               default:
+                       stat = USB_ST_STALLED;
+               }
+               break;
+
+       case RH_GET_DESCRIPTOR | RH_CLASS:
+       {
+               __u32 temp = 0x00000001;
+
+               data[0] = 9;            /* min length; */
+               data[1] = 0x29;
+               data[2] = temp & RH_A_NDP;
+               data[3] = 0;
+               if (temp & RH_A_PSM)
+                       data[3] |= 0x1;
+               if (temp & RH_A_NOCP)
+                       data[3] |= 0x10;
+               else if (temp & RH_A_OCPM)
+                       data[3] |= 0x8;
+
+               /* corresponds to data[4-7] */
+               data[5] = (temp & RH_A_POTPGT) >> 24;
+               data[7] = temp & RH_B_DR;
+               if (data[2] < 7) {
+                       data[8] = 0xff;
+               } else {
+                       data[0] += 2;
+                       data[8] = (temp & RH_B_DR) >> 8;
+                       data[10] = data[9] = 0xff;
+               }
+
+               len = min_t(unsigned int, leni,
+                           min_t(unsigned int, data[0], wLength));
+               memcpy(buffer, data, len);
+               break;
+       }
+
+       case RH_GET_CONFIGURATION:
+               *(__u8 *) buffer = 0x01;
+               len = 1;
+               break;
+       case RH_SET_CONFIGURATION:
+               break;
+       default:
+               R8A66597_DPRINT("unsupported root hub command");
+               stat = USB_ST_STALLED;
+       }
+
+       wait_ms(1);
+
+       len = min_t(int, len, leni);
+
+       dev->act_len = len;
+       dev->status = stat;
+
+       return stat;
+}
+
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                   int transfer_len)
+{
+       struct r8a66597 *r8a66597 = &gr8a66597;
+       int ret = 0;
+
+       R8A66597_DPRINT("%s\n", __func__);
+       R8A66597_DPRINT("pipe = %08x, buffer = %p, len = %d, devnum = %d\n",
+                       pipe, buffer, transfer_len, dev->devnum);
+
+       set_devadd(r8a66597, dev->devnum, dev, 0);
+
+       pipe_buffer_setting(r8a66597, dev, pipe);
+
+       dev->act_len = 0;
+       while (dev->act_len < transfer_len && ret == 0) {
+               if (ctrlc())
+                       return -1;
+
+               if (usb_pipein(pipe))
+                       ret = receive_bulk_packet(r8a66597, dev, pipe, buffer,
+                                                       transfer_len);
+               else
+                       ret = send_bulk_packet(r8a66597, dev, pipe, buffer,
+                                                       transfer_len);
+       }
+
+       if (ret == 0)
+               dev->status = 0;
+
+       return ret;
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe,
+                      void *buffer, int transfer_len, struct devrequest *setup)
+{
+       struct r8a66597 *r8a66597 = &gr8a66597;
+       u16 r8a66597_address = setup->request == USB_REQ_SET_ADDRESS ?
+                                       0 : dev->devnum;
+
+       R8A66597_DPRINT("%s\n", __func__);
+       if (usb_pipedevice(pipe) == r8a66597->rh_devnum)
+               return r8a66597_submit_rh_msg(dev, pipe, buffer, transfer_len,
+                                               setup);
+
+       R8A66597_DPRINT("%s: setup\n", __func__);
+       set_devadd(r8a66597, r8a66597_address, dev, 0);
+
+       if (send_setup_packet(r8a66597, dev, setup) < 0) {
+               printf("setup packet send error\n");
+               return -1;
+       }
+
+       dev->act_len = 0;
+       if (usb_pipein(pipe))
+               if (receive_control_packet(r8a66597, dev, buffer,
+                                               transfer_len) < 0)
+                       return -1;
+
+       if (send_status_packet(r8a66597, pipe) < 0)
+               return -1;
+
+       dev->status = 0;
+
+       return 0;
+}
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                       int transfer_len, int interval)
+{
+       /* no implement */
+       R8A66597_DPRINT("%s\n", __func__);
+       return 0;
+}
+
+void usb_event_poll(void)
+{
+       /* no implement */
+       R8A66597_DPRINT("%s\n", __func__);
+}
+
+int usb_lowlevel_init(void)
+{
+       struct r8a66597 *r8a66597 = &gr8a66597;
+
+       R8A66597_DPRINT("%s\n", __func__);
+
+       memset(r8a66597, 0, sizeof(r8a66597));
+       r8a66597->reg = CONFIG_R8A66597_BASE_ADDR;
+
+       disable_controller(r8a66597);
+       wait_ms(100);
+
+       enable_controller(r8a66597);
+       r8a66597_port_power(r8a66597, 0 , 1);
+
+       /* check usb device */
+       check_usb_device_connecting(r8a66597);
+
+       wait_ms(50);
+
+       return 0;
+}
+
+int usb_lowlevel_stop(void)
+{
+       disable_controller(&gr8a66597);
+
+       return 0;
+}
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h
new file mode 100644 (file)
index 0000000..9af6446
--- /dev/null
@@ -0,0 +1,659 @@
+/*
+ * R8A66597 HCD (Host Controller Driver) for u-boot
+ *
+ * Copyright (C) 2008  Yoshihiro Shimoda <shimoda.yoshihiro@renesas.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; version 2 of the License.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __R8A66597_H__
+#define __R8A66597_H__
+
+#define SYSCFG0                0x00
+#define SYSCFG1                0x02
+#define SYSSTS0                0x04
+#define SYSSTS1                0x06
+#define DVSTCTR0       0x08
+#define DVSTCTR1       0x0A
+#define TESTMODE       0x0C
+#define PINCFG         0x0E
+#define DMA0CFG                0x10
+#define DMA1CFG                0x12
+#define CFIFO          0x14
+#define D0FIFO         0x18
+#define D1FIFO         0x1C
+#define CFIFOSEL       0x20
+#define CFIFOCTR       0x22
+#define CFIFOSIE       0x24
+#define D0FIFOSEL      0x28
+#define D0FIFOCTR      0x2A
+#define D1FIFOSEL      0x2C
+#define D1FIFOCTR      0x2E
+#define INTENB0                0x30
+#define INTENB1                0x32
+#define INTENB2                0x34
+#define BRDYENB                0x36
+#define NRDYENB                0x38
+#define BEMPENB                0x3A
+#define SOFCFG         0x3C
+#define INTSTS0                0x40
+#define INTSTS1                0x42
+#define INTSTS2                0x44
+#define BRDYSTS                0x46
+#define NRDYSTS                0x48
+#define BEMPSTS                0x4A
+#define FRMNUM         0x4C
+#define UFRMNUM                0x4E
+#define USBADDR                0x50
+#define USBREQ         0x54
+#define USBVAL         0x56
+#define USBINDX                0x58
+#define USBLENG                0x5A
+#define DCPCFG         0x5C
+#define DCPMAXP                0x5E
+#define DCPCTR         0x60
+#define PIPESEL                0x64
+#define PIPECFG                0x68
+#define PIPEBUF                0x6A
+#define PIPEMAXP       0x6C
+#define PIPEPERI       0x6E
+#define PIPE1CTR       0x70
+#define PIPE2CTR       0x72
+#define PIPE3CTR       0x74
+#define PIPE4CTR       0x76
+#define PIPE5CTR       0x78
+#define PIPE6CTR       0x7A
+#define PIPE7CTR       0x7C
+#define PIPE8CTR       0x7E
+#define PIPE9CTR       0x80
+#define PIPE1TRE       0x90
+#define PIPE1TRN       0x92
+#define PIPE2TRE       0x94
+#define PIPE2TRN       0x96
+#define PIPE3TRE       0x98
+#define PIPE3TRN       0x9A
+#define PIPE4TRE       0x9C
+#define        PIPE4TRN        0x9E
+#define        PIPE5TRE        0xA0
+#define        PIPE5TRN        0xA2
+#define DEVADD0                0xD0
+#define DEVADD1                0xD2
+#define DEVADD2                0xD4
+#define DEVADD3                0xD6
+#define DEVADD4                0xD8
+#define DEVADD5                0xDA
+#define DEVADD6                0xDC
+#define DEVADD7                0xDE
+#define DEVADD8                0xE0
+#define DEVADD9                0xE2
+#define DEVADDA                0xE4
+
+/* System Configuration Control Register */
+#define        XTAL            0xC000  /* b15-14: Crystal selection */
+#define          XTAL48         0x8000   /* 48MHz */
+#define          XTAL24         0x4000   /* 24MHz */
+#define          XTAL12         0x0000   /* 12MHz */
+#define        XCKE            0x2000  /* b13: External clock enable */
+#define        PLLC            0x0800  /* b11: PLL control */
+#define        SCKE            0x0400  /* b10: USB clock enable */
+#define        PCSDIS          0x0200  /* b9: not CS wakeup */
+#define        LPSME           0x0100  /* b8: Low power sleep mode */
+#define        HSE             0x0080  /* b7: Hi-speed enable */
+#define        DCFM            0x0040  /* b6: Controller function select  */
+#define        DRPD            0x0020  /* b5: D+/- pull down control */
+#define        DPRPU           0x0010  /* b4: D+ pull up control */
+#define        USBE            0x0001  /* b0: USB module operation enable */
+
+/* System Configuration Status Register */
+#define        OVCBIT          0x8000  /* b15-14: Over-current bit */
+#define        OVCMON          0xC000  /* b15-14: Over-current monitor */
+#define        SOFEA           0x0020  /* b5: SOF monitor */
+#define        IDMON           0x0004  /* b3: ID-pin monitor */
+#define        LNST            0x0003  /* b1-0: D+, D- line status */
+#define          SE1            0x0003   /* SE1 */
+#define          FS_KSTS        0x0002   /* Full-Speed K State */
+#define          FS_JSTS        0x0001   /* Full-Speed J State */
+#define          LS_JSTS        0x0002   /* Low-Speed J State */
+#define          LS_KSTS        0x0001   /* Low-Speed K State */
+#define          SE0            0x0000   /* SE0 */
+
+/* Device State Control Register */
+#define        EXTLP0          0x0400  /* b10: External port */
+#define        VBOUT           0x0200  /* b9: VBUS output */
+#define        WKUP            0x0100  /* b8: Remote wakeup */
+#define        RWUPE           0x0080  /* b7: Remote wakeup sense */
+#define        USBRST          0x0040  /* b6: USB reset enable */
+#define        RESUME          0x0020  /* b5: Resume enable */
+#define        UACT            0x0010  /* b4: USB bus enable */
+#define        RHST            0x0007  /* b1-0: Reset handshake status */
+#define          HSPROC         0x0004   /* HS handshake is processing */
+#define          HSMODE         0x0003   /* Hi-Speed mode */
+#define          FSMODE         0x0002   /* Full-Speed mode */
+#define          LSMODE         0x0001   /* Low-Speed mode */
+#define          UNDECID        0x0000   /* Undecided */
+
+/* Test Mode Register */
+#define        UTST                    0x000F  /* b3-0: Test select */
+#define          H_TST_PACKET           0x000C   /* HOST TEST Packet */
+#define          H_TST_SE0_NAK          0x000B   /* HOST TEST SE0 NAK */
+#define          H_TST_K                0x000A   /* HOST TEST K */
+#define          H_TST_J                0x0009   /* HOST TEST J */
+#define          H_TST_NORMAL           0x0000   /* HOST Normal Mode */
+#define          P_TST_PACKET           0x0004   /* PERI TEST Packet */
+#define          P_TST_SE0_NAK          0x0003   /* PERI TEST SE0 NAK */
+#define          P_TST_K                0x0002   /* PERI TEST K */
+#define          P_TST_J                0x0001   /* PERI TEST J */
+#define          P_TST_NORMAL           0x0000   /* PERI Normal Mode */
+
+/* Data Pin Configuration Register */
+#define        LDRV                    0x8000  /* b15: Drive Current Adjust */
+#define          VIF1                    0x0000                /* VIF = 1.8V */
+#define          VIF3                    0x8000                /* VIF = 3.3V */
+#define        INTA                    0x0001  /* b1: USB INT-pin active */
+
+/* DMAx Pin Configuration Register */
+#define        DREQA                   0x4000  /* b14: Dreq active select */
+#define        BURST                   0x2000  /* b13: Burst mode */
+#define        DACKA                   0x0400  /* b10: Dack active select */
+#define        DFORM                   0x0380  /* b9-7: DMA mode select */
+#define          CPU_ADR_RD_WR          0x0000   /* Address + RD/WR mode (CPU bus) */
+#define          CPU_DACK_RD_WR         0x0100   /* DACK + RD/WR mode (CPU bus) */
+#define          CPU_DACK_ONLY          0x0180   /* DACK only mode (CPU bus) */
+#define          SPLIT_DACK_ONLY        0x0200   /* DACK only mode (SPLIT bus) */
+#define        DENDA                   0x0040  /* b6: Dend active select */
+#define        PKTM                    0x0020  /* b5: Packet mode */
+#define        DENDE                   0x0010  /* b4: Dend enable */
+#define        OBUS                    0x0004  /* b2: OUTbus mode */
+
+/* CFIFO/DxFIFO Port Select Register */
+#define        RCNT            0x8000  /* b15: Read count mode */
+#define        REW             0x4000  /* b14: Buffer rewind */
+#define        DCLRM           0x2000  /* b13: DMA buffer clear mode */
+#define        DREQE           0x1000  /* b12: DREQ output enable */
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+#define        MBW             0x0800
+#else
+#define        MBW             0x0400  /* b10: Maximum bit width for FIFO access */
+#endif
+#define          MBW_8          0x0000   /*  8bit */
+#define          MBW_16         0x0400   /* 16bit */
+#define        BIGEND          0x0100  /* b8: Big endian mode */
+#define          BYTE_LITTLE    0x0000         /* little dendian */
+#define          BYTE_BIG       0x0100         /* big endifan */
+#define        ISEL            0x0020  /* b5: DCP FIFO port direction select */
+#define        CURPIPE         0x000F  /* b2-0: PIPE select */
+
+/* CFIFO/DxFIFO Port Control Register */
+#define        BVAL            0x8000  /* b15: Buffer valid flag */
+#define        BCLR            0x4000  /* b14: Buffer clear */
+#define        FRDY            0x2000  /* b13: FIFO ready */
+#define        DTLN            0x0FFF  /* b11-0: FIFO received data length */
+
+/* Interrupt Enable Register 0 */
+#define        VBSE    0x8000  /* b15: VBUS interrupt */
+#define        RSME    0x4000  /* b14: Resume interrupt */
+#define        SOFE    0x2000  /* b13: Frame update interrupt */
+#define        DVSE    0x1000  /* b12: Device state transition interrupt */
+#define        CTRE    0x0800  /* b11: Control transfer stage transition interrupt */
+#define        BEMPE   0x0400  /* b10: Buffer empty interrupt */
+#define        NRDYE   0x0200  /* b9: Buffer not ready interrupt */
+#define        BRDYE   0x0100  /* b8: Buffer ready interrupt */
+
+/* Interrupt Enable Register 1 */
+#define        OVRCRE          0x8000  /* b15: Over-current interrupt */
+#define        BCHGE           0x4000  /* b14: USB us chenge interrupt */
+#define        DTCHE           0x1000  /* b12: Detach sense interrupt */
+#define        ATTCHE          0x0800  /* b11: Attach sense interrupt */
+#define        EOFERRE         0x0040  /* b6: EOF error interrupt */
+#define        SIGNE           0x0020  /* b5: SETUP IGNORE interrupt */
+#define        SACKE           0x0010  /* b4: SETUP ACK interrupt */
+
+/* BRDY Interrupt Enable/Status Register */
+#define        BRDY9           0x0200  /* b9: PIPE9 */
+#define        BRDY8           0x0100  /* b8: PIPE8 */
+#define        BRDY7           0x0080  /* b7: PIPE7 */
+#define        BRDY6           0x0040  /* b6: PIPE6 */
+#define        BRDY5           0x0020  /* b5: PIPE5 */
+#define        BRDY4           0x0010  /* b4: PIPE4 */
+#define        BRDY3           0x0008  /* b3: PIPE3 */
+#define        BRDY2           0x0004  /* b2: PIPE2 */
+#define        BRDY1           0x0002  /* b1: PIPE1 */
+#define        BRDY0           0x0001  /* b1: PIPE0 */
+
+/* NRDY Interrupt Enable/Status Register */
+#define        NRDY9           0x0200  /* b9: PIPE9 */
+#define        NRDY8           0x0100  /* b8: PIPE8 */
+#define        NRDY7           0x0080  /* b7: PIPE7 */
+#define        NRDY6           0x0040  /* b6: PIPE6 */
+#define        NRDY5           0x0020  /* b5: PIPE5 */
+#define        NRDY4           0x0010  /* b4: PIPE4 */
+#define        NRDY3           0x0008  /* b3: PIPE3 */
+#define        NRDY2           0x0004  /* b2: PIPE2 */
+#define        NRDY1           0x0002  /* b1: PIPE1 */
+#define        NRDY0           0x0001  /* b1: PIPE0 */
+
+/* BEMP Interrupt Enable/Status Register */
+#define        BEMP9           0x0200  /* b9: PIPE9 */
+#define        BEMP8           0x0100  /* b8: PIPE8 */
+#define        BEMP7           0x0080  /* b7: PIPE7 */
+#define        BEMP6           0x0040  /* b6: PIPE6 */
+#define        BEMP5           0x0020  /* b5: PIPE5 */
+#define        BEMP4           0x0010  /* b4: PIPE4 */
+#define        BEMP3           0x0008  /* b3: PIPE3 */
+#define        BEMP2           0x0004  /* b2: PIPE2 */
+#define        BEMP1           0x0002  /* b1: PIPE1 */
+#define        BEMP0           0x0001  /* b0: PIPE0 */
+
+/* SOF Pin Configuration Register */
+#define        TRNENSEL        0x0100  /* b8: Select transaction enable period */
+#define        BRDYM           0x0040  /* b6: BRDY clear timing */
+#define        INTL            0x0020  /* b5: Interrupt sense select */
+#define        EDGESTS         0x0010  /* b4:  */
+#define        SOFMODE         0x000C  /* b3-2: SOF pin select */
+#define          SOF_125US      0x0008   /* SOF OUT 125us Frame Signal */
+#define          SOF_1MS        0x0004   /* SOF OUT 1ms Frame Signal */
+#define          SOF_DISABLE    0x0000   /* SOF OUT Disable */
+
+/* Interrupt Status Register 0 */
+#define        VBINT   0x8000  /* b15: VBUS interrupt */
+#define        RESM    0x4000  /* b14: Resume interrupt */
+#define        SOFR    0x2000  /* b13: SOF frame update interrupt */
+#define        DVST    0x1000  /* b12: Device state transition interrupt */
+#define        CTRT    0x0800  /* b11: Control transfer stage transition interrupt */
+#define        BEMP    0x0400  /* b10: Buffer empty interrupt */
+#define        NRDY    0x0200  /* b9: Buffer not ready interrupt */
+#define        BRDY    0x0100  /* b8: Buffer ready interrupt */
+#define        VBSTS   0x0080  /* b7: VBUS input port */
+#define        DVSQ    0x0070  /* b6-4: Device state */
+#define          DS_SPD_CNFG    0x0070   /* Suspend Configured */
+#define          DS_SPD_ADDR    0x0060   /* Suspend Address */
+#define          DS_SPD_DFLT    0x0050   /* Suspend Default */
+#define          DS_SPD_POWR    0x0040   /* Suspend Powered */
+#define          DS_SUSP        0x0040   /* Suspend */
+#define          DS_CNFG        0x0030   /* Configured */
+#define          DS_ADDS        0x0020   /* Address */
+#define          DS_DFLT        0x0010   /* Default */
+#define          DS_POWR        0x0000   /* Powered */
+#define        DVSQS           0x0030  /* b5-4: Device state */
+#define        VALID           0x0008  /* b3: Setup packet detected flag */
+#define        CTSQ            0x0007  /* b2-0: Control transfer stage */
+#define          CS_SQER        0x0006   /* Sequence error */
+#define          CS_WRND        0x0005   /* Control write nodata status stage */
+#define          CS_WRSS        0x0004   /* Control write status stage */
+#define          CS_WRDS        0x0003   /* Control write data stage */
+#define          CS_RDSS        0x0002   /* Control read status stage */
+#define          CS_RDDS        0x0001   /* Control read data stage */
+#define          CS_IDST        0x0000   /* Idle or setup stage */
+
+/* Interrupt Status Register 1 */
+#define        OVRCR           0x8000  /* b15: Over-current interrupt */
+#define        BCHG            0x4000  /* b14: USB bus chenge interrupt */
+#define        DTCH            0x1000  /* b12: Detach sense interrupt */
+#define        ATTCH           0x0800  /* b11: Attach sense interrupt */
+#define        EOFERR          0x0040  /* b6: EOF-error interrupt */
+#define        SIGN            0x0020  /* b5: Setup ignore interrupt */
+#define        SACK            0x0010  /* b4: Setup acknowledge interrupt */
+
+/* Frame Number Register */
+#define        OVRN            0x8000  /* b15: Overrun error */
+#define        CRCE            0x4000  /* b14: Received data error */
+#define        FRNM            0x07FF  /* b10-0: Frame number */
+
+/* Micro Frame Number Register */
+#define        UFRNM           0x0007  /* b2-0: Micro frame number */
+
+/* Default Control Pipe Maxpacket Size Register */
+/* Pipe Maxpacket Size Register */
+#define        DEVSEL  0xF000  /* b15-14: Device address select */
+#define        MAXP    0x007F  /* b6-0: Maxpacket size of default control pipe */
+
+/* Default Control Pipe Control Register */
+#define        BSTS            0x8000  /* b15: Buffer status */
+#define        SUREQ           0x4000  /* b14: Send USB request  */
+#define        CSCLR           0x2000  /* b13: complete-split status clear */
+#define        CSSTS           0x1000  /* b12: complete-split status */
+#define        SUREQCLR        0x0800  /* b11: stop setup request */
+#define        SQCLR           0x0100  /* b8: Sequence toggle bit clear */
+#define        SQSET           0x0080  /* b7: Sequence toggle bit set */
+#define        SQMON           0x0040  /* b6: Sequence toggle bit monitor */
+#define        PBUSY           0x0020  /* b5: pipe busy */
+#define        PINGE           0x0010  /* b4: ping enable */
+#define        CCPL            0x0004  /* b2: Enable control transfer complete */
+#define        PID             0x0003  /* b1-0: Response PID */
+#define          PID_STALL11    0x0003   /* STALL */
+#define          PID_STALL      0x0002   /* STALL */
+#define          PID_BUF        0x0001   /* BUF */
+#define          PID_NAK        0x0000   /* NAK */
+
+/* Pipe Window Select Register */
+#define        PIPENM          0x0007  /* b2-0: Pipe select */
+
+/* Pipe Configuration Register */
+#define        R8A66597_TYP    0xC000  /* b15-14: Transfer type */
+#define          R8A66597_ISO   0xC000           /* Isochronous */
+#define          R8A66597_INT   0x8000           /* Interrupt */
+#define          R8A66597_BULK  0x4000           /* Bulk */
+#define        R8A66597_BFRE   0x0400  /* b10: Buffer ready interrupt mode select */
+#define        R8A66597_DBLB   0x0200  /* b9: Double buffer mode select */
+#define        R8A66597_CNTMD  0x0100  /* b8: Continuous transfer mode select */
+#define        R8A66597_SHTNAK 0x0080  /* b7: Transfer end NAK */
+#define        R8A66597_DIR    0x0010  /* b4: Transfer direction select */
+#define        R8A66597_EPNUM  0x000F  /* b3-0: Eendpoint number select */
+
+/* Pipe Buffer Configuration Register */
+#define        BUFSIZE         0x7C00  /* b14-10: Pipe buffer size */
+#define        BUFNMB          0x007F  /* b6-0: Pipe buffer number */
+#define        PIPE0BUF        256
+#define        PIPExBUF        64
+
+/* Pipe Maxpacket Size Register */
+#define        MXPS            0x07FF  /* b10-0: Maxpacket size */
+
+/* Pipe Cycle Configuration Register */
+#define        IFIS    0x1000  /* b12: Isochronous in-buffer flush mode select */
+#define        IITV    0x0007  /* b2-0: Isochronous interval */
+
+/* Pipex Control Register */
+#define        BSTS    0x8000  /* b15: Buffer status */
+#define        INBUFM  0x4000  /* b14: IN buffer monitor (Only for PIPE1 to 5) */
+#define        CSCLR   0x2000  /* b13: complete-split status clear */
+#define        CSSTS   0x1000  /* b12: complete-split status */
+#define        ATREPM  0x0400  /* b10: Auto repeat mode */
+#define        ACLRM   0x0200  /* b9: Out buffer auto clear mode */
+#define        SQCLR   0x0100  /* b8: Sequence toggle bit clear */
+#define        SQSET   0x0080  /* b7: Sequence toggle bit set */
+#define        SQMON   0x0040  /* b6: Sequence toggle bit monitor */
+#define        PBUSY   0x0020  /* b5: pipe busy */
+#define        PID     0x0003  /* b1-0: Response PID */
+
+/* PIPExTRE */
+#define        TRENB           0x0200  /* b9: Transaction counter enable */
+#define        TRCLR           0x0100  /* b8: Transaction counter clear */
+
+/* PIPExTRN */
+#define        TRNCNT          0xFFFF  /* b15-0: Transaction counter */
+
+/* DEVADDx */
+#define        UPPHUB          0x7800
+#define        HUBPORT         0x0700
+#define        USBSPD          0x00C0
+#define        RTPORT          0x0001
+
+#define R8A66597_MAX_NUM_PIPE          10
+#define R8A66597_BUF_BSIZE             8
+#define R8A66597_MAX_DEVICE            10
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+#define R8A66597_MAX_ROOT_HUB          1
+#else
+#define R8A66597_MAX_ROOT_HUB          2
+#endif
+#define R8A66597_MAX_SAMPLING          5
+#define R8A66597_RH_POLL_TIME          10
+
+#define BULK_IN_PIPENUM                3
+#define BULK_IN_BUFNUM         8
+
+#define BULK_OUT_PIPENUM       4
+#define BULK_OUT_BUFNUM                40
+
+#define check_bulk_or_isoc(pipenum)    ((pipenum >= 1 && pipenum <= 5))
+#define check_interrupt(pipenum)       ((pipenum >= 6 && pipenum <= 9))
+#define make_devsel(addr)              (addr << 12)
+
+struct r8a66597 {
+       unsigned long reg;
+       unsigned short pipe_config;     /* bit field */
+       unsigned short port_status;
+       unsigned short port_change;
+       u16 speed;      /* HSMODE or FSMODE or LSMODE */
+       unsigned char rh_devnum;
+};
+
+static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
+{
+       return inw(r8a66597->reg + offset);
+}
+
+static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
+                                     unsigned long offset, void *buf,
+                                     int len)
+{
+       int i;
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+       unsigned long fifoaddr = r8a66597->reg + offset;
+       unsigned long count;
+       unsigned long *p = buf;
+
+       count = len / 4;
+       for (i = 0; i < count; i++)
+               inl(p[i], r8a66597->reg + offset);
+
+       if (len & 0x00000003) {
+               unsigned long tmp = inl(fifoaddr);
+               memcpy((unsigned char *)buf + count * 4, &tmp, len & 0x03);
+       }
+#else
+       unsigned short *p = buf;
+
+       len = (len + 1) / 2;
+       for (i = 0; i < len; i++)
+               p[i] = inw(r8a66597->reg + offset);
+#endif
+}
+
+static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
+                                 unsigned long offset)
+{
+       outw(val, r8a66597->reg + offset);
+}
+
+static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
+                                      unsigned long offset, void *buf,
+                                      int len)
+{
+       int i;
+       unsigned long fifoaddr = r8a66597->reg + offset;
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+       unsigned long count;
+       unsigned char *pb;
+       unsigned long *p = buf;
+
+       count = len / 4;
+       for (i = 0; i < count; i++)
+               outl(p[i], fifoaddr);
+
+       if (len & 0x00000003) {
+               pb = (unsigned char *)buf + count * 4;
+               for (i = 0; i < (len & 0x00000003); i++) {
+                       if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
+                               outb(pb[i], fifoaddr + i);
+                       else
+                               outb(pb[i], fifoaddr + 3 - i);
+               }
+       }
+#else
+       int odd = len & 0x0001;
+       unsigned short *p = buf;
+
+       len = len / 2;
+       for (i = 0; i < len; i++)
+               outw(p[i], fifoaddr);
+
+       if (odd) {
+               unsigned char *pb = (unsigned char *)(buf + len);
+               outb(*pb, fifoaddr);
+       }
+#endif
+}
+
+static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
+                                u16 val, u16 pat, unsigned long offset)
+{
+       u16 tmp;
+       tmp = r8a66597_read(r8a66597, offset);
+       tmp = tmp & (~pat);
+       tmp = tmp | val;
+       r8a66597_write(r8a66597, tmp, offset);
+}
+
+#define r8a66597_bclr(r8a66597, val, offset)   \
+                       r8a66597_mdfy(r8a66597, 0, val, offset)
+#define r8a66597_bset(r8a66597, val, offset)   \
+                       r8a66597_mdfy(r8a66597, val, 0, offset)
+
+static inline unsigned long get_syscfg_reg(int port)
+{
+       return port == 0 ? SYSCFG0 : SYSCFG1;
+}
+
+static inline unsigned long get_syssts_reg(int port)
+{
+       return port == 0 ? SYSSTS0 : SYSSTS1;
+}
+
+static inline unsigned long get_dvstctr_reg(int port)
+{
+       return port == 0 ? DVSTCTR0 : DVSTCTR1;
+}
+
+static inline unsigned long get_dmacfg_reg(int port)
+{
+       return port == 0 ? DMA0CFG : DMA1CFG;
+}
+
+static inline unsigned long get_intenb_reg(int port)
+{
+       return port == 0 ? INTENB1 : INTENB2;
+}
+
+static inline unsigned long get_intsts_reg(int port)
+{
+       return port == 0 ? INTSTS1 : INTSTS2;
+}
+
+static inline u16 get_rh_usb_speed(struct r8a66597 *r8a66597, int port)
+{
+       unsigned long dvstctr_reg = get_dvstctr_reg(port);
+
+       return r8a66597_read(r8a66597, dvstctr_reg) & RHST;
+}
+
+static inline void r8a66597_port_power(struct r8a66597 *r8a66597, int port,
+                                      int power)
+{
+       unsigned long dvstctr_reg = get_dvstctr_reg(port);
+
+       if (power)
+               r8a66597_bset(r8a66597, VBOUT, dvstctr_reg);
+       else
+               r8a66597_bclr(r8a66597, VBOUT, dvstctr_reg);
+}
+
+#define get_pipectr_addr(pipenum)      (PIPE1CTR + (pipenum - 1) * 2)
+#define get_pipetre_addr(pipenum)      (PIPE1TRE + (pipenum - 1) * 4)
+#define get_pipetrn_addr(pipenum)      (PIPE1TRN + (pipenum - 1) * 4)
+#define get_devadd_addr(address)       (DEVADD0 + address * 2)
+
+
+/* USB HUB CONSTANTS (not OHCI-specific; see hub.h, based on usb_ohci.h) */
+
+/* destination of request */
+#define RH_INTERFACE              0x01
+#define RH_ENDPOINT               0x02
+#define RH_OTHER                  0x03
+
+#define RH_CLASS                  0x20
+#define RH_VENDOR                 0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS          0x0080
+#define RH_CLEAR_FEATURE       0x0100
+#define RH_SET_FEATURE         0x0300
+#define RH_SET_ADDRESS         0x0500
+#define RH_GET_DESCRIPTOR      0x0680
+#define RH_SET_DESCRIPTOR      0x0700
+#define RH_GET_CONFIGURATION   0x0880
+#define RH_SET_CONFIGURATION   0x0900
+#define RH_GET_STATE           0x0280
+#define RH_GET_INTERFACE       0x0A80
+#define RH_SET_INTERFACE       0x0B00
+#define RH_SYNC_FRAME          0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP              0x2000
+
+/* Hub port features */
+#define RH_PORT_CONNECTION        0x00
+#define RH_PORT_ENABLE            0x01
+#define RH_PORT_SUSPEND                   0x02
+#define RH_PORT_OVER_CURRENT      0x03
+#define RH_PORT_RESET             0x04
+#define RH_PORT_POWER             0x08
+#define RH_PORT_LOW_SPEED         0x09
+
+#define RH_C_PORT_CONNECTION      0x10
+#define RH_C_PORT_ENABLE          0x11
+#define RH_C_PORT_SUSPEND         0x12
+#define RH_C_PORT_OVER_CURRENT    0x13
+#define RH_C_PORT_RESET                   0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER      0x00
+#define RH_C_HUB_OVER_CURRENT     0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP           0x00
+#define RH_ENDPOINT_STALL         0x01
+
+#define RH_ACK                    0x01
+#define RH_REQ_ERR                -1
+#define RH_NACK                           0x00
+
+/* OHCI ROOT HUB REGISTER MASKS */
+
+/* roothub.portstatus [i] bits */
+#define RH_PS_CCS      0x00000001      /* current connect status */
+#define RH_PS_PES      0x00000002      /* port enable status*/
+#define RH_PS_PSS      0x00000004      /* port suspend status */
+#define RH_PS_POCI     0x00000008      /* port over current indicator */
+#define RH_PS_PRS      0x00000010      /* port reset status */
+#define RH_PS_PPS      0x00000100      /* port power status */
+#define RH_PS_LSDA     0x00000200      /* low speed device attached */
+#define RH_PS_CSC      0x00010000      /* connect status change */
+#define RH_PS_PESC     0x00020000      /* port enable status change */
+#define RH_PS_PSSC     0x00040000      /* port suspend status change */
+#define RH_PS_OCIC     0x00080000      /* over current indicator change */
+#define RH_PS_PRSC     0x00100000      /* port reset status change */
+
+/* roothub.status bits */
+#define RH_HS_LPS      0x00000001      /* local power status */
+#define RH_HS_OCI      0x00000002      /* over current indicator */
+#define RH_HS_DRWE     0x00008000      /* device remote wakeup enable */
+#define RH_HS_LPSC     0x00010000      /* local power status change */
+#define RH_HS_OCIC     0x00020000      /* over current indicator change */
+#define RH_HS_CRWE     0x80000000      /* clear remote wakeup enable */
+
+/* roothub.b masks */
+#define RH_B_DR                0x0000ffff      /* device removable flags */
+#define RH_B_PPCM      0xffff0000      /* port power control mask */
+
+/* roothub.a masks */
+#define RH_A_NDP       (0xff << 0)     /* number of downstream ports */
+#define RH_A_PSM       (1 << 8)        /* power switching mode */
+#define RH_A_NPS       (1 << 9)        /* no power switching */
+#define RH_A_DT                (1 << 10)       /* device type (mbz) */
+#define RH_A_OCPM      (1 << 11)       /* over current protection mode */
+#define RH_A_NOCP      (1 << 12)       /* no over current protection */
+#define RH_A_POTPGT    (0xff << 24)    /* power on to power good time */
+
+#endif /* __R8A66597_H__ */
diff --git a/drivers/usb/host/s3c64xx-hcd.c b/drivers/usb/host/s3c64xx-hcd.c
new file mode 100644 (file)
index 0000000..274a4ed
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) initialization for USB on the S3C64XX.
+ *
+ * Copyright (C) 2008,
+ * Guennadi Liakhovetski, DENX Software Engineering <lg@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 <s3c6400.h>
+
+int usb_cpu_init(void)
+{
+       OTHERS_REG |= 0x10000;
+       return 0;
+}
+
+int usb_cpu_stop(void)
+{
+       OTHERS_REG &= ~0x10000;
+       return 0;
+}
+
+void usb_cpu_init_fail(void)
+{
+       OTHERS_REG &= ~0x10000;
+}
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
new file mode 100644 (file)
index 0000000..82a8b36
--- /dev/null
@@ -0,0 +1,734 @@
+/*
+ * (C) Copyright 2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * This code is based on linux driver for sl811hs chip, source at
+ * drivers/usb/host/sl811.c:
+ *
+ * SL811 Host Controller Interface driver for USB.
+ *
+ * Copyright (c) 2003/06, Courage Co., Ltd.
+ *
+ * Based on:
+ *     1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap,
+ *       Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber,
+ *       Adam Richter, Gregory P. Smith;
+ *     2.Original SL811 driver (hc_sl811.o) by Pei Liu <pbl@cypress.com>
+ *     3.Rewrited as sl811.o by Yin Aihua <yinah:couragetech.com.cn>
+ *
+ * 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 <mpc8xx.h>
+#include <usb.h>
+#include "sl811.h"
+
+#include "../../../board/kup/common/kup.h"
+
+#ifdef __PPC__
+# define EIEIO         __asm__ volatile ("eieio")
+#else
+# define EIEIO         /* nothing */
+#endif
+
+#define         SL811_ADR (0x50000000)
+#define         SL811_DAT (0x50000001)
+
+#define mdelay(n) ({unsigned long msec=(n); while (msec--) udelay(1000);})
+
+#ifdef SL811_DEBUG
+static int debug = 9;
+#endif
+
+static int root_hub_devnum = 0;
+static struct usb_port_status rh_status = { 0 };/* root hub port status */
+
+static int sl811_rh_submit_urb(struct usb_device *usb_dev, unsigned long pipe,
+                              void *data, int buf_len, struct devrequest *cmd);
+
+static void sl811_write (__u8 index, __u8 data)
+{
+       *(volatile unsigned char *) (SL811_ADR) = index;
+       EIEIO;
+       *(volatile unsigned char *) (SL811_DAT) = data;
+       EIEIO;
+}
+
+static __u8 sl811_read (__u8 index)
+{
+       __u8 data;
+
+       *(volatile unsigned char *) (SL811_ADR) = index;
+       EIEIO;
+       data = *(volatile unsigned char *) (SL811_DAT);
+       EIEIO;
+       return (data);
+}
+
+/*
+ * Read consecutive bytes of data from the SL811H/SL11H buffer
+ */
+static void inline sl811_read_buf(__u8 offset, __u8 *buf, __u8 size)
+{
+       *(volatile unsigned char *) (SL811_ADR) = offset;
+       EIEIO;
+       while (size--) {
+               *buf++ = *(volatile unsigned char *) (SL811_DAT);
+               EIEIO;
+       }
+}
+
+/*
+ * Write consecutive bytes of data to the SL811H/SL11H buffer
+ */
+static void inline sl811_write_buf(__u8 offset, __u8 *buf, __u8 size)
+{
+       *(volatile unsigned char *) (SL811_ADR) = offset;
+       EIEIO;
+       while (size--) {
+               *(volatile unsigned char *) (SL811_DAT) = *buf++;
+               EIEIO;
+       }
+}
+
+int usb_init_kup4x (void)
+{
+       volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+       volatile memctl8xx_t *memctl = &immap->im_memctl;
+       int i;
+       unsigned char tmp;
+
+       memctl = &immap->im_memctl;
+       memctl->memc_or7 = 0xFFFF8726;
+       memctl->memc_br7 = 0x50000401;  /* start at 0x50000000 */
+       /* BP 14 low = USB ON */
+       immap->im_cpm.cp_pbdat &= ~(BP_USB_VCC);
+       /* PB 14 nomal port */
+       immap->im_cpm.cp_pbpar &= ~(BP_USB_VCC);
+       /* output */
+       immap->im_cpm.cp_pbdir |= (BP_USB_VCC);
+
+       puts ("USB:   ");
+
+       for (i = 0x10; i < 0xff; i++) {
+               sl811_write(i, i);
+               tmp = (sl811_read(i));
+               if (tmp != i) {
+                       printf ("SL811 compare error index=0x%02x read=0x%02x\n", i, tmp);
+                       return (-1);
+               }
+       }
+       printf ("SL811 ready\n");
+       return (0);
+}
+
+/*
+ * This function resets SL811HS controller and detects the speed of
+ * the connecting device
+ *
+ * Return: 0 = no device attached; 1 = USB device attached
+ */
+static int sl811_hc_reset(void)
+{
+       int status ;
+
+       sl811_write(SL811_CTRL2, SL811_CTL2_HOST | SL811_12M_HI);
+       sl811_write(SL811_CTRL1, SL811_CTRL1_RESET);
+
+       mdelay(20);
+
+       /* Disable hardware SOF generation, clear all irq status. */
+       sl811_write(SL811_CTRL1, 0);
+       mdelay(2);
+       sl811_write(SL811_INTRSTS, 0xff);
+       status = sl811_read(SL811_INTRSTS);
+
+       if (status & SL811_INTR_NOTPRESENT) {
+               /* Device is not present */
+               PDEBUG(0, "Device not present\n");
+               rh_status.wPortStatus &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE);
+               rh_status.wPortChange |= USB_PORT_STAT_C_CONNECTION;
+               sl811_write(SL811_INTR, SL811_INTR_INSRMV);
+               return 0;
+       }
+
+       /* Send SOF to address 0, endpoint 0. */
+       sl811_write(SL811_LEN_B, 0);
+       sl811_write(SL811_PIDEP_B, PIDEP(USB_PID_SOF, 0));
+       sl811_write(SL811_DEV_B, 0x00);
+       sl811_write(SL811_SOFLOW, SL811_12M_LOW);
+
+       if (status & SL811_INTR_SPEED_FULL) {
+               /* full speed device connect directly to root hub */
+               PDEBUG (0, "Full speed Device attached\n");
+
+               sl811_write(SL811_CTRL1, SL811_CTRL1_RESET);
+               mdelay(20);
+               sl811_write(SL811_CTRL2, SL811_CTL2_HOST | SL811_12M_HI);
+               sl811_write(SL811_CTRL1, SL811_CTRL1_SOF);
+
+               /* start the SOF or EOP */
+               sl811_write(SL811_CTRL_B, SL811_USB_CTRL_ARM);
+               rh_status.wPortStatus |= USB_PORT_STAT_CONNECTION;
+               rh_status.wPortStatus &= ~USB_PORT_STAT_LOW_SPEED;
+               mdelay(2);
+               sl811_write(SL811_INTRSTS, 0xff);
+       } else {
+               /* slow speed device connect directly to root-hub */
+               PDEBUG(0, "Low speed Device attached\n");
+
+               sl811_write(SL811_CTRL1, SL811_CTRL1_RESET);
+               mdelay(20);
+               sl811_write(SL811_CTRL2, SL811_CTL2_HOST | SL811_CTL2_DSWAP | SL811_12M_HI);
+               sl811_write(SL811_CTRL1, SL811_CTRL1_SPEED_LOW | SL811_CTRL1_SOF);
+
+               /* start the SOF or EOP */
+               sl811_write(SL811_CTRL_B, SL811_USB_CTRL_ARM);
+               rh_status.wPortStatus |= USB_PORT_STAT_CONNECTION | USB_PORT_STAT_LOW_SPEED;
+               mdelay(2);
+               sl811_write(SL811_INTRSTS, 0xff);
+       }
+
+       rh_status.wPortChange |= USB_PORT_STAT_C_CONNECTION;
+       sl811_write(SL811_INTR, /*SL811_INTR_INSRMV*/SL811_INTR_DONE_A);
+
+       return 1;
+}
+
+int usb_lowlevel_init(void)
+{
+       root_hub_devnum = 0;
+       sl811_hc_reset();
+       return 0;
+}
+
+int usb_lowlevel_stop(void)
+{
+       sl811_hc_reset();
+       return 0;
+}
+
+static int calc_needed_buswidth(int bytes, int need_preamble)
+{
+       return !need_preamble ? bytes * 8 + 256 : 8 * 8 * bytes + 2048;
+}
+
+static int sl811_send_packet(struct usb_device *dev, unsigned long pipe, __u8 *buffer, int len)
+{
+       __u8 ctrl = SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE;
+       __u16 status = 0;
+       int err = 0, time_start = get_timer(0);
+       int need_preamble = !(rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED) &&
+               usb_pipeslow(pipe);
+
+       if (len > 239)
+               return -1;
+
+       if (usb_pipeout(pipe))
+               ctrl |= SL811_USB_CTRL_DIR_OUT;
+       if (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)))
+               ctrl |= SL811_USB_CTRL_TOGGLE_1;
+       if (need_preamble)
+               ctrl |= SL811_USB_CTRL_PREAMBLE;
+
+       sl811_write(SL811_INTRSTS, 0xff);
+
+       while (err < 3) {
+               sl811_write(SL811_ADDR_A, 0x10);
+               sl811_write(SL811_LEN_A, len);
+               if (usb_pipeout(pipe) && len)
+                       sl811_write_buf(0x10, buffer, len);
+
+               if (!(rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED) &&
+                   sl811_read(SL811_SOFCNTDIV)*64 < calc_needed_buswidth(len, need_preamble))
+                       ctrl |= SL811_USB_CTRL_SOF;
+               else
+                       ctrl &= ~SL811_USB_CTRL_SOF;
+
+               sl811_write(SL811_CTRL_A, ctrl);
+               while (!(sl811_read(SL811_INTRSTS) & SL811_INTR_DONE_A)) {
+                       if (5*CONFIG_SYS_HZ < get_timer(time_start)) {
+                               printf("USB transmit timed out\n");
+                               return -USB_ST_CRC_ERR;
+                       }
+               }
+
+               sl811_write(SL811_INTRSTS, 0xff);
+               status = sl811_read(SL811_STS_A);
+
+               if (status & SL811_USB_STS_ACK) {
+                       int remainder = sl811_read(SL811_CNT_A);
+                       if (remainder) {
+                               PDEBUG(0, "usb transfer remainder = %d\n", remainder);
+                               len -= remainder;
+                       }
+                       if (usb_pipein(pipe) && len)
+                               sl811_read_buf(0x10, buffer, len);
+                       return len;
+               }
+
+               if ((status & SL811_USB_STS_NAK) == SL811_USB_STS_NAK)
+                       continue;
+
+               PDEBUG(0, "usb transfer error %#x\n", (int)status);
+               err++;
+       }
+
+       err = 0;
+
+       if (status & SL811_USB_STS_ERROR)
+               err |= USB_ST_BUF_ERR;
+       if (status & SL811_USB_STS_TIMEOUT)
+               err |= USB_ST_CRC_ERR;
+       if (status & SL811_USB_STS_STALL)
+               err |= USB_ST_STALLED;
+
+       return -err;
+}
+
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                   int len)
+{
+       int dir_out = usb_pipeout(pipe);
+       int ep = usb_pipeendpoint(pipe);
+       int max = usb_maxpacket(dev, pipe);
+       int done = 0;
+
+       PDEBUG(7, "dev = %ld pipe = %ld buf = %p size = %d dir_out = %d\n",
+              usb_pipedevice(pipe), usb_pipeendpoint(pipe), buffer, len, dir_out);
+
+       dev->status = 0;
+
+       sl811_write(SL811_DEV_A, usb_pipedevice(pipe));
+       sl811_write(SL811_PIDEP_A, PIDEP(!dir_out ? USB_PID_IN : USB_PID_OUT, ep));
+       while (done < len) {
+               int res = sl811_send_packet(dev, pipe, (__u8*)buffer+done,
+                                           max > len - done ? len - done : max);
+               if (res < 0) {
+                       dev->status = -res;
+                       return res;
+               }
+
+               if (!dir_out && res < max) /* short packet */
+                       break;
+
+               done += res;
+               usb_dotoggle(dev, ep, dir_out);
+       }
+
+       dev->act_len = done;
+
+       return 0;
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                      int len,struct devrequest *setup)
+{
+       int done = 0;
+       int devnum = usb_pipedevice(pipe);
+       int ep = usb_pipeendpoint(pipe);
+
+       dev->status = 0;
+
+       if (devnum == root_hub_devnum)
+               return sl811_rh_submit_urb(dev, pipe, buffer, len, setup);
+
+       PDEBUG(7, "dev = %d pipe = %ld buf = %p size = %d rt = %#x req = %#x bus = %i\n",
+              devnum, ep, buffer, len, (int)setup->requesttype,
+              (int)setup->request, sl811_read(SL811_SOFCNTDIV)*64);
+
+       sl811_write(SL811_DEV_A, devnum);
+       sl811_write(SL811_PIDEP_A, PIDEP(USB_PID_SETUP, ep));
+       /* setup phase */
+       usb_settoggle(dev, ep, 1, 0);
+       if (sl811_send_packet(dev, usb_sndctrlpipe(dev, ep),
+                             (__u8*)setup, sizeof(*setup)) == sizeof(*setup)) {
+               int dir_in = usb_pipein(pipe);
+               int max = usb_maxpacket(dev, pipe);
+
+               /* data phase */
+               sl811_write(SL811_PIDEP_A,
+                           PIDEP(dir_in ? USB_PID_IN : USB_PID_OUT, ep));
+               usb_settoggle(dev, ep, usb_pipeout(pipe), 1);
+               while (done < len) {
+                       int res = sl811_send_packet(dev, pipe, (__u8*)buffer+done,
+                                                   max > len - done ? len - done : max);
+                       if (res < 0) {
+                               PDEBUG(0, "status data failed!\n");
+                               dev->status = -res;
+                               return 0;
+                       }
+                       done += res;
+                       usb_dotoggle(dev, ep, usb_pipeout(pipe));
+                       if (dir_in && res < max) /* short packet */
+                               break;
+               }
+
+               /* status phase */
+               sl811_write(SL811_PIDEP_A,
+                           PIDEP(!dir_in ? USB_PID_IN : USB_PID_OUT, ep));
+               usb_settoggle(dev, ep, !usb_pipeout(pipe), 1);
+               if (sl811_send_packet(dev,
+                                     !dir_in ? usb_rcvctrlpipe(dev, ep) :
+                                     usb_sndctrlpipe(dev, ep),
+                                     0, 0) < 0) {
+                       PDEBUG(0, "status phase failed!\n");
+                       dev->status = -1;
+               }
+       } else {
+               PDEBUG(0, "setup phase failed!\n");
+               dev->status = -1;
+       }
+
+       dev->act_len = done;
+
+       return done;
+}
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                  int len, int interval)
+{
+       PDEBUG(0, "dev = %p pipe = %#lx buf = %p size = %d int = %d\n", dev, pipe,
+              buffer, len, interval);
+       return -1;
+}
+
+/*
+ * SL811 Virtual Root Hub
+ */
+
+/* Device descriptor */
+static __u8 sl811_rh_dev_des[] =
+{
+       0x12,       /*  __u8  bLength; */
+       0x01,       /*  __u8  bDescriptorType; Device */
+       0x10,       /*  __u16 bcdUSB; v1.1 */
+       0x01,
+       0x09,       /*  __u8  bDeviceClass; HUB_CLASSCODE */
+       0x00,       /*  __u8  bDeviceSubClass; */
+       0x00,       /*  __u8  bDeviceProtocol; */
+       0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
+       0x00,       /*  __u16 idVendor; */
+       0x00,
+       0x00,       /*  __u16 idProduct; */
+       0x00,
+       0x00,       /*  __u16 bcdDevice; */
+       0x00,
+       0x00,       /*  __u8  iManufacturer; */
+       0x02,       /*  __u8  iProduct; */
+       0x01,       /*  __u8  iSerialNumber; */
+       0x01        /*  __u8  bNumConfigurations; */
+};
+
+/* Configuration descriptor */
+static __u8 sl811_rh_config_des[] =
+{
+       0x09,       /*  __u8  bLength; */
+       0x02,       /*  __u8  bDescriptorType; Configuration */
+       0x19,       /*  __u16 wTotalLength; */
+       0x00,
+       0x01,       /*  __u8  bNumInterfaces; */
+       0x01,       /*  __u8  bConfigurationValue; */
+       0x00,       /*  __u8  iConfiguration; */
+       0x40,       /*  __u8  bmAttributes;
+                   Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup,
+                   4..0: resvd */
+       0x00,       /*  __u8  MaxPower; */
+
+       /* interface */
+       0x09,       /*  __u8  if_bLength; */
+       0x04,       /*  __u8  if_bDescriptorType; Interface */
+       0x00,       /*  __u8  if_bInterfaceNumber; */
+       0x00,       /*  __u8  if_bAlternateSetting; */
+       0x01,       /*  __u8  if_bNumEndpoints; */
+       0x09,       /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
+       0x00,       /*  __u8  if_bInterfaceSubClass; */
+       0x00,       /*  __u8  if_bInterfaceProtocol; */
+       0x00,       /*  __u8  if_iInterface; */
+
+       /* endpoint */
+       0x07,       /*  __u8  ep_bLength; */
+       0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
+       0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
+       0x03,       /*  __u8  ep_bmAttributes; Interrupt */
+       0x08,       /*  __u16 ep_wMaxPacketSize; */
+       0x00,
+       0xff        /*  __u8  ep_bInterval; 255 ms */
+};
+
+/* root hub class descriptor*/
+static __u8 sl811_rh_hub_des[] =
+{
+       0x09,                   /*  __u8  bLength; */
+       0x29,                   /*  __u8  bDescriptorType; Hub-descriptor */
+       0x01,                   /*  __u8  bNbrPorts; */
+       0x00,                   /* __u16  wHubCharacteristics; */
+       0x00,
+       0x50,                   /*  __u8  bPwrOn2pwrGood; 2ms */
+       0x00,                   /*  __u8  bHubContrCurrent; 0 mA */
+       0xfc,                   /*  __u8  DeviceRemovable; *** 7 Ports max *** */
+       0xff                    /*  __u8  PortPwrCtrlMask; *** 7 ports max *** */
+};
+
+/*
+ * helper routine for returning string descriptors in UTF-16LE
+ * input can actually be ISO-8859-1; ASCII is its 7-bit subset
+ */
+static int ascii2utf (char *s, u8 *utf, int utfmax)
+{
+       int retval;
+
+       for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) {
+               *utf++ = *s++;
+               *utf++ = 0;
+       }
+       return retval;
+}
+
+/*
+ * root_hub_string is used by each host controller's root hub code,
+ * so that they're identified consistently throughout the system.
+ */
+static int usb_root_hub_string (int id, int serial, char *type, __u8 *data, int len)
+{
+       char buf [30];
+
+       /* assert (len > (2 * (sizeof (buf) + 1)));
+          assert (strlen (type) <= 8);*/
+
+       /* language ids */
+       if (id == 0) {
+               *data++ = 4; *data++ = 3;       /* 4 bytes data */
+               *data++ = 0; *data++ = 0;       /* some language id */
+               return 4;
+
+       /* serial number */
+       } else if (id == 1) {
+               sprintf (buf, "%#x", serial);
+
+       /* product description */
+       } else if (id == 2) {
+               sprintf (buf, "USB %s Root Hub", type);
+
+       /* id 3 == vendor description */
+
+       /* unsupported IDs --> "stall" */
+       } else
+           return 0;
+
+       ascii2utf (buf, data + 2, len - 2);
+       data [0] = 2 + strlen(buf) * 2;
+       data [1] = 3;
+       return data [0];
+}
+
+/* helper macro */
+#define OK(x)  len = (x); break
+
+/*
+ * This function handles all USB request to the the virtual root hub
+ */
+static int sl811_rh_submit_urb(struct usb_device *usb_dev, unsigned long pipe,
+                              void *data, int buf_len, struct devrequest *cmd)
+{
+       __u8 data_buf[16];
+       __u8 *bufp = data_buf;
+       int len = 0;
+       int status = 0;
+
+       __u16 bmRType_bReq;
+       __u16 wValue;
+       __u16 wIndex;
+       __u16 wLength;
+
+       if (usb_pipeint(pipe)) {
+               PDEBUG(0, "interrupt transfer unimplemented!\n");
+               return 0;
+       }
+
+       bmRType_bReq  = cmd->requesttype | (cmd->request << 8);
+       wValue        = le16_to_cpu (cmd->value);
+       wIndex        = le16_to_cpu (cmd->index);
+       wLength       = le16_to_cpu (cmd->length);
+
+       PDEBUG(5, "submit rh urb, req = %d(%x) val = %#x index = %#x len=%d\n",
+              bmRType_bReq, bmRType_bReq, wValue, wIndex, wLength);
+
+       /* Request Destination:
+                  without flags: Device,
+                  USB_RECIP_INTERFACE: interface,
+                  USB_RECIP_ENDPOINT: endpoint,
+                  USB_TYPE_CLASS means HUB here,
+                  USB_RECIP_OTHER | USB_TYPE_CLASS  almost ever means HUB_PORT here
+       */
+       switch (bmRType_bReq) {
+       case RH_GET_STATUS:
+               *(__u16 *)bufp = cpu_to_le16(1);
+               OK(2);
+
+       case RH_GET_STATUS | USB_RECIP_INTERFACE:
+               *(__u16 *)bufp = cpu_to_le16(0);
+               OK(2);
+
+       case RH_GET_STATUS | USB_RECIP_ENDPOINT:
+               *(__u16 *)bufp = cpu_to_le16(0);
+               OK(2);
+
+       case RH_GET_STATUS | USB_TYPE_CLASS:
+               *(__u32 *)bufp = cpu_to_le32(0);
+               OK(4);
+
+       case RH_GET_STATUS | USB_RECIP_OTHER | USB_TYPE_CLASS:
+               *(__u32 *)bufp = cpu_to_le32(rh_status.wPortChange<<16 | rh_status.wPortStatus);
+               OK(4);
+
+       case RH_CLEAR_FEATURE | USB_RECIP_ENDPOINT:
+               switch (wValue) {
+               case 1:
+                       OK(0);
+               }
+               break;
+
+       case RH_CLEAR_FEATURE | USB_TYPE_CLASS:
+               switch (wValue) {
+               case C_HUB_LOCAL_POWER:
+                       OK(0);
+
+               case C_HUB_OVER_CURRENT:
+                       OK(0);
+               }
+               break;
+
+       case RH_CLEAR_FEATURE | USB_RECIP_OTHER | USB_TYPE_CLASS:
+               switch (wValue) {
+               case USB_PORT_FEAT_ENABLE:
+                       rh_status.wPortStatus &= ~USB_PORT_STAT_ENABLE;
+                       OK(0);
+
+               case USB_PORT_FEAT_SUSPEND:
+                       rh_status.wPortStatus &= ~USB_PORT_STAT_SUSPEND;
+                       OK(0);
+
+               case USB_PORT_FEAT_POWER:
+                       rh_status.wPortStatus &= ~USB_PORT_STAT_POWER;
+                       OK(0);
+
+               case USB_PORT_FEAT_C_CONNECTION:
+                       rh_status.wPortChange &= ~USB_PORT_STAT_C_CONNECTION;
+                       OK(0);
+
+               case USB_PORT_FEAT_C_ENABLE:
+                       rh_status.wPortChange &= ~USB_PORT_STAT_C_ENABLE;
+                       OK(0);
+
+               case USB_PORT_FEAT_C_SUSPEND:
+                       rh_status.wPortChange &= ~USB_PORT_STAT_C_SUSPEND;
+                       OK(0);
+
+               case USB_PORT_FEAT_C_OVER_CURRENT:
+                       rh_status.wPortChange &= ~USB_PORT_STAT_C_OVERCURRENT;
+                       OK(0);
+
+               case USB_PORT_FEAT_C_RESET:
+                       rh_status.wPortChange &= ~USB_PORT_STAT_C_RESET;
+                       OK(0);
+               }
+               break;
+
+       case RH_SET_FEATURE | USB_RECIP_OTHER | USB_TYPE_CLASS:
+               switch (wValue) {
+               case USB_PORT_FEAT_SUSPEND:
+                       rh_status.wPortStatus |= USB_PORT_STAT_SUSPEND;
+                       OK(0);
+
+               case USB_PORT_FEAT_RESET:
+                       rh_status.wPortStatus |= USB_PORT_STAT_RESET;
+                       rh_status.wPortChange = 0;
+                       rh_status.wPortChange |= USB_PORT_STAT_C_RESET;
+                       rh_status.wPortStatus &= ~USB_PORT_STAT_RESET;
+                       rh_status.wPortStatus |= USB_PORT_STAT_ENABLE;
+                       OK(0);
+
+               case USB_PORT_FEAT_POWER:
+                       rh_status.wPortStatus |= USB_PORT_STAT_POWER;
+                       OK(0);
+
+               case USB_PORT_FEAT_ENABLE:
+                       rh_status.wPortStatus |= USB_PORT_STAT_ENABLE;
+                       OK(0);
+               }
+               break;
+
+       case RH_SET_ADDRESS:
+               root_hub_devnum = wValue;
+               OK(0);
+
+       case RH_GET_DESCRIPTOR:
+               switch ((wValue & 0xff00) >> 8) {
+               case USB_DT_DEVICE:
+                       len = sizeof(sl811_rh_dev_des);
+                       bufp = sl811_rh_dev_des;
+                       OK(len);
+
+               case USB_DT_CONFIG:
+                       len = sizeof(sl811_rh_config_des);
+                       bufp = sl811_rh_config_des;
+                       OK(len);
+
+               case USB_DT_STRING:
+                       len = usb_root_hub_string(wValue & 0xff, (int)(long)0,  "SL811HS", data, wLength);
+                       if (len > 0) {
+                               bufp = data;
+                               OK(len);
+                       }
+
+               default:
+                       status = -32;
+               }
+               break;
+
+       case RH_GET_DESCRIPTOR | USB_TYPE_CLASS:
+               len = sizeof(sl811_rh_hub_des);
+               bufp = sl811_rh_hub_des;
+               OK(len);
+
+       case RH_GET_CONFIGURATION:
+               bufp[0] = 0x01;
+               OK(1);
+
+       case RH_SET_CONFIGURATION:
+               OK(0);
+
+       default:
+               PDEBUG(1, "unsupported root hub command\n");
+               status = -32;
+       }
+
+       len = min(len, buf_len);
+       if (data != bufp)
+               memcpy(data, bufp, len);
+
+       PDEBUG(5, "len = %d, status = %d\n", len, status);
+
+       usb_dev->status = status;
+       usb_dev->act_len = len;
+
+       return status == 0 ? len : status;
+}
diff --git a/drivers/usb/host/sl811.h b/drivers/usb/host/sl811.h
new file mode 100644 (file)
index 0000000..c1f9f01
--- /dev/null
@@ -0,0 +1,104 @@
+#ifndef __UBOOT_SL811_H
+#define __UBOOT_SL811_H
+
+#undef SL811_DEBUG
+
+#ifdef SL811_DEBUG
+       #define PDEBUG(level, fmt, args...) \
+               if (debug >= (level)) printf("[%s:%d] " fmt, \
+               __PRETTY_FUNCTION__, __LINE__ , ## args)
+#else
+       #define PDEBUG(level, fmt, args...) do {} while(0)
+#endif
+
+/* Sl811 host control register */
+#define        SL811_CTRL_A            0x00
+#define        SL811_ADDR_A            0x01
+#define        SL811_LEN_A             0x02
+#define        SL811_STS_A             0x03    /* read */
+#define        SL811_PIDEP_A           0x03    /* write */
+#define        SL811_CNT_A             0x04    /* read */
+#define        SL811_DEV_A             0x04    /* write */
+#define        SL811_CTRL1             0x05
+#define        SL811_INTR              0x06
+#define        SL811_CTRL_B            0x08
+#define        SL811_ADDR_B            0x09
+#define        SL811_LEN_B             0x0A
+#define        SL811_STS_B             0x0B    /* read */
+#define        SL811_PIDEP_B           0x0B    /* write */
+#define        SL811_CNT_B             0x0C    /* read */
+#define        SL811_DEV_B             0x0C    /* write */
+#define        SL811_INTRSTS           0x0D    /* write clears bitwise */
+#define        SL811_HWREV             0x0E    /* read */
+#define        SL811_SOFLOW            0x0E    /* write */
+#define        SL811_SOFCNTDIV         0x0F    /* read */
+#define        SL811_CTRL2             0x0F    /* write */
+
+/* USB control register bits (addr 0x00 and addr 0x08) */
+#define        SL811_USB_CTRL_ARM      0x01
+#define        SL811_USB_CTRL_ENABLE   0x02
+#define        SL811_USB_CTRL_DIR_OUT  0x04
+#define        SL811_USB_CTRL_ISO      0x10
+#define        SL811_USB_CTRL_SOF      0x20
+#define        SL811_USB_CTRL_TOGGLE_1 0x40
+#define        SL811_USB_CTRL_PREAMBLE 0x80
+
+/* USB status register bits (addr 0x03 and addr 0x0B) */
+#define        SL811_USB_STS_ACK       0x01
+#define        SL811_USB_STS_ERROR     0x02
+#define        SL811_USB_STS_TIMEOUT   0x04
+#define        SL811_USB_STS_TOGGLE_1  0x08
+#define        SL811_USB_STS_SETUP     0x10
+#define        SL811_USB_STS_OVERFLOW  0x20
+#define        SL811_USB_STS_NAK       0x40
+#define        SL811_USB_STS_STALL     0x80
+
+/* Control register 1 bits (addr 0x05) */
+#define        SL811_CTRL1_SOF         0x01
+#define        SL811_CTRL1_RESET       0x08
+#define        SL811_CTRL1_JKSTATE     0x10
+#define        SL811_CTRL1_SPEED_LOW   0x20
+#define        SL811_CTRL1_SUSPEND     0x40
+
+/* Interrut enable (addr 0x06) and interrupt status register bits (addr 0x0D) */
+#define        SL811_INTR_DONE_A       0x01
+#define        SL811_INTR_DONE_B       0x02
+#define        SL811_INTR_SOF          0x10
+#define        SL811_INTR_INSRMV       0x20
+#define        SL811_INTR_DETECT       0x40
+#define        SL811_INTR_NOTPRESENT   0x40
+#define        SL811_INTR_SPEED_FULL   0x80    /* only in status reg */
+
+/* HW rev and SOF lo register bits (addr 0x0E) */
+#define        SL811_HWR_HWREV         0xF0
+
+/* SOF counter and control reg 2 (addr 0x0F) */
+#define        SL811_CTL2_SOFHI        0x3F
+#define        SL811_CTL2_DSWAP        0x40
+#define        SL811_CTL2_HOST         0x80
+
+/* Set up for 1-ms SOF time. */
+#define SL811_12M_LOW          0xE0
+#define SL811_12M_HI           0x2E
+
+#define SL811_DATA_START       0x10
+#define SL811_DATA_LIMIT       240
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS           0x0080
+#define RH_CLEAR_FEATURE        0x0100
+#define RH_SET_FEATURE          0x0300
+#define RH_SET_ADDRESS         0x0500
+#define RH_GET_DESCRIPTOR      0x0680
+#define RH_SET_DESCRIPTOR       0x0700
+#define RH_GET_CONFIGURATION   0x0880
+#define RH_SET_CONFIGURATION   0x0900
+#define RH_GET_STATE            0x0280
+#define RH_GET_INTERFACE        0x0A80
+#define RH_SET_INTERFACE        0x0B00
+#define RH_SYNC_FRAME           0x0C80
+
+
+#define PIDEP(pid, ep) (((pid) & 0x0f) << 4 | (ep))
+
+#endif /* __UBOOT_SL811_H */
diff --git a/drivers/usb/isp116x-hcd.c b/drivers/usb/isp116x-hcd.c
deleted file mode 100644 (file)
index 348e404..0000000
+++ /dev/null
@@ -1,1441 +0,0 @@
-/*
- * ISP116x HCD (Host Controller Driver) for u-boot.
- *
- * Copyright (C) 2006-2007 Rodolfo Giometti <giometti@linux.it>
- * Copyright (C) 2006-2007 Eurotech S.p.A. <info@eurotech.it>
- *
- * 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
- *
- *
- * Derived in part from the SL811 HCD driver "u-boot/drivers/usb/sl811_usb.c"
- * (original copyright message follows):
- *
- *    (C) Copyright 2004
- *    Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- *    This code is based on linux driver for sl811hs chip, source at
- *    drivers/usb/host/sl811.c:
- *
- *    SL811 Host Controller Interface driver for USB.
- *
- *    Copyright (c) 2003/06, Courage Co., Ltd.
- *
- *    Based on:
- *         1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap,
- *           Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber,
- *           Adam Richter, Gregory P. Smith;
- *         2.Original SL811 driver (hc_sl811.o) by Pei Liu <pbl@cypress.com>
- *         3.Rewrited as sl811.o by Yin Aihua <yinah:couragetech.com.cn>
- *
- *    [[GNU/GPL disclaimer]]
- *
- * and in part from AU1x00 OHCI HCD driver "u-boot/cpu/mips/au1x00_usb_ohci.c"
- * (original copyright message follows):
- *
- *    URB OHCI HCD (Host Controller Driver) for USB on the AU1x00.
- *
- *    (C) Copyright 2003
- *    Gary Jennejohn, DENX Software Engineering <gj@denx.de>
- *
- *    [[GNU/GPL disclaimer]]
- *
- *    Note: Part of this code has been derived from linux
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <usb.h>
-#include <malloc.h>
-#include <linux/list.h>
-
-/*
- * ISP116x chips require certain delays between accesses to its
- * registers. The following timing options exist.
- *
- * 1. Configure your memory controller (the best)
- * 2. Use ndelay (easiest, poorest). For that, enable the following macro.
- *
- * Value is in microseconds.
- */
-#ifdef ISP116X_HCD_USE_UDELAY
-#define UDELAY         1
-#endif
-
-/*
- * On some (slowly?) machines an extra delay after data packing into
- * controller's FIFOs is required, * otherwise you may get the following
- * error:
- *
- *   uboot> usb start
- *   (Re)start USB...
- *   USB:   scanning bus for devices... isp116x: isp116x_submit_job: CTL:TIMEOUT
- *   isp116x: isp116x_submit_job: ****** FIFO not ready! ******
- *
- *         USB device not responding, giving up (status=4)
- *         isp116x: isp116x_submit_job: ****** FIFO not empty! ******
- *         isp116x: isp116x_submit_job: ****** FIFO not empty! ******
- *         isp116x: isp116x_submit_job: ****** FIFO not empty! ******
- *         3 USB Device(s) found
- *                scanning bus for storage devices... 0 Storage Device(s) found
- *
- * Value is in milliseconds.
- */
-#ifdef ISP116X_HCD_USE_EXTRA_DELAY
-#define EXTRA_DELAY    2
-#endif
-
-/*
- * Enable the following defines if you wish enable debugging messages.
- */
-#undef DEBUG                   /* enable debugging messages */
-#undef TRACE                   /* enable tracing code */
-#undef VERBOSE                 /* verbose debugging messages */
-
-#include "isp116x.h"
-
-#define DRIVER_VERSION "08 Jan 2007"
-static const char hcd_name[] = "isp116x-hcd";
-
-struct isp116x isp116x_dev;
-struct isp116x_platform_data isp116x_board;
-static int got_rhsc;           /* root hub status change */
-struct usb_device *devgone;    /* device which was disconnected */
-static int rh_devnum;          /* address of Root Hub endpoint */
-
-/* ------------------------------------------------------------------------- */
-
-#define ALIGN(x,a)     (((x)+(a)-1UL)&~((a)-1UL))
-#define min_t(type,x,y)        \
-       ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; })
-
-/* ------------------------------------------------------------------------- */
-
-static int isp116x_reset(struct isp116x *isp116x);
-
-/* --- Debugging functions ------------------------------------------------- */
-
-#define isp116x_show_reg(d, r) {                               \
-       if ((r) < 0x20) {                                       \
-               DBG("%-12s[%02x]: %08x", #r,                    \
-                       r, isp116x_read_reg32(d, r));           \
-       } else {                                                \
-               DBG("%-12s[%02x]:     %04x", #r,                \
-                       r, isp116x_read_reg16(d, r));           \
-       }                                                       \
-}
-
-#define isp116x_show_regs(d) {                                 \
-       isp116x_show_reg(d, HCREVISION);                        \
-       isp116x_show_reg(d, HCCONTROL);                         \
-       isp116x_show_reg(d, HCCMDSTAT);                         \
-       isp116x_show_reg(d, HCINTSTAT);                         \
-       isp116x_show_reg(d, HCINTENB);                          \
-       isp116x_show_reg(d, HCFMINTVL);                         \
-       isp116x_show_reg(d, HCFMREM);                           \
-       isp116x_show_reg(d, HCFMNUM);                           \
-       isp116x_show_reg(d, HCLSTHRESH);                        \
-       isp116x_show_reg(d, HCRHDESCA);                         \
-       isp116x_show_reg(d, HCRHDESCB);                         \
-       isp116x_show_reg(d, HCRHSTATUS);                        \
-       isp116x_show_reg(d, HCRHPORT1);                         \
-       isp116x_show_reg(d, HCRHPORT2);                         \
-       isp116x_show_reg(d, HCHWCFG);                           \
-       isp116x_show_reg(d, HCDMACFG);                          \
-       isp116x_show_reg(d, HCXFERCTR);                         \
-       isp116x_show_reg(d, HCuPINT);                           \
-       isp116x_show_reg(d, HCuPINTENB);                        \
-       isp116x_show_reg(d, HCCHIPID);                          \
-       isp116x_show_reg(d, HCSCRATCH);                         \
-       isp116x_show_reg(d, HCITLBUFLEN);                       \
-       isp116x_show_reg(d, HCATLBUFLEN);                       \
-       isp116x_show_reg(d, HCBUFSTAT);                         \
-       isp116x_show_reg(d, HCRDITL0LEN);                       \
-       isp116x_show_reg(d, HCRDITL1LEN);                       \
-}
-
-#if defined(TRACE)
-
-static int isp116x_get_current_frame_number(struct usb_device *usb_dev)
-{
-       struct isp116x *isp116x = &isp116x_dev;
-
-       return isp116x_read_reg32(isp116x, HCFMNUM);
-}
-
-static void dump_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-                    int len, char *str)
-{
-#if defined(VERBOSE)
-       int i;
-#endif
-
-       DBG("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d stat:%#lx",
-           str,
-           isp116x_get_current_frame_number(dev),
-           usb_pipedevice(pipe),
-           usb_pipeendpoint(pipe),
-           usb_pipeout(pipe) ? 'O' : 'I',
-           usb_pipetype(pipe) < 2 ?
-           (usb_pipeint(pipe) ?
-            "INTR" : "ISOC") :
-           (usb_pipecontrol(pipe) ? "CTRL" : "BULK"), len, dev->status);
-#if defined(VERBOSE)
-       if (len > 0 && buffer) {
-               printf(__FILE__ ": data(%d):", len);
-               for (i = 0; i < 16 && i < len; i++)
-                       printf(" %02x", ((__u8 *) buffer)[i]);
-               printf("%s\n", i < len ? "..." : "");
-       }
-#endif
-}
-
-#define PTD_DIR_STR(ptd)  ({char __c;          \
-       switch(PTD_GET_DIR(ptd)){               \
-       case 0:  __c = 's'; break;              \
-       case 1:  __c = 'o'; break;              \
-       default: __c = 'i'; break;              \
-       }; __c;})
-
-/*
-  Dump PTD info. The code documents the format
-  perfectly, right :)
-*/
-static inline void dump_ptd(struct ptd *ptd)
-{
-#if defined(VERBOSE)
-       int k;
-#endif
-
-       DBG("PTD(ext) : cc:%x %d%c%d %d,%d,%d t:%x %x%x%x",
-           PTD_GET_CC(ptd),
-           PTD_GET_FA(ptd), PTD_DIR_STR(ptd), PTD_GET_EP(ptd),
-           PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd),
-           PTD_GET_TOGGLE(ptd),
-           PTD_GET_ACTIVE(ptd), PTD_GET_SPD(ptd), PTD_GET_LAST(ptd));
-#if defined(VERBOSE)
-       printf("isp116x: %s: PTD(byte): ", __FUNCTION__);
-       for (k = 0; k < sizeof(struct ptd); ++k)
-               printf("%02x ", ((u8 *) ptd)[k]);
-       printf("\n");
-#endif
-}
-
-static inline void dump_ptd_data(struct ptd *ptd, u8 * buf, int type)
-{
-#if defined(VERBOSE)
-       int k;
-
-       if (type == 0 /* 0ut data */ ) {
-               printf("isp116x: %s: out data: ", __FUNCTION__);
-               for (k = 0; k < PTD_GET_LEN(ptd); ++k)
-                       printf("%02x ", ((u8 *) buf)[k]);
-               printf("\n");
-       }
-       if (type == 1 /* 1n data */ ) {
-               printf("isp116x: %s: in data: ", __FUNCTION__);
-               for (k = 0; k < PTD_GET_COUNT(ptd); ++k)
-                       printf("%02x ", ((u8 *) buf)[k]);
-               printf("\n");
-       }
-
-       if (PTD_GET_LAST(ptd))
-               DBG("--- last PTD ---");
-#endif
-}
-
-#else
-
-#define dump_msg(dev, pipe, buffer, len, str)                  do { } while (0)
-#define dump_pkt(dev, pipe, buffer, len, setup, str, small)    do {} while (0)
-
-#define dump_ptd(ptd)                  do {} while (0)
-#define dump_ptd_data(ptd, buf, type)  do {} while (0)
-
-#endif
-
-/* --- Virtual Root Hub ---------------------------------------------------- */
-
-/* Device descriptor */
-static __u8 root_hub_dev_des[] = {
-       0x12,                   /*  __u8  bLength; */
-       0x01,                   /*  __u8  bDescriptorType; Device */
-       0x10,                   /*  __u16 bcdUSB; v1.1 */
-       0x01,
-       0x09,                   /*  __u8  bDeviceClass; HUB_CLASSCODE */
-       0x00,                   /*  __u8  bDeviceSubClass; */
-       0x00,                   /*  __u8  bDeviceProtocol; */
-       0x08,                   /*  __u8  bMaxPacketSize0; 8 Bytes */
-       0x00,                   /*  __u16 idVendor; */
-       0x00,
-       0x00,                   /*  __u16 idProduct; */
-       0x00,
-       0x00,                   /*  __u16 bcdDevice; */
-       0x00,
-       0x00,                   /*  __u8  iManufacturer; */
-       0x01,                   /*  __u8  iProduct; */
-       0x00,                   /*  __u8  iSerialNumber; */
-       0x01                    /*  __u8  bNumConfigurations; */
-};
-
-/* Configuration descriptor */
-static __u8 root_hub_config_des[] = {
-       0x09,                   /*  __u8  bLength; */
-       0x02,                   /*  __u8  bDescriptorType; Configuration */
-       0x19,                   /*  __u16 wTotalLength; */
-       0x00,
-       0x01,                   /*  __u8  bNumInterfaces; */
-       0x01,                   /*  __u8  bConfigurationValue; */
-       0x00,                   /*  __u8  iConfiguration; */
-       0x40,                   /*  __u8  bmAttributes;
-                                  Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
-       0x00,                   /*  __u8  MaxPower; */
-
-       /* interface */
-       0x09,                   /*  __u8  if_bLength; */
-       0x04,                   /*  __u8  if_bDescriptorType; Interface */
-       0x00,                   /*  __u8  if_bInterfaceNumber; */
-       0x00,                   /*  __u8  if_bAlternateSetting; */
-       0x01,                   /*  __u8  if_bNumEndpoints; */
-       0x09,                   /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
-       0x00,                   /*  __u8  if_bInterfaceSubClass; */
-       0x00,                   /*  __u8  if_bInterfaceProtocol; */
-       0x00,                   /*  __u8  if_iInterface; */
-
-       /* endpoint */
-       0x07,                   /*  __u8  ep_bLength; */
-       0x05,                   /*  __u8  ep_bDescriptorType; Endpoint */
-       0x81,                   /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
-       0x03,                   /*  __u8  ep_bmAttributes; Interrupt */
-       0x00,                   /*  __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
-       0x02,
-       0xff                    /*  __u8  ep_bInterval; 255 ms */
-};
-
-static unsigned char root_hub_str_index0[] = {
-       0x04,                   /*  __u8  bLength; */
-       0x03,                   /*  __u8  bDescriptorType; String-descriptor */
-       0x09,                   /*  __u8  lang ID */
-       0x04,                   /*  __u8  lang ID */
-};
-
-static unsigned char root_hub_str_index1[] = {
-       0x22,                   /*  __u8  bLength; */
-       0x03,                   /*  __u8  bDescriptorType; String-descriptor */
-       'I',                    /*  __u8  Unicode */
-       0,                      /*  __u8  Unicode */
-       'S',                    /*  __u8  Unicode */
-       0,                      /*  __u8  Unicode */
-       'P',                    /*  __u8  Unicode */
-       0,                      /*  __u8  Unicode */
-       '1',                    /*  __u8  Unicode */
-       0,                      /*  __u8  Unicode */
-       '1',                    /*  __u8  Unicode */
-       0,                      /*  __u8  Unicode */
-       '6',                    /*  __u8  Unicode */
-       0,                      /*  __u8  Unicode */
-       'x',                    /*  __u8  Unicode */
-       0,                      /*  __u8  Unicode */
-       ' ',                    /*  __u8  Unicode */
-       0,                      /*  __u8  Unicode */
-       'R',                    /*  __u8  Unicode */
-       0,                      /*  __u8  Unicode */
-       'o',                    /*  __u8  Unicode */
-       0,                      /*  __u8  Unicode */
-       'o',                    /*  __u8  Unicode */
-       0,                      /*  __u8  Unicode */
-       't',                    /*  __u8  Unicode */
-       0,                      /*  __u8  Unicode */
-       ' ',                    /*  __u8  Unicode */
-       0,                      /*  __u8  Unicode */
-       'H',                    /*  __u8  Unicode */
-       0,                      /*  __u8  Unicode */
-       'u',                    /*  __u8  Unicode */
-       0,                      /*  __u8  Unicode */
-       'b',                    /*  __u8  Unicode */
-       0,                      /*  __u8  Unicode */
-};
-
-/*
- * Hub class-specific descriptor is constructed dynamically
- */
-
-/* --- Virtual root hub management functions ------------------------------- */
-
-static int rh_check_port_status(struct isp116x *isp116x)
-{
-       u32 temp, ndp, i;
-       int res;
-
-       res = -1;
-       temp = isp116x_read_reg32(isp116x, HCRHSTATUS);
-       ndp = (temp & RH_A_NDP);
-       for (i = 0; i < ndp; i++) {
-               temp = isp116x_read_reg32(isp116x, HCRHPORT1 + i);
-               /* check for a device disconnect */
-               if (((temp & (RH_PS_PESC | RH_PS_CSC)) ==
-                    (RH_PS_PESC | RH_PS_CSC)) && ((temp & RH_PS_CCS) == 0)) {
-                       res = i;
-                       break;
-               }
-       }
-       return res;
-}
-
-/* --- HC management functions --------------------------------------------- */
-
-/* Write len bytes to fifo, pad till 32-bit boundary
- */
-static void write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, int len)
-{
-       u8 *dp = (u8 *) buf;
-       u16 *dp2 = (u16 *) buf;
-       u16 w;
-       int quot = len % 4;
-
-       if ((unsigned long)dp2 & 1) {
-               /* not aligned */
-               for (; len > 1; len -= 2) {
-                       w = *dp++;
-                       w |= *dp++ << 8;
-                       isp116x_raw_write_data16(isp116x, w);
-               }
-               if (len)
-                       isp116x_write_data16(isp116x, (u16) * dp);
-       } else {
-               /* aligned */
-               for (; len > 1; len -= 2)
-                       isp116x_raw_write_data16(isp116x, *dp2++);
-               if (len)
-                       isp116x_write_data16(isp116x, 0xff & *((u8 *) dp2));
-       }
-       if (quot == 1 || quot == 2)
-               isp116x_raw_write_data16(isp116x, 0);
-}
-
-/* Read len bytes from fifo and then read till 32-bit boundary
- */
-static void read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, int len)
-{
-       u8 *dp = (u8 *) buf;
-       u16 *dp2 = (u16 *) buf;
-       u16 w;
-       int quot = len % 4;
-
-       if ((unsigned long)dp2 & 1) {
-               /* not aligned */
-               for (; len > 1; len -= 2) {
-                       w = isp116x_raw_read_data16(isp116x);
-                       *dp++ = w & 0xff;
-                       *dp++ = (w >> 8) & 0xff;
-               }
-               if (len)
-                       *dp = 0xff & isp116x_read_data16(isp116x);
-       } else {
-               /* aligned */
-               for (; len > 1; len -= 2)
-                       *dp2++ = isp116x_raw_read_data16(isp116x);
-               if (len)
-                       *(u8 *) dp2 = 0xff & isp116x_read_data16(isp116x);
-       }
-       if (quot == 1 || quot == 2)
-               isp116x_raw_read_data16(isp116x);
-}
-
-/* Write PTD's and data for scheduled transfers into the fifo ram.
- * Fifo must be empty and ready */
-static void pack_fifo(struct isp116x *isp116x, struct usb_device *dev,
-                     unsigned long pipe, struct ptd *ptd, int n, void *data,
-                     int len)
-{
-       int buflen = n * sizeof(struct ptd) + len;
-       int i, done;
-
-       DBG("--- pack buffer %p - %d bytes (fifo %d) ---", data, len, buflen);
-
-       isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT);
-       isp116x_write_reg16(isp116x, HCXFERCTR, buflen);
-       isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET);
-
-       done = 0;
-       for (i = 0; i < n; i++) {
-               DBG("i=%d - done=%d - len=%d", i, done, PTD_GET_LEN(&ptd[i]));
-
-               dump_ptd(&ptd[i]);
-               isp116x_write_data16(isp116x, ptd[i].count);
-               isp116x_write_data16(isp116x, ptd[i].mps);
-               isp116x_write_data16(isp116x, ptd[i].len);
-               isp116x_write_data16(isp116x, ptd[i].faddr);
-
-               dump_ptd_data(&ptd[i], (__u8 *) data + done, 0);
-               write_ptddata_to_fifo(isp116x,
-                                     (__u8 *) data + done,
-                                     PTD_GET_LEN(&ptd[i]));
-
-               done += PTD_GET_LEN(&ptd[i]);
-       }
-}
-
-/* Read the processed PTD's and data from fifo ram back to URBs' buffers.
- * Fifo must be full and done */
-static int unpack_fifo(struct isp116x *isp116x, struct usb_device *dev,
-                      unsigned long pipe, struct ptd *ptd, int n, void *data,
-                      int len)
-{
-       int buflen = n * sizeof(struct ptd) + len;
-       int i, done, cc, ret;
-
-       isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT);
-       isp116x_write_reg16(isp116x, HCXFERCTR, buflen);
-       isp116x_write_addr(isp116x, HCATLPORT);
-
-       ret = TD_CC_NOERROR;
-       done = 0;
-       for (i = 0; i < n; i++) {
-               DBG("i=%d - done=%d - len=%d", i, done, PTD_GET_LEN(&ptd[i]));
-
-               ptd[i].count = isp116x_read_data16(isp116x);
-               ptd[i].mps = isp116x_read_data16(isp116x);
-               ptd[i].len = isp116x_read_data16(isp116x);
-               ptd[i].faddr = isp116x_read_data16(isp116x);
-               dump_ptd(&ptd[i]);
-
-               read_ptddata_from_fifo(isp116x,
-                                      (__u8 *) data + done,
-                                      PTD_GET_LEN(&ptd[i]));
-               dump_ptd_data(&ptd[i], (__u8 *) data + done, 1);
-
-               done += PTD_GET_LEN(&ptd[i]);
-
-               cc = PTD_GET_CC(&ptd[i]);
-
-               /* Data underrun means basically that we had more buffer space than
-                * the function had data. It is perfectly normal but upper levels have
-                * to know how much we actually transferred.
-                */
-               if (cc == TD_NOTACCESSED ||
-                               (cc != TD_CC_NOERROR && (ret == TD_CC_NOERROR || ret == TD_DATAUNDERRUN)))
-                       ret = cc;
-       }
-
-       DBG("--- unpack buffer %p - %d bytes (fifo %d) ---", data, len, buflen);
-
-       return ret;
-}
-
-/* Interrupt handling
- */
-static int isp116x_interrupt(struct isp116x *isp116x)
-{
-       u16 irqstat;
-       u32 intstat;
-       int ret = 0;
-
-       isp116x_write_reg16(isp116x, HCuPINTENB, 0);
-       irqstat = isp116x_read_reg16(isp116x, HCuPINT);
-       isp116x_write_reg16(isp116x, HCuPINT, irqstat);
-       DBG(">>>>>> irqstat %x <<<<<<", irqstat);
-
-       if (irqstat & HCuPINT_ATL) {
-               DBG(">>>>>> HCuPINT_ATL <<<<<<");
-               udelay(500);
-               ret = 1;
-       }
-
-       if (irqstat & HCuPINT_OPR) {
-               intstat = isp116x_read_reg32(isp116x, HCINTSTAT);
-               isp116x_write_reg32(isp116x, HCINTSTAT, intstat);
-               DBG(">>>>>> HCuPINT_OPR %x <<<<<<", intstat);
-
-               if (intstat & HCINT_UE) {
-                       ERR("unrecoverable error, controller disabled");
-
-                       /* FIXME: be optimistic, hope that bug won't repeat
-                        * often. Make some non-interrupt context restart the
-                        * controller. Count and limit the retries though;
-                        * either hardware or software errors can go forever...
-                        */
-                       isp116x_reset(isp116x);
-                       ret = -1;
-                       return -1;
-               }
-
-               if (intstat & HCINT_RHSC) {
-                       got_rhsc = 1;
-                       ret = 1;
-                       /* When root hub or any of its ports is going
-                          to come out of suspend, it may take more
-                          than 10ms for status bits to stabilize. */
-                       wait_ms(20);
-               }
-
-               if (intstat & HCINT_SO) {
-                       ERR("schedule overrun");
-                       ret = -1;
-               }
-
-               irqstat &= ~HCuPINT_OPR;
-       }
-
-       return ret;
-}
-
-/* With one PTD we can transfer almost 1K in one go;
- * HC does the splitting into endpoint digestible transactions
- */
-struct ptd ptd[1];
-
-static inline int max_transfer_len(struct usb_device *dev, unsigned long pipe)
-{
-       unsigned mpck = usb_maxpacket(dev, pipe);
-
-       /* One PTD can transfer 1023 bytes but try to always
-        * transfer multiples of endpoint buffer size
-        */
-       return 1023 / mpck * mpck;
-}
-
-/* Do an USB transfer
- */
-static int isp116x_submit_job(struct usb_device *dev, unsigned long pipe,
-                             int dir, void *buffer, int len)
-{
-       struct isp116x *isp116x = &isp116x_dev;
-       int type = usb_pipetype(pipe);
-       int epnum = usb_pipeendpoint(pipe);
-       int max = usb_maxpacket(dev, pipe);
-       int dir_out = usb_pipeout(pipe);
-       int speed_low = usb_pipeslow(pipe);
-       int i, done = 0, stat, timeout, cc;
-
-       /* 500 frames or 0.5s timeout when function is busy and NAKs transactions for a while */
-       int retries = 500;
-
-       DBG("------------------------------------------------");
-       dump_msg(dev, pipe, buffer, len, "SUBMIT");
-       DBG("------------------------------------------------");
-
-       if (len >= 1024) {
-               ERR("Too big job");
-               dev->status = USB_ST_CRC_ERR;
-               return -1;
-       }
-
-       if (isp116x->disabled) {
-               ERR("EPIPE");
-               dev->status = USB_ST_CRC_ERR;
-               return -1;
-       }
-
-       /* device pulled? Shortcut the action. */
-       if (devgone == dev) {
-               ERR("ENODEV");
-               dev->status = USB_ST_CRC_ERR;
-               return USB_ST_CRC_ERR;
-       }
-
-       if (!max) {
-               ERR("pipesize for pipe %lx is zero", pipe);
-               dev->status = USB_ST_CRC_ERR;
-               return -1;
-       }
-
-       if (type == PIPE_ISOCHRONOUS) {
-               ERR("isochronous transfers not supported");
-               dev->status = USB_ST_CRC_ERR;
-               return -1;
-       }
-
-       /* FIFO not empty? */
-       if (isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_FULL) {
-               ERR("****** FIFO not empty! ******");
-               dev->status = USB_ST_BUF_ERR;
-               return -1;
-       }
-
-      retry:
-       isp116x_write_reg32(isp116x, HCINTSTAT, 0xff);
-
-       /* Prepare the PTD data */
-       ptd->count = PTD_CC_MSK | PTD_ACTIVE_MSK |
-               PTD_TOGGLE(usb_gettoggle(dev, epnum, dir_out));
-       ptd->mps = PTD_MPS(max) | PTD_SPD(speed_low) | PTD_EP(epnum) | PTD_LAST_MSK;
-       ptd->len = PTD_LEN(len) | PTD_DIR(dir);
-       ptd->faddr = PTD_FA(usb_pipedevice(pipe));
-
-retry_same:
-       /* Pack data into FIFO ram */
-       pack_fifo(isp116x, dev, pipe, ptd, 1, buffer, len);
-#ifdef EXTRA_DELAY
-       wait_ms(EXTRA_DELAY);
-#endif
-
-       /* Start the data transfer */
-
-       /* Allow more time for a BULK device to react - some are slow */
-       if (usb_pipebulk(pipe))
-               timeout = 5000;
-       else
-               timeout = 100;
-
-       /* Wait for it to complete */
-       for (;;) {
-               /* Check whether the controller is done */
-               stat = isp116x_interrupt(isp116x);
-
-               if (stat < 0) {
-                       dev->status = USB_ST_CRC_ERR;
-                       break;
-               }
-               if (stat > 0)
-                       break;
-
-               /* Check the timeout */
-               if (--timeout)
-                       udelay(1);
-               else {
-                       ERR("CTL:TIMEOUT ");
-                       stat = USB_ST_CRC_ERR;
-                       break;
-               }
-       }
-
-       /* We got an Root Hub Status Change interrupt */
-       if (got_rhsc) {
-               isp116x_show_regs(isp116x);
-
-               got_rhsc = 0;
-
-               /* Abuse timeout */
-               timeout = rh_check_port_status(isp116x);
-               if (timeout >= 0) {
-                       /*
-                        * FIXME! NOTE! AAAARGH!
-                        * This is potentially dangerous because it assumes
-                        * that only one device is ever plugged in!
-                        */
-                       devgone = dev;
-               }
-       }
-
-       /* Ok, now we can read transfer status */
-
-       /* FIFO not ready? */
-       if (!(isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_DONE)) {
-               ERR("****** FIFO not ready! ******");
-               dev->status = USB_ST_BUF_ERR;
-               return -1;
-       }
-
-       /* Unpack data from FIFO ram */
-       cc = unpack_fifo(isp116x, dev, pipe, ptd, 1, buffer, len);
-
-       i = PTD_GET_COUNT(ptd);
-       done += i;
-       buffer += i;
-       len -= i;
-
-       /* There was some kind of real problem; Prepare the PTD again
-        * and retry from the failed transaction on
-        */
-       if (cc && cc != TD_NOTACCESSED && cc != TD_DATAUNDERRUN) {
-               if (retries >= 100) {
-                       retries -= 100;
-                       /* The chip will have toggled the toggle bit for the failed
-                        * transaction too. We have to toggle it back.
-                        */
-                       usb_settoggle(dev, epnum, dir_out, !PTD_GET_TOGGLE(ptd));
-                       goto retry;
-               }
-       }
-       /* "Normal" errors; TD_NOTACCESSED would mean in effect that the function have NAKed
-        * the transactions from the first on for the whole frame. It may be busy and we retry
-        * with the same PTD. PTD_ACTIVE (and not TD_NOTACCESSED) would mean that some of the
-        * PTD didn't make it because the function was busy or the frame ended before the PTD
-        * finished. We prepare the rest of the data and try again.
-        */
-       else if (cc == TD_NOTACCESSED || PTD_GET_ACTIVE(ptd) || (cc != TD_DATAUNDERRUN && PTD_GET_COUNT(ptd) < PTD_GET_LEN(ptd))) {
-               if (retries) {
-                       --retries;
-                       if (cc == TD_NOTACCESSED && PTD_GET_ACTIVE(ptd) && !PTD_GET_COUNT(ptd)) goto retry_same;
-                       usb_settoggle(dev, epnum, dir_out, PTD_GET_TOGGLE(ptd));
-                       goto retry;
-               }
-       }
-
-       if (cc != TD_CC_NOERROR && cc != TD_DATAUNDERRUN) {
-               DBG("****** completition code error %x ******", cc);
-               switch (cc) {
-               case TD_CC_BITSTUFFING:
-                       dev->status = USB_ST_BIT_ERR;
-                       break;
-               case TD_CC_STALL:
-                       dev->status = USB_ST_STALLED;
-                       break;
-               case TD_BUFFEROVERRUN:
-               case TD_BUFFERUNDERRUN:
-                       dev->status = USB_ST_BUF_ERR;
-                       break;
-               default:
-                       dev->status = USB_ST_CRC_ERR;
-               }
-               return -cc;
-       }
-       else usb_settoggle(dev, epnum, dir_out, PTD_GET_TOGGLE(ptd));
-
-       dump_msg(dev, pipe, buffer, len, "SUBMIT(ret)");
-
-       dev->status = 0;
-       return done;
-}
-
-/* Adapted from au1x00_usb_ohci.c
- */
-static int isp116x_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
-                                void *buffer, int transfer_len,
-                                struct devrequest *cmd)
-{
-       struct isp116x *isp116x = &isp116x_dev;
-       u32 tmp = 0;
-
-       int leni = transfer_len;
-       int len = 0;
-       int stat = 0;
-       u32 datab[4];
-       u8 *data_buf = (u8 *) datab;
-       u16 bmRType_bReq;
-       u16 wValue;
-       u16 wIndex;
-       u16 wLength;
-
-       if (usb_pipeint(pipe)) {
-               INFO("Root-Hub submit IRQ: NOT implemented");
-               return 0;
-       }
-
-       bmRType_bReq = cmd->requesttype | (cmd->request << 8);
-       wValue = swap_16(cmd->value);
-       wIndex = swap_16(cmd->index);
-       wLength = swap_16(cmd->length);
-
-       DBG("--- HUB ----------------------------------------");
-       DBG("submit rh urb, req=%x val=%#x index=%#x len=%d",
-           bmRType_bReq, wValue, wIndex, wLength);
-       dump_msg(dev, pipe, buffer, transfer_len, "RH");
-       DBG("------------------------------------------------");
-
-       switch (bmRType_bReq) {
-       case RH_GET_STATUS:
-               DBG("RH_GET_STATUS");
-
-               *(__u16 *) data_buf = swap_16(1);
-               len = 2;
-               break;
-
-       case RH_GET_STATUS | RH_INTERFACE:
-               DBG("RH_GET_STATUS | RH_INTERFACE");
-
-               *(__u16 *) data_buf = swap_16(0);
-               len = 2;
-               break;
-
-       case RH_GET_STATUS | RH_ENDPOINT:
-               DBG("RH_GET_STATUS | RH_ENDPOINT");
-
-               *(__u16 *) data_buf = swap_16(0);
-               len = 2;
-               break;
-
-       case RH_GET_STATUS | RH_CLASS:
-               DBG("RH_GET_STATUS | RH_CLASS");
-
-               tmp = isp116x_read_reg32(isp116x, HCRHSTATUS);
-
-               *(__u32 *) data_buf = swap_32(tmp & ~(RH_HS_CRWE | RH_HS_DRWE));
-               len = 4;
-               break;
-
-       case RH_GET_STATUS | RH_OTHER | RH_CLASS:
-               DBG("RH_GET_STATUS | RH_OTHER | RH_CLASS");
-
-               tmp = isp116x_read_reg32(isp116x, HCRHPORT1 + wIndex - 1);
-               *(__u32 *) data_buf = swap_32(tmp);
-               isp116x_show_regs(isp116x);
-               len = 4;
-               break;
-
-       case RH_CLEAR_FEATURE | RH_ENDPOINT:
-               DBG("RH_CLEAR_FEATURE | RH_ENDPOINT");
-
-               switch (wValue) {
-               case RH_ENDPOINT_STALL:
-                       DBG("C_HUB_ENDPOINT_STALL");
-                       len = 0;
-                       break;
-               }
-               break;
-
-       case RH_CLEAR_FEATURE | RH_CLASS:
-               DBG("RH_CLEAR_FEATURE | RH_CLASS");
-
-               switch (wValue) {
-               case RH_C_HUB_LOCAL_POWER:
-                       DBG("C_HUB_LOCAL_POWER");
-                       len = 0;
-                       break;
-
-               case RH_C_HUB_OVER_CURRENT:
-                       DBG("C_HUB_OVER_CURRENT");
-                       isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_OCIC);
-                       len = 0;
-                       break;
-               }
-               break;
-
-       case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
-               DBG("RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS");
-
-               switch (wValue) {
-               case RH_PORT_ENABLE:
-                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-                                           RH_PS_CCS);
-                       len = 0;
-                       break;
-
-               case RH_PORT_SUSPEND:
-                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-                                           RH_PS_POCI);
-                       len = 0;
-                       break;
-
-               case RH_PORT_POWER:
-                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-                                           RH_PS_LSDA);
-                       len = 0;
-                       break;
-
-               case RH_C_PORT_CONNECTION:
-                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-                                           RH_PS_CSC);
-                       len = 0;
-                       break;
-
-               case RH_C_PORT_ENABLE:
-                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-                                           RH_PS_PESC);
-                       len = 0;
-                       break;
-
-               case RH_C_PORT_SUSPEND:
-                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-                                           RH_PS_PSSC);
-                       len = 0;
-                       break;
-
-               case RH_C_PORT_OVER_CURRENT:
-                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-                                           RH_PS_POCI);
-                       len = 0;
-                       break;
-
-               case RH_C_PORT_RESET:
-                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-                                           RH_PS_PRSC);
-                       len = 0;
-                       break;
-
-               default:
-                       ERR("invalid wValue");
-                       stat = USB_ST_STALLED;
-               }
-
-               isp116x_show_regs(isp116x);
-
-               break;
-
-       case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
-               DBG("RH_SET_FEATURE | RH_OTHER | RH_CLASS");
-
-               switch (wValue) {
-               case RH_PORT_SUSPEND:
-                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-                                           RH_PS_PSS);
-                       len = 0;
-                       break;
-
-               case RH_PORT_RESET:
-                       /* Spin until any current reset finishes */
-                       while (1) {
-                               tmp =
-                                   isp116x_read_reg32(isp116x,
-                                                      HCRHPORT1 + wIndex - 1);
-                               if (!(tmp & RH_PS_PRS))
-                                       break;
-                               wait_ms(1);
-                       }
-                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-                                           RH_PS_PRS);
-                       wait_ms(10);
-
-                       len = 0;
-                       break;
-
-               case RH_PORT_POWER:
-                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-                                           RH_PS_PPS);
-                       len = 0;
-                       break;
-
-               case RH_PORT_ENABLE:
-                       isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-                                           RH_PS_PES);
-                       len = 0;
-                       break;
-
-               default:
-                       ERR("invalid wValue");
-                       stat = USB_ST_STALLED;
-               }
-
-               isp116x_show_regs(isp116x);
-
-               break;
-
-       case RH_SET_ADDRESS:
-               DBG("RH_SET_ADDRESS");
-
-               rh_devnum = wValue;
-               len = 0;
-               break;
-
-       case RH_GET_DESCRIPTOR:
-               DBG("RH_GET_DESCRIPTOR: %x, %d", wValue, wLength);
-
-               switch (wValue) {
-               case (USB_DT_DEVICE << 8):      /* device descriptor */
-                       len = min_t(unsigned int,
-                                   leni, min_t(unsigned int,
-                                               sizeof(root_hub_dev_des),
-                                               wLength));
-                       data_buf = root_hub_dev_des;
-                       break;
-
-               case (USB_DT_CONFIG << 8):      /* configuration descriptor */
-                       len = min_t(unsigned int,
-                                   leni, min_t(unsigned int,
-                                               sizeof(root_hub_config_des),
-                                               wLength));
-                       data_buf = root_hub_config_des;
-                       break;
-
-               case ((USB_DT_STRING << 8) | 0x00):     /* string 0 descriptors */
-                       len = min_t(unsigned int,
-                                   leni, min_t(unsigned int,
-                                               sizeof(root_hub_str_index0),
-                                               wLength));
-                       data_buf = root_hub_str_index0;
-                       break;
-
-               case ((USB_DT_STRING << 8) | 0x01):     /* string 1 descriptors */
-                       len = min_t(unsigned int,
-                                   leni, min_t(unsigned int,
-                                               sizeof(root_hub_str_index1),
-                                               wLength));
-                       data_buf = root_hub_str_index1;
-                       break;
-
-               default:
-                       ERR("invalid wValue");
-                       stat = USB_ST_STALLED;
-               }
-
-               break;
-
-       case RH_GET_DESCRIPTOR | RH_CLASS:
-               DBG("RH_GET_DESCRIPTOR | RH_CLASS");
-
-               tmp = isp116x_read_reg32(isp116x, HCRHDESCA);
-
-               data_buf[0] = 0x09;     /* min length; */
-               data_buf[1] = 0x29;
-               data_buf[2] = tmp & RH_A_NDP;
-               data_buf[3] = 0;
-               if (tmp & RH_A_PSM)     /* per-port power switching? */
-                       data_buf[3] |= 0x01;
-               if (tmp & RH_A_NOCP)    /* no overcurrent reporting? */
-                       data_buf[3] |= 0x10;
-               else if (tmp & RH_A_OCPM)       /* per-port overcurrent rep? */
-                       data_buf[3] |= 0x08;
-
-               /* Corresponds to data_buf[4-7] */
-               datab[1] = 0;
-               data_buf[5] = (tmp & RH_A_POTPGT) >> 24;
-
-               tmp = isp116x_read_reg32(isp116x, HCRHDESCB);
-
-               data_buf[7] = tmp & RH_B_DR;
-               if (data_buf[2] < 7)
-                       data_buf[8] = 0xff;
-               else {
-                       data_buf[0] += 2;
-                       data_buf[8] = (tmp & RH_B_DR) >> 8;
-                       data_buf[10] = data_buf[9] = 0xff;
-               }
-
-               len = min_t(unsigned int, leni,
-                           min_t(unsigned int, data_buf[0], wLength));
-               break;
-
-       case RH_GET_CONFIGURATION:
-               DBG("RH_GET_CONFIGURATION");
-
-               *(__u8 *) data_buf = 0x01;
-               len = 1;
-               break;
-
-       case RH_SET_CONFIGURATION:
-               DBG("RH_SET_CONFIGURATION");
-
-               isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPSC);
-               len = 0;
-               break;
-
-       default:
-               ERR("*** *** *** unsupported root hub command *** *** ***");
-               stat = USB_ST_STALLED;
-       }
-
-       len = min_t(int, len, leni);
-       if (buffer != data_buf)
-               memcpy(buffer, data_buf, len);
-
-       dev->act_len = len;
-       dev->status = stat;
-       DBG("dev act_len %d, status %d", dev->act_len, dev->status);
-
-       dump_msg(dev, pipe, buffer, transfer_len, "RH(ret)");
-
-       return stat;
-}
-
-/* --- Transfer functions -------------------------------------------------- */
-
-int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-                  int len, int interval)
-{
-       DBG("dev=%p pipe=%#lx buf=%p size=%d int=%d",
-           dev, pipe, buffer, len, interval);
-
-       return -1;
-}
-
-int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-                      int len, struct devrequest *setup)
-{
-       int devnum = usb_pipedevice(pipe);
-       int epnum = usb_pipeendpoint(pipe);
-       int max = max_transfer_len(dev, pipe);
-       int dir_in = usb_pipein(pipe);
-       int done, ret;
-
-       /* Control message is for the HUB? */
-       if (devnum == rh_devnum)
-               return isp116x_submit_rh_msg(dev, pipe, buffer, len, setup);
-
-       /* Ok, no HUB message so send the message to the device */
-
-       /* Setup phase */
-       DBG("--- SETUP PHASE --------------------------------");
-       usb_settoggle(dev, epnum, 1, 0);
-       ret = isp116x_submit_job(dev, pipe,
-                                PTD_DIR_SETUP,
-                                setup, sizeof(struct devrequest));
-       if (ret < 0) {
-               DBG("control setup phase error (ret = %d", ret);
-               return -1;
-       }
-
-       /* Data phase */
-       DBG("--- DATA PHASE ---------------------------------");
-       done = 0;
-       usb_settoggle(dev, epnum, !dir_in, 1);
-       while (done < len) {
-               ret = isp116x_submit_job(dev, pipe,
-                                        dir_in ? PTD_DIR_IN : PTD_DIR_OUT,
-                                        (__u8 *) buffer + done,
-                                        max > len - done ? len - done : max);
-               if (ret < 0) {
-                       DBG("control data phase error (ret = %d)", ret);
-                       return -1;
-               }
-               done += ret;
-
-               if (dir_in && ret < max)        /* short packet */
-                       break;
-       }
-
-       /* Status phase */
-       DBG("--- STATUS PHASE -------------------------------");
-       usb_settoggle(dev, epnum, !dir_in, 1);
-       ret = isp116x_submit_job(dev, pipe,
-                                !dir_in ? PTD_DIR_IN : PTD_DIR_OUT, NULL, 0);
-       if (ret < 0) {
-               DBG("control status phase error (ret = %d", ret);
-               return -1;
-       }
-
-       dev->act_len = done;
-
-       dump_msg(dev, pipe, buffer, len, "DEV(ret)");
-
-       return done;
-}
-
-int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-                   int len)
-{
-       int dir_out = usb_pipeout(pipe);
-       int max = max_transfer_len(dev, pipe);
-       int done, ret;
-
-       DBG("--- BULK ---------------------------------------");
-       DBG("dev=%ld pipe=%ld buf=%p size=%d dir_out=%d",
-           usb_pipedevice(pipe), usb_pipeendpoint(pipe), buffer, len, dir_out);
-
-       done = 0;
-       while (done < len) {
-               ret = isp116x_submit_job(dev, pipe,
-                                        !dir_out ? PTD_DIR_IN : PTD_DIR_OUT,
-                                        (__u8 *) buffer + done,
-                                        max > len - done ? len - done : max);
-               if (ret < 0) {
-                       DBG("error on bulk message (ret = %d)", ret);
-                       return -1;
-               }
-
-               done += ret;
-
-               if (!dir_out && ret < max)      /* short packet */
-                       break;
-       }
-
-       dev->act_len = done;
-
-       return 0;
-}
-
-/* --- Basic functions ----------------------------------------------------- */
-
-static int isp116x_sw_reset(struct isp116x *isp116x)
-{
-       int retries = 15;
-       int ret = 0;
-
-       DBG("");
-
-       isp116x->disabled = 1;
-
-       isp116x_write_reg16(isp116x, HCSWRES, HCSWRES_MAGIC);
-       isp116x_write_reg32(isp116x, HCCMDSTAT, HCCMDSTAT_HCR);
-       while (--retries) {
-               /* It usually resets within 1 ms */
-               wait_ms(1);
-               if (!(isp116x_read_reg32(isp116x, HCCMDSTAT) & HCCMDSTAT_HCR))
-                       break;
-       }
-       if (!retries) {
-               ERR("software reset timeout");
-               ret = -1;
-       }
-       return ret;
-}
-
-static int isp116x_reset(struct isp116x *isp116x)
-{
-       unsigned long t;
-       u16 clkrdy = 0;
-       int ret, timeout = 15 /* ms */ ;
-
-       DBG("");
-
-       ret = isp116x_sw_reset(isp116x);
-       if (ret)
-               return ret;
-
-       for (t = 0; t < timeout; t++) {
-               clkrdy = isp116x_read_reg16(isp116x, HCuPINT) & HCuPINT_CLKRDY;
-               if (clkrdy)
-                       break;
-               wait_ms(1);
-       }
-       if (!clkrdy) {
-               ERR("clock not ready after %dms", timeout);
-               /* After sw_reset the clock won't report to be ready, if
-                  H_WAKEUP pin is high. */
-               ERR("please make sure that the H_WAKEUP pin is pulled low!");
-               ret = -1;
-       }
-       return ret;
-}
-
-static void isp116x_stop(struct isp116x *isp116x)
-{
-       u32 val;
-
-       DBG("");
-
-       isp116x_write_reg16(isp116x, HCuPINTENB, 0);
-
-       /* Switch off ports' power, some devices don't come up
-          after next 'start' without this */
-       val = isp116x_read_reg32(isp116x, HCRHDESCA);
-       val &= ~(RH_A_NPS | RH_A_PSM);
-       isp116x_write_reg32(isp116x, HCRHDESCA, val);
-       isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS);
-
-       isp116x_sw_reset(isp116x);
-}
-
-/*
- *  Configure the chip. The chip must be successfully reset by now.
- */
-static int isp116x_start(struct isp116x *isp116x)
-{
-       struct isp116x_platform_data *board = isp116x->board;
-       u32 val;
-
-       DBG("");
-
-       /* Clear interrupt status and disable all interrupt sources */
-       isp116x_write_reg16(isp116x, HCuPINT, 0xff);
-       isp116x_write_reg16(isp116x, HCuPINTENB, 0);
-
-       isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE);
-       isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE);
-
-       /* Hardware configuration */
-       val = HCHWCFG_DBWIDTH(1);
-       if (board->sel15Kres)
-               val |= HCHWCFG_15KRSEL;
-       /* Remote wakeup won't work without working clock */
-       if (board->remote_wakeup_enable)
-               val |= HCHWCFG_CLKNOTSTOP;
-       if (board->oc_enable)
-               val |= HCHWCFG_ANALOG_OC;
-       isp116x_write_reg16(isp116x, HCHWCFG, val);
-
-       /* --- Root hub configuration */
-       val = (25 << 24) & RH_A_POTPGT;
-       /* AN10003_1.pdf recommends RH_A_NPS (no power switching) to
-          be always set. Yet, instead, we request individual port
-          power switching. */
-       val |= RH_A_PSM;
-       /* Report overcurrent per port */
-       val |= RH_A_OCPM;
-       isp116x_write_reg32(isp116x, HCRHDESCA, val);
-       isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA);
-
-       val = RH_B_PPCM;
-       isp116x_write_reg32(isp116x, HCRHDESCB, val);
-       isp116x->rhdescb = isp116x_read_reg32(isp116x, HCRHDESCB);
-
-       val = 0;
-       if (board->remote_wakeup_enable)
-               val |= RH_HS_DRWE;
-       isp116x_write_reg32(isp116x, HCRHSTATUS, val);
-       isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS);
-
-       isp116x_write_reg32(isp116x, HCFMINTVL, 0x27782edf);
-
-       /* Go operational */
-       val = HCCONTROL_USB_OPER;
-       if (board->remote_wakeup_enable)
-               val |= HCCONTROL_RWE;
-       isp116x_write_reg32(isp116x, HCCONTROL, val);
-
-       /* Disable ports to avoid race in device enumeration */
-       isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS);
-       isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS);
-
-       isp116x_show_regs(isp116x);
-
-       isp116x->disabled = 0;
-
-       return 0;
-}
-
-/* --- Init functions ------------------------------------------------------ */
-
-int isp116x_check_id(struct isp116x *isp116x)
-{
-       int val;
-
-       val = isp116x_read_reg16(isp116x, HCCHIPID);
-       if ((val & HCCHIPID_MASK) != HCCHIPID_MAGIC) {
-               ERR("invalid chip ID %04x", val);
-               return -1;
-       }
-
-       return 0;
-}
-
-int usb_lowlevel_init(void)
-{
-       struct isp116x *isp116x = &isp116x_dev;
-
-       DBG("");
-
-       got_rhsc = rh_devnum = 0;
-
-       /* Init device registers addr */
-       isp116x->addr_reg = (u16 *) ISP116X_HCD_ADDR;
-       isp116x->data_reg = (u16 *) ISP116X_HCD_DATA;
-
-       /* Setup specific board settings */
-#ifdef ISP116X_HCD_SEL15kRES
-       isp116x_board.sel15Kres = 1;
-#endif
-#ifdef ISP116X_HCD_OC_ENABLE
-       isp116x_board.oc_enable = 1;
-#endif
-#ifdef ISP116X_HCD_REMOTE_WAKEUP_ENABLE
-       isp116x_board.remote_wakeup_enable = 1;
-#endif
-       isp116x->board = &isp116x_board;
-
-       /* Try to get ISP116x silicon chip ID */
-       if (isp116x_check_id(isp116x) < 0)
-               return -1;
-
-       isp116x->disabled = 1;
-       isp116x->sleeping = 0;
-
-       isp116x_reset(isp116x);
-       isp116x_start(isp116x);
-
-       return 0;
-}
-
-int usb_lowlevel_stop(void)
-{
-       struct isp116x *isp116x = &isp116x_dev;
-
-       DBG("");
-
-       if (!isp116x->disabled)
-               isp116x_stop(isp116x);
-
-       return 0;
-}
diff --git a/drivers/usb/isp116x.h b/drivers/usb/isp116x.h
deleted file mode 100644 (file)
index a3ce3b5..0000000
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * ISP116x register declarations and HCD data structures
- *
- * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
- * Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
- * Copyright (C) 2005 Olav Kongas <ok@artecdesign.ee>
- * Portions:
- * Copyright (C) 2004 Lothar Wassmann
- * Copyright (C) 2004 Psion Teklogix
- * Copyright (C) 2004 David Brownell
- *
- * 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
- */
-
-#ifdef DEBUG
-#define DBG(fmt, args...)      \
-               printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args)
-#else
-#define DBG(fmt, args...)      do {} while (0)
-#endif
-
-#ifdef VERBOSE
-#    define VDBG               DBG
-#else
-#    define VDBG(fmt, args...) do {} while (0)
-#endif
-
-#define ERR(fmt, args...)      \
-               printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args)
-#define WARN(fmt, args...)     \
-               printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args)
-#define INFO(fmt, args...)     \
-               printf("isp116x: " fmt "\n" , ## args)
-
-/* ------------------------------------------------------------------------- */
-
-/* us of 1ms frame */
-#define  MAX_LOAD_LIMIT                850
-
-/* Full speed: max # of bytes to transfer for a single urb
-   at a time must be < 1024 && must be multiple of 64.
-   832 allows transfering 4kiB within 5 frames. */
-#define MAX_TRANSFER_SIZE_FULLSPEED    832
-
-/* Low speed: there is no reason to schedule in very big
-   chunks; often the requested long transfers are for
-   string descriptors containing short strings. */
-#define MAX_TRANSFER_SIZE_LOWSPEED     64
-
-/* Bytetime (us), a rough indication of how much time it
-   would take to transfer a byte of useful data over USB */
-#define BYTE_TIME_FULLSPEED    1
-#define BYTE_TIME_LOWSPEED     20
-
-/* Buffer sizes */
-#define ISP116x_BUF_SIZE       4096
-#define ISP116x_ITL_BUFSIZE    0
-#define ISP116x_ATL_BUFSIZE    ((ISP116x_BUF_SIZE) - 2*(ISP116x_ITL_BUFSIZE))
-
-#define ISP116x_WRITE_OFFSET   0x80
-
-/* --- ISP116x registers/bits ---------------------------------------------- */
-
-#define        HCREVISION      0x00
-#define        HCCONTROL       0x01
-#define                HCCONTROL_HCFS  (3 << 6)        /* host controller
-                                                  functional state */
-#define                HCCONTROL_USB_RESET     (0 << 6)
-#define                HCCONTROL_USB_RESUME    (1 << 6)
-#define                HCCONTROL_USB_OPER      (2 << 6)
-#define                HCCONTROL_USB_SUSPEND   (3 << 6)
-#define                HCCONTROL_RWC   (1 << 9)        /* remote wakeup connected */
-#define                HCCONTROL_RWE   (1 << 10)       /* remote wakeup enable */
-#define        HCCMDSTAT       0x02
-#define                HCCMDSTAT_HCR   (1 << 0)        /* host controller reset */
-#define                HCCMDSTAT_SOC   (3 << 16)       /* scheduling overrun count */
-#define        HCINTSTAT       0x03
-#define                HCINT_SO        (1 << 0)        /* scheduling overrun */
-#define                HCINT_WDH       (1 << 1)        /* writeback of done_head */
-#define                HCINT_SF        (1 << 2)        /* start frame */
-#define                HCINT_RD        (1 << 3)        /* resume detect */
-#define                HCINT_UE        (1 << 4)        /* unrecoverable error */
-#define                HCINT_FNO       (1 << 5)        /* frame number overflow */
-#define                HCINT_RHSC      (1 << 6)        /* root hub status change */
-#define                HCINT_OC        (1 << 30)       /* ownership change */
-#define                HCINT_MIE       (1 << 31)       /* master interrupt enable */
-#define        HCINTENB        0x04
-#define        HCINTDIS        0x05
-#define        HCFMINTVL       0x0d
-#define        HCFMREM         0x0e
-#define        HCFMNUM         0x0f
-#define        HCLSTHRESH      0x11
-#define        HCRHDESCA       0x12
-#define                RH_A_NDP        (0x3 << 0)      /* # downstream ports */
-#define                RH_A_PSM        (1 << 8)        /* power switching mode */
-#define                RH_A_NPS        (1 << 9)        /* no power switching */
-#define                RH_A_DT         (1 << 10)       /* device type (mbz) */
-#define                RH_A_OCPM       (1 << 11)       /* overcurrent protection
-                                                  mode */
-#define                RH_A_NOCP       (1 << 12)       /* no overcurrent protection */
-#define                RH_A_POTPGT     (0xff << 24)    /* power on -> power good
-                                                  time */
-#define        HCRHDESCB       0x13
-#define                RH_B_DR         (0xffff << 0)   /* device removable flags */
-#define                RH_B_PPCM       (0xffff << 16)  /* port power control mask */
-#define        HCRHSTATUS      0x14
-#define                RH_HS_LPS       (1 << 0)        /* local power status */
-#define                RH_HS_OCI       (1 << 1)        /* over current indicator */
-#define                RH_HS_DRWE      (1 << 15)       /* device remote wakeup
-                                                  enable */
-#define                RH_HS_LPSC      (1 << 16)       /* local power status change */
-#define                RH_HS_OCIC      (1 << 17)       /* over current indicator
-                                                  change */
-#define                RH_HS_CRWE      (1 << 31)       /* clear remote wakeup
-                                                  enable */
-#define        HCRHPORT1       0x15
-#define                RH_PS_CCS       (1 << 0)        /* current connect status */
-#define                RH_PS_PES       (1 << 1)        /* port enable status */
-#define                RH_PS_PSS       (1 << 2)        /* port suspend status */
-#define                RH_PS_POCI      (1 << 3)        /* port over current
-                                                  indicator */
-#define                RH_PS_PRS       (1 << 4)        /* port reset status */
-#define                RH_PS_PPS       (1 << 8)        /* port power status */
-#define                RH_PS_LSDA      (1 << 9)        /* low speed device attached */
-#define                RH_PS_CSC       (1 << 16)       /* connect status change */
-#define                RH_PS_PESC      (1 << 17)       /* port enable status change */
-#define                RH_PS_PSSC      (1 << 18)       /* port suspend status
-                                                  change */
-#define                RH_PS_OCIC      (1 << 19)       /* over current indicator
-                                                  change */
-#define                RH_PS_PRSC      (1 << 20)       /* port reset status change */
-#define                HCRHPORT_CLRMASK        (0x1f << 16)
-#define        HCRHPORT2       0x16
-#define        HCHWCFG         0x20
-#define                HCHWCFG_15KRSEL         (1 << 12)
-#define                HCHWCFG_CLKNOTSTOP      (1 << 11)
-#define                HCHWCFG_ANALOG_OC       (1 << 10)
-#define                HCHWCFG_DACK_MODE       (1 << 8)
-#define                HCHWCFG_EOT_POL         (1 << 7)
-#define                HCHWCFG_DACK_POL        (1 << 6)
-#define                HCHWCFG_DREQ_POL        (1 << 5)
-#define                HCHWCFG_DBWIDTH_MASK    (0x03 << 3)
-#define                HCHWCFG_DBWIDTH(n)      (((n) << 3) & HCHWCFG_DBWIDTH_MASK)
-#define                HCHWCFG_INT_POL         (1 << 2)
-#define                HCHWCFG_INT_TRIGGER     (1 << 1)
-#define                HCHWCFG_INT_ENABLE      (1 << 0)
-#define        HCDMACFG        0x21
-#define                HCDMACFG_BURST_LEN_MASK (0x03 << 5)
-#define                HCDMACFG_BURST_LEN(n)   (((n) << 5) & HCDMACFG_BURST_LEN_MASK)
-#define                HCDMACFG_BURST_LEN_1    HCDMACFG_BURST_LEN(0)
-#define                HCDMACFG_BURST_LEN_4    HCDMACFG_BURST_LEN(1)
-#define                HCDMACFG_BURST_LEN_8    HCDMACFG_BURST_LEN(2)
-#define                HCDMACFG_DMA_ENABLE     (1 << 4)
-#define                HCDMACFG_BUF_TYPE_MASK  (0x07 << 1)
-#define                HCDMACFG_CTR_SEL        (1 << 2)
-#define                HCDMACFG_ITLATL_SEL     (1 << 1)
-#define                HCDMACFG_DMA_RW_SELECT  (1 << 0)
-#define        HCXFERCTR       0x22
-#define        HCuPINT         0x24
-#define                HCuPINT_SOF             (1 << 0)
-#define                HCuPINT_ATL             (1 << 1)
-#define                HCuPINT_AIIEOT          (1 << 2)
-#define                HCuPINT_OPR             (1 << 4)
-#define                HCuPINT_SUSP            (1 << 5)
-#define                HCuPINT_CLKRDY          (1 << 6)
-#define        HCuPINTENB      0x25
-#define        HCCHIPID        0x27
-#define                HCCHIPID_MASK           0xff00
-#define                HCCHIPID_MAGIC          0x6100
-#define        HCSCRATCH       0x28
-#define        HCSWRES         0x29
-#define                HCSWRES_MAGIC           0x00f6
-#define        HCITLBUFLEN     0x2a
-#define        HCATLBUFLEN     0x2b
-#define        HCBUFSTAT       0x2c
-#define                HCBUFSTAT_ITL0_FULL     (1 << 0)
-#define                HCBUFSTAT_ITL1_FULL     (1 << 1)
-#define                HCBUFSTAT_ATL_FULL      (1 << 2)
-#define                HCBUFSTAT_ITL0_DONE     (1 << 3)
-#define                HCBUFSTAT_ITL1_DONE     (1 << 4)
-#define                HCBUFSTAT_ATL_DONE      (1 << 5)
-#define        HCRDITL0LEN     0x2d
-#define        HCRDITL1LEN     0x2e
-#define        HCITLPORT       0x40
-#define        HCATLPORT       0x41
-
-/* PTD accessor macros. */
-#define PTD_GET_COUNT(p)       (((p)->count & PTD_COUNT_MSK) >> 0)
-#define PTD_COUNT(v)           (((v) << 0) & PTD_COUNT_MSK)
-#define PTD_GET_TOGGLE(p)      (((p)->count & PTD_TOGGLE_MSK) >> 10)
-#define PTD_TOGGLE(v)          (((v) << 10) & PTD_TOGGLE_MSK)
-#define PTD_GET_ACTIVE(p)      (((p)->count & PTD_ACTIVE_MSK) >> 11)
-#define PTD_ACTIVE(v)          (((v) << 11) & PTD_ACTIVE_MSK)
-#define PTD_GET_CC(p)          (((p)->count & PTD_CC_MSK) >> 12)
-#define PTD_CC(v)              (((v) << 12) & PTD_CC_MSK)
-#define PTD_GET_MPS(p)         (((p)->mps & PTD_MPS_MSK) >> 0)
-#define PTD_MPS(v)             (((v) << 0) & PTD_MPS_MSK)
-#define PTD_GET_SPD(p)         (((p)->mps & PTD_SPD_MSK) >> 10)
-#define PTD_SPD(v)             (((v) << 10) & PTD_SPD_MSK)
-#define PTD_GET_LAST(p)                (((p)->mps & PTD_LAST_MSK) >> 11)
-#define PTD_LAST(v)            (((v) << 11) & PTD_LAST_MSK)
-#define PTD_GET_EP(p)          (((p)->mps & PTD_EP_MSK) >> 12)
-#define PTD_EP(v)              (((v) << 12) & PTD_EP_MSK)
-#define PTD_GET_LEN(p)         (((p)->len & PTD_LEN_MSK) >> 0)
-#define PTD_LEN(v)             (((v) << 0) & PTD_LEN_MSK)
-#define PTD_GET_DIR(p)         (((p)->len & PTD_DIR_MSK) >> 10)
-#define PTD_DIR(v)             (((v) << 10) & PTD_DIR_MSK)
-#define PTD_GET_B5_5(p)                (((p)->len & PTD_B5_5_MSK) >> 13)
-#define PTD_B5_5(v)            (((v) << 13) & PTD_B5_5_MSK)
-#define PTD_GET_FA(p)          (((p)->faddr & PTD_FA_MSK) >> 0)
-#define PTD_FA(v)              (((v) << 0) & PTD_FA_MSK)
-#define PTD_GET_FMT(p)         (((p)->faddr & PTD_FMT_MSK) >> 7)
-#define PTD_FMT(v)             (((v) << 7) & PTD_FMT_MSK)
-
-/*  Hardware transfer status codes -- CC from ptd->count */
-#define TD_CC_NOERROR      0x00
-#define TD_CC_CRC          0x01
-#define TD_CC_BITSTUFFING  0x02
-#define TD_CC_DATATOGGLEM  0x03
-#define TD_CC_STALL        0x04
-#define TD_DEVNOTRESP      0x05
-#define TD_PIDCHECKFAIL    0x06
-#define TD_UNEXPECTEDPID   0x07
-#define TD_DATAOVERRUN     0x08
-#define TD_DATAUNDERRUN    0x09
-    /* 0x0A, 0x0B reserved for hardware */
-#define TD_BUFFEROVERRUN   0x0C
-#define TD_BUFFERUNDERRUN  0x0D
-    /* 0x0E, 0x0F reserved for HCD */
-#define TD_NOTACCESSED     0x0F
-
-/* ------------------------------------------------------------------------- */
-
-#define        LOG2_PERIODIC_SIZE      5       /* arbitrary; this matches OHCI */
-#define        PERIODIC_SIZE           (1 << LOG2_PERIODIC_SIZE)
-
-/* Philips transfer descriptor */
-struct ptd {
-       u16 count;
-#define        PTD_COUNT_MSK   (0x3ff << 0)
-#define        PTD_TOGGLE_MSK  (1 << 10)
-#define        PTD_ACTIVE_MSK  (1 << 11)
-#define        PTD_CC_MSK      (0xf << 12)
-       u16 mps;
-#define        PTD_MPS_MSK     (0x3ff << 0)
-#define        PTD_SPD_MSK     (1 << 10)
-#define        PTD_LAST_MSK    (1 << 11)
-#define        PTD_EP_MSK      (0xf << 12)
-       u16 len;
-#define        PTD_LEN_MSK     (0x3ff << 0)
-#define        PTD_DIR_MSK     (3 << 10)
-#define        PTD_DIR_SETUP   (0)
-#define        PTD_DIR_OUT     (1)
-#define        PTD_DIR_IN      (2)
-#define        PTD_B5_5_MSK    (1 << 13)
-       u16 faddr;
-#define        PTD_FA_MSK      (0x7f << 0)
-#define        PTD_FMT_MSK     (1 << 7)
-} __attribute__ ((packed, aligned(2)));
-
-struct isp116x_ep {
-       struct usb_device *udev;
-       struct ptd ptd;
-
-       u8 maxpacket;
-       u8 epnum;
-       u8 nextpid;
-
-       u16 length;             /* of current packet */
-       unsigned char *data;    /* to databuf */
-
-       u16 error_count;
-};
-
-/* URB struct */
-#define N_URB_TD               48
-#define URB_DEL                        1
-typedef struct {
-       struct isp116x_ep *ed;
-       void *transfer_buffer;  /* (in) associated data buffer */
-       int actual_length;      /* (return) actual transfer length */
-       unsigned long pipe;     /* (in) pipe information */
-#if 0
-       int state;
-#endif
-} urb_priv_t;
-
-struct isp116x_platform_data {
-       /* Enable internal resistors on downstream ports */
-       unsigned sel15Kres:1;
-       /* On-chip overcurrent detection */
-       unsigned oc_enable:1;
-       /* Enable wakeup by devices on usb bus (e.g. wakeup
-          by attachment/detachment or by device activity
-          such as moving a mouse). When chosen, this option
-          prevents stopping internal clock, increasing
-          thereby power consumption in suspended state. */
-       unsigned remote_wakeup_enable:1;
-};
-
-struct isp116x {
-       u16 *addr_reg;
-       u16 *data_reg;
-
-       struct isp116x_platform_data *board;
-
-       struct dentry *dentry;
-       unsigned long stat1, stat2, stat4, stat8, stat16;
-
-       /* Status flags */
-       unsigned disabled:1;
-       unsigned sleeping:1;
-
-       /* Root hub registers */
-       u32 rhdesca;
-       u32 rhdescb;
-       u32 rhstatus;
-       u32 rhport[2];
-
-       /* Schedule for the current frame */
-       struct isp116x_ep *atl_active;
-       int atl_buflen;
-       int atl_bufshrt;
-       int atl_last_dir;
-       int atl_finishing;
-};
-
-/* ------------------------------------------------- */
-
-/* Inter-io delay (ns). The chip is picky about access timings; it
- * expects at least:
- * 150ns delay between consecutive accesses to DATA_REG,
- * 300ns delay between access to ADDR_REG and DATA_REG
- * OE, WE MUST NOT be changed during these intervals
- */
-#if defined(UDELAY)
-#define        isp116x_delay(h,d)      udelay(d)
-#else
-#define        isp116x_delay(h,d)      do {} while (0)
-#endif
-
-static inline void isp116x_write_addr(struct isp116x *isp116x, unsigned reg)
-{
-       writew(reg & 0xff, isp116x->addr_reg);
-       isp116x_delay(isp116x, UDELAY);
-}
-
-static inline void isp116x_write_data16(struct isp116x *isp116x, u16 val)
-{
-       writew(val, isp116x->data_reg);
-       isp116x_delay(isp116x, UDELAY);
-}
-
-static inline void isp116x_raw_write_data16(struct isp116x *isp116x, u16 val)
-{
-       __raw_writew(val, isp116x->data_reg);
-       isp116x_delay(isp116x, UDELAY);
-}
-
-static inline u16 isp116x_read_data16(struct isp116x *isp116x)
-{
-       u16 val;
-
-       val = readw(isp116x->data_reg);
-       isp116x_delay(isp116x, UDELAY);
-       return val;
-}
-
-static inline u16 isp116x_raw_read_data16(struct isp116x *isp116x)
-{
-       u16 val;
-
-       val = __raw_readw(isp116x->data_reg);
-       isp116x_delay(isp116x, UDELAY);
-       return val;
-}
-
-static inline void isp116x_write_data32(struct isp116x *isp116x, u32 val)
-{
-       writew(val & 0xffff, isp116x->data_reg);
-       isp116x_delay(isp116x, UDELAY);
-       writew(val >> 16, isp116x->data_reg);
-       isp116x_delay(isp116x, UDELAY);
-}
-
-static inline u32 isp116x_read_data32(struct isp116x *isp116x)
-{
-       u32 val;
-
-       val = (u32) readw(isp116x->data_reg);
-       isp116x_delay(isp116x, UDELAY);
-       val |= ((u32) readw(isp116x->data_reg)) << 16;
-       isp116x_delay(isp116x, UDELAY);
-       return val;
-}
-
-/* Let's keep register access functions out of line. Hint:
-   we wait at least 150 ns at every access.
-*/
-static u16 isp116x_read_reg16(struct isp116x *isp116x, unsigned reg)
-{
-       isp116x_write_addr(isp116x, reg);
-       return isp116x_read_data16(isp116x);
-}
-
-static u32 isp116x_read_reg32(struct isp116x *isp116x, unsigned reg)
-{
-       isp116x_write_addr(isp116x, reg);
-       return isp116x_read_data32(isp116x);
-}
-
-static void isp116x_write_reg16(struct isp116x *isp116x, unsigned reg,
-                               unsigned val)
-{
-       isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET);
-       isp116x_write_data16(isp116x, (u16) (val & 0xffff));
-}
-
-static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg,
-                               unsigned val)
-{
-       isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET);
-       isp116x_write_data32(isp116x, (u32) val);
-}
-
-/* --- USB HUB constants (not OHCI-specific; see hub.h) -------------------- */
-
-/* destination of request */
-#define RH_INTERFACE               0x01
-#define RH_ENDPOINT                0x02
-#define RH_OTHER                   0x03
-
-#define RH_CLASS                   0x20
-#define RH_VENDOR                  0x40
-
-/* Requests: bRequest << 8 | bmRequestType */
-#define RH_GET_STATUS           0x0080
-#define RH_CLEAR_FEATURE        0x0100
-#define RH_SET_FEATURE          0x0300
-#define RH_SET_ADDRESS          0x0500
-#define RH_GET_DESCRIPTOR       0x0680
-#define RH_SET_DESCRIPTOR       0x0700
-#define RH_GET_CONFIGURATION    0x0880
-#define RH_SET_CONFIGURATION    0x0900
-#define RH_GET_STATE            0x0280
-#define RH_GET_INTERFACE        0x0A80
-#define RH_SET_INTERFACE        0x0B00
-#define RH_SYNC_FRAME           0x0C80
-/* Our Vendor Specific Request */
-#define RH_SET_EP               0x2000
-
-/* Hub port features */
-#define RH_PORT_CONNECTION         0x00
-#define RH_PORT_ENABLE             0x01
-#define RH_PORT_SUSPEND            0x02
-#define RH_PORT_OVER_CURRENT       0x03
-#define RH_PORT_RESET              0x04
-#define RH_PORT_POWER              0x08
-#define RH_PORT_LOW_SPEED          0x09
-
-#define RH_C_PORT_CONNECTION       0x10
-#define RH_C_PORT_ENABLE           0x11
-#define RH_C_PORT_SUSPEND          0x12
-#define RH_C_PORT_OVER_CURRENT     0x13
-#define RH_C_PORT_RESET            0x14
-
-/* Hub features */
-#define RH_C_HUB_LOCAL_POWER       0x00
-#define RH_C_HUB_OVER_CURRENT      0x01
-
-#define RH_DEVICE_REMOTE_WAKEUP    0x00
-#define RH_ENDPOINT_STALL          0x01
-
-#define RH_ACK                     0x01
-#define RH_REQ_ERR                 -1
-#define RH_NACK                    0x00
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
new file mode 100644 (file)
index 0000000..09e0a5f
--- /dev/null
@@ -0,0 +1,47 @@
+#
+# (C) Copyright 2000-2007
+# 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    := $(obj)libusb_musb.a
+
+COBJS-$(CONFIG_MUSB_HCD) += musb_hcd.o musb_core.o
+COBJS-$(CONFIG_USB_DAVINCI) += davinci.o
+
+COBJS  := $(COBJS-y)
+SRCS   := $(COBJS:.o=.c)
+OBJS   := $(addprefix $(obj),$(COBJS))
+
+all:   $(LIB)
+
+$(LIB):        $(obj).depend $(OBJS)
+       $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
new file mode 100644 (file)
index 0000000..a7648fc
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * TI's Davinci platform specific USB wrapper functions.
+ *
+ * Copyright (c) 2008 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
+ *
+ * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include "davinci.h"
+
+/* MUSB platform configuration */
+struct musb_config musb_cfg = {
+       (struct musb_regs *)MENTOR_USB0_BASE,
+       DAVINCI_USB_TIMEOUT,
+       0
+};
+
+/* MUSB module register overlay */
+struct davinci_usb_regs *dregs;
+
+/*
+ * Enable the USB phy
+ */
+static u8 phy_on(void)
+{
+       u32 timeout;
+
+       /* Wait until the USB phy is turned on */
+       writel(USBPHY_SESNDEN | USBPHY_VBDTCTEN, USBPHY_CTL_PADDR);
+       timeout = musb_cfg.timeout;
+       while (timeout--)
+               if (readl(USBPHY_CTL_PADDR) & USBPHY_PHYCLKGD)
+                       return 1;
+
+       /* USB phy was not turned on */
+       return 0;
+}
+
+/*
+ * Disable the USB phy
+ */
+static void phy_off(void)
+{
+       /* powerdown the on-chip PHY and its oscillator */
+       writel(USBPHY_OSCPDWN | USBPHY_PHYPDWN, USBPHY_CTL_PADDR);
+}
+
+/*
+ * This function performs Davinci platform specific initialization for usb0.
+ */
+int musb_platform_init(void)
+{
+       u32  revision;
+
+       /* enable USB VBUS */
+       enable_vbus();
+
+       /* start the on-chip USB phy and its pll */
+       if (!phy_on())
+               return -1;
+
+       /* reset the controller */
+       dregs = (struct davinci_usb_regs *)DAVINCI_USB0_BASE;
+       writel(1, &dregs->ctrlr);
+       udelay(5000);
+
+       /* Returns zero if e.g. not clocked */
+       revision = readl(&dregs->version);
+       if (!revision)
+               return -1;
+
+       /* Disable all interrupts */
+       writel(DAVINCI_USB_USBINT_MASK | DAVINCI_USB_RXINT_MASK |
+                       DAVINCI_USB_TXINT_MASK , &dregs->intmsksetr);
+       return 0;
+}
+
+/*
+ * This function performs Davinci platform specific deinitialization for usb0.
+ */
+void musb_platform_deinit(void)
+{
+       /* Turn of the phy */
+       phy_off();
+
+       /* flush any interrupts */
+       writel(DAVINCI_USB_USBINT_MASK | DAVINCI_USB_TXINT_MASK |
+                       DAVINCI_USB_RXINT_MASK , &dregs->intclrr);
+}
diff --git a/drivers/usb/musb/davinci.h b/drivers/usb/musb/davinci.h
new file mode 100644 (file)
index 0000000..f6751bf
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * TI's Davinci platform specific USB wrapper functions.
+ *
+ * Copyright (c) 2008 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
+ *
+ * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
+ */
+
+#ifndef __DAVINCI_USB_H__
+#define __DAVINCI_USB_H__
+
+#include <asm/arch/hardware.h>
+#include "musb_core.h"
+
+/* Base address of DAVINCI usb0 wrapper */
+#define DAVINCI_USB0_BASE 0x01C64000
+
+/* Base address of DAVINCI musb core */
+#define MENTOR_USB0_BASE (DAVINCI_USB0_BASE+0x400)
+
+/*
+ * Davinci platform USB wrapper register overlay. Note: Only the required
+ * registers are included in this structure. It can be expanded as required.
+ */
+struct davinci_usb_regs {
+       u32     version;
+       u32     ctrlr;
+       u32     reserved[0x20];
+       u32     intclrr;
+       u32     intmskr;
+       u32     intmsksetr;
+};
+
+#define DAVINCI_USB_TX_ENDPTS_MASK     0x1f /* ep0 + 4 tx */
+#define DAVINCI_USB_RX_ENDPTS_MASK     0x1e /* 4 rx */
+#define DAVINCI_USB_USBINT_SHIFT       16
+#define DAVINCI_USB_TXINT_SHIFT        0
+#define DAVINCI_USB_RXINT_SHIFT        8
+#define DAVINCI_INTR_DRVVBUS           0x0100
+
+#define DAVINCI_USB_USBINT_MASK        0x01ff0000      /* 8 Mentor, DRVVBUS */
+#define DAVINCI_USB_TXINT_MASK \
+               (DAVINCI_USB_TX_ENDPTS_MASK << DAVINCI_USB_TXINT_SHIFT)
+#define DAVINCI_USB_RXINT_MASK \
+               (DAVINCI_USB_RX_ENDPTS_MASK << DAVINCI_USB_RXINT_SHIFT)
+#define MGC_BUSCTL_OFFSET(_bEnd, _bOffset) \
+               (0x80 + (8*(_bEnd)) + (_bOffset))
+
+/* Integrated highspeed/otg PHY */
+#define USBPHY_CTL_PADDR       (DAVINCI_SYSTEM_MODULE_BASE + 0x34)
+#define USBPHY_PHYCLKGD        (1 << 8)
+#define USBPHY_SESNDEN         (1 << 7)        /* v(sess_end) comparator */
+#define USBPHY_VBDTCTEN        (1 << 6)        /* v(bus) comparator */
+#define USBPHY_PHYPLLON        (1 << 4)        /* override pll suspend */
+#define USBPHY_CLKO1SEL        (1 << 3)
+#define USBPHY_OSCPDWN         (1 << 2)
+#define USBPHY_PHYPDWN         (1 << 0)
+
+/* Timeout for Davinci USB module */
+#define DAVINCI_USB_TIMEOUT 0x3FFFFFF
+
+/* IO Expander I2C address and VBUS enable mask */
+#define IOEXP_I2C_ADDR 0x3A
+#define IOEXP_VBUSEN_MASK 1
+
+/* extern functions */
+extern void lpsc_on(unsigned int id);
+extern int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len);
+extern int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len);
+extern void enable_vbus(void);
+#endif /* __DAVINCI_USB_H__ */
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
new file mode 100644 (file)
index 0000000..ec57fc8
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Mentor USB OTG Core functionality common for both Host and Device
+ * functionality.
+ *
+ * Copyright (c) 2008 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
+ *
+ * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
+ */
+
+#include <common.h>
+
+#include "musb_core.h"
+struct musb_regs *musbr;
+
+/*
+ * program the mentor core to start (enable interrupts, dma, etc.)
+ */
+void musb_start(void)
+{
+       u8 devctl;
+
+       /* disable all interrupts */
+       writew(0, &musbr->intrtxe);
+       writew(0, &musbr->intrrxe);
+       writeb(0, &musbr->intrusbe);
+       writeb(0, &musbr->testmode);
+
+       /* put into basic highspeed mode and start session */
+       writeb(MUSB_POWER_HSENAB, &musbr->power);
+#if defined(CONFIG_MUSB_HCD)
+       devctl = readb(&musbr->devctl);
+       writeb(devctl | MUSB_DEVCTL_SESSION, &musbr->devctl);
+#endif
+}
+
+/*
+ * This function configures the endpoint configuration. The musb hcd or musb
+ * device implementation can use this function to configure the endpoints
+ * and set the FIFO sizes. Note: The summation of FIFO sizes of all endpoints
+ * should not be more than the available FIFO size.
+ *
+ * epinfo      - Pointer to EP configuration table
+ * cnt         - Number of entries in the EP conf table.
+ */
+void musb_configure_ep(struct musb_epinfo *epinfo, u8 cnt)
+{
+       u16 csr;
+       u16 fifoaddr = 64; /* First 64 bytes of FIFO reserved for EP0 */
+       u32 fifosize;
+       u8  idx;
+
+       while (cnt--) {
+               /* prepare fifosize to write to register */
+               fifosize = epinfo->epsize >> 3;
+               idx = ffs(fifosize) - 1;
+
+               writeb(epinfo->epnum, &musbr->index);
+               if (epinfo->epdir) {
+                       /* Configure fifo size and fifo base address */
+                       writeb(idx, &musbr->txfifosz);
+                       writew(fifoaddr >> 3, &musbr->txfifoadd);
+#if defined(CONFIG_MUSB_HCD)
+                       /* clear the data toggle bit */
+                       csr = readw(&musbr->txcsr);
+                       writew(csr | MUSB_TXCSR_CLRDATATOG, &musbr->txcsr);
+#endif
+                       /* Flush fifo if required */
+                       if (csr & MUSB_TXCSR_TXPKTRDY)
+                               writew(csr | MUSB_TXCSR_FLUSHFIFO,
+                                       &musbr->txcsr);
+               } else {
+                       /* Configure fifo size and fifo base address */
+                       writeb(idx, &musbr->rxfifosz);
+                       writew(fifoaddr >> 3, &musbr->rxfifoadd);
+#if defined(CONFIG_MUSB_HCD)
+                       /* clear the data toggle bit */
+                       csr = readw(&musbr->rxcsr);
+                       writew(csr | MUSB_RXCSR_CLRDATATOG, &musbr->rxcsr);
+#endif
+                       /* Flush fifo if required */
+                       if (csr & MUSB_RXCSR_RXPKTRDY)
+                               writew(csr | MUSB_RXCSR_FLUSHFIFO,
+                                       &musbr->rxcsr);
+               }
+               fifoaddr += epinfo->epsize;
+               epinfo++;
+       }
+}
+
+/*
+ * This function writes data to endpoint fifo
+ *
+ * ep          - endpoint number
+ * length      - number of bytes to write to FIFO
+ * fifo_data   - Pointer to data buffer that contains the data to write
+ */
+void write_fifo(u8 ep, u32 length, void *fifo_data)
+{
+       u8  *data = (u8 *)fifo_data;
+
+       /* select the endpoint index */
+       writeb(ep, &musbr->index);
+
+       /* write the data to the fifo */
+       while (length--)
+               writeb(*data++, &musbr->fifox[ep]);
+}
+
+/*
+ * This function reads data from endpoint fifo
+ *
+ * ep           - endpoint number
+ * length       - number of bytes to read from FIFO
+ * fifo_data    - pointer to data buffer into which data is read
+ */
+void read_fifo(u8 ep, u32 length, void *fifo_data)
+{
+       u8  *data = (u8 *)fifo_data;
+
+       /* select the endpoint index */
+       writeb(ep, &musbr->index);
+
+       /* read the data to the fifo */
+       while (length--)
+               *data++ = readb(&musbr->fifox[ep]);
+}
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
new file mode 100644 (file)
index 0000000..2597c5f
--- /dev/null
@@ -0,0 +1,316 @@
+/******************************************************************
+ * Copyright 2008 Mentor Graphics Corporation
+ * Copyright (C) 2008 by Texas Instruments
+ *
+ * This file is part of the Inventra Controller Driver for Linux.
+ *
+ * The Inventra Controller Driver for Linux is free software; you
+ * can redistribute it and/or modify it under the terms of the GNU
+ * General Public License version 2 as published by the Free Software
+ * Foundation.
+ *
+ * The Inventra Controller Driver for Linux 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 The Inventra Controller Driver for Linux ; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA  02111-1307  USA
+ *
+ * ANY DOWNLOAD, USE, REPRODUCTION, MODIFICATION OR DISTRIBUTION
+ * OF THIS DRIVER INDICATES YOUR COMPLETE AND UNCONDITIONAL ACCEPTANCE
+ * OF THOSE TERMS.THIS DRIVER IS PROVIDED "AS IS" AND MENTOR GRAPHICS
+ * MAKES NO WARRANTIES, EXPRESS OR IMPLIED, RELATED TO THIS DRIVER.
+ * MENTOR GRAPHICS SPECIFICALLY DISCLAIMS ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY; FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  MENTOR GRAPHICS DOES NOT PROVIDE SUPPORT
+ * SERVICES OR UPDATES FOR THIS DRIVER, EVEN IF YOU ARE A MENTOR
+ * GRAPHICS SUPPORT CUSTOMER.
+ ******************************************************************/
+
+#ifndef __MUSB_HDRC_DEFS_H__
+#define __MUSB_HDRC_DEFS_H__
+
+#include <usb.h>
+#include <usb_defs.h>
+#include <asm/io.h>
+
+#define MUSB_EP0_FIFOSIZE      64      /* This is non-configurable */
+
+/* Mentor USB core register overlay structure */
+struct musb_regs {
+       /* common registers */
+       u8      faddr;
+       u8      power;
+       u16     intrtx;
+       u16     intrrx;
+       u16     intrtxe;
+       u16     intrrxe;
+       u8      intrusb;
+       u8      intrusbe;
+       u16     frame;
+       u8      index;
+       u8      testmode;
+       /* indexed registers */
+       u16     txmaxp;
+       u16     txcsr;
+       u16     rxmaxp;
+       u16     rxcsr;
+       u16     rxcount;
+       u8      txtype;
+       u8      txinterval;
+       u8      rxtype;
+       u8      rxinterval;
+       u8      reserved0;
+       u8      fifosize;
+       /* fifo */
+       u32     fifox[16];
+       /* OTG, dynamic FIFO, version & vendor registers */
+       u8      devctl;
+       u8      reserved1;
+       u8      txfifosz;
+       u8      rxfifosz;
+       u16     txfifoadd;
+       u16     rxfifoadd;
+       u32     vcontrol;
+       u16     hwvers;
+       u16     reserved2[5];
+       u8      epinfo;
+       u8      raminfo;
+       u8      linkinfo;
+       u8      vplen;
+       u8      hseof1;
+       u8      fseof1;
+       u8      lseof1;
+       u8      reserved3;
+       /* target address registers */
+       struct musb_tar_regs {
+               u8      txfuncaddr;
+               u8      reserved0;
+               u8      txhubaddr;
+               u8      txhubport;
+               u8      rxfuncaddr;
+               u8      reserved1;
+               u8      rxhubaddr;
+               u8      rxhubport;
+       } tar[16];
+} __attribute((aligned(32)));
+
+/*
+ * MUSB Register bits
+ */
+
+/* POWER */
+#define MUSB_POWER_ISOUPDATE   0x80
+#define MUSB_POWER_SOFTCONN    0x40
+#define MUSB_POWER_HSENAB      0x20
+#define MUSB_POWER_HSMODE      0x10
+#define MUSB_POWER_RESET       0x08
+#define MUSB_POWER_RESUME      0x04
+#define MUSB_POWER_SUSPENDM    0x02
+#define MUSB_POWER_ENSUSPEND   0x01
+#define MUSB_POWER_HSMODE_SHIFT        4
+
+/* INTRUSB */
+#define MUSB_INTR_SUSPEND      0x01
+#define MUSB_INTR_RESUME       0x02
+#define MUSB_INTR_RESET                0x04
+#define MUSB_INTR_BABBLE       0x04
+#define MUSB_INTR_SOF          0x08
+#define MUSB_INTR_CONNECT      0x10
+#define MUSB_INTR_DISCONNECT   0x20
+#define MUSB_INTR_SESSREQ      0x40
+#define MUSB_INTR_VBUSERROR    0x80    /* For SESSION end */
+
+/* DEVCTL */
+#define MUSB_DEVCTL_BDEVICE    0x80
+#define MUSB_DEVCTL_FSDEV      0x40
+#define MUSB_DEVCTL_LSDEV      0x20
+#define MUSB_DEVCTL_VBUS       0x18
+#define MUSB_DEVCTL_VBUS_SHIFT 3
+#define MUSB_DEVCTL_HM         0x04
+#define MUSB_DEVCTL_HR         0x02
+#define MUSB_DEVCTL_SESSION    0x01
+
+/* TESTMODE */
+#define MUSB_TEST_FORCE_HOST   0x80
+#define MUSB_TEST_FIFO_ACCESS  0x40
+#define MUSB_TEST_FORCE_FS     0x20
+#define MUSB_TEST_FORCE_HS     0x10
+#define MUSB_TEST_PACKET       0x08
+#define MUSB_TEST_K            0x04
+#define MUSB_TEST_J            0x02
+#define MUSB_TEST_SE0_NAK      0x01
+
+/* Allocate for double-packet buffering (effectively doubles assigned _SIZE) */
+#define MUSB_FIFOSZ_DPB                0x10
+/* Allocation size (8, 16, 32, ... 4096) */
+#define MUSB_FIFOSZ_SIZE       0x0f
+
+/* CSR0 */
+#define MUSB_CSR0_FLUSHFIFO    0x0100
+#define MUSB_CSR0_TXPKTRDY     0x0002
+#define MUSB_CSR0_RXPKTRDY     0x0001
+
+/* CSR0 in Peripheral mode */
+#define MUSB_CSR0_P_SVDSETUPEND        0x0080
+#define MUSB_CSR0_P_SVDRXPKTRDY        0x0040
+#define MUSB_CSR0_P_SENDSTALL  0x0020
+#define MUSB_CSR0_P_SETUPEND   0x0010
+#define MUSB_CSR0_P_DATAEND    0x0008
+#define MUSB_CSR0_P_SENTSTALL  0x0004
+
+/* CSR0 in Host mode */
+#define MUSB_CSR0_H_DIS_PING           0x0800
+#define MUSB_CSR0_H_WR_DATATOGGLE      0x0400  /* Set to allow setting: */
+#define MUSB_CSR0_H_DATATOGGLE         0x0200  /* Data toggle control */
+#define MUSB_CSR0_H_NAKTIMEOUT         0x0080
+#define MUSB_CSR0_H_STATUSPKT          0x0040
+#define MUSB_CSR0_H_REQPKT             0x0020
+#define MUSB_CSR0_H_ERROR              0x0010
+#define MUSB_CSR0_H_SETUPPKT           0x0008
+#define MUSB_CSR0_H_RXSTALL            0x0004
+
+/* CSR0 bits to avoid zeroing (write zero clears, write 1 ignored) */
+#define MUSB_CSR0_P_WZC_BITS   \
+       (MUSB_CSR0_P_SENTSTALL)
+#define MUSB_CSR0_H_WZC_BITS   \
+       (MUSB_CSR0_H_NAKTIMEOUT | MUSB_CSR0_H_RXSTALL \
+       | MUSB_CSR0_RXPKTRDY)
+
+/* TxType/RxType */
+#define MUSB_TYPE_SPEED                0xc0
+#define MUSB_TYPE_SPEED_SHIFT  6
+#define MUSB_TYPE_SPEED_HIGH   1
+#define MUSB_TYPE_SPEED_FULL   2
+#define MUSB_TYPE_SPEED_LOW    3
+#define MUSB_TYPE_PROTO                0x30    /* Implicitly zero for ep0 */
+#define MUSB_TYPE_PROTO_SHIFT  4
+#define MUSB_TYPE_REMOTE_END   0xf     /* Implicitly zero for ep0 */
+#define MUSB_TYPE_PROTO_BULK   2
+#define MUSB_TYPE_PROTO_INTR   3
+
+/* CONFIGDATA */
+#define MUSB_CONFIGDATA_MPRXE          0x80    /* Auto bulk pkt combining */
+#define MUSB_CONFIGDATA_MPTXE          0x40    /* Auto bulk pkt splitting */
+#define MUSB_CONFIGDATA_BIGENDIAN      0x20
+#define MUSB_CONFIGDATA_HBRXE          0x10    /* HB-ISO for RX */
+#define MUSB_CONFIGDATA_HBTXE          0x08    /* HB-ISO for TX */
+#define MUSB_CONFIGDATA_DYNFIFO                0x04    /* Dynamic FIFO sizing */
+#define MUSB_CONFIGDATA_SOFTCONE       0x02    /* SoftConnect */
+#define MUSB_CONFIGDATA_UTMIDW         0x01    /* Data width 0/1 => 8/16bits */
+
+/* TXCSR in Peripheral and Host mode */
+#define MUSB_TXCSR_AUTOSET             0x8000
+#define MUSB_TXCSR_MODE                        0x2000
+#define MUSB_TXCSR_DMAENAB             0x1000
+#define MUSB_TXCSR_FRCDATATOG          0x0800
+#define MUSB_TXCSR_DMAMODE             0x0400
+#define MUSB_TXCSR_CLRDATATOG          0x0040
+#define MUSB_TXCSR_FLUSHFIFO           0x0008
+#define MUSB_TXCSR_FIFONOTEMPTY                0x0002
+#define MUSB_TXCSR_TXPKTRDY            0x0001
+
+/* TXCSR in Peripheral mode */
+#define MUSB_TXCSR_P_ISO               0x4000
+#define MUSB_TXCSR_P_INCOMPTX          0x0080
+#define MUSB_TXCSR_P_SENTSTALL         0x0020
+#define MUSB_TXCSR_P_SENDSTALL         0x0010
+#define MUSB_TXCSR_P_UNDERRUN          0x0004
+
+/* TXCSR in Host mode */
+#define MUSB_TXCSR_H_WR_DATATOGGLE     0x0200
+#define MUSB_TXCSR_H_DATATOGGLE                0x0100
+#define MUSB_TXCSR_H_NAKTIMEOUT                0x0080
+#define MUSB_TXCSR_H_RXSTALL           0x0020
+#define MUSB_TXCSR_H_ERROR             0x0004
+#define MUSB_TXCSR_H_DATATOGGLE_SHIFT  8
+
+/* TXCSR bits to avoid zeroing (write zero clears, write 1 ignored) */
+#define MUSB_TXCSR_P_WZC_BITS  \
+       (MUSB_TXCSR_P_INCOMPTX | MUSB_TXCSR_P_SENTSTALL \
+       | MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_FIFONOTEMPTY)
+#define MUSB_TXCSR_H_WZC_BITS  \
+       (MUSB_TXCSR_H_NAKTIMEOUT | MUSB_TXCSR_H_RXSTALL \
+       | MUSB_TXCSR_H_ERROR | MUSB_TXCSR_FIFONOTEMPTY)
+
+/* RXCSR in Peripheral and Host mode */
+#define MUSB_RXCSR_AUTOCLEAR           0x8000
+#define MUSB_RXCSR_DMAENAB             0x2000
+#define MUSB_RXCSR_DISNYET             0x1000
+#define MUSB_RXCSR_PID_ERR             0x1000
+#define MUSB_RXCSR_DMAMODE             0x0800
+#define MUSB_RXCSR_INCOMPRX            0x0100
+#define MUSB_RXCSR_CLRDATATOG          0x0080
+#define MUSB_RXCSR_FLUSHFIFO           0x0010
+#define MUSB_RXCSR_DATAERROR           0x0008
+#define MUSB_RXCSR_FIFOFULL            0x0002
+#define MUSB_RXCSR_RXPKTRDY            0x0001
+
+/* RXCSR in Peripheral mode */
+#define MUSB_RXCSR_P_ISO               0x4000
+#define MUSB_RXCSR_P_SENTSTALL         0x0040
+#define MUSB_RXCSR_P_SENDSTALL         0x0020
+#define MUSB_RXCSR_P_OVERRUN           0x0004
+
+/* RXCSR in Host mode */
+#define MUSB_RXCSR_H_AUTOREQ           0x4000
+#define MUSB_RXCSR_H_WR_DATATOGGLE     0x0400
+#define MUSB_RXCSR_H_DATATOGGLE                0x0200
+#define MUSB_RXCSR_H_RXSTALL           0x0040
+#define MUSB_RXCSR_H_REQPKT            0x0020
+#define MUSB_RXCSR_H_ERROR             0x0004
+#define MUSB_S_RXCSR_H_DATATOGGLE      9
+
+/* RXCSR bits to avoid zeroing (write zero clears, write 1 ignored) */
+#define MUSB_RXCSR_P_WZC_BITS  \
+       (MUSB_RXCSR_P_SENTSTALL | MUSB_RXCSR_P_OVERRUN \
+       | MUSB_RXCSR_RXPKTRDY)
+#define MUSB_RXCSR_H_WZC_BITS  \
+       (MUSB_RXCSR_H_RXSTALL | MUSB_RXCSR_H_ERROR \
+       | MUSB_RXCSR_DATAERROR | MUSB_RXCSR_RXPKTRDY)
+
+/* HUBADDR */
+#define MUSB_HUBADDR_MULTI_TT          0x80
+
+/* Endpoint configuration information. Note: The value of endpoint fifo size
+ * element should be either 8,16,32,64,128,256,512,1024,2048 or 4096. Other
+ * values are not supported
+ */
+struct musb_epinfo {
+       u8      epnum;  /* endpoint number      */
+       u8      epdir;  /* endpoint direction   */
+       u16     epsize; /* endpoint FIFO size   */
+};
+
+/*
+ * Platform specific MUSB configuration. Any platform using the musb
+ * functionality should create one instance of this structure in the
+ * platform specific file.
+ */
+struct musb_config {
+       struct  musb_regs       *regs;
+       u32                     timeout;
+       u8                      musb_speed;
+};
+
+/* externally defined data */
+extern struct musb_config      musb_cfg;
+extern struct musb_regs                *musbr;
+
+/* exported functions */
+extern void musb_start(void);
+extern void musb_configure_ep(struct musb_epinfo *epinfo, u8 cnt);
+extern void write_fifo(u8 ep, u32 length, void *fifo_data);
+extern void read_fifo(u8 ep, u32 length, void *fifo_data);
+
+/* extern functions */
+extern inline void musb_writew(u32 offset, u16 value);
+extern inline void musb_writeb(u32 offset, u8 value);
+extern inline u16 musb_readw(u32 offset);
+extern inline u8 musb_readb(u32 offset);
+
+#endif /* __MUSB_HDRC_DEFS_H__ */
diff --git a/drivers/usb/musb/musb_hcd.c b/drivers/usb/musb/musb_hcd.c
new file mode 100644 (file)
index 0000000..352a0d4
--- /dev/null
@@ -0,0 +1,792 @@
+/*
+ * Mentor USB OTG Core host controller driver.
+ *
+ * Copyright (c) 2008 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
+ *
+ * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
+ */
+
+#include <common.h>
+#include "musb_hcd.h"
+
+/* MSC control transfers */
+#define USB_MSC_BBB_RESET      0xFF
+#define USB_MSC_BBB_GET_MAX_LUN        0xFE
+
+/* Endpoint configuration information */
+static struct musb_epinfo epinfo[3] = {
+       {MUSB_BULK_EP, 1, 512}, /* EP1 - Bluk Out - 512 Bytes */
+       {MUSB_BULK_EP, 0, 512}, /* EP1 - Bluk In  - 512 Bytes */
+       {MUSB_INTR_EP, 0, 64}   /* EP2 - Interrupt IN - 64 Bytes */
+};
+
+/*
+ * This function writes the data toggle value.
+ */
+static void write_toggle(struct usb_device *dev, u8 ep, u8 dir_out)
+{
+       u16 toggle = usb_gettoggle(dev, ep, dir_out);
+       u16 csr;
+
+       if (dir_out) {
+               if (!toggle)
+                       writew(MUSB_TXCSR_CLRDATATOG, &musbr->txcsr);
+               else {
+                       csr = readw(&musbr->txcsr);
+                       csr |= MUSB_TXCSR_H_WR_DATATOGGLE;
+                       writew(csr, &musbr->txcsr);
+                       csr |= (toggle << MUSB_TXCSR_H_DATATOGGLE_SHIFT);
+                       writew(csr, &musbr->txcsr);
+               }
+       } else {
+               if (!toggle)
+                       writew(MUSB_RXCSR_CLRDATATOG, &musbr->rxcsr);
+               else {
+                       csr = readw(&musbr->rxcsr);
+                       csr |= MUSB_RXCSR_H_WR_DATATOGGLE;
+                       writew(csr, &musbr->rxcsr);
+                       csr |= (toggle << MUSB_S_RXCSR_H_DATATOGGLE);
+                       writew(csr, &musbr->rxcsr);
+               }
+       }
+}
+
+/*
+ * This function checks if RxStall has occured on the endpoint. If a RxStall
+ * has occured, the RxStall is cleared and 1 is returned. If RxStall has
+ * not occured, 0 is returned.
+ */
+static u8 check_stall(u8 ep, u8 dir_out)
+{
+       u16 csr;
+
+       /* For endpoint 0 */
+       if (!ep) {
+               csr = readw(&musbr->txcsr);
+               if (csr & MUSB_CSR0_H_RXSTALL) {
+                       csr &= ~MUSB_CSR0_H_RXSTALL;
+                       writew(csr, &musbr->txcsr);
+                       return 1;
+               }
+       } else { /* For non-ep0 */
+               if (dir_out) { /* is it tx ep */
+                       csr = readw(&musbr->txcsr);
+                       if (csr & MUSB_TXCSR_H_RXSTALL) {
+                               csr &= ~MUSB_TXCSR_H_RXSTALL;
+                               writew(csr, &musbr->txcsr);
+                               return 1;
+                       }
+               } else { /* is it rx ep */
+                       csr = readw(&musbr->rxcsr);
+                       if (csr & MUSB_RXCSR_H_RXSTALL) {
+                               csr &= ~MUSB_RXCSR_H_RXSTALL;
+                               writew(csr, &musbr->rxcsr);
+                               return 1;
+                       }
+               }
+       }
+       return 0;
+}
+
+/*
+ * waits until ep0 is ready. Returns 0 if ep is ready, -1 for timeout
+ * error and -2 for stall.
+ */
+static int wait_until_ep0_ready(struct usb_device *dev, u32 bit_mask)
+{
+       u16 csr;
+       int result = 1;
+
+       while (result > 0) {
+               csr = readw(&musbr->txcsr);
+               if (csr & MUSB_CSR0_H_ERROR) {
+                       csr &= ~MUSB_CSR0_H_ERROR;
+                       writew(csr, &musbr->txcsr);
+                       dev->status = USB_ST_CRC_ERR;
+                       result = -1;
+                       break;
+               }
+
+               switch (bit_mask) {
+               case MUSB_CSR0_TXPKTRDY:
+                       if (!(csr & MUSB_CSR0_TXPKTRDY)) {
+                               if (check_stall(MUSB_CONTROL_EP, 0)) {
+                                       dev->status = USB_ST_STALLED;
+                                       result = -2;
+                               } else
+                                       result = 0;
+                       }
+                       break;
+
+               case MUSB_CSR0_RXPKTRDY:
+                       if (check_stall(MUSB_CONTROL_EP, 0)) {
+                               dev->status = USB_ST_STALLED;
+                               result = -2;
+                       } else
+                               if (csr & MUSB_CSR0_RXPKTRDY)
+                                       result = 0;
+                       break;
+
+               case MUSB_CSR0_H_REQPKT:
+                       if (!(csr & MUSB_CSR0_H_REQPKT)) {
+                               if (check_stall(MUSB_CONTROL_EP, 0)) {
+                                       dev->status = USB_ST_STALLED;
+                                       result = -2;
+                               } else
+                                       result = 0;
+                       }
+                       break;
+               }
+       }
+       return result;
+}
+
+/*
+ * waits until tx ep is ready. Returns 1 when ep is ready and 0 on error.
+ */
+static u8 wait_until_txep_ready(struct usb_device *dev, u8 ep)
+{
+       u16 csr;
+
+       do {
+               if (check_stall(ep, 1)) {
+                       dev->status = USB_ST_STALLED;
+                       return 0;
+               }
+
+               csr = readw(&musbr->txcsr);
+               if (csr & MUSB_TXCSR_H_ERROR) {
+                       dev->status = USB_ST_CRC_ERR;
+                       return 0;
+               }
+       } while (csr & MUSB_TXCSR_TXPKTRDY);
+       return 1;
+}
+
+/*
+ * waits until rx ep is ready. Returns 1 when ep is ready and 0 on error.
+ */
+static u8 wait_until_rxep_ready(struct usb_device *dev, u8 ep)
+{
+       u16 csr;
+
+       do {
+               if (check_stall(ep, 0)) {
+                       dev->status = USB_ST_STALLED;
+                       return 0;
+               }
+
+               csr = readw(&musbr->rxcsr);
+               if (csr & MUSB_RXCSR_H_ERROR) {
+                       dev->status = USB_ST_CRC_ERR;
+                       return 0;
+               }
+       } while (!(csr & MUSB_RXCSR_RXPKTRDY));
+       return 1;
+}
+
+/*
+ * This function performs the setup phase of the control transfer
+ */
+static int ctrlreq_setup_phase(struct usb_device *dev, struct devrequest *setup)
+{
+       int result;
+       u16 csr;
+
+       /* write the control request to ep0 fifo */
+       write_fifo(MUSB_CONTROL_EP, sizeof(struct devrequest), (void *)setup);
+
+       /* enable transfer of setup packet */
+       csr = readw(&musbr->txcsr);
+       csr |= (MUSB_CSR0_TXPKTRDY|MUSB_CSR0_H_SETUPPKT);
+       writew(csr, &musbr->txcsr);
+
+       /* wait until the setup packet is transmitted */
+       result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY);
+       dev->act_len = 0;
+       return result;
+}
+
+/*
+ * This function handles the control transfer in data phase
+ */
+static int ctrlreq_in_data_phase(struct usb_device *dev, u32 len, void *buffer)
+{
+       u16 csr;
+       u32 rxlen = 0;
+       u32 nextlen = 0;
+       u8  maxpktsize = (1 << dev->maxpacketsize) * 8;
+       u8  *rxbuff = (u8 *)buffer;
+       u8  rxedlength;
+       int result;
+
+       while (rxlen < len) {
+               /* Determine the next read length */
+               nextlen = ((len-rxlen) > maxpktsize) ? maxpktsize : (len-rxlen);
+
+               /* Set the ReqPkt bit */
+               csr = readw(&musbr->txcsr);
+               writew(csr | MUSB_CSR0_H_REQPKT, &musbr->txcsr);
+               result = wait_until_ep0_ready(dev, MUSB_CSR0_RXPKTRDY);
+               if (result < 0)
+                       return result;
+
+               /* Actual number of bytes received by usb */
+               rxedlength = readb(&musbr->rxcount);
+
+               /* Read the data from the RxFIFO */
+               read_fifo(MUSB_CONTROL_EP, rxedlength, &rxbuff[rxlen]);
+
+               /* Clear the RxPktRdy Bit */
+               csr = readw(&musbr->txcsr);
+               csr &= ~MUSB_CSR0_RXPKTRDY;
+               writew(csr, &musbr->txcsr);
+
+               /* short packet? */
+               if (rxedlength != nextlen) {
+                       dev->act_len += rxedlength;
+                       break;
+               }
+               rxlen += nextlen;
+               dev->act_len = rxlen;
+       }
+       return 0;
+}
+
+/*
+ * This function handles the control transfer out data phase
+ */
+static int ctrlreq_out_data_phase(struct usb_device *dev, u32 len, void *buffer)
+{
+       u16 csr;
+       u32 txlen = 0;
+       u32 nextlen = 0;
+       u8  maxpktsize = (1 << dev->maxpacketsize) * 8;
+       u8  *txbuff = (u8 *)buffer;
+       int result = 0;
+
+       while (txlen < len) {
+               /* Determine the next write length */
+               nextlen = ((len-txlen) > maxpktsize) ? maxpktsize : (len-txlen);
+
+               /* Load the data to send in FIFO */
+               write_fifo(MUSB_CONTROL_EP, txlen, &txbuff[txlen]);
+
+               /* Set TXPKTRDY bit */
+               csr = readw(&musbr->txcsr);
+               writew(csr | MUSB_CSR0_H_DIS_PING | MUSB_CSR0_TXPKTRDY,
+                                       &musbr->txcsr);
+               result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY);
+               if (result < 0)
+                       break;
+
+               txlen += nextlen;
+               dev->act_len = txlen;
+       }
+       return result;
+}
+
+/*
+ * This function handles the control transfer out status phase
+ */
+static int ctrlreq_out_status_phase(struct usb_device *dev)
+{
+       u16 csr;
+       int result;
+
+       /* Set the StatusPkt bit */
+       csr = readw(&musbr->txcsr);
+       csr |= (MUSB_CSR0_H_DIS_PING | MUSB_CSR0_TXPKTRDY |
+                       MUSB_CSR0_H_STATUSPKT);
+       writew(csr, &musbr->txcsr);
+
+       /* Wait until TXPKTRDY bit is cleared */
+       result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY);
+       return result;
+}
+
+/*
+ * This function handles the control transfer in status phase
+ */
+static int ctrlreq_in_status_phase(struct usb_device *dev)
+{
+       u16 csr;
+       int result;
+
+       /* Set the StatusPkt bit and ReqPkt bit */
+       csr = MUSB_CSR0_H_DIS_PING | MUSB_CSR0_H_REQPKT | MUSB_CSR0_H_STATUSPKT;
+       writew(csr, &musbr->txcsr);
+       result = wait_until_ep0_ready(dev, MUSB_CSR0_H_REQPKT);
+
+       /* clear StatusPkt bit and RxPktRdy bit */
+       csr = readw(&musbr->txcsr);
+       csr &= ~(MUSB_CSR0_RXPKTRDY | MUSB_CSR0_H_STATUSPKT);
+       writew(csr, &musbr->txcsr);
+       return result;
+}
+
+/*
+ * determines the speed of the device (High/Full/Slow)
+ */
+static u8 get_dev_speed(struct usb_device *dev)
+{
+       return (dev->speed & USB_SPEED_HIGH) ? MUSB_TYPE_SPEED_HIGH :
+               ((dev->speed & USB_SPEED_LOW) ? MUSB_TYPE_SPEED_LOW :
+                                               MUSB_TYPE_SPEED_FULL);
+}
+
+/*
+ * configure the hub address and the port address.
+ */
+static void config_hub_port(struct usb_device *dev, u8 ep)
+{
+       u8 chid;
+       u8 hub;
+
+       /* Find out the nearest parent which is high speed */
+       while (dev->parent->parent != NULL)
+               if (get_dev_speed(dev->parent) !=  MUSB_TYPE_SPEED_HIGH)
+                       dev = dev->parent;
+               else
+                       break;
+
+       /* determine the port address at that hub */
+       hub = dev->parent->devnum;
+       for (chid = 0; chid < USB_MAXCHILDREN; chid++)
+               if (dev->parent->children[chid] == dev)
+                       break;
+
+       /* configure the hub address and the port address */
+       writeb(hub, &musbr->tar[ep].txhubaddr);
+       writeb((chid + 1), &musbr->tar[ep].txhubport);
+       writeb(hub, &musbr->tar[ep].rxhubaddr);
+       writeb((chid + 1), &musbr->tar[ep].rxhubport);
+}
+
+/*
+ * do a control transfer
+ */
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                       int len, struct devrequest *setup)
+{
+       int devnum = usb_pipedevice(pipe);
+       u16 csr;
+       u8  devspeed;
+
+       /* select control endpoint */
+       writeb(MUSB_CONTROL_EP, &musbr->index);
+       csr = readw(&musbr->txcsr);
+
+       /* target addr and (for multipoint) hub addr/port */
+       writeb(devnum, &musbr->tar[MUSB_CONTROL_EP].txfuncaddr);
+       writeb(devnum, &musbr->tar[MUSB_CONTROL_EP].rxfuncaddr);
+
+       /* configure the hub address and the port number as required */
+       devspeed = get_dev_speed(dev);
+       if ((musb_ishighspeed()) && (dev->parent != NULL) &&
+               (devspeed != MUSB_TYPE_SPEED_HIGH)) {
+               config_hub_port(dev, MUSB_CONTROL_EP);
+               writeb(devspeed << 6, &musbr->txtype);
+       } else {
+               writeb(musb_cfg.musb_speed << 6, &musbr->txtype);
+               writeb(0, &musbr->tar[MUSB_CONTROL_EP].txhubaddr);
+               writeb(0, &musbr->tar[MUSB_CONTROL_EP].txhubport);
+               writeb(0, &musbr->tar[MUSB_CONTROL_EP].rxhubaddr);
+               writeb(0, &musbr->tar[MUSB_CONTROL_EP].rxhubport);
+       }
+
+       /* Control transfer setup phase */
+       if (ctrlreq_setup_phase(dev, setup) < 0)
+               return 0;
+
+       switch (setup->request) {
+       case USB_REQ_GET_DESCRIPTOR:
+       case USB_REQ_GET_CONFIGURATION:
+       case USB_REQ_GET_INTERFACE:
+       case USB_REQ_GET_STATUS:
+       case USB_MSC_BBB_GET_MAX_LUN:
+               /* control transfer in-data-phase */
+               if (ctrlreq_in_data_phase(dev, len, buffer) < 0)
+                       return 0;
+               /* control transfer out-status-phase */
+               if (ctrlreq_out_status_phase(dev) < 0)
+                       return 0;
+               break;
+
+       case USB_REQ_SET_ADDRESS:
+       case USB_REQ_SET_CONFIGURATION:
+       case USB_REQ_SET_FEATURE:
+       case USB_REQ_SET_INTERFACE:
+       case USB_REQ_CLEAR_FEATURE:
+       case USB_MSC_BBB_RESET:
+               /* control transfer in status phase */
+               if (ctrlreq_in_status_phase(dev) < 0)
+                       return 0;
+               break;
+
+       case USB_REQ_SET_DESCRIPTOR:
+               /* control transfer out data phase */
+               if (ctrlreq_out_data_phase(dev, len, buffer) < 0)
+                       return 0;
+               /* control transfer in status phase */
+               if (ctrlreq_in_status_phase(dev) < 0)
+                       return 0;
+               break;
+
+       default:
+               /* unhandled control transfer */
+               return -1;
+       }
+
+       dev->status = 0;
+       dev->act_len = len;
+       return len;
+}
+
+/*
+ * do a bulk transfer
+ */
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
+                                       void *buffer, int len)
+{
+       int dir_out = usb_pipeout(pipe);
+       int ep = usb_pipeendpoint(pipe);
+       int devnum = usb_pipedevice(pipe);
+       u8  type;
+       u16 csr;
+       u32 txlen = 0;
+       u32 nextlen = 0;
+       u8  devspeed;
+
+       /* select bulk endpoint */
+       writeb(MUSB_BULK_EP, &musbr->index);
+
+       /* write the address of the device */
+       if (dir_out)
+               writeb(devnum, &musbr->tar[MUSB_BULK_EP].txfuncaddr);
+       else
+               writeb(devnum, &musbr->tar[MUSB_BULK_EP].rxfuncaddr);
+
+       /* configure the hub address and the port number as required */
+       devspeed = get_dev_speed(dev);
+       if ((musb_ishighspeed()) && (dev->parent != NULL) &&
+               (devspeed != MUSB_TYPE_SPEED_HIGH)) {
+               /*
+                * MUSB is in high speed and the destination device is full
+                * speed device. So configure the hub address and port
+                * address registers.
+                */
+               config_hub_port(dev, MUSB_BULK_EP);
+       } else {
+               if (dir_out) {
+                       writeb(0, &musbr->tar[MUSB_BULK_EP].txhubaddr);
+                       writeb(0, &musbr->tar[MUSB_BULK_EP].txhubport);
+               } else {
+                       writeb(0, &musbr->tar[MUSB_BULK_EP].rxhubaddr);
+                       writeb(0, &musbr->tar[MUSB_BULK_EP].rxhubport);
+               }
+               devspeed = musb_cfg.musb_speed;
+       }
+
+       /* Write the saved toggle bit value */
+       write_toggle(dev, ep, dir_out);
+
+       if (dir_out) { /* bulk-out transfer */
+               /* Program the TxType register */
+               type = (devspeed << MUSB_TYPE_SPEED_SHIFT) |
+                          (MUSB_TYPE_PROTO_BULK << MUSB_TYPE_PROTO_SHIFT) |
+                          (ep & MUSB_TYPE_REMOTE_END);
+               writeb(type, &musbr->txtype);
+
+               /* Write maximum packet size to the TxMaxp register */
+               writew(dev->epmaxpacketout[ep], &musbr->txmaxp);
+               while (txlen < len) {
+                       nextlen = ((len-txlen) < dev->epmaxpacketout[ep]) ?
+                                       (len-txlen) : dev->epmaxpacketout[ep];
+
+                       /* Write the data to the FIFO */
+                       write_fifo(MUSB_BULK_EP, nextlen,
+                                       (void *)(((u8 *)buffer) + txlen));
+
+                       /* Set the TxPktRdy bit */
+                       csr = readw(&musbr->txcsr);
+                       writew(csr | MUSB_TXCSR_TXPKTRDY, &musbr->txcsr);
+
+                       /* Wait until the TxPktRdy bit is cleared */
+                       if (!wait_until_txep_ready(dev, MUSB_BULK_EP)) {
+                               readw(&musbr->txcsr);
+                               usb_settoggle(dev, ep, dir_out,
+                               (csr >> MUSB_TXCSR_H_DATATOGGLE_SHIFT) & 1);
+                               dev->act_len = txlen;
+                               return 0;
+                       }
+                       txlen += nextlen;
+               }
+
+               /* Keep a copy of the data toggle bit */
+               csr = readw(&musbr->txcsr);
+               usb_settoggle(dev, ep, dir_out,
+                               (csr >> MUSB_TXCSR_H_DATATOGGLE_SHIFT) & 1);
+       } else { /* bulk-in transfer */
+               /* Write the saved toggle bit value */
+               write_toggle(dev, ep, dir_out);
+
+               /* Program the RxType register */
+               type = (devspeed << MUSB_TYPE_SPEED_SHIFT) |
+                          (MUSB_TYPE_PROTO_BULK << MUSB_TYPE_PROTO_SHIFT) |
+                          (ep & MUSB_TYPE_REMOTE_END);
+               writeb(type, &musbr->rxtype);
+
+               /* Write the maximum packet size to the RxMaxp register */
+               writew(dev->epmaxpacketin[ep], &musbr->rxmaxp);
+               while (txlen < len) {
+                       nextlen = ((len-txlen) < dev->epmaxpacketin[ep]) ?
+                                       (len-txlen) : dev->epmaxpacketin[ep];
+
+                       /* Set the ReqPkt bit */
+                       writew(MUSB_RXCSR_H_REQPKT, &musbr->rxcsr);
+
+                       /* Wait until the RxPktRdy bit is set */
+                       if (!wait_until_rxep_ready(dev, MUSB_BULK_EP)) {
+                               csr = readw(&musbr->rxcsr);
+                               usb_settoggle(dev, ep, dir_out,
+                               (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
+                               csr &= ~MUSB_RXCSR_RXPKTRDY;
+                               writew(csr, &musbr->rxcsr);
+                               dev->act_len = txlen;
+                               return 0;
+                       }
+
+                       /* Read the data from the FIFO */
+                       read_fifo(MUSB_BULK_EP, nextlen,
+                                       (void *)(((u8 *)buffer) + txlen));
+
+                       /* Clear the RxPktRdy bit */
+                       csr =  readw(&musbr->rxcsr);
+                       csr &= ~MUSB_RXCSR_RXPKTRDY;
+                       writew(csr, &musbr->rxcsr);
+                       txlen += nextlen;
+               }
+
+               /* Keep a copy of the data toggle bit */
+               csr = readw(&musbr->rxcsr);
+               usb_settoggle(dev, ep, dir_out,
+                               (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
+       }
+
+       /* bulk transfer is complete */
+       dev->status = 0;
+       dev->act_len = len;
+       return 0;
+}
+
+/*
+ * This function initializes the usb controller module.
+ */
+int usb_lowlevel_init(void)
+{
+       u8  power;
+       u32 timeout;
+
+       if (musb_platform_init() == -1)
+               return -1;
+
+       /* Configure all the endpoint FIFO's and start usb controller */
+       musbr = musb_cfg.regs;
+       musb_configure_ep(&epinfo[0],
+                       sizeof(epinfo) / sizeof(struct musb_epinfo));
+       musb_start();
+
+       /*
+        * Wait until musb is enabled in host mode with a timeout. There
+        * should be a usb device connected.
+        */
+       timeout = musb_cfg.timeout;
+       while (timeout--)
+               if (readb(&musbr->devctl) & MUSB_DEVCTL_HM)
+                       break;
+
+       /* if musb core is not in host mode, then return */
+       if (!timeout)
+               return -1;
+
+       /* start usb bus reset */
+       power = readb(&musbr->power);
+       writeb(power | MUSB_POWER_RESET, &musbr->power);
+
+       /* After initiating a usb reset, wait for about 20ms to 30ms */
+       udelay(30000);
+
+       /* stop usb bus reset */
+       power = readb(&musbr->power);
+       power &= ~MUSB_POWER_RESET;
+       writeb(power, &musbr->power);
+
+       /* Determine if the connected device is a high/full/low speed device */
+       musb_cfg.musb_speed = (readb(&musbr->power) & MUSB_POWER_HSMODE) ?
+                       MUSB_TYPE_SPEED_HIGH :
+                       ((readb(&musbr->devctl) & MUSB_DEVCTL_FSDEV) ?
+                       MUSB_TYPE_SPEED_FULL : MUSB_TYPE_SPEED_LOW);
+       return 0;
+}
+
+/*
+ * This function stops the operation of the davinci usb module.
+ */
+int usb_lowlevel_stop(void)
+{
+       /* Reset the USB module */
+       musb_platform_deinit();
+       writeb(0, &musbr->devctl);
+       return 0;
+}
+
+/*
+ * This function supports usb interrupt transfers. Currently, usb interrupt
+ * transfers are not supported.
+ */
+int submit_int_msg(struct usb_device *dev, unsigned long pipe,
+                               void *buffer, int len, int interval)
+{
+       int dir_out = usb_pipeout(pipe);
+       int ep = usb_pipeendpoint(pipe);
+       int devnum = usb_pipedevice(pipe);
+       u8  type;
+       u16 csr;
+       u32 txlen = 0;
+       u32 nextlen = 0;
+       u8  devspeed;
+
+       /* select interrupt endpoint */
+       writeb(MUSB_INTR_EP, &musbr->index);
+
+       /* write the address of the device */
+       if (dir_out)
+               writeb(devnum, &musbr->tar[MUSB_INTR_EP].txfuncaddr);
+       else
+               writeb(devnum, &musbr->tar[MUSB_INTR_EP].rxfuncaddr);
+
+       /* configure the hub address and the port number as required */
+       devspeed = get_dev_speed(dev);
+       if ((musb_ishighspeed()) && (dev->parent != NULL) &&
+               (devspeed != MUSB_TYPE_SPEED_HIGH)) {
+               /*
+                * MUSB is in high speed and the destination device is full
+                * speed device. So configure the hub address and port
+                * address registers.
+                */
+               config_hub_port(dev, MUSB_INTR_EP);
+       } else {
+               if (dir_out) {
+                       writeb(0, &musbr->tar[MUSB_INTR_EP].txhubaddr);
+                       writeb(0, &musbr->tar[MUSB_INTR_EP].txhubport);
+               } else {
+                       writeb(0, &musbr->tar[MUSB_INTR_EP].rxhubaddr);
+                       writeb(0, &musbr->tar[MUSB_INTR_EP].rxhubport);
+               }
+               devspeed = musb_cfg.musb_speed;
+       }
+
+       /* Write the saved toggle bit value */
+       write_toggle(dev, ep, dir_out);
+
+       if (!dir_out) { /* intrrupt-in transfer */
+               /* Write the saved toggle bit value */
+               write_toggle(dev, ep, dir_out);
+               writeb(interval, &musbr->rxinterval);
+
+               /* Program the RxType register */
+               type = (devspeed << MUSB_TYPE_SPEED_SHIFT) |
+                          (MUSB_TYPE_PROTO_INTR << MUSB_TYPE_PROTO_SHIFT) |
+                          (ep & MUSB_TYPE_REMOTE_END);
+               writeb(type, &musbr->rxtype);
+
+               /* Write the maximum packet size to the RxMaxp register */
+               writew(dev->epmaxpacketin[ep], &musbr->rxmaxp);
+
+               while (txlen < len) {
+                       nextlen = ((len-txlen) < dev->epmaxpacketin[ep]) ?
+                                       (len-txlen) : dev->epmaxpacketin[ep];
+
+                       /* Set the ReqPkt bit */
+                       writew(MUSB_RXCSR_H_REQPKT, &musbr->rxcsr);
+
+                       /* Wait until the RxPktRdy bit is set */
+                       if (!wait_until_rxep_ready(dev, MUSB_INTR_EP)) {
+                               csr = readw(&musbr->rxcsr);
+                               usb_settoggle(dev, ep, dir_out,
+                               (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
+                               csr &= ~MUSB_RXCSR_RXPKTRDY;
+                               writew(csr, &musbr->rxcsr);
+                               dev->act_len = txlen;
+                               return 0;
+                       }
+
+                       /* Read the data from the FIFO */
+                       read_fifo(MUSB_INTR_EP, nextlen,
+                                       (void *)(((u8 *)buffer) + txlen));
+
+                       /* Clear the RxPktRdy bit */
+                       csr =  readw(&musbr->rxcsr);
+                       csr &= ~MUSB_RXCSR_RXPKTRDY;
+                       writew(csr, &musbr->rxcsr);
+                       txlen += nextlen;
+               }
+
+               /* Keep a copy of the data toggle bit */
+               csr = readw(&musbr->rxcsr);
+               usb_settoggle(dev, ep, dir_out,
+                               (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
+       }
+
+       /* interrupt transfer is complete */
+       dev->irq_status = 0;
+       dev->irq_act_len = len;
+       dev->irq_handle(dev);
+       dev->status = 0;
+       dev->act_len = len;
+       return 0;
+}
+
+
+#ifdef CONFIG_SYS_USB_EVENT_POLL
+/*
+ * This function polls for USB keyboard data.
+ */
+void usb_event_poll()
+{
+       device_t *dev;
+       struct usb_device *usb_kbd_dev;
+       struct usb_interface_descriptor *iface;
+       struct usb_endpoint_descriptor *ep;
+       int pipe;
+       int maxp;
+
+       /* Get the pointer to USB Keyboard device pointer */
+       dev = device_get_by_name("usbkbd");
+       usb_kbd_dev = (struct usb_device *)dev->priv;
+       iface = &usb_kbd_dev->config.if_desc[0];
+       ep = &iface->ep_desc[0];
+       pipe = usb_rcvintpipe(usb_kbd_dev, ep->bEndpointAddress);
+
+       /* Submit a interrupt transfer request */
+       maxp = usb_maxpacket(usb_kbd_dev, pipe);
+       usb_submit_int_msg(usb_kbd_dev, pipe, &new[0],
+                       maxp > 8 ? 8 : maxp, ep->bInterval);
+}
+#endif /* CONFIG_SYS_USB_EVENT_POLL */
diff --git a/drivers/usb/musb/musb_hcd.h b/drivers/usb/musb/musb_hcd.h
new file mode 100644 (file)
index 0000000..bb83311
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Mentor USB OTG Core host controller driver.
+ *
+ * Copyright (c) 2008 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
+ *
+ * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
+ */
+
+#ifndef __MUSB_HCD_H__
+#define __MUSB_HCD_H__
+
+#include "musb_core.h"
+#ifdef CONFIG_USB_KEYBOARD
+#include <devices.h>
+extern unsigned char new[];
+#endif
+
+/* This defines the endpoint number used for control transfers */
+#define MUSB_CONTROL_EP 0
+
+/* This defines the endpoint number used for bulk transfer */
+#define MUSB_BULK_EP 1
+
+/* This defines the endpoint number used for interrupt transfer */
+#define MUSB_INTR_EP 2
+
+/* Determine the operating speed of MUSB core */
+#define musb_ishighspeed() \
+       ((readb(&musbr->power) & MUSB_POWER_HSMODE) \
+               >> MUSB_POWER_HSMODE_SHIFT)
+
+/* extern functions */
+extern int musb_platform_init(void);
+extern void musb_platform_deinit(void);
+
+#endif /* __MUSB_HCD_H__ */
diff --git a/drivers/usb/musb_core.c b/drivers/usb/musb_core.c
deleted file mode 100644 (file)
index ec57fc8..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Mentor USB OTG Core functionality common for both Host and Device
- * functionality.
- *
- * Copyright (c) 2008 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
- *
- * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
- */
-
-#include <common.h>
-
-#include "musb_core.h"
-struct musb_regs *musbr;
-
-/*
- * program the mentor core to start (enable interrupts, dma, etc.)
- */
-void musb_start(void)
-{
-       u8 devctl;
-
-       /* disable all interrupts */
-       writew(0, &musbr->intrtxe);
-       writew(0, &musbr->intrrxe);
-       writeb(0, &musbr->intrusbe);
-       writeb(0, &musbr->testmode);
-
-       /* put into basic highspeed mode and start session */
-       writeb(MUSB_POWER_HSENAB, &musbr->power);
-#if defined(CONFIG_MUSB_HCD)
-       devctl = readb(&musbr->devctl);
-       writeb(devctl | MUSB_DEVCTL_SESSION, &musbr->devctl);
-#endif
-}
-
-/*
- * This function configures the endpoint configuration. The musb hcd or musb
- * device implementation can use this function to configure the endpoints
- * and set the FIFO sizes. Note: The summation of FIFO sizes of all endpoints
- * should not be more than the available FIFO size.
- *
- * epinfo      - Pointer to EP configuration table
- * cnt         - Number of entries in the EP conf table.
- */
-void musb_configure_ep(struct musb_epinfo *epinfo, u8 cnt)
-{
-       u16 csr;
-       u16 fifoaddr = 64; /* First 64 bytes of FIFO reserved for EP0 */
-       u32 fifosize;
-       u8  idx;
-
-       while (cnt--) {
-               /* prepare fifosize to write to register */
-               fifosize = epinfo->epsize >> 3;
-               idx = ffs(fifosize) - 1;
-
-               writeb(epinfo->epnum, &musbr->index);
-               if (epinfo->epdir) {
-                       /* Configure fifo size and fifo base address */
-                       writeb(idx, &musbr->txfifosz);
-                       writew(fifoaddr >> 3, &musbr->txfifoadd);
-#if defined(CONFIG_MUSB_HCD)
-                       /* clear the data toggle bit */
-                       csr = readw(&musbr->txcsr);
-                       writew(csr | MUSB_TXCSR_CLRDATATOG, &musbr->txcsr);
-#endif
-                       /* Flush fifo if required */
-                       if (csr & MUSB_TXCSR_TXPKTRDY)
-                               writew(csr | MUSB_TXCSR_FLUSHFIFO,
-                                       &musbr->txcsr);
-               } else {
-                       /* Configure fifo size and fifo base address */
-                       writeb(idx, &musbr->rxfifosz);
-                       writew(fifoaddr >> 3, &musbr->rxfifoadd);
-#if defined(CONFIG_MUSB_HCD)
-                       /* clear the data toggle bit */
-                       csr = readw(&musbr->rxcsr);
-                       writew(csr | MUSB_RXCSR_CLRDATATOG, &musbr->rxcsr);
-#endif
-                       /* Flush fifo if required */
-                       if (csr & MUSB_RXCSR_RXPKTRDY)
-                               writew(csr | MUSB_RXCSR_FLUSHFIFO,
-                                       &musbr->rxcsr);
-               }
-               fifoaddr += epinfo->epsize;
-               epinfo++;
-       }
-}
-
-/*
- * This function writes data to endpoint fifo
- *
- * ep          - endpoint number
- * length      - number of bytes to write to FIFO
- * fifo_data   - Pointer to data buffer that contains the data to write
- */
-void write_fifo(u8 ep, u32 length, void *fifo_data)
-{
-       u8  *data = (u8 *)fifo_data;
-
-       /* select the endpoint index */
-       writeb(ep, &musbr->index);
-
-       /* write the data to the fifo */
-       while (length--)
-               writeb(*data++, &musbr->fifox[ep]);
-}
-
-/*
- * This function reads data from endpoint fifo
- *
- * ep           - endpoint number
- * length       - number of bytes to read from FIFO
- * fifo_data    - pointer to data buffer into which data is read
- */
-void read_fifo(u8 ep, u32 length, void *fifo_data)
-{
-       u8  *data = (u8 *)fifo_data;
-
-       /* select the endpoint index */
-       writeb(ep, &musbr->index);
-
-       /* read the data to the fifo */
-       while (length--)
-               *data++ = readb(&musbr->fifox[ep]);
-}
diff --git a/drivers/usb/musb_core.h b/drivers/usb/musb_core.h
deleted file mode 100644 (file)
index 2597c5f..0000000
+++ /dev/null
@@ -1,316 +0,0 @@
-/******************************************************************
- * Copyright 2008 Mentor Graphics Corporation
- * Copyright (C) 2008 by Texas Instruments
- *
- * This file is part of the Inventra Controller Driver for Linux.
- *
- * The Inventra Controller Driver for Linux is free software; you
- * can redistribute it and/or modify it under the terms of the GNU
- * General Public License version 2 as published by the Free Software
- * Foundation.
- *
- * The Inventra Controller Driver for Linux 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 The Inventra Controller Driver for Linux ; if not,
- * write to the Free Software Foundation, Inc., 59 Temple Place,
- * Suite 330, Boston, MA  02111-1307  USA
- *
- * ANY DOWNLOAD, USE, REPRODUCTION, MODIFICATION OR DISTRIBUTION
- * OF THIS DRIVER INDICATES YOUR COMPLETE AND UNCONDITIONAL ACCEPTANCE
- * OF THOSE TERMS.THIS DRIVER IS PROVIDED "AS IS" AND MENTOR GRAPHICS
- * MAKES NO WARRANTIES, EXPRESS OR IMPLIED, RELATED TO THIS DRIVER.
- * MENTOR GRAPHICS SPECIFICALLY DISCLAIMS ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY; FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT.  MENTOR GRAPHICS DOES NOT PROVIDE SUPPORT
- * SERVICES OR UPDATES FOR THIS DRIVER, EVEN IF YOU ARE A MENTOR
- * GRAPHICS SUPPORT CUSTOMER.
- ******************************************************************/
-
-#ifndef __MUSB_HDRC_DEFS_H__
-#define __MUSB_HDRC_DEFS_H__
-
-#include <usb.h>
-#include <usb_defs.h>
-#include <asm/io.h>
-
-#define MUSB_EP0_FIFOSIZE      64      /* This is non-configurable */
-
-/* Mentor USB core register overlay structure */
-struct musb_regs {
-       /* common registers */
-       u8      faddr;
-       u8      power;
-       u16     intrtx;
-       u16     intrrx;
-       u16     intrtxe;
-       u16     intrrxe;
-       u8      intrusb;
-       u8      intrusbe;
-       u16     frame;
-       u8      index;
-       u8      testmode;
-       /* indexed registers */
-       u16     txmaxp;
-       u16     txcsr;
-       u16     rxmaxp;
-       u16     rxcsr;
-       u16     rxcount;
-       u8      txtype;
-       u8      txinterval;
-       u8      rxtype;
-       u8      rxinterval;
-       u8      reserved0;
-       u8      fifosize;
-       /* fifo */
-       u32     fifox[16];
-       /* OTG, dynamic FIFO, version & vendor registers */
-       u8      devctl;
-       u8      reserved1;
-       u8      txfifosz;
-       u8      rxfifosz;
-       u16     txfifoadd;
-       u16     rxfifoadd;
-       u32     vcontrol;
-       u16     hwvers;
-       u16     reserved2[5];
-       u8      epinfo;
-       u8      raminfo;
-       u8      linkinfo;
-       u8      vplen;
-       u8      hseof1;
-       u8      fseof1;
-       u8      lseof1;
-       u8      reserved3;
-       /* target address registers */
-       struct musb_tar_regs {
-               u8      txfuncaddr;
-               u8      reserved0;
-               u8      txhubaddr;
-               u8      txhubport;
-               u8      rxfuncaddr;
-               u8      reserved1;
-               u8      rxhubaddr;
-               u8      rxhubport;
-       } tar[16];
-} __attribute((aligned(32)));
-
-/*
- * MUSB Register bits
- */
-
-/* POWER */
-#define MUSB_POWER_ISOUPDATE   0x80
-#define MUSB_POWER_SOFTCONN    0x40
-#define MUSB_POWER_HSENAB      0x20
-#define MUSB_POWER_HSMODE      0x10
-#define MUSB_POWER_RESET       0x08
-#define MUSB_POWER_RESUME      0x04
-#define MUSB_POWER_SUSPENDM    0x02
-#define MUSB_POWER_ENSUSPEND   0x01
-#define MUSB_POWER_HSMODE_SHIFT        4
-
-/* INTRUSB */
-#define MUSB_INTR_SUSPEND      0x01
-#define MUSB_INTR_RESUME       0x02
-#define MUSB_INTR_RESET                0x04
-#define MUSB_INTR_BABBLE       0x04
-#define MUSB_INTR_SOF          0x08
-#define MUSB_INTR_CONNECT      0x10
-#define MUSB_INTR_DISCONNECT   0x20
-#define MUSB_INTR_SESSREQ      0x40
-#define MUSB_INTR_VBUSERROR    0x80    /* For SESSION end */
-
-/* DEVCTL */
-#define MUSB_DEVCTL_BDEVICE    0x80
-#define MUSB_DEVCTL_FSDEV      0x40
-#define MUSB_DEVCTL_LSDEV      0x20
-#define MUSB_DEVCTL_VBUS       0x18
-#define MUSB_DEVCTL_VBUS_SHIFT 3
-#define MUSB_DEVCTL_HM         0x04
-#define MUSB_DEVCTL_HR         0x02
-#define MUSB_DEVCTL_SESSION    0x01
-
-/* TESTMODE */
-#define MUSB_TEST_FORCE_HOST   0x80
-#define MUSB_TEST_FIFO_ACCESS  0x40
-#define MUSB_TEST_FORCE_FS     0x20
-#define MUSB_TEST_FORCE_HS     0x10
-#define MUSB_TEST_PACKET       0x08
-#define MUSB_TEST_K            0x04
-#define MUSB_TEST_J            0x02
-#define MUSB_TEST_SE0_NAK      0x01
-
-/* Allocate for double-packet buffering (effectively doubles assigned _SIZE) */
-#define MUSB_FIFOSZ_DPB                0x10
-/* Allocation size (8, 16, 32, ... 4096) */
-#define MUSB_FIFOSZ_SIZE       0x0f
-
-/* CSR0 */
-#define MUSB_CSR0_FLUSHFIFO    0x0100
-#define MUSB_CSR0_TXPKTRDY     0x0002
-#define MUSB_CSR0_RXPKTRDY     0x0001
-
-/* CSR0 in Peripheral mode */
-#define MUSB_CSR0_P_SVDSETUPEND        0x0080
-#define MUSB_CSR0_P_SVDRXPKTRDY        0x0040
-#define MUSB_CSR0_P_SENDSTALL  0x0020
-#define MUSB_CSR0_P_SETUPEND   0x0010
-#define MUSB_CSR0_P_DATAEND    0x0008
-#define MUSB_CSR0_P_SENTSTALL  0x0004
-
-/* CSR0 in Host mode */
-#define MUSB_CSR0_H_DIS_PING           0x0800
-#define MUSB_CSR0_H_WR_DATATOGGLE      0x0400  /* Set to allow setting: */
-#define MUSB_CSR0_H_DATATOGGLE         0x0200  /* Data toggle control */
-#define MUSB_CSR0_H_NAKTIMEOUT         0x0080
-#define MUSB_CSR0_H_STATUSPKT          0x0040
-#define MUSB_CSR0_H_REQPKT             0x0020
-#define MUSB_CSR0_H_ERROR              0x0010
-#define MUSB_CSR0_H_SETUPPKT           0x0008
-#define MUSB_CSR0_H_RXSTALL            0x0004
-
-/* CSR0 bits to avoid zeroing (write zero clears, write 1 ignored) */
-#define MUSB_CSR0_P_WZC_BITS   \
-       (MUSB_CSR0_P_SENTSTALL)
-#define MUSB_CSR0_H_WZC_BITS   \
-       (MUSB_CSR0_H_NAKTIMEOUT | MUSB_CSR0_H_RXSTALL \
-       | MUSB_CSR0_RXPKTRDY)
-
-/* TxType/RxType */
-#define MUSB_TYPE_SPEED                0xc0
-#define MUSB_TYPE_SPEED_SHIFT  6
-#define MUSB_TYPE_SPEED_HIGH   1
-#define MUSB_TYPE_SPEED_FULL   2
-#define MUSB_TYPE_SPEED_LOW    3
-#define MUSB_TYPE_PROTO                0x30    /* Implicitly zero for ep0 */
-#define MUSB_TYPE_PROTO_SHIFT  4
-#define MUSB_TYPE_REMOTE_END   0xf     /* Implicitly zero for ep0 */
-#define MUSB_TYPE_PROTO_BULK   2
-#define MUSB_TYPE_PROTO_INTR   3
-
-/* CONFIGDATA */
-#define MUSB_CONFIGDATA_MPRXE          0x80    /* Auto bulk pkt combining */
-#define MUSB_CONFIGDATA_MPTXE          0x40    /* Auto bulk pkt splitting */
-#define MUSB_CONFIGDATA_BIGENDIAN      0x20
-#define MUSB_CONFIGDATA_HBRXE          0x10    /* HB-ISO for RX */
-#define MUSB_CONFIGDATA_HBTXE          0x08    /* HB-ISO for TX */
-#define MUSB_CONFIGDATA_DYNFIFO                0x04    /* Dynamic FIFO sizing */
-#define MUSB_CONFIGDATA_SOFTCONE       0x02    /* SoftConnect */
-#define MUSB_CONFIGDATA_UTMIDW         0x01    /* Data width 0/1 => 8/16bits */
-
-/* TXCSR in Peripheral and Host mode */
-#define MUSB_TXCSR_AUTOSET             0x8000
-#define MUSB_TXCSR_MODE                        0x2000
-#define MUSB_TXCSR_DMAENAB             0x1000
-#define MUSB_TXCSR_FRCDATATOG          0x0800
-#define MUSB_TXCSR_DMAMODE             0x0400
-#define MUSB_TXCSR_CLRDATATOG          0x0040
-#define MUSB_TXCSR_FLUSHFIFO           0x0008
-#define MUSB_TXCSR_FIFONOTEMPTY                0x0002
-#define MUSB_TXCSR_TXPKTRDY            0x0001
-
-/* TXCSR in Peripheral mode */
-#define MUSB_TXCSR_P_ISO               0x4000
-#define MUSB_TXCSR_P_INCOMPTX          0x0080
-#define MUSB_TXCSR_P_SENTSTALL         0x0020
-#define MUSB_TXCSR_P_SENDSTALL         0x0010
-#define MUSB_TXCSR_P_UNDERRUN          0x0004
-
-/* TXCSR in Host mode */
-#define MUSB_TXCSR_H_WR_DATATOGGLE     0x0200
-#define MUSB_TXCSR_H_DATATOGGLE                0x0100
-#define MUSB_TXCSR_H_NAKTIMEOUT                0x0080
-#define MUSB_TXCSR_H_RXSTALL           0x0020
-#define MUSB_TXCSR_H_ERROR             0x0004
-#define MUSB_TXCSR_H_DATATOGGLE_SHIFT  8
-
-/* TXCSR bits to avoid zeroing (write zero clears, write 1 ignored) */
-#define MUSB_TXCSR_P_WZC_BITS  \
-       (MUSB_TXCSR_P_INCOMPTX | MUSB_TXCSR_P_SENTSTALL \
-       | MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_FIFONOTEMPTY)
-#define MUSB_TXCSR_H_WZC_BITS  \
-       (MUSB_TXCSR_H_NAKTIMEOUT | MUSB_TXCSR_H_RXSTALL \
-       | MUSB_TXCSR_H_ERROR | MUSB_TXCSR_FIFONOTEMPTY)
-
-/* RXCSR in Peripheral and Host mode */
-#define MUSB_RXCSR_AUTOCLEAR           0x8000
-#define MUSB_RXCSR_DMAENAB             0x2000
-#define MUSB_RXCSR_DISNYET             0x1000
-#define MUSB_RXCSR_PID_ERR             0x1000
-#define MUSB_RXCSR_DMAMODE             0x0800
-#define MUSB_RXCSR_INCOMPRX            0x0100
-#define MUSB_RXCSR_CLRDATATOG          0x0080
-#define MUSB_RXCSR_FLUSHFIFO           0x0010
-#define MUSB_RXCSR_DATAERROR           0x0008
-#define MUSB_RXCSR_FIFOFULL            0x0002
-#define MUSB_RXCSR_RXPKTRDY            0x0001
-
-/* RXCSR in Peripheral mode */
-#define MUSB_RXCSR_P_ISO               0x4000
-#define MUSB_RXCSR_P_SENTSTALL         0x0040
-#define MUSB_RXCSR_P_SENDSTALL         0x0020
-#define MUSB_RXCSR_P_OVERRUN           0x0004
-
-/* RXCSR in Host mode */
-#define MUSB_RXCSR_H_AUTOREQ           0x4000
-#define MUSB_RXCSR_H_WR_DATATOGGLE     0x0400
-#define MUSB_RXCSR_H_DATATOGGLE                0x0200
-#define MUSB_RXCSR_H_RXSTALL           0x0040
-#define MUSB_RXCSR_H_REQPKT            0x0020
-#define MUSB_RXCSR_H_ERROR             0x0004
-#define MUSB_S_RXCSR_H_DATATOGGLE      9
-
-/* RXCSR bits to avoid zeroing (write zero clears, write 1 ignored) */
-#define MUSB_RXCSR_P_WZC_BITS  \
-       (MUSB_RXCSR_P_SENTSTALL | MUSB_RXCSR_P_OVERRUN \
-       | MUSB_RXCSR_RXPKTRDY)
-#define MUSB_RXCSR_H_WZC_BITS  \
-       (MUSB_RXCSR_H_RXSTALL | MUSB_RXCSR_H_ERROR \
-       | MUSB_RXCSR_DATAERROR | MUSB_RXCSR_RXPKTRDY)
-
-/* HUBADDR */
-#define MUSB_HUBADDR_MULTI_TT          0x80
-
-/* Endpoint configuration information. Note: The value of endpoint fifo size
- * element should be either 8,16,32,64,128,256,512,1024,2048 or 4096. Other
- * values are not supported
- */
-struct musb_epinfo {
-       u8      epnum;  /* endpoint number      */
-       u8      epdir;  /* endpoint direction   */
-       u16     epsize; /* endpoint FIFO size   */
-};
-
-/*
- * Platform specific MUSB configuration. Any platform using the musb
- * functionality should create one instance of this structure in the
- * platform specific file.
- */
-struct musb_config {
-       struct  musb_regs       *regs;
-       u32                     timeout;
-       u8                      musb_speed;
-};
-
-/* externally defined data */
-extern struct musb_config      musb_cfg;
-extern struct musb_regs                *musbr;
-
-/* exported functions */
-extern void musb_start(void);
-extern void musb_configure_ep(struct musb_epinfo *epinfo, u8 cnt);
-extern void write_fifo(u8 ep, u32 length, void *fifo_data);
-extern void read_fifo(u8 ep, u32 length, void *fifo_data);
-
-/* extern functions */
-extern inline void musb_writew(u32 offset, u16 value);
-extern inline void musb_writeb(u32 offset, u8 value);
-extern inline u16 musb_readw(u32 offset);
-extern inline u8 musb_readb(u32 offset);
-
-#endif /* __MUSB_HDRC_DEFS_H__ */
diff --git a/drivers/usb/musb_hcd.c b/drivers/usb/musb_hcd.c
deleted file mode 100644 (file)
index 352a0d4..0000000
+++ /dev/null
@@ -1,792 +0,0 @@
-/*
- * Mentor USB OTG Core host controller driver.
- *
- * Copyright (c) 2008 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
- *
- * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
- */
-
-#include <common.h>
-#include "musb_hcd.h"
-
-/* MSC control transfers */
-#define USB_MSC_BBB_RESET      0xFF
-#define USB_MSC_BBB_GET_MAX_LUN        0xFE
-
-/* Endpoint configuration information */
-static struct musb_epinfo epinfo[3] = {
-       {MUSB_BULK_EP, 1, 512}, /* EP1 - Bluk Out - 512 Bytes */
-       {MUSB_BULK_EP, 0, 512}, /* EP1 - Bluk In  - 512 Bytes */
-       {MUSB_INTR_EP, 0, 64}   /* EP2 - Interrupt IN - 64 Bytes */
-};
-
-/*
- * This function writes the data toggle value.
- */
-static void write_toggle(struct usb_device *dev, u8 ep, u8 dir_out)
-{
-       u16 toggle = usb_gettoggle(dev, ep, dir_out);
-       u16 csr;
-
-       if (dir_out) {
-               if (!toggle)
-                       writew(MUSB_TXCSR_CLRDATATOG, &musbr->txcsr);
-               else {
-                       csr = readw(&musbr->txcsr);
-                       csr |= MUSB_TXCSR_H_WR_DATATOGGLE;
-                       writew(csr, &musbr->txcsr);
-                       csr |= (toggle << MUSB_TXCSR_H_DATATOGGLE_SHIFT);
-                       writew(csr, &musbr->txcsr);
-               }
-       } else {
-               if (!toggle)
-                       writew(MUSB_RXCSR_CLRDATATOG, &musbr->rxcsr);
-               else {
-                       csr = readw(&musbr->rxcsr);
-                       csr |= MUSB_RXCSR_H_WR_DATATOGGLE;
-                       writew(csr, &musbr->rxcsr);
-                       csr |= (toggle << MUSB_S_RXCSR_H_DATATOGGLE);
-                       writew(csr, &musbr->rxcsr);
-               }
-       }
-}
-
-/*
- * This function checks if RxStall has occured on the endpoint. If a RxStall
- * has occured, the RxStall is cleared and 1 is returned. If RxStall has
- * not occured, 0 is returned.
- */
-static u8 check_stall(u8 ep, u8 dir_out)
-{
-       u16 csr;
-
-       /* For endpoint 0 */
-       if (!ep) {
-               csr = readw(&musbr->txcsr);
-               if (csr & MUSB_CSR0_H_RXSTALL) {
-                       csr &= ~MUSB_CSR0_H_RXSTALL;
-                       writew(csr, &musbr->txcsr);
-                       return 1;
-               }
-       } else { /* For non-ep0 */
-               if (dir_out) { /* is it tx ep */
-                       csr = readw(&musbr->txcsr);
-                       if (csr & MUSB_TXCSR_H_RXSTALL) {
-                               csr &= ~MUSB_TXCSR_H_RXSTALL;
-                               writew(csr, &musbr->txcsr);
-                               return 1;
-                       }
-               } else { /* is it rx ep */
-                       csr = readw(&musbr->rxcsr);
-                       if (csr & MUSB_RXCSR_H_RXSTALL) {
-                               csr &= ~MUSB_RXCSR_H_RXSTALL;
-                               writew(csr, &musbr->rxcsr);
-                               return 1;
-                       }
-               }
-       }
-       return 0;
-}
-
-/*
- * waits until ep0 is ready. Returns 0 if ep is ready, -1 for timeout
- * error and -2 for stall.
- */
-static int wait_until_ep0_ready(struct usb_device *dev, u32 bit_mask)
-{
-       u16 csr;
-       int result = 1;
-
-       while (result > 0) {
-               csr = readw(&musbr->txcsr);
-               if (csr & MUSB_CSR0_H_ERROR) {
-                       csr &= ~MUSB_CSR0_H_ERROR;
-                       writew(csr, &musbr->txcsr);
-                       dev->status = USB_ST_CRC_ERR;
-                       result = -1;
-                       break;
-               }
-
-               switch (bit_mask) {
-               case MUSB_CSR0_TXPKTRDY:
-                       if (!(csr & MUSB_CSR0_TXPKTRDY)) {
-                               if (check_stall(MUSB_CONTROL_EP, 0)) {
-                                       dev->status = USB_ST_STALLED;
-                                       result = -2;
-                               } else
-                                       result = 0;
-                       }
-                       break;
-
-               case MUSB_CSR0_RXPKTRDY:
-                       if (check_stall(MUSB_CONTROL_EP, 0)) {
-                               dev->status = USB_ST_STALLED;
-                               result = -2;
-                       } else
-                               if (csr & MUSB_CSR0_RXPKTRDY)
-                                       result = 0;
-                       break;
-
-               case MUSB_CSR0_H_REQPKT:
-                       if (!(csr & MUSB_CSR0_H_REQPKT)) {
-                               if (check_stall(MUSB_CONTROL_EP, 0)) {
-                                       dev->status = USB_ST_STALLED;
-                                       result = -2;
-                               } else
-                                       result = 0;
-                       }
-                       break;
-               }
-       }
-       return result;
-}
-
-/*
- * waits until tx ep is ready. Returns 1 when ep is ready and 0 on error.
- */
-static u8 wait_until_txep_ready(struct usb_device *dev, u8 ep)
-{
-       u16 csr;
-
-       do {
-               if (check_stall(ep, 1)) {
-                       dev->status = USB_ST_STALLED;
-                       return 0;
-               }
-
-               csr = readw(&musbr->txcsr);
-               if (csr & MUSB_TXCSR_H_ERROR) {
-                       dev->status = USB_ST_CRC_ERR;
-                       return 0;
-               }
-       } while (csr & MUSB_TXCSR_TXPKTRDY);
-       return 1;
-}
-
-/*
- * waits until rx ep is ready. Returns 1 when ep is ready and 0 on error.
- */
-static u8 wait_until_rxep_ready(struct usb_device *dev, u8 ep)
-{
-       u16 csr;
-
-       do {
-               if (check_stall(ep, 0)) {
-                       dev->status = USB_ST_STALLED;
-                       return 0;
-               }
-
-               csr = readw(&musbr->rxcsr);
-               if (csr & MUSB_RXCSR_H_ERROR) {
-                       dev->status = USB_ST_CRC_ERR;
-                       return 0;
-               }
-       } while (!(csr & MUSB_RXCSR_RXPKTRDY));
-       return 1;
-}
-
-/*
- * This function performs the setup phase of the control transfer
- */
-static int ctrlreq_setup_phase(struct usb_device *dev, struct devrequest *setup)
-{
-       int result;
-       u16 csr;
-
-       /* write the control request to ep0 fifo */
-       write_fifo(MUSB_CONTROL_EP, sizeof(struct devrequest), (void *)setup);
-
-       /* enable transfer of setup packet */
-       csr = readw(&musbr->txcsr);
-       csr |= (MUSB_CSR0_TXPKTRDY|MUSB_CSR0_H_SETUPPKT);
-       writew(csr, &musbr->txcsr);
-
-       /* wait until the setup packet is transmitted */
-       result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY);
-       dev->act_len = 0;
-       return result;
-}
-
-/*
- * This function handles the control transfer in data phase
- */
-static int ctrlreq_in_data_phase(struct usb_device *dev, u32 len, void *buffer)
-{
-       u16 csr;
-       u32 rxlen = 0;
-       u32 nextlen = 0;
-       u8  maxpktsize = (1 << dev->maxpacketsize) * 8;
-       u8  *rxbuff = (u8 *)buffer;
-       u8  rxedlength;
-       int result;
-
-       while (rxlen < len) {
-               /* Determine the next read length */
-               nextlen = ((len-rxlen) > maxpktsize) ? maxpktsize : (len-rxlen);
-
-               /* Set the ReqPkt bit */
-               csr = readw(&musbr->txcsr);
-               writew(csr | MUSB_CSR0_H_REQPKT, &musbr->txcsr);
-               result = wait_until_ep0_ready(dev, MUSB_CSR0_RXPKTRDY);
-               if (result < 0)
-                       return result;
-
-               /* Actual number of bytes received by usb */
-               rxedlength = readb(&musbr->rxcount);
-
-               /* Read the data from the RxFIFO */
-               read_fifo(MUSB_CONTROL_EP, rxedlength, &rxbuff[rxlen]);
-
-               /* Clear the RxPktRdy Bit */
-               csr = readw(&musbr->txcsr);
-               csr &= ~MUSB_CSR0_RXPKTRDY;
-               writew(csr, &musbr->txcsr);
-
-               /* short packet? */
-               if (rxedlength != nextlen) {
-                       dev->act_len += rxedlength;
-                       break;
-               }
-               rxlen += nextlen;
-               dev->act_len = rxlen;
-       }
-       return 0;
-}
-
-/*
- * This function handles the control transfer out data phase
- */
-static int ctrlreq_out_data_phase(struct usb_device *dev, u32 len, void *buffer)
-{
-       u16 csr;
-       u32 txlen = 0;
-       u32 nextlen = 0;
-       u8  maxpktsize = (1 << dev->maxpacketsize) * 8;
-       u8  *txbuff = (u8 *)buffer;
-       int result = 0;
-
-       while (txlen < len) {
-               /* Determine the next write length */
-               nextlen = ((len-txlen) > maxpktsize) ? maxpktsize : (len-txlen);
-
-               /* Load the data to send in FIFO */
-               write_fifo(MUSB_CONTROL_EP, txlen, &txbuff[txlen]);
-
-               /* Set TXPKTRDY bit */
-               csr = readw(&musbr->txcsr);
-               writew(csr | MUSB_CSR0_H_DIS_PING | MUSB_CSR0_TXPKTRDY,
-                                       &musbr->txcsr);
-               result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY);
-               if (result < 0)
-                       break;
-
-               txlen += nextlen;
-               dev->act_len = txlen;
-       }
-       return result;
-}
-
-/*
- * This function handles the control transfer out status phase
- */
-static int ctrlreq_out_status_phase(struct usb_device *dev)
-{
-       u16 csr;
-       int result;
-
-       /* Set the StatusPkt bit */
-       csr = readw(&musbr->txcsr);
-       csr |= (MUSB_CSR0_H_DIS_PING | MUSB_CSR0_TXPKTRDY |
-                       MUSB_CSR0_H_STATUSPKT);
-       writew(csr, &musbr->txcsr);
-
-       /* Wait until TXPKTRDY bit is cleared */
-       result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY);
-       return result;
-}
-
-/*
- * This function handles the control transfer in status phase
- */
-static int ctrlreq_in_status_phase(struct usb_device *dev)
-{
-       u16 csr;
-       int result;
-
-       /* Set the StatusPkt bit and ReqPkt bit */
-       csr = MUSB_CSR0_H_DIS_PING | MUSB_CSR0_H_REQPKT | MUSB_CSR0_H_STATUSPKT;
-       writew(csr, &musbr->txcsr);
-       result = wait_until_ep0_ready(dev, MUSB_CSR0_H_REQPKT);
-
-       /* clear StatusPkt bit and RxPktRdy bit */
-       csr = readw(&musbr->txcsr);
-       csr &= ~(MUSB_CSR0_RXPKTRDY | MUSB_CSR0_H_STATUSPKT);
-       writew(csr, &musbr->txcsr);
-       return result;
-}
-
-/*
- * determines the speed of the device (High/Full/Slow)
- */
-static u8 get_dev_speed(struct usb_device *dev)
-{
-       return (dev->speed & USB_SPEED_HIGH) ? MUSB_TYPE_SPEED_HIGH :
-               ((dev->speed & USB_SPEED_LOW) ? MUSB_TYPE_SPEED_LOW :
-                                               MUSB_TYPE_SPEED_FULL);
-}
-
-/*
- * configure the hub address and the port address.
- */
-static void config_hub_port(struct usb_device *dev, u8 ep)
-{
-       u8 chid;
-       u8 hub;
-
-       /* Find out the nearest parent which is high speed */
-       while (dev->parent->parent != NULL)
-               if (get_dev_speed(dev->parent) !=  MUSB_TYPE_SPEED_HIGH)
-                       dev = dev->parent;
-               else
-                       break;
-
-       /* determine the port address at that hub */
-       hub = dev->parent->devnum;
-       for (chid = 0; chid < USB_MAXCHILDREN; chid++)
-               if (dev->parent->children[chid] == dev)
-                       break;
-
-       /* configure the hub address and the port address */
-       writeb(hub, &musbr->tar[ep].txhubaddr);
-       writeb((chid + 1), &musbr->tar[ep].txhubport);
-       writeb(hub, &musbr->tar[ep].rxhubaddr);
-       writeb((chid + 1), &musbr->tar[ep].rxhubport);
-}
-
-/*
- * do a control transfer
- */
-int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-                       int len, struct devrequest *setup)
-{
-       int devnum = usb_pipedevice(pipe);
-       u16 csr;
-       u8  devspeed;
-
-       /* select control endpoint */
-       writeb(MUSB_CONTROL_EP, &musbr->index);
-       csr = readw(&musbr->txcsr);
-
-       /* target addr and (for multipoint) hub addr/port */
-       writeb(devnum, &musbr->tar[MUSB_CONTROL_EP].txfuncaddr);
-       writeb(devnum, &musbr->tar[MUSB_CONTROL_EP].rxfuncaddr);
-
-       /* configure the hub address and the port number as required */
-       devspeed = get_dev_speed(dev);
-       if ((musb_ishighspeed()) && (dev->parent != NULL) &&
-               (devspeed != MUSB_TYPE_SPEED_HIGH)) {
-               config_hub_port(dev, MUSB_CONTROL_EP);
-               writeb(devspeed << 6, &musbr->txtype);
-       } else {
-               writeb(musb_cfg.musb_speed << 6, &musbr->txtype);
-               writeb(0, &musbr->tar[MUSB_CONTROL_EP].txhubaddr);
-               writeb(0, &musbr->tar[MUSB_CONTROL_EP].txhubport);
-               writeb(0, &musbr->tar[MUSB_CONTROL_EP].rxhubaddr);
-               writeb(0, &musbr->tar[MUSB_CONTROL_EP].rxhubport);
-       }
-
-       /* Control transfer setup phase */
-       if (ctrlreq_setup_phase(dev, setup) < 0)
-               return 0;
-
-       switch (setup->request) {
-       case USB_REQ_GET_DESCRIPTOR:
-       case USB_REQ_GET_CONFIGURATION:
-       case USB_REQ_GET_INTERFACE:
-       case USB_REQ_GET_STATUS:
-       case USB_MSC_BBB_GET_MAX_LUN:
-               /* control transfer in-data-phase */
-               if (ctrlreq_in_data_phase(dev, len, buffer) < 0)
-                       return 0;
-               /* control transfer out-status-phase */
-               if (ctrlreq_out_status_phase(dev) < 0)
-                       return 0;
-               break;
-
-       case USB_REQ_SET_ADDRESS:
-       case USB_REQ_SET_CONFIGURATION:
-       case USB_REQ_SET_FEATURE:
-       case USB_REQ_SET_INTERFACE:
-       case USB_REQ_CLEAR_FEATURE:
-       case USB_MSC_BBB_RESET:
-               /* control transfer in status phase */
-               if (ctrlreq_in_status_phase(dev) < 0)
-                       return 0;
-               break;
-
-       case USB_REQ_SET_DESCRIPTOR:
-               /* control transfer out data phase */
-               if (ctrlreq_out_data_phase(dev, len, buffer) < 0)
-                       return 0;
-               /* control transfer in status phase */
-               if (ctrlreq_in_status_phase(dev) < 0)
-                       return 0;
-               break;
-
-       default:
-               /* unhandled control transfer */
-               return -1;
-       }
-
-       dev->status = 0;
-       dev->act_len = len;
-       return len;
-}
-
-/*
- * do a bulk transfer
- */
-int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
-                                       void *buffer, int len)
-{
-       int dir_out = usb_pipeout(pipe);
-       int ep = usb_pipeendpoint(pipe);
-       int devnum = usb_pipedevice(pipe);
-       u8  type;
-       u16 csr;
-       u32 txlen = 0;
-       u32 nextlen = 0;
-       u8  devspeed;
-
-       /* select bulk endpoint */
-       writeb(MUSB_BULK_EP, &musbr->index);
-
-       /* write the address of the device */
-       if (dir_out)
-               writeb(devnum, &musbr->tar[MUSB_BULK_EP].txfuncaddr);
-       else
-               writeb(devnum, &musbr->tar[MUSB_BULK_EP].rxfuncaddr);
-
-       /* configure the hub address and the port number as required */
-       devspeed = get_dev_speed(dev);
-       if ((musb_ishighspeed()) && (dev->parent != NULL) &&
-               (devspeed != MUSB_TYPE_SPEED_HIGH)) {
-               /*
-                * MUSB is in high speed and the destination device is full
-                * speed device. So configure the hub address and port
-                * address registers.
-                */
-               config_hub_port(dev, MUSB_BULK_EP);
-       } else {
-               if (dir_out) {
-                       writeb(0, &musbr->tar[MUSB_BULK_EP].txhubaddr);
-                       writeb(0, &musbr->tar[MUSB_BULK_EP].txhubport);
-               } else {
-                       writeb(0, &musbr->tar[MUSB_BULK_EP].rxhubaddr);
-                       writeb(0, &musbr->tar[MUSB_BULK_EP].rxhubport);
-               }
-               devspeed = musb_cfg.musb_speed;
-       }
-
-       /* Write the saved toggle bit value */
-       write_toggle(dev, ep, dir_out);
-
-       if (dir_out) { /* bulk-out transfer */
-               /* Program the TxType register */
-               type = (devspeed << MUSB_TYPE_SPEED_SHIFT) |
-                          (MUSB_TYPE_PROTO_BULK << MUSB_TYPE_PROTO_SHIFT) |
-                          (ep & MUSB_TYPE_REMOTE_END);
-               writeb(type, &musbr->txtype);
-
-               /* Write maximum packet size to the TxMaxp register */
-               writew(dev->epmaxpacketout[ep], &musbr->txmaxp);
-               while (txlen < len) {
-                       nextlen = ((len-txlen) < dev->epmaxpacketout[ep]) ?
-                                       (len-txlen) : dev->epmaxpacketout[ep];
-
-                       /* Write the data to the FIFO */
-                       write_fifo(MUSB_BULK_EP, nextlen,
-                                       (void *)(((u8 *)buffer) + txlen));
-
-                       /* Set the TxPktRdy bit */
-                       csr = readw(&musbr->txcsr);
-                       writew(csr | MUSB_TXCSR_TXPKTRDY, &musbr->txcsr);
-
-                       /* Wait until the TxPktRdy bit is cleared */
-                       if (!wait_until_txep_ready(dev, MUSB_BULK_EP)) {
-                               readw(&musbr->txcsr);
-                               usb_settoggle(dev, ep, dir_out,
-                               (csr >> MUSB_TXCSR_H_DATATOGGLE_SHIFT) & 1);
-                               dev->act_len = txlen;
-                               return 0;
-                       }
-                       txlen += nextlen;
-               }
-
-               /* Keep a copy of the data toggle bit */
-               csr = readw(&musbr->txcsr);
-               usb_settoggle(dev, ep, dir_out,
-                               (csr >> MUSB_TXCSR_H_DATATOGGLE_SHIFT) & 1);
-       } else { /* bulk-in transfer */
-               /* Write the saved toggle bit value */
-               write_toggle(dev, ep, dir_out);
-
-               /* Program the RxType register */
-               type = (devspeed << MUSB_TYPE_SPEED_SHIFT) |
-                          (MUSB_TYPE_PROTO_BULK << MUSB_TYPE_PROTO_SHIFT) |
-                          (ep & MUSB_TYPE_REMOTE_END);
-               writeb(type, &musbr->rxtype);
-
-               /* Write the maximum packet size to the RxMaxp register */
-               writew(dev->epmaxpacketin[ep], &musbr->rxmaxp);
-               while (txlen < len) {
-                       nextlen = ((len-txlen) < dev->epmaxpacketin[ep]) ?
-                                       (len-txlen) : dev->epmaxpacketin[ep];
-
-                       /* Set the ReqPkt bit */
-                       writew(MUSB_RXCSR_H_REQPKT, &musbr->rxcsr);
-
-                       /* Wait until the RxPktRdy bit is set */
-                       if (!wait_until_rxep_ready(dev, MUSB_BULK_EP)) {
-                               csr = readw(&musbr->rxcsr);
-                               usb_settoggle(dev, ep, dir_out,
-                               (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
-                               csr &= ~MUSB_RXCSR_RXPKTRDY;
-                               writew(csr, &musbr->rxcsr);
-                               dev->act_len = txlen;
-                               return 0;
-                       }
-
-                       /* Read the data from the FIFO */
-                       read_fifo(MUSB_BULK_EP, nextlen,
-                                       (void *)(((u8 *)buffer) + txlen));
-
-                       /* Clear the RxPktRdy bit */
-                       csr =  readw(&musbr->rxcsr);
-                       csr &= ~MUSB_RXCSR_RXPKTRDY;
-                       writew(csr, &musbr->rxcsr);
-                       txlen += nextlen;
-               }
-
-               /* Keep a copy of the data toggle bit */
-               csr = readw(&musbr->rxcsr);
-               usb_settoggle(dev, ep, dir_out,
-                               (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
-       }
-
-       /* bulk transfer is complete */
-       dev->status = 0;
-       dev->act_len = len;
-       return 0;
-}
-
-/*
- * This function initializes the usb controller module.
- */
-int usb_lowlevel_init(void)
-{
-       u8  power;
-       u32 timeout;
-
-       if (musb_platform_init() == -1)
-               return -1;
-
-       /* Configure all the endpoint FIFO's and start usb controller */
-       musbr = musb_cfg.regs;
-       musb_configure_ep(&epinfo[0],
-                       sizeof(epinfo) / sizeof(struct musb_epinfo));
-       musb_start();
-
-       /*
-        * Wait until musb is enabled in host mode with a timeout. There
-        * should be a usb device connected.
-        */
-       timeout = musb_cfg.timeout;
-       while (timeout--)
-               if (readb(&musbr->devctl) & MUSB_DEVCTL_HM)
-                       break;
-
-       /* if musb core is not in host mode, then return */
-       if (!timeout)
-               return -1;
-
-       /* start usb bus reset */
-       power = readb(&musbr->power);
-       writeb(power | MUSB_POWER_RESET, &musbr->power);
-
-       /* After initiating a usb reset, wait for about 20ms to 30ms */
-       udelay(30000);
-
-       /* stop usb bus reset */
-       power = readb(&musbr->power);
-       power &= ~MUSB_POWER_RESET;
-       writeb(power, &musbr->power);
-
-       /* Determine if the connected device is a high/full/low speed device */
-       musb_cfg.musb_speed = (readb(&musbr->power) & MUSB_POWER_HSMODE) ?
-                       MUSB_TYPE_SPEED_HIGH :
-                       ((readb(&musbr->devctl) & MUSB_DEVCTL_FSDEV) ?
-                       MUSB_TYPE_SPEED_FULL : MUSB_TYPE_SPEED_LOW);
-       return 0;
-}
-
-/*
- * This function stops the operation of the davinci usb module.
- */
-int usb_lowlevel_stop(void)
-{
-       /* Reset the USB module */
-       musb_platform_deinit();
-       writeb(0, &musbr->devctl);
-       return 0;
-}
-
-/*
- * This function supports usb interrupt transfers. Currently, usb interrupt
- * transfers are not supported.
- */
-int submit_int_msg(struct usb_device *dev, unsigned long pipe,
-                               void *buffer, int len, int interval)
-{
-       int dir_out = usb_pipeout(pipe);
-       int ep = usb_pipeendpoint(pipe);
-       int devnum = usb_pipedevice(pipe);
-       u8  type;
-       u16 csr;
-       u32 txlen = 0;
-       u32 nextlen = 0;
-       u8  devspeed;
-
-       /* select interrupt endpoint */
-       writeb(MUSB_INTR_EP, &musbr->index);
-
-       /* write the address of the device */
-       if (dir_out)
-               writeb(devnum, &musbr->tar[MUSB_INTR_EP].txfuncaddr);
-       else
-               writeb(devnum, &musbr->tar[MUSB_INTR_EP].rxfuncaddr);
-
-       /* configure the hub address and the port number as required */
-       devspeed = get_dev_speed(dev);
-       if ((musb_ishighspeed()) && (dev->parent != NULL) &&
-               (devspeed != MUSB_TYPE_SPEED_HIGH)) {
-               /*
-                * MUSB is in high speed and the destination device is full
-                * speed device. So configure the hub address and port
-                * address registers.
-                */
-               config_hub_port(dev, MUSB_INTR_EP);
-       } else {
-               if (dir_out) {
-                       writeb(0, &musbr->tar[MUSB_INTR_EP].txhubaddr);
-                       writeb(0, &musbr->tar[MUSB_INTR_EP].txhubport);
-               } else {
-                       writeb(0, &musbr->tar[MUSB_INTR_EP].rxhubaddr);
-                       writeb(0, &musbr->tar[MUSB_INTR_EP].rxhubport);
-               }
-               devspeed = musb_cfg.musb_speed;
-       }
-
-       /* Write the saved toggle bit value */
-       write_toggle(dev, ep, dir_out);
-
-       if (!dir_out) { /* intrrupt-in transfer */
-               /* Write the saved toggle bit value */
-               write_toggle(dev, ep, dir_out);
-               writeb(interval, &musbr->rxinterval);
-
-               /* Program the RxType register */
-               type = (devspeed << MUSB_TYPE_SPEED_SHIFT) |
-                          (MUSB_TYPE_PROTO_INTR << MUSB_TYPE_PROTO_SHIFT) |
-                          (ep & MUSB_TYPE_REMOTE_END);
-               writeb(type, &musbr->rxtype);
-
-               /* Write the maximum packet size to the RxMaxp register */
-               writew(dev->epmaxpacketin[ep], &musbr->rxmaxp);
-
-               while (txlen < len) {
-                       nextlen = ((len-txlen) < dev->epmaxpacketin[ep]) ?
-                                       (len-txlen) : dev->epmaxpacketin[ep];
-
-                       /* Set the ReqPkt bit */
-                       writew(MUSB_RXCSR_H_REQPKT, &musbr->rxcsr);
-
-                       /* Wait until the RxPktRdy bit is set */
-                       if (!wait_until_rxep_ready(dev, MUSB_INTR_EP)) {
-                               csr = readw(&musbr->rxcsr);
-                               usb_settoggle(dev, ep, dir_out,
-                               (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
-                               csr &= ~MUSB_RXCSR_RXPKTRDY;
-                               writew(csr, &musbr->rxcsr);
-                               dev->act_len = txlen;
-                               return 0;
-                       }
-
-                       /* Read the data from the FIFO */
-                       read_fifo(MUSB_INTR_EP, nextlen,
-                                       (void *)(((u8 *)buffer) + txlen));
-
-                       /* Clear the RxPktRdy bit */
-                       csr =  readw(&musbr->rxcsr);
-                       csr &= ~MUSB_RXCSR_RXPKTRDY;
-                       writew(csr, &musbr->rxcsr);
-                       txlen += nextlen;
-               }
-
-               /* Keep a copy of the data toggle bit */
-               csr = readw(&musbr->rxcsr);
-               usb_settoggle(dev, ep, dir_out,
-                               (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
-       }
-
-       /* interrupt transfer is complete */
-       dev->irq_status = 0;
-       dev->irq_act_len = len;
-       dev->irq_handle(dev);
-       dev->status = 0;
-       dev->act_len = len;
-       return 0;
-}
-
-
-#ifdef CONFIG_SYS_USB_EVENT_POLL
-/*
- * This function polls for USB keyboard data.
- */
-void usb_event_poll()
-{
-       device_t *dev;
-       struct usb_device *usb_kbd_dev;
-       struct usb_interface_descriptor *iface;
-       struct usb_endpoint_descriptor *ep;
-       int pipe;
-       int maxp;
-
-       /* Get the pointer to USB Keyboard device pointer */
-       dev = device_get_by_name("usbkbd");
-       usb_kbd_dev = (struct usb_device *)dev->priv;
-       iface = &usb_kbd_dev->config.if_desc[0];
-       ep = &iface->ep_desc[0];
-       pipe = usb_rcvintpipe(usb_kbd_dev, ep->bEndpointAddress);
-
-       /* Submit a interrupt transfer request */
-       maxp = usb_maxpacket(usb_kbd_dev, pipe);
-       usb_submit_int_msg(usb_kbd_dev, pipe, &new[0],
-                       maxp > 8 ? 8 : maxp, ep->bInterval);
-}
-#endif /* CONFIG_SYS_USB_EVENT_POLL */
diff --git a/drivers/usb/musb_hcd.h b/drivers/usb/musb_hcd.h
deleted file mode 100644 (file)
index bb83311..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Mentor USB OTG Core host controller driver.
- *
- * Copyright (c) 2008 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
- *
- * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
- */
-
-#ifndef __MUSB_HCD_H__
-#define __MUSB_HCD_H__
-
-#include "musb_core.h"
-#ifdef CONFIG_USB_KEYBOARD
-#include <devices.h>
-extern unsigned char new[];
-#endif
-
-/* This defines the endpoint number used for control transfers */
-#define MUSB_CONTROL_EP 0
-
-/* This defines the endpoint number used for bulk transfer */
-#define MUSB_BULK_EP 1
-
-/* This defines the endpoint number used for interrupt transfer */
-#define MUSB_INTR_EP 2
-
-/* Determine the operating speed of MUSB core */
-#define musb_ishighspeed() \
-       ((readb(&musbr->power) & MUSB_POWER_HSMODE) \
-               >> MUSB_POWER_HSMODE_SHIFT)
-
-/* extern functions */
-extern int musb_platform_init(void);
-extern void musb_platform_deinit(void);
-
-#endif /* __MUSB_HCD_H__ */
diff --git a/drivers/usb/r8a66597-hcd.c b/drivers/usb/r8a66597-hcd.c
deleted file mode 100644 (file)
index db611b6..0000000
+++ /dev/null
@@ -1,945 +0,0 @@
-/*
- * R8A66597 HCD (Host Controller Driver) for u-boot
- *
- * Copyright (C) 2008  Yoshihiro Shimoda <shimoda.yoshihiro@renesas.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; version 2 of the License.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#include <common.h>
-#include <usb.h>
-#include <asm/io.h>
-
-#include "r8a66597.h"
-
-#ifdef R8A66597_DEBUG
-#define R8A66597_DPRINT                printf
-#else
-#define R8A66597_DPRINT(...)
-#endif
-
-static const char hcd_name[] = "r8a66597_hcd";
-static unsigned short clock = CONFIG_R8A66597_XTAL;
-static unsigned short vif = CONFIG_R8A66597_LDRV;
-static unsigned short endian = CONFIG_R8A66597_ENDIAN;
-static struct r8a66597 gr8a66597;
-
-static void get_hub_data(struct usb_device *dev, u16 *hub_devnum, u16 *hubport)
-{
-       int i;
-
-       *hub_devnum = 0;
-       *hubport = 0;
-
-       /* check a device connected to root_hub */
-       if ((dev->parent && dev->parent->devnum == 1) ||
-           (dev->devnum == 1))
-               return;
-
-       for (i = 0; i < USB_MAXCHILDREN; i++) {
-               if (dev->parent->children[i] == dev) {
-                       *hub_devnum = (u8)dev->parent->devnum;
-                       *hubport = i;
-                       return;
-               }
-       }
-
-       printf("get_hub_data error.\n");
-}
-
-static void set_devadd(struct r8a66597 *r8a66597, u8 r8a66597_address,
-                       struct usb_device *dev, int port)
-{
-       u16 val, usbspd, upphub, hubport;
-       unsigned long devadd_reg = get_devadd_addr(r8a66597_address);
-
-       get_hub_data(dev, &upphub, &hubport);
-       usbspd = r8a66597->speed;
-       val = (upphub << 11) | (hubport << 8) | (usbspd << 6) | (port & 0x0001);
-       r8a66597_write(r8a66597, val, devadd_reg);
-}
-
-static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
-{
-       u16 tmp;
-       int i = 0;
-
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
-       do {
-               r8a66597_write(r8a66597, SCKE, SYSCFG0);
-               tmp = r8a66597_read(r8a66597, SYSCFG0);
-               if (i++ > 1000) {
-                       printf("register access fail.\n");
-                       return -1;
-               }
-       } while ((tmp & SCKE) != SCKE);
-       r8a66597_write(r8a66597, 0x04, 0x02);
-#else
-       do {
-               r8a66597_write(r8a66597, USBE, SYSCFG0);
-               tmp = r8a66597_read(r8a66597, SYSCFG0);
-               if (i++ > 1000) {
-                       printf("register access fail.\n");
-                       return -1;
-               }
-       } while ((tmp & USBE) != USBE);
-       r8a66597_bclr(r8a66597, USBE, SYSCFG0);
-       r8a66597_mdfy(r8a66597, clock, XTAL, SYSCFG0);
-
-       i = 0;
-       r8a66597_bset(r8a66597, XCKE, SYSCFG0);
-       do {
-               udelay(1000);
-               tmp = r8a66597_read(r8a66597, SYSCFG0);
-               if (i++ > 500) {
-                       printf("register access fail.\n");
-                       return -1;
-               }
-       } while ((tmp & SCKE) != SCKE);
-#endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
-
-       return 0;
-}
-
-static void r8a66597_clock_disable(struct r8a66597 *r8a66597)
-{
-       r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
-       udelay(1);
-#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
-       r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
-       r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
-       r8a66597_bclr(r8a66597, USBE, SYSCFG0);
-#endif
-}
-
-static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port)
-{
-       u16 val;
-
-       val = port ? DRPD : DCFM | DRPD;
-       r8a66597_bset(r8a66597, val, get_syscfg_reg(port));
-       r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
-
-       r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, get_dmacfg_reg(port));
-}
-
-static void r8a66597_disable_port(struct r8a66597 *r8a66597, int port)
-{
-       u16 val, tmp;
-
-       r8a66597_write(r8a66597, 0, get_intenb_reg(port));
-       r8a66597_write(r8a66597, 0, get_intsts_reg(port));
-
-       r8a66597_port_power(r8a66597, port, 0);
-
-       do {
-               tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS;
-               udelay(640);
-       } while (tmp == EDGESTS);
-
-       val = port ? DRPD : DCFM | DRPD;
-       r8a66597_bclr(r8a66597, val, get_syscfg_reg(port));
-       r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));
-}
-
-static int enable_controller(struct r8a66597 *r8a66597)
-{
-       int ret, port;
-
-       ret = r8a66597_clock_enable(r8a66597);
-       if (ret < 0)
-               return ret;
-
-       r8a66597_bset(r8a66597, vif & LDRV, PINCFG);
-       r8a66597_bset(r8a66597, USBE, SYSCFG0);
-
-       r8a66597_bset(r8a66597, INTL, SOFCFG);
-       r8a66597_write(r8a66597, 0, INTENB0);
-       r8a66597_write(r8a66597, 0, INTENB1);
-       r8a66597_write(r8a66597, 0, INTENB2);
-
-       r8a66597_bset(r8a66597, endian & BIGEND, CFIFOSEL);
-       r8a66597_bset(r8a66597, endian & BIGEND, D0FIFOSEL);
-       r8a66597_bset(r8a66597, endian & BIGEND, D1FIFOSEL);
-       r8a66597_bset(r8a66597, TRNENSEL, SOFCFG);
-
-       for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
-               r8a66597_enable_port(r8a66597, port);
-
-       return 0;
-}
-
-static void disable_controller(struct r8a66597 *r8a66597)
-{
-       int i;
-
-       if (!(r8a66597_read(r8a66597, SYSCFG0) & USBE))
-               return;
-
-       r8a66597_write(r8a66597, 0, INTENB0);
-       r8a66597_write(r8a66597, 0, INTSTS0);
-
-       r8a66597_write(r8a66597, 0, D0FIFOSEL);
-       r8a66597_write(r8a66597, 0, D1FIFOSEL);
-       r8a66597_write(r8a66597, 0, DCPCFG);
-       r8a66597_write(r8a66597, 0x40, DCPMAXP);
-       r8a66597_write(r8a66597, 0, DCPCTR);
-
-       for (i = 0; i <= 10; i++)
-               r8a66597_write(r8a66597, 0, get_devadd_addr(i));
-       for (i = 1; i <= 5; i++) {
-               r8a66597_write(r8a66597, 0, get_pipetre_addr(i));
-               r8a66597_write(r8a66597, 0, get_pipetrn_addr(i));
-       }
-       for (i = 1; i < R8A66597_MAX_NUM_PIPE; i++) {
-               r8a66597_write(r8a66597, 0, get_pipectr_addr(i));
-               r8a66597_write(r8a66597, i, PIPESEL);
-               r8a66597_write(r8a66597, 0, PIPECFG);
-               r8a66597_write(r8a66597, 0, PIPEBUF);
-               r8a66597_write(r8a66597, 0, PIPEMAXP);
-               r8a66597_write(r8a66597, 0, PIPEPERI);
-       }
-
-       for (i = 0; i < R8A66597_MAX_ROOT_HUB; i++)
-               r8a66597_disable_port(r8a66597, i);
-
-       r8a66597_clock_disable(r8a66597);
-}
-
-static void r8a66597_reg_wait(struct r8a66597 *r8a66597, unsigned long reg,
-                             u16 mask, u16 loop)
-{
-       u16 tmp;
-       int i = 0;
-
-       do {
-               tmp = r8a66597_read(r8a66597, reg);
-               if (i++ > 1000000) {
-                       printf("register%lx, loop %x is timeout\n", reg, loop);
-                       break;
-               }
-       } while ((tmp & mask) != loop);
-}
-
-static void pipe_buffer_setting(struct r8a66597 *r8a66597,
-                               struct usb_device *dev, unsigned long pipe)
-{
-       u16 val = 0;
-       u16 pipenum, bufnum, maxpacket;
-
-       if (usb_pipein(pipe)) {
-               pipenum = BULK_IN_PIPENUM;
-               bufnum = BULK_IN_BUFNUM;
-               maxpacket = dev->epmaxpacketin[usb_pipeendpoint(pipe)];
-       } else {
-               pipenum = BULK_OUT_PIPENUM;
-               bufnum = BULK_OUT_BUFNUM;
-               maxpacket = dev->epmaxpacketout[usb_pipeendpoint(pipe)];
-       }
-
-       if (r8a66597->pipe_config & (1 << pipenum))
-               return;
-       r8a66597->pipe_config |= (1 << pipenum);
-
-       r8a66597_bset(r8a66597, ACLRM, get_pipectr_addr(pipenum));
-       r8a66597_bclr(r8a66597, ACLRM, get_pipectr_addr(pipenum));
-       r8a66597_write(r8a66597, pipenum, PIPESEL);
-
-       /* FIXME: This driver support bulk transfer only. */
-       if (!usb_pipein(pipe))
-               val |= R8A66597_DIR;
-       else
-               val |= R8A66597_SHTNAK;
-       val |= R8A66597_BULK | R8A66597_DBLB | usb_pipeendpoint(pipe);
-       r8a66597_write(r8a66597, val, PIPECFG);
-
-       r8a66597_write(r8a66597, (8 << 10) | bufnum, PIPEBUF);
-       r8a66597_write(r8a66597, make_devsel(usb_pipedevice(pipe)) |
-                                maxpacket, PIPEMAXP);
-       r8a66597_write(r8a66597, 0, PIPEPERI);
-       r8a66597_write(r8a66597, SQCLR, get_pipectr_addr(pipenum));
-}
-
-static int send_setup_packet(struct r8a66597 *r8a66597, struct usb_device *dev,
-                            struct devrequest *setup)
-{
-       int i;
-       unsigned short *p = (unsigned short *)setup;
-       unsigned long setup_addr = USBREQ;
-       u16 intsts1;
-       int timeout = 3000;
-       u16 devsel = setup->request == USB_REQ_SET_ADDRESS ? 0 : dev->devnum;
-
-       r8a66597_write(r8a66597, make_devsel(devsel) |
-                                (8 << dev->maxpacketsize), DCPMAXP);
-       r8a66597_write(r8a66597, ~(SIGN | SACK), INTSTS1);
-
-       for (i = 0; i < 4; i++) {
-               r8a66597_write(r8a66597, le16_to_cpu(p[i]), setup_addr);
-               setup_addr += 2;
-       }
-       r8a66597_write(r8a66597, ~0x0001, BRDYSTS);
-       r8a66597_write(r8a66597, SUREQ, DCPCTR);
-
-       while (1) {
-               intsts1 = r8a66597_read(r8a66597, INTSTS1);
-               if (intsts1 & SACK)
-                       break;
-               if (intsts1 & SIGN) {
-                       printf("setup packet send error\n");
-                       return -1;
-               }
-               if (timeout-- < 0) {
-                       printf("setup packet timeout\n");
-                       return -1;
-               }
-               udelay(500);
-       }
-
-       return 0;
-}
-
-static int send_bulk_packet(struct r8a66597 *r8a66597, struct usb_device *dev,
-                           unsigned long pipe, void *buffer, int transfer_len)
-{
-       u16 tmp, bufsize;
-       u16 *buf;
-       size_t size;
-
-       R8A66597_DPRINT("%s\n", __func__);
-
-       r8a66597_mdfy(r8a66597, MBW | BULK_OUT_PIPENUM,
-                       MBW | CURPIPE, CFIFOSEL);
-       r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, BULK_OUT_PIPENUM);
-       tmp = r8a66597_read(r8a66597, CFIFOCTR);
-       if ((tmp & FRDY) == 0) {
-               printf("%s FRDY is not set (%x)\n", __func__, tmp);
-               return -1;
-       }
-
-       /* prepare parameters */
-       bufsize = dev->epmaxpacketout[usb_pipeendpoint(pipe)];
-       buf = (u16 *)(buffer + dev->act_len);
-       size = min((int)bufsize, transfer_len - dev->act_len);
-
-       /* write fifo */
-       r8a66597_write(r8a66597, ~(1 << BULK_OUT_PIPENUM), BEMPSTS);
-       if (buffer) {
-               r8a66597_write_fifo(r8a66597, CFIFO, buf, size);
-               r8a66597_write(r8a66597, BVAL, CFIFOCTR);
-       }
-
-       /* update parameters */
-       dev->act_len += size;
-
-       r8a66597_mdfy(r8a66597, PID_BUF, PID,
-                       get_pipectr_addr(BULK_OUT_PIPENUM));
-
-       while (!(r8a66597_read(r8a66597, BEMPSTS) & (1 << BULK_OUT_PIPENUM)))
-               if (ctrlc())
-                       return -1;
-       r8a66597_write(r8a66597, ~(1 << BULK_OUT_PIPENUM), BEMPSTS);
-
-       if (dev->act_len >= transfer_len)
-               r8a66597_mdfy(r8a66597, PID_NAK, PID,
-                               get_pipectr_addr(BULK_OUT_PIPENUM));
-
-       return 0;
-}
-
-static int receive_bulk_packet(struct r8a66597 *r8a66597,
-                              struct usb_device *dev,
-                              unsigned long pipe,
-                              void *buffer, int transfer_len)
-{
-       u16 tmp;
-       u16 *buf;
-       const u16 pipenum = BULK_IN_PIPENUM;
-       int rcv_len;
-       int maxpacket = dev->epmaxpacketin[usb_pipeendpoint(pipe)];
-
-       R8A66597_DPRINT("%s\n", __func__);
-
-       /* prepare */
-       if (dev->act_len == 0) {
-               r8a66597_mdfy(r8a66597, PID_NAK, PID,
-                               get_pipectr_addr(pipenum));
-               r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS);
-
-               r8a66597_write(r8a66597, TRCLR, get_pipetre_addr(pipenum));
-               r8a66597_write(r8a66597,
-                               (transfer_len + maxpacket - 1) / maxpacket,
-                               get_pipetrn_addr(pipenum));
-               r8a66597_bset(r8a66597, TRENB, get_pipetre_addr(pipenum));
-
-               r8a66597_mdfy(r8a66597, PID_BUF, PID,
-                               get_pipectr_addr(pipenum));
-       }
-
-       r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL);
-       r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, pipenum);
-
-       while (!(r8a66597_read(r8a66597, BRDYSTS) & (1 << pipenum)))
-               if (ctrlc())
-                       return -1;
-       r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS);
-
-       tmp = r8a66597_read(r8a66597, CFIFOCTR);
-       if ((tmp & FRDY) == 0) {
-               printf("%s FRDY is not set. (%x)\n", __func__, tmp);
-               return -1;
-       }
-
-       buf = (u16 *)(buffer + dev->act_len);
-       rcv_len = tmp & DTLN;
-       dev->act_len += rcv_len;
-
-       if (buffer) {
-               if (rcv_len == 0)
-                       r8a66597_write(r8a66597, BCLR, CFIFOCTR);
-               else
-                       r8a66597_read_fifo(r8a66597, CFIFO, buf, rcv_len);
-       }
-
-       return 0;
-}
-
-static int receive_control_packet(struct r8a66597 *r8a66597,
-                                 struct usb_device *dev,
-                                 void *buffer, int transfer_len)
-{
-       u16 tmp;
-       int rcv_len;
-
-       /* FIXME: limit transfer size : 64byte or less */
-
-       r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
-       r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL);
-       r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
-       r8a66597_bset(r8a66597, SQSET, DCPCTR);
-       r8a66597_write(r8a66597, BCLR, CFIFOCTR);
-       r8a66597_mdfy(r8a66597, PID_BUF, PID, DCPCTR);
-
-       while (!(r8a66597_read(r8a66597, BRDYSTS) & 0x0001))
-               if (ctrlc())
-                       return -1;
-       r8a66597_write(r8a66597, ~0x0001, BRDYSTS);
-
-       r8a66597_mdfy(r8a66597, MBW, MBW | CURPIPE, CFIFOSEL);
-       r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
-
-       tmp = r8a66597_read(r8a66597, CFIFOCTR);
-       if ((tmp & FRDY) == 0) {
-               printf("%s FRDY is not set. (%x)\n", __func__, tmp);
-               return -1;
-       }
-
-       rcv_len = tmp & DTLN;
-       dev->act_len += rcv_len;
-
-       r8a66597_mdfy(r8a66597, PID_NAK, PID, DCPCTR);
-
-       if (buffer) {
-               if (rcv_len == 0)
-                       r8a66597_write(r8a66597, BCLR, DCPCTR);
-               else
-                       r8a66597_read_fifo(r8a66597, CFIFO, buffer, rcv_len);
-       }
-
-       return 0;
-}
-
-static int send_status_packet(struct r8a66597 *r8a66597,
-                              unsigned long pipe)
-{
-       r8a66597_bset(r8a66597, SQSET, DCPCTR);
-       r8a66597_mdfy(r8a66597, PID_NAK, PID, DCPCTR);
-
-       if (usb_pipein(pipe)) {
-               r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG);
-               r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL);
-               r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
-               r8a66597_write(r8a66597, ~BEMP0, BEMPSTS);
-               r8a66597_write(r8a66597, BCLR | BVAL, CFIFOCTR);
-       } else {
-               r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
-               r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL);
-               r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
-               r8a66597_write(r8a66597, BCLR, CFIFOCTR);
-       }
-       r8a66597_mdfy(r8a66597, PID_BUF, PID, DCPCTR);
-
-       while (!(r8a66597_read(r8a66597, BEMPSTS) & 0x0001))
-               if (ctrlc())
-                       return -1;
-
-       return 0;
-}
-
-static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port)
-{
-       int count = R8A66597_MAX_SAMPLING;
-       unsigned short syssts, old_syssts;
-
-       R8A66597_DPRINT("%s\n", __func__);
-
-       old_syssts = r8a66597_read(r8a66597, get_syssts_reg(port) & LNST);
-       while (count > 0) {
-               wait_ms(R8A66597_RH_POLL_TIME);
-
-               syssts = r8a66597_read(r8a66597, get_syssts_reg(port) & LNST);
-               if (syssts == old_syssts) {
-                       count--;
-               } else {
-                       count = R8A66597_MAX_SAMPLING;
-                       old_syssts = syssts;
-               }
-       }
-}
-
-static void r8a66597_bus_reset(struct r8a66597 *r8a66597, int port)
-{
-       wait_ms(10);
-       r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT, get_dvstctr_reg(port));
-       wait_ms(50);
-       r8a66597_mdfy(r8a66597, UACT, USBRST | UACT, get_dvstctr_reg(port));
-       wait_ms(50);
-}
-
-static int check_usb_device_connecting(struct r8a66597 *r8a66597)
-{
-       int timeout = 10000;    /* 100usec * 10000 = 1sec */
-       int i;
-
-       for (i = 0; i < 5; i++) {
-               /* check a usb cable connect */
-               while (!(r8a66597_read(r8a66597, INTSTS1) & ATTCH)) {
-                       if (timeout-- < 0) {
-                               printf("%s timeout.\n", __func__);
-                               return -1;
-                       }
-                       udelay(100);
-               }
-
-               /* check a data line */
-               r8a66597_check_syssts(r8a66597, 0);
-
-               r8a66597_bus_reset(r8a66597, 0);
-               r8a66597->speed = get_rh_usb_speed(r8a66597, 0);
-
-               if (!(r8a66597_read(r8a66597, INTSTS1) & DTCH)) {
-                       r8a66597->port_change = USB_PORT_STAT_C_CONNECTION;
-                       r8a66597->port_status = USB_PORT_STAT_CONNECTION |
-                                               USB_PORT_STAT_ENABLE;
-                       return 0;       /* success */
-               }
-
-               R8A66597_DPRINT("USB device has detached. retry = %d\n", i);
-               r8a66597_write(r8a66597, ~DTCH, INTSTS1);
-       }
-
-       return -1;      /* fail */
-}
-
-/* based on usb_ohci.c */
-#define min_t(type, x, y) \
-               ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; })
-/*-------------------------------------------------------------------------*
- * Virtual Root Hub
- *-------------------------------------------------------------------------*/
-
-/* Device descriptor */
-static __u8 root_hub_dev_des[] =
-{
-       0x12,       /*  __u8  bLength; */
-       0x01,       /*  __u8  bDescriptorType; Device */
-       0x10,       /*  __u16 bcdUSB; v1.1 */
-       0x01,
-       0x09,       /*  __u8  bDeviceClass; HUB_CLASSCODE */
-       0x00,       /*  __u8  bDeviceSubClass; */
-       0x00,       /*  __u8  bDeviceProtocol; */
-       0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
-       0x00,       /*  __u16 idVendor; */
-       0x00,
-       0x00,       /*  __u16 idProduct; */
-       0x00,
-       0x00,       /*  __u16 bcdDevice; */
-       0x00,
-       0x00,       /*  __u8  iManufacturer; */
-       0x01,       /*  __u8  iProduct; */
-       0x00,       /*  __u8  iSerialNumber; */
-       0x01        /*  __u8  bNumConfigurations; */
-};
-
-/* Configuration descriptor */
-static __u8 root_hub_config_des[] =
-{
-       0x09,       /*  __u8  bLength; */
-       0x02,       /*  __u8  bDescriptorType; Configuration */
-       0x19,       /*  __u16 wTotalLength; */
-       0x00,
-       0x01,       /*  __u8  bNumInterfaces; */
-       0x01,       /*  __u8  bConfigurationValue; */
-       0x00,       /*  __u8  iConfiguration; */
-       0x40,       /*  __u8  bmAttributes; */
-
-       0x00,       /*  __u8  MaxPower; */
-
-       /* interface */
-       0x09,       /*  __u8  if_bLength; */
-       0x04,       /*  __u8  if_bDescriptorType; Interface */
-       0x00,       /*  __u8  if_bInterfaceNumber; */
-       0x00,       /*  __u8  if_bAlternateSetting; */
-       0x01,       /*  __u8  if_bNumEndpoints; */
-       0x09,       /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
-       0x00,       /*  __u8  if_bInterfaceSubClass; */
-       0x00,       /*  __u8  if_bInterfaceProtocol; */
-       0x00,       /*  __u8  if_iInterface; */
-
-       /* endpoint */
-       0x07,       /*  __u8  ep_bLength; */
-       0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
-       0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
-       0x03,       /*  __u8  ep_bmAttributes; Interrupt */
-       0x02,       /*  __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
-       0x00,
-       0xff        /*  __u8  ep_bInterval; 255 ms */
-};
-
-static unsigned char root_hub_str_index0[] =
-{
-       0x04,                   /*  __u8  bLength; */
-       0x03,                   /*  __u8  bDescriptorType; String-descriptor */
-       0x09,                   /*  __u8  lang ID */
-       0x04,                   /*  __u8  lang ID */
-};
-
-static unsigned char root_hub_str_index1[] =
-{
-       34,                     /*  __u8  bLength; */
-       0x03,                   /*  __u8  bDescriptorType; String-descriptor */
-       'R',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       '8',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       'A',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       '6',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       '6',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       '5',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       '9',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       '7',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       ' ',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       'R',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       'o',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       'o',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       't',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       'H',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       'u',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       'b',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-};
-
-static int r8a66597_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
-                       void *buffer, int transfer_len, struct devrequest *cmd)
-{
-       struct r8a66597 *r8a66597 = &gr8a66597;
-       int leni = transfer_len;
-       int len = 0;
-       int stat = 0;
-       __u16 bmRType_bReq;
-       __u16 wValue;
-       __u16 wIndex;
-       __u16 wLength;
-       unsigned char data[32];
-
-       R8A66597_DPRINT("%s\n", __func__);
-
-       if (usb_pipeint(pipe)) {
-               printf("Root-Hub submit IRQ: NOT implemented");
-               return 0;
-       }
-
-       bmRType_bReq  = cmd->requesttype | (cmd->request << 8);
-       wValue        = cpu_to_le16 (cmd->value);
-       wIndex        = cpu_to_le16 (cmd->index);
-       wLength       = cpu_to_le16 (cmd->length);
-
-       switch (bmRType_bReq) {
-       case RH_GET_STATUS:
-               *(__u16 *)buffer = cpu_to_le16(1);
-               len = 2;
-               break;
-       case RH_GET_STATUS | RH_INTERFACE:
-               *(__u16 *)buffer = cpu_to_le16(0);
-               len = 2;
-               break;
-       case RH_GET_STATUS | RH_ENDPOINT:
-               *(__u16 *)buffer = cpu_to_le16(0);
-               len = 2;
-               break;
-       case RH_GET_STATUS | RH_CLASS:
-               *(__u32 *)buffer = cpu_to_le32(0);
-               len = 4;
-               break;
-       case RH_GET_STATUS | RH_OTHER | RH_CLASS:
-               *(__u32 *)buffer = cpu_to_le32(r8a66597->port_status |
-                                               (r8a66597->port_change << 16));
-               len = 4;
-               break;
-       case RH_CLEAR_FEATURE | RH_ENDPOINT:
-       case RH_CLEAR_FEATURE | RH_CLASS:
-               break;
-
-       case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
-               switch (wValue) {
-               case RH_C_PORT_CONNECTION:
-                       r8a66597->port_change &= ~USB_PORT_STAT_C_CONNECTION;
-                       break;
-               }
-               break;
-
-       case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
-               switch (wValue) {
-               case (RH_PORT_SUSPEND):
-                       break;
-               case (RH_PORT_RESET):
-                       r8a66597_bus_reset(r8a66597, 0);
-                       break;
-               case (RH_PORT_POWER):
-                       break;
-               case (RH_PORT_ENABLE):
-                       break;
-               }
-               break;
-       case RH_SET_ADDRESS:
-               gr8a66597.rh_devnum = wValue;
-               break;
-       case RH_GET_DESCRIPTOR:
-               switch ((wValue & 0xff00) >> 8) {
-               case (0x01): /* device descriptor */
-                       len = min_t(unsigned int,
-                                 leni,
-                                 min_t(unsigned int,
-                                     sizeof(root_hub_dev_des),
-                                     wLength));
-                       memcpy(buffer, root_hub_dev_des, len);
-                       break;
-               case (0x02): /* configuration descriptor */
-                       len = min_t(unsigned int,
-                                 leni,
-                                 min_t(unsigned int,
-                                     sizeof(root_hub_config_des),
-                                     wLength));
-                       memcpy(buffer, root_hub_config_des, len);
-                       break;
-               case (0x03): /* string descriptors */
-                       if (wValue == 0x0300) {
-                               len = min_t(unsigned int,
-                                         leni,
-                                         min_t(unsigned int,
-                                             sizeof(root_hub_str_index0),
-                                             wLength));
-                               memcpy(buffer, root_hub_str_index0, len);
-                       }
-                       if (wValue == 0x0301) {
-                               len = min_t(unsigned int,
-                                         leni,
-                                         min_t(unsigned int,
-                                             sizeof(root_hub_str_index1),
-                                             wLength));
-                               memcpy(buffer, root_hub_str_index1, len);
-                       }
-                       break;
-               default:
-                       stat = USB_ST_STALLED;
-               }
-               break;
-
-       case RH_GET_DESCRIPTOR | RH_CLASS:
-       {
-               __u32 temp = 0x00000001;
-
-               data[0] = 9;            /* min length; */
-               data[1] = 0x29;
-               data[2] = temp & RH_A_NDP;
-               data[3] = 0;
-               if (temp & RH_A_PSM)
-                       data[3] |= 0x1;
-               if (temp & RH_A_NOCP)
-                       data[3] |= 0x10;
-               else if (temp & RH_A_OCPM)
-                       data[3] |= 0x8;
-
-               /* corresponds to data[4-7] */
-               data[5] = (temp & RH_A_POTPGT) >> 24;
-               data[7] = temp & RH_B_DR;
-               if (data[2] < 7) {
-                       data[8] = 0xff;
-               } else {
-                       data[0] += 2;
-                       data[8] = (temp & RH_B_DR) >> 8;
-                       data[10] = data[9] = 0xff;
-               }
-
-               len = min_t(unsigned int, leni,
-                           min_t(unsigned int, data[0], wLength));
-               memcpy(buffer, data, len);
-               break;
-       }
-
-       case RH_GET_CONFIGURATION:
-               *(__u8 *) buffer = 0x01;
-               len = 1;
-               break;
-       case RH_SET_CONFIGURATION:
-               break;
-       default:
-               R8A66597_DPRINT("unsupported root hub command");
-               stat = USB_ST_STALLED;
-       }
-
-       wait_ms(1);
-
-       len = min_t(int, len, leni);
-
-       dev->act_len = len;
-       dev->status = stat;
-
-       return stat;
-}
-
-int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-                   int transfer_len)
-{
-       struct r8a66597 *r8a66597 = &gr8a66597;
-       int ret = 0;
-
-       R8A66597_DPRINT("%s\n", __func__);
-       R8A66597_DPRINT("pipe = %08x, buffer = %p, len = %d, devnum = %d\n",
-                       pipe, buffer, transfer_len, dev->devnum);
-
-       set_devadd(r8a66597, dev->devnum, dev, 0);
-
-       pipe_buffer_setting(r8a66597, dev, pipe);
-
-       dev->act_len = 0;
-       while (dev->act_len < transfer_len && ret == 0) {
-               if (ctrlc())
-                       return -1;
-
-               if (usb_pipein(pipe))
-                       ret = receive_bulk_packet(r8a66597, dev, pipe, buffer,
-                                                       transfer_len);
-               else
-                       ret = send_bulk_packet(r8a66597, dev, pipe, buffer,
-                                                       transfer_len);
-       }
-
-       if (ret == 0)
-               dev->status = 0;
-
-       return ret;
-}
-
-int submit_control_msg(struct usb_device *dev, unsigned long pipe,
-                      void *buffer, int transfer_len, struct devrequest *setup)
-{
-       struct r8a66597 *r8a66597 = &gr8a66597;
-       u16 r8a66597_address = setup->request == USB_REQ_SET_ADDRESS ?
-                                       0 : dev->devnum;
-
-       R8A66597_DPRINT("%s\n", __func__);
-       if (usb_pipedevice(pipe) == r8a66597->rh_devnum)
-               return r8a66597_submit_rh_msg(dev, pipe, buffer, transfer_len,
-                                               setup);
-
-       R8A66597_DPRINT("%s: setup\n", __func__);
-       set_devadd(r8a66597, r8a66597_address, dev, 0);
-
-       if (send_setup_packet(r8a66597, dev, setup) < 0) {
-               printf("setup packet send error\n");
-               return -1;
-       }
-
-       dev->act_len = 0;
-       if (usb_pipein(pipe))
-               if (receive_control_packet(r8a66597, dev, buffer,
-                                               transfer_len) < 0)
-                       return -1;
-
-       if (send_status_packet(r8a66597, pipe) < 0)
-               return -1;
-
-       dev->status = 0;
-
-       return 0;
-}
-
-int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-                       int transfer_len, int interval)
-{
-       /* no implement */
-       R8A66597_DPRINT("%s\n", __func__);
-       return 0;
-}
-
-void usb_event_poll(void)
-{
-       /* no implement */
-       R8A66597_DPRINT("%s\n", __func__);
-}
-
-int usb_lowlevel_init(void)
-{
-       struct r8a66597 *r8a66597 = &gr8a66597;
-
-       R8A66597_DPRINT("%s\n", __func__);
-
-       memset(r8a66597, 0, sizeof(r8a66597));
-       r8a66597->reg = CONFIG_R8A66597_BASE_ADDR;
-
-       disable_controller(r8a66597);
-       wait_ms(100);
-
-       enable_controller(r8a66597);
-       r8a66597_port_power(r8a66597, 0 , 1);
-
-       /* check usb device */
-       check_usb_device_connecting(r8a66597);
-
-       wait_ms(50);
-
-       return 0;
-}
-
-int usb_lowlevel_stop(void)
-{
-       disable_controller(&gr8a66597);
-
-       return 0;
-}
diff --git a/drivers/usb/r8a66597.h b/drivers/usb/r8a66597.h
deleted file mode 100644 (file)
index 9af6446..0000000
+++ /dev/null
@@ -1,659 +0,0 @@
-/*
- * R8A66597 HCD (Host Controller Driver) for u-boot
- *
- * Copyright (C) 2008  Yoshihiro Shimoda <shimoda.yoshihiro@renesas.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; version 2 of the License.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#ifndef __R8A66597_H__
-#define __R8A66597_H__
-
-#define SYSCFG0                0x00
-#define SYSCFG1                0x02
-#define SYSSTS0                0x04
-#define SYSSTS1                0x06
-#define DVSTCTR0       0x08
-#define DVSTCTR1       0x0A
-#define TESTMODE       0x0C
-#define PINCFG         0x0E
-#define DMA0CFG                0x10
-#define DMA1CFG                0x12
-#define CFIFO          0x14
-#define D0FIFO         0x18
-#define D1FIFO         0x1C
-#define CFIFOSEL       0x20
-#define CFIFOCTR       0x22
-#define CFIFOSIE       0x24
-#define D0FIFOSEL      0x28
-#define D0FIFOCTR      0x2A
-#define D1FIFOSEL      0x2C
-#define D1FIFOCTR      0x2E
-#define INTENB0                0x30
-#define INTENB1                0x32
-#define INTENB2                0x34
-#define BRDYENB                0x36
-#define NRDYENB                0x38
-#define BEMPENB                0x3A
-#define SOFCFG         0x3C
-#define INTSTS0                0x40
-#define INTSTS1                0x42
-#define INTSTS2                0x44
-#define BRDYSTS                0x46
-#define NRDYSTS                0x48
-#define BEMPSTS                0x4A
-#define FRMNUM         0x4C
-#define UFRMNUM                0x4E
-#define USBADDR                0x50
-#define USBREQ         0x54
-#define USBVAL         0x56
-#define USBINDX                0x58
-#define USBLENG                0x5A
-#define DCPCFG         0x5C
-#define DCPMAXP                0x5E
-#define DCPCTR         0x60
-#define PIPESEL                0x64
-#define PIPECFG                0x68
-#define PIPEBUF                0x6A
-#define PIPEMAXP       0x6C
-#define PIPEPERI       0x6E
-#define PIPE1CTR       0x70
-#define PIPE2CTR       0x72
-#define PIPE3CTR       0x74
-#define PIPE4CTR       0x76
-#define PIPE5CTR       0x78
-#define PIPE6CTR       0x7A
-#define PIPE7CTR       0x7C
-#define PIPE8CTR       0x7E
-#define PIPE9CTR       0x80
-#define PIPE1TRE       0x90
-#define PIPE1TRN       0x92
-#define PIPE2TRE       0x94
-#define PIPE2TRN       0x96
-#define PIPE3TRE       0x98
-#define PIPE3TRN       0x9A
-#define PIPE4TRE       0x9C
-#define        PIPE4TRN        0x9E
-#define        PIPE5TRE        0xA0
-#define        PIPE5TRN        0xA2
-#define DEVADD0                0xD0
-#define DEVADD1                0xD2
-#define DEVADD2                0xD4
-#define DEVADD3                0xD6
-#define DEVADD4                0xD8
-#define DEVADD5                0xDA
-#define DEVADD6                0xDC
-#define DEVADD7                0xDE
-#define DEVADD8                0xE0
-#define DEVADD9                0xE2
-#define DEVADDA                0xE4
-
-/* System Configuration Control Register */
-#define        XTAL            0xC000  /* b15-14: Crystal selection */
-#define          XTAL48         0x8000   /* 48MHz */
-#define          XTAL24         0x4000   /* 24MHz */
-#define          XTAL12         0x0000   /* 12MHz */
-#define        XCKE            0x2000  /* b13: External clock enable */
-#define        PLLC            0x0800  /* b11: PLL control */
-#define        SCKE            0x0400  /* b10: USB clock enable */
-#define        PCSDIS          0x0200  /* b9: not CS wakeup */
-#define        LPSME           0x0100  /* b8: Low power sleep mode */
-#define        HSE             0x0080  /* b7: Hi-speed enable */
-#define        DCFM            0x0040  /* b6: Controller function select  */
-#define        DRPD            0x0020  /* b5: D+/- pull down control */
-#define        DPRPU           0x0010  /* b4: D+ pull up control */
-#define        USBE            0x0001  /* b0: USB module operation enable */
-
-/* System Configuration Status Register */
-#define        OVCBIT          0x8000  /* b15-14: Over-current bit */
-#define        OVCMON          0xC000  /* b15-14: Over-current monitor */
-#define        SOFEA           0x0020  /* b5: SOF monitor */
-#define        IDMON           0x0004  /* b3: ID-pin monitor */
-#define        LNST            0x0003  /* b1-0: D+, D- line status */
-#define          SE1            0x0003   /* SE1 */
-#define          FS_KSTS        0x0002   /* Full-Speed K State */
-#define          FS_JSTS        0x0001   /* Full-Speed J State */
-#define          LS_JSTS        0x0002   /* Low-Speed J State */
-#define          LS_KSTS        0x0001   /* Low-Speed K State */
-#define          SE0            0x0000   /* SE0 */
-
-/* Device State Control Register */
-#define        EXTLP0          0x0400  /* b10: External port */
-#define        VBOUT           0x0200  /* b9: VBUS output */
-#define        WKUP            0x0100  /* b8: Remote wakeup */
-#define        RWUPE           0x0080  /* b7: Remote wakeup sense */
-#define        USBRST          0x0040  /* b6: USB reset enable */
-#define        RESUME          0x0020  /* b5: Resume enable */
-#define        UACT            0x0010  /* b4: USB bus enable */
-#define        RHST            0x0007  /* b1-0: Reset handshake status */
-#define          HSPROC         0x0004   /* HS handshake is processing */
-#define          HSMODE         0x0003   /* Hi-Speed mode */
-#define          FSMODE         0x0002   /* Full-Speed mode */
-#define          LSMODE         0x0001   /* Low-Speed mode */
-#define          UNDECID        0x0000   /* Undecided */
-
-/* Test Mode Register */
-#define        UTST                    0x000F  /* b3-0: Test select */
-#define          H_TST_PACKET           0x000C   /* HOST TEST Packet */
-#define          H_TST_SE0_NAK          0x000B   /* HOST TEST SE0 NAK */
-#define          H_TST_K                0x000A   /* HOST TEST K */
-#define          H_TST_J                0x0009   /* HOST TEST J */
-#define          H_TST_NORMAL           0x0000   /* HOST Normal Mode */
-#define          P_TST_PACKET           0x0004   /* PERI TEST Packet */
-#define          P_TST_SE0_NAK          0x0003   /* PERI TEST SE0 NAK */
-#define          P_TST_K                0x0002   /* PERI TEST K */
-#define          P_TST_J                0x0001   /* PERI TEST J */
-#define          P_TST_NORMAL           0x0000   /* PERI Normal Mode */
-
-/* Data Pin Configuration Register */
-#define        LDRV                    0x8000  /* b15: Drive Current Adjust */
-#define          VIF1                    0x0000                /* VIF = 1.8V */
-#define          VIF3                    0x8000                /* VIF = 3.3V */
-#define        INTA                    0x0001  /* b1: USB INT-pin active */
-
-/* DMAx Pin Configuration Register */
-#define        DREQA                   0x4000  /* b14: Dreq active select */
-#define        BURST                   0x2000  /* b13: Burst mode */
-#define        DACKA                   0x0400  /* b10: Dack active select */
-#define        DFORM                   0x0380  /* b9-7: DMA mode select */
-#define          CPU_ADR_RD_WR          0x0000   /* Address + RD/WR mode (CPU bus) */
-#define          CPU_DACK_RD_WR         0x0100   /* DACK + RD/WR mode (CPU bus) */
-#define          CPU_DACK_ONLY          0x0180   /* DACK only mode (CPU bus) */
-#define          SPLIT_DACK_ONLY        0x0200   /* DACK only mode (SPLIT bus) */
-#define        DENDA                   0x0040  /* b6: Dend active select */
-#define        PKTM                    0x0020  /* b5: Packet mode */
-#define        DENDE                   0x0010  /* b4: Dend enable */
-#define        OBUS                    0x0004  /* b2: OUTbus mode */
-
-/* CFIFO/DxFIFO Port Select Register */
-#define        RCNT            0x8000  /* b15: Read count mode */
-#define        REW             0x4000  /* b14: Buffer rewind */
-#define        DCLRM           0x2000  /* b13: DMA buffer clear mode */
-#define        DREQE           0x1000  /* b12: DREQ output enable */
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
-#define        MBW             0x0800
-#else
-#define        MBW             0x0400  /* b10: Maximum bit width for FIFO access */
-#endif
-#define          MBW_8          0x0000   /*  8bit */
-#define          MBW_16         0x0400   /* 16bit */
-#define        BIGEND          0x0100  /* b8: Big endian mode */
-#define          BYTE_LITTLE    0x0000         /* little dendian */
-#define          BYTE_BIG       0x0100         /* big endifan */
-#define        ISEL            0x0020  /* b5: DCP FIFO port direction select */
-#define        CURPIPE         0x000F  /* b2-0: PIPE select */
-
-/* CFIFO/DxFIFO Port Control Register */
-#define        BVAL            0x8000  /* b15: Buffer valid flag */
-#define        BCLR            0x4000  /* b14: Buffer clear */
-#define        FRDY            0x2000  /* b13: FIFO ready */
-#define        DTLN            0x0FFF  /* b11-0: FIFO received data length */
-
-/* Interrupt Enable Register 0 */
-#define        VBSE    0x8000  /* b15: VBUS interrupt */
-#define        RSME    0x4000  /* b14: Resume interrupt */
-#define        SOFE    0x2000  /* b13: Frame update interrupt */
-#define        DVSE    0x1000  /* b12: Device state transition interrupt */
-#define        CTRE    0x0800  /* b11: Control transfer stage transition interrupt */
-#define        BEMPE   0x0400  /* b10: Buffer empty interrupt */
-#define        NRDYE   0x0200  /* b9: Buffer not ready interrupt */
-#define        BRDYE   0x0100  /* b8: Buffer ready interrupt */
-
-/* Interrupt Enable Register 1 */
-#define        OVRCRE          0x8000  /* b15: Over-current interrupt */
-#define        BCHGE           0x4000  /* b14: USB us chenge interrupt */
-#define        DTCHE           0x1000  /* b12: Detach sense interrupt */
-#define        ATTCHE          0x0800  /* b11: Attach sense interrupt */
-#define        EOFERRE         0x0040  /* b6: EOF error interrupt */
-#define        SIGNE           0x0020  /* b5: SETUP IGNORE interrupt */
-#define        SACKE           0x0010  /* b4: SETUP ACK interrupt */
-
-/* BRDY Interrupt Enable/Status Register */
-#define        BRDY9           0x0200  /* b9: PIPE9 */
-#define        BRDY8           0x0100  /* b8: PIPE8 */
-#define        BRDY7           0x0080  /* b7: PIPE7 */
-#define        BRDY6           0x0040  /* b6: PIPE6 */
-#define        BRDY5           0x0020  /* b5: PIPE5 */
-#define        BRDY4           0x0010  /* b4: PIPE4 */
-#define        BRDY3           0x0008  /* b3: PIPE3 */
-#define        BRDY2           0x0004  /* b2: PIPE2 */
-#define        BRDY1           0x0002  /* b1: PIPE1 */
-#define        BRDY0           0x0001  /* b1: PIPE0 */
-
-/* NRDY Interrupt Enable/Status Register */
-#define        NRDY9           0x0200  /* b9: PIPE9 */
-#define        NRDY8           0x0100  /* b8: PIPE8 */
-#define        NRDY7           0x0080  /* b7: PIPE7 */
-#define        NRDY6           0x0040  /* b6: PIPE6 */
-#define        NRDY5           0x0020  /* b5: PIPE5 */
-#define        NRDY4           0x0010  /* b4: PIPE4 */
-#define        NRDY3           0x0008  /* b3: PIPE3 */
-#define        NRDY2           0x0004  /* b2: PIPE2 */
-#define        NRDY1           0x0002  /* b1: PIPE1 */
-#define        NRDY0           0x0001  /* b1: PIPE0 */
-
-/* BEMP Interrupt Enable/Status Register */
-#define        BEMP9           0x0200  /* b9: PIPE9 */
-#define        BEMP8           0x0100  /* b8: PIPE8 */
-#define        BEMP7           0x0080  /* b7: PIPE7 */
-#define        BEMP6           0x0040  /* b6: PIPE6 */
-#define        BEMP5           0x0020  /* b5: PIPE5 */
-#define        BEMP4           0x0010  /* b4: PIPE4 */
-#define        BEMP3           0x0008  /* b3: PIPE3 */
-#define        BEMP2           0x0004  /* b2: PIPE2 */
-#define        BEMP1           0x0002  /* b1: PIPE1 */
-#define        BEMP0           0x0001  /* b0: PIPE0 */
-
-/* SOF Pin Configuration Register */
-#define        TRNENSEL        0x0100  /* b8: Select transaction enable period */
-#define        BRDYM           0x0040  /* b6: BRDY clear timing */
-#define        INTL            0x0020  /* b5: Interrupt sense select */
-#define        EDGESTS         0x0010  /* b4:  */
-#define        SOFMODE         0x000C  /* b3-2: SOF pin select */
-#define          SOF_125US      0x0008   /* SOF OUT 125us Frame Signal */
-#define          SOF_1MS        0x0004   /* SOF OUT 1ms Frame Signal */
-#define          SOF_DISABLE    0x0000   /* SOF OUT Disable */
-
-/* Interrupt Status Register 0 */
-#define        VBINT   0x8000  /* b15: VBUS interrupt */
-#define        RESM    0x4000  /* b14: Resume interrupt */
-#define        SOFR    0x2000  /* b13: SOF frame update interrupt */
-#define        DVST    0x1000  /* b12: Device state transition interrupt */
-#define        CTRT    0x0800  /* b11: Control transfer stage transition interrupt */
-#define        BEMP    0x0400  /* b10: Buffer empty interrupt */
-#define        NRDY    0x0200  /* b9: Buffer not ready interrupt */
-#define        BRDY    0x0100  /* b8: Buffer ready interrupt */
-#define        VBSTS   0x0080  /* b7: VBUS input port */
-#define        DVSQ    0x0070  /* b6-4: Device state */
-#define          DS_SPD_CNFG    0x0070   /* Suspend Configured */
-#define          DS_SPD_ADDR    0x0060   /* Suspend Address */
-#define          DS_SPD_DFLT    0x0050   /* Suspend Default */
-#define          DS_SPD_POWR    0x0040   /* Suspend Powered */
-#define          DS_SUSP        0x0040   /* Suspend */
-#define          DS_CNFG        0x0030   /* Configured */
-#define          DS_ADDS        0x0020   /* Address */
-#define          DS_DFLT        0x0010   /* Default */
-#define          DS_POWR        0x0000   /* Powered */
-#define        DVSQS           0x0030  /* b5-4: Device state */
-#define        VALID           0x0008  /* b3: Setup packet detected flag */
-#define        CTSQ            0x0007  /* b2-0: Control transfer stage */
-#define          CS_SQER        0x0006   /* Sequence error */
-#define          CS_WRND        0x0005   /* Control write nodata status stage */
-#define          CS_WRSS        0x0004   /* Control write status stage */
-#define          CS_WRDS        0x0003   /* Control write data stage */
-#define          CS_RDSS        0x0002   /* Control read status stage */
-#define          CS_RDDS        0x0001   /* Control read data stage */
-#define          CS_IDST        0x0000   /* Idle or setup stage */
-
-/* Interrupt Status Register 1 */
-#define        OVRCR           0x8000  /* b15: Over-current interrupt */
-#define        BCHG            0x4000  /* b14: USB bus chenge interrupt */
-#define        DTCH            0x1000  /* b12: Detach sense interrupt */
-#define        ATTCH           0x0800  /* b11: Attach sense interrupt */
-#define        EOFERR          0x0040  /* b6: EOF-error interrupt */
-#define        SIGN            0x0020  /* b5: Setup ignore interrupt */
-#define        SACK            0x0010  /* b4: Setup acknowledge interrupt */
-
-/* Frame Number Register */
-#define        OVRN            0x8000  /* b15: Overrun error */
-#define        CRCE            0x4000  /* b14: Received data error */
-#define        FRNM            0x07FF  /* b10-0: Frame number */
-
-/* Micro Frame Number Register */
-#define        UFRNM           0x0007  /* b2-0: Micro frame number */
-
-/* Default Control Pipe Maxpacket Size Register */
-/* Pipe Maxpacket Size Register */
-#define        DEVSEL  0xF000  /* b15-14: Device address select */
-#define        MAXP    0x007F  /* b6-0: Maxpacket size of default control pipe */
-
-/* Default Control Pipe Control Register */
-#define        BSTS            0x8000  /* b15: Buffer status */
-#define        SUREQ           0x4000  /* b14: Send USB request  */
-#define        CSCLR           0x2000  /* b13: complete-split status clear */
-#define        CSSTS           0x1000  /* b12: complete-split status */
-#define        SUREQCLR        0x0800  /* b11: stop setup request */
-#define        SQCLR           0x0100  /* b8: Sequence toggle bit clear */
-#define        SQSET           0x0080  /* b7: Sequence toggle bit set */
-#define        SQMON           0x0040  /* b6: Sequence toggle bit monitor */
-#define        PBUSY           0x0020  /* b5: pipe busy */
-#define        PINGE           0x0010  /* b4: ping enable */
-#define        CCPL            0x0004  /* b2: Enable control transfer complete */
-#define        PID             0x0003  /* b1-0: Response PID */
-#define          PID_STALL11    0x0003   /* STALL */
-#define          PID_STALL      0x0002   /* STALL */
-#define          PID_BUF        0x0001   /* BUF */
-#define          PID_NAK        0x0000   /* NAK */
-
-/* Pipe Window Select Register */
-#define        PIPENM          0x0007  /* b2-0: Pipe select */
-
-/* Pipe Configuration Register */
-#define        R8A66597_TYP    0xC000  /* b15-14: Transfer type */
-#define          R8A66597_ISO   0xC000           /* Isochronous */
-#define          R8A66597_INT   0x8000           /* Interrupt */
-#define          R8A66597_BULK  0x4000           /* Bulk */
-#define        R8A66597_BFRE   0x0400  /* b10: Buffer ready interrupt mode select */
-#define        R8A66597_DBLB   0x0200  /* b9: Double buffer mode select */
-#define        R8A66597_CNTMD  0x0100  /* b8: Continuous transfer mode select */
-#define        R8A66597_SHTNAK 0x0080  /* b7: Transfer end NAK */
-#define        R8A66597_DIR    0x0010  /* b4: Transfer direction select */
-#define        R8A66597_EPNUM  0x000F  /* b3-0: Eendpoint number select */
-
-/* Pipe Buffer Configuration Register */
-#define        BUFSIZE         0x7C00  /* b14-10: Pipe buffer size */
-#define        BUFNMB          0x007F  /* b6-0: Pipe buffer number */
-#define        PIPE0BUF        256
-#define        PIPExBUF        64
-
-/* Pipe Maxpacket Size Register */
-#define        MXPS            0x07FF  /* b10-0: Maxpacket size */
-
-/* Pipe Cycle Configuration Register */
-#define        IFIS    0x1000  /* b12: Isochronous in-buffer flush mode select */
-#define        IITV    0x0007  /* b2-0: Isochronous interval */
-
-/* Pipex Control Register */
-#define        BSTS    0x8000  /* b15: Buffer status */
-#define        INBUFM  0x4000  /* b14: IN buffer monitor (Only for PIPE1 to 5) */
-#define        CSCLR   0x2000  /* b13: complete-split status clear */
-#define        CSSTS   0x1000  /* b12: complete-split status */
-#define        ATREPM  0x0400  /* b10: Auto repeat mode */
-#define        ACLRM   0x0200  /* b9: Out buffer auto clear mode */
-#define        SQCLR   0x0100  /* b8: Sequence toggle bit clear */
-#define        SQSET   0x0080  /* b7: Sequence toggle bit set */
-#define        SQMON   0x0040  /* b6: Sequence toggle bit monitor */
-#define        PBUSY   0x0020  /* b5: pipe busy */
-#define        PID     0x0003  /* b1-0: Response PID */
-
-/* PIPExTRE */
-#define        TRENB           0x0200  /* b9: Transaction counter enable */
-#define        TRCLR           0x0100  /* b8: Transaction counter clear */
-
-/* PIPExTRN */
-#define        TRNCNT          0xFFFF  /* b15-0: Transaction counter */
-
-/* DEVADDx */
-#define        UPPHUB          0x7800
-#define        HUBPORT         0x0700
-#define        USBSPD          0x00C0
-#define        RTPORT          0x0001
-
-#define R8A66597_MAX_NUM_PIPE          10
-#define R8A66597_BUF_BSIZE             8
-#define R8A66597_MAX_DEVICE            10
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
-#define R8A66597_MAX_ROOT_HUB          1
-#else
-#define R8A66597_MAX_ROOT_HUB          2
-#endif
-#define R8A66597_MAX_SAMPLING          5
-#define R8A66597_RH_POLL_TIME          10
-
-#define BULK_IN_PIPENUM                3
-#define BULK_IN_BUFNUM         8
-
-#define BULK_OUT_PIPENUM       4
-#define BULK_OUT_BUFNUM                40
-
-#define check_bulk_or_isoc(pipenum)    ((pipenum >= 1 && pipenum <= 5))
-#define check_interrupt(pipenum)       ((pipenum >= 6 && pipenum <= 9))
-#define make_devsel(addr)              (addr << 12)
-
-struct r8a66597 {
-       unsigned long reg;
-       unsigned short pipe_config;     /* bit field */
-       unsigned short port_status;
-       unsigned short port_change;
-       u16 speed;      /* HSMODE or FSMODE or LSMODE */
-       unsigned char rh_devnum;
-};
-
-static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
-{
-       return inw(r8a66597->reg + offset);
-}
-
-static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
-                                     unsigned long offset, void *buf,
-                                     int len)
-{
-       int i;
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
-       unsigned long fifoaddr = r8a66597->reg + offset;
-       unsigned long count;
-       unsigned long *p = buf;
-
-       count = len / 4;
-       for (i = 0; i < count; i++)
-               inl(p[i], r8a66597->reg + offset);
-
-       if (len & 0x00000003) {
-               unsigned long tmp = inl(fifoaddr);
-               memcpy((unsigned char *)buf + count * 4, &tmp, len & 0x03);
-       }
-#else
-       unsigned short *p = buf;
-
-       len = (len + 1) / 2;
-       for (i = 0; i < len; i++)
-               p[i] = inw(r8a66597->reg + offset);
-#endif
-}
-
-static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
-                                 unsigned long offset)
-{
-       outw(val, r8a66597->reg + offset);
-}
-
-static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
-                                      unsigned long offset, void *buf,
-                                      int len)
-{
-       int i;
-       unsigned long fifoaddr = r8a66597->reg + offset;
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
-       unsigned long count;
-       unsigned char *pb;
-       unsigned long *p = buf;
-
-       count = len / 4;
-       for (i = 0; i < count; i++)
-               outl(p[i], fifoaddr);
-
-       if (len & 0x00000003) {
-               pb = (unsigned char *)buf + count * 4;
-               for (i = 0; i < (len & 0x00000003); i++) {
-                       if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
-                               outb(pb[i], fifoaddr + i);
-                       else
-                               outb(pb[i], fifoaddr + 3 - i);
-               }
-       }
-#else
-       int odd = len & 0x0001;
-       unsigned short *p = buf;
-
-       len = len / 2;
-       for (i = 0; i < len; i++)
-               outw(p[i], fifoaddr);
-
-       if (odd) {
-               unsigned char *pb = (unsigned char *)(buf + len);
-               outb(*pb, fifoaddr);
-       }
-#endif
-}
-
-static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
-                                u16 val, u16 pat, unsigned long offset)
-{
-       u16 tmp;
-       tmp = r8a66597_read(r8a66597, offset);
-       tmp = tmp & (~pat);
-       tmp = tmp | val;
-       r8a66597_write(r8a66597, tmp, offset);
-}
-
-#define r8a66597_bclr(r8a66597, val, offset)   \
-                       r8a66597_mdfy(r8a66597, 0, val, offset)
-#define r8a66597_bset(r8a66597, val, offset)   \
-                       r8a66597_mdfy(r8a66597, val, 0, offset)
-
-static inline unsigned long get_syscfg_reg(int port)
-{
-       return port == 0 ? SYSCFG0 : SYSCFG1;
-}
-
-static inline unsigned long get_syssts_reg(int port)
-{
-       return port == 0 ? SYSSTS0 : SYSSTS1;
-}
-
-static inline unsigned long get_dvstctr_reg(int port)
-{
-       return port == 0 ? DVSTCTR0 : DVSTCTR1;
-}
-
-static inline unsigned long get_dmacfg_reg(int port)
-{
-       return port == 0 ? DMA0CFG : DMA1CFG;
-}
-
-static inline unsigned long get_intenb_reg(int port)
-{
-       return port == 0 ? INTENB1 : INTENB2;
-}
-
-static inline unsigned long get_intsts_reg(int port)
-{
-       return port == 0 ? INTSTS1 : INTSTS2;
-}
-
-static inline u16 get_rh_usb_speed(struct r8a66597 *r8a66597, int port)
-{
-       unsigned long dvstctr_reg = get_dvstctr_reg(port);
-
-       return r8a66597_read(r8a66597, dvstctr_reg) & RHST;
-}
-
-static inline void r8a66597_port_power(struct r8a66597 *r8a66597, int port,
-                                      int power)
-{
-       unsigned long dvstctr_reg = get_dvstctr_reg(port);
-
-       if (power)
-               r8a66597_bset(r8a66597, VBOUT, dvstctr_reg);
-       else
-               r8a66597_bclr(r8a66597, VBOUT, dvstctr_reg);
-}
-
-#define get_pipectr_addr(pipenum)      (PIPE1CTR + (pipenum - 1) * 2)
-#define get_pipetre_addr(pipenum)      (PIPE1TRE + (pipenum - 1) * 4)
-#define get_pipetrn_addr(pipenum)      (PIPE1TRN + (pipenum - 1) * 4)
-#define get_devadd_addr(address)       (DEVADD0 + address * 2)
-
-
-/* USB HUB CONSTANTS (not OHCI-specific; see hub.h, based on usb_ohci.h) */
-
-/* destination of request */
-#define RH_INTERFACE              0x01
-#define RH_ENDPOINT               0x02
-#define RH_OTHER                  0x03
-
-#define RH_CLASS                  0x20
-#define RH_VENDOR                 0x40
-
-/* Requests: bRequest << 8 | bmRequestType */
-#define RH_GET_STATUS          0x0080
-#define RH_CLEAR_FEATURE       0x0100
-#define RH_SET_FEATURE         0x0300
-#define RH_SET_ADDRESS         0x0500
-#define RH_GET_DESCRIPTOR      0x0680
-#define RH_SET_DESCRIPTOR      0x0700
-#define RH_GET_CONFIGURATION   0x0880
-#define RH_SET_CONFIGURATION   0x0900
-#define RH_GET_STATE           0x0280
-#define RH_GET_INTERFACE       0x0A80
-#define RH_SET_INTERFACE       0x0B00
-#define RH_SYNC_FRAME          0x0C80
-/* Our Vendor Specific Request */
-#define RH_SET_EP              0x2000
-
-/* Hub port features */
-#define RH_PORT_CONNECTION        0x00
-#define RH_PORT_ENABLE            0x01
-#define RH_PORT_SUSPEND                   0x02
-#define RH_PORT_OVER_CURRENT      0x03
-#define RH_PORT_RESET             0x04
-#define RH_PORT_POWER             0x08
-#define RH_PORT_LOW_SPEED         0x09
-
-#define RH_C_PORT_CONNECTION      0x10
-#define RH_C_PORT_ENABLE          0x11
-#define RH_C_PORT_SUSPEND         0x12
-#define RH_C_PORT_OVER_CURRENT    0x13
-#define RH_C_PORT_RESET                   0x14
-
-/* Hub features */
-#define RH_C_HUB_LOCAL_POWER      0x00
-#define RH_C_HUB_OVER_CURRENT     0x01
-
-#define RH_DEVICE_REMOTE_WAKEUP           0x00
-#define RH_ENDPOINT_STALL         0x01
-
-#define RH_ACK                    0x01
-#define RH_REQ_ERR                -1
-#define RH_NACK                           0x00
-
-/* OHCI ROOT HUB REGISTER MASKS */
-
-/* roothub.portstatus [i] bits */
-#define RH_PS_CCS      0x00000001      /* current connect status */
-#define RH_PS_PES      0x00000002      /* port enable status*/
-#define RH_PS_PSS      0x00000004      /* port suspend status */
-#define RH_PS_POCI     0x00000008      /* port over current indicator */
-#define RH_PS_PRS      0x00000010      /* port reset status */
-#define RH_PS_PPS      0x00000100      /* port power status */
-#define RH_PS_LSDA     0x00000200      /* low speed device attached */
-#define RH_PS_CSC      0x00010000      /* connect status change */
-#define RH_PS_PESC     0x00020000      /* port enable status change */
-#define RH_PS_PSSC     0x00040000      /* port suspend status change */
-#define RH_PS_OCIC     0x00080000      /* over current indicator change */
-#define RH_PS_PRSC     0x00100000      /* port reset status change */
-
-/* roothub.status bits */
-#define RH_HS_LPS      0x00000001      /* local power status */
-#define RH_HS_OCI      0x00000002      /* over current indicator */
-#define RH_HS_DRWE     0x00008000      /* device remote wakeup enable */
-#define RH_HS_LPSC     0x00010000      /* local power status change */
-#define RH_HS_OCIC     0x00020000      /* over current indicator change */
-#define RH_HS_CRWE     0x80000000      /* clear remote wakeup enable */
-
-/* roothub.b masks */
-#define RH_B_DR                0x0000ffff      /* device removable flags */
-#define RH_B_PPCM      0xffff0000      /* port power control mask */
-
-/* roothub.a masks */
-#define RH_A_NDP       (0xff << 0)     /* number of downstream ports */
-#define RH_A_PSM       (1 << 8)        /* power switching mode */
-#define RH_A_NPS       (1 << 9)        /* no power switching */
-#define RH_A_DT                (1 << 10)       /* device type (mbz) */
-#define RH_A_OCPM      (1 << 11)       /* over current protection mode */
-#define RH_A_NOCP      (1 << 12)       /* no over current protection */
-#define RH_A_POTPGT    (0xff << 24)    /* power on to power good time */
-
-#endif /* __R8A66597_H__ */
diff --git a/drivers/usb/s3c64xx_usb.c b/drivers/usb/s3c64xx_usb.c
deleted file mode 100644 (file)
index 274a4ed..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * URB OHCI HCD (Host Controller Driver) initialization for USB on the S3C64XX.
- *
- * Copyright (C) 2008,
- * Guennadi Liakhovetski, DENX Software Engineering <lg@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 <s3c6400.h>
-
-int usb_cpu_init(void)
-{
-       OTHERS_REG |= 0x10000;
-       return 0;
-}
-
-int usb_cpu_stop(void)
-{
-       OTHERS_REG &= ~0x10000;
-       return 0;
-}
-
-void usb_cpu_init_fail(void)
-{
-       OTHERS_REG &= ~0x10000;
-}
diff --git a/drivers/usb/sl811.h b/drivers/usb/sl811.h
deleted file mode 100644 (file)
index c1f9f01..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-#ifndef __UBOOT_SL811_H
-#define __UBOOT_SL811_H
-
-#undef SL811_DEBUG
-
-#ifdef SL811_DEBUG
-       #define PDEBUG(level, fmt, args...) \
-               if (debug >= (level)) printf("[%s:%d] " fmt, \
-               __PRETTY_FUNCTION__, __LINE__ , ## args)
-#else
-       #define PDEBUG(level, fmt, args...) do {} while(0)
-#endif
-
-/* Sl811 host control register */
-#define        SL811_CTRL_A            0x00
-#define        SL811_ADDR_A            0x01
-#define        SL811_LEN_A             0x02
-#define        SL811_STS_A             0x03    /* read */
-#define        SL811_PIDEP_A           0x03    /* write */
-#define        SL811_CNT_A             0x04    /* read */
-#define        SL811_DEV_A             0x04    /* write */
-#define        SL811_CTRL1             0x05
-#define        SL811_INTR              0x06
-#define        SL811_CTRL_B            0x08
-#define        SL811_ADDR_B            0x09
-#define        SL811_LEN_B             0x0A
-#define        SL811_STS_B             0x0B    /* read */
-#define        SL811_PIDEP_B           0x0B    /* write */
-#define        SL811_CNT_B             0x0C    /* read */
-#define        SL811_DEV_B             0x0C    /* write */
-#define        SL811_INTRSTS           0x0D    /* write clears bitwise */
-#define        SL811_HWREV             0x0E    /* read */
-#define        SL811_SOFLOW            0x0E    /* write */
-#define        SL811_SOFCNTDIV         0x0F    /* read */
-#define        SL811_CTRL2             0x0F    /* write */
-
-/* USB control register bits (addr 0x00 and addr 0x08) */
-#define        SL811_USB_CTRL_ARM      0x01
-#define        SL811_USB_CTRL_ENABLE   0x02
-#define        SL811_USB_CTRL_DIR_OUT  0x04
-#define        SL811_USB_CTRL_ISO      0x10
-#define        SL811_USB_CTRL_SOF      0x20
-#define        SL811_USB_CTRL_TOGGLE_1 0x40
-#define        SL811_USB_CTRL_PREAMBLE 0x80
-
-/* USB status register bits (addr 0x03 and addr 0x0B) */
-#define        SL811_USB_STS_ACK       0x01
-#define        SL811_USB_STS_ERROR     0x02
-#define        SL811_USB_STS_TIMEOUT   0x04
-#define        SL811_USB_STS_TOGGLE_1  0x08
-#define        SL811_USB_STS_SETUP     0x10
-#define        SL811_USB_STS_OVERFLOW  0x20
-#define        SL811_USB_STS_NAK       0x40
-#define        SL811_USB_STS_STALL     0x80
-
-/* Control register 1 bits (addr 0x05) */
-#define        SL811_CTRL1_SOF         0x01
-#define        SL811_CTRL1_RESET       0x08
-#define        SL811_CTRL1_JKSTATE     0x10
-#define        SL811_CTRL1_SPEED_LOW   0x20
-#define        SL811_CTRL1_SUSPEND     0x40
-
-/* Interrut enable (addr 0x06) and interrupt status register bits (addr 0x0D) */
-#define        SL811_INTR_DONE_A       0x01
-#define        SL811_INTR_DONE_B       0x02
-#define        SL811_INTR_SOF          0x10
-#define        SL811_INTR_INSRMV       0x20
-#define        SL811_INTR_DETECT       0x40
-#define        SL811_INTR_NOTPRESENT   0x40
-#define        SL811_INTR_SPEED_FULL   0x80    /* only in status reg */
-
-/* HW rev and SOF lo register bits (addr 0x0E) */
-#define        SL811_HWR_HWREV         0xF0
-
-/* SOF counter and control reg 2 (addr 0x0F) */
-#define        SL811_CTL2_SOFHI        0x3F
-#define        SL811_CTL2_DSWAP        0x40
-#define        SL811_CTL2_HOST         0x80
-
-/* Set up for 1-ms SOF time. */
-#define SL811_12M_LOW          0xE0
-#define SL811_12M_HI           0x2E
-
-#define SL811_DATA_START       0x10
-#define SL811_DATA_LIMIT       240
-
-/* Requests: bRequest << 8 | bmRequestType */
-#define RH_GET_STATUS           0x0080
-#define RH_CLEAR_FEATURE        0x0100
-#define RH_SET_FEATURE          0x0300
-#define RH_SET_ADDRESS         0x0500
-#define RH_GET_DESCRIPTOR      0x0680
-#define RH_SET_DESCRIPTOR       0x0700
-#define RH_GET_CONFIGURATION   0x0880
-#define RH_SET_CONFIGURATION   0x0900
-#define RH_GET_STATE            0x0280
-#define RH_GET_INTERFACE        0x0A80
-#define RH_SET_INTERFACE        0x0B00
-#define RH_SYNC_FRAME           0x0C80
-
-
-#define PIDEP(pid, ep) (((pid) & 0x0f) << 4 | (ep))
-
-#endif /* __UBOOT_SL811_H */
diff --git a/drivers/usb/sl811_usb.c b/drivers/usb/sl811_usb.c
deleted file mode 100644 (file)
index a03e469..0000000
+++ /dev/null
@@ -1,734 +0,0 @@
-/*
- * (C) Copyright 2004
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * This code is based on linux driver for sl811hs chip, source at
- * drivers/usb/host/sl811.c:
- *
- * SL811 Host Controller Interface driver for USB.
- *
- * Copyright (c) 2003/06, Courage Co., Ltd.
- *
- * Based on:
- *     1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap,
- *       Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber,
- *       Adam Richter, Gregory P. Smith;
- *     2.Original SL811 driver (hc_sl811.o) by Pei Liu <pbl@cypress.com>
- *     3.Rewrited as sl811.o by Yin Aihua <yinah:couragetech.com.cn>
- *
- * 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 <mpc8xx.h>
-#include <usb.h>
-#include "sl811.h"
-
-#include "../../board/kup/common/kup.h"
-
-#ifdef __PPC__
-# define EIEIO         __asm__ volatile ("eieio")
-#else
-# define EIEIO         /* nothing */
-#endif
-
-#define         SL811_ADR (0x50000000)
-#define         SL811_DAT (0x50000001)
-
-#define mdelay(n) ({unsigned long msec=(n); while (msec--) udelay(1000);})
-
-#ifdef SL811_DEBUG
-static int debug = 9;
-#endif
-
-static int root_hub_devnum = 0;
-static struct usb_port_status rh_status = { 0 };/* root hub port status */
-
-static int sl811_rh_submit_urb(struct usb_device *usb_dev, unsigned long pipe,
-                              void *data, int buf_len, struct devrequest *cmd);
-
-static void sl811_write (__u8 index, __u8 data)
-{
-       *(volatile unsigned char *) (SL811_ADR) = index;
-       EIEIO;
-       *(volatile unsigned char *) (SL811_DAT) = data;
-       EIEIO;
-}
-
-static __u8 sl811_read (__u8 index)
-{
-       __u8 data;
-
-       *(volatile unsigned char *) (SL811_ADR) = index;
-       EIEIO;
-       data = *(volatile unsigned char *) (SL811_DAT);
-       EIEIO;
-       return (data);
-}
-
-/*
- * Read consecutive bytes of data from the SL811H/SL11H buffer
- */
-static void inline sl811_read_buf(__u8 offset, __u8 *buf, __u8 size)
-{
-       *(volatile unsigned char *) (SL811_ADR) = offset;
-       EIEIO;
-       while (size--) {
-               *buf++ = *(volatile unsigned char *) (SL811_DAT);
-               EIEIO;
-       }
-}
-
-/*
- * Write consecutive bytes of data to the SL811H/SL11H buffer
- */
-static void inline sl811_write_buf(__u8 offset, __u8 *buf, __u8 size)
-{
-       *(volatile unsigned char *) (SL811_ADR) = offset;
-       EIEIO;
-       while (size--) {
-               *(volatile unsigned char *) (SL811_DAT) = *buf++;
-               EIEIO;
-       }
-}
-
-int usb_init_kup4x (void)
-{
-       volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
-       volatile memctl8xx_t *memctl = &immap->im_memctl;
-       int i;
-       unsigned char tmp;
-
-       memctl = &immap->im_memctl;
-       memctl->memc_or7 = 0xFFFF8726;
-       memctl->memc_br7 = 0x50000401;  /* start at 0x50000000 */
-       /* BP 14 low = USB ON */
-       immap->im_cpm.cp_pbdat &= ~(BP_USB_VCC);
-       /* PB 14 nomal port */
-       immap->im_cpm.cp_pbpar &= ~(BP_USB_VCC);
-       /* output */
-       immap->im_cpm.cp_pbdir |= (BP_USB_VCC);
-
-       puts ("USB:   ");
-
-       for (i = 0x10; i < 0xff; i++) {
-               sl811_write(i, i);
-               tmp = (sl811_read(i));
-               if (tmp != i) {
-                       printf ("SL811 compare error index=0x%02x read=0x%02x\n", i, tmp);
-                       return (-1);
-               }
-       }
-       printf ("SL811 ready\n");
-       return (0);
-}
-
-/*
- * This function resets SL811HS controller and detects the speed of
- * the connecting device
- *
- * Return: 0 = no device attached; 1 = USB device attached
- */
-static int sl811_hc_reset(void)
-{
-       int status ;
-
-       sl811_write(SL811_CTRL2, SL811_CTL2_HOST | SL811_12M_HI);
-       sl811_write(SL811_CTRL1, SL811_CTRL1_RESET);
-
-       mdelay(20);
-
-       /* Disable hardware SOF generation, clear all irq status. */
-       sl811_write(SL811_CTRL1, 0);
-       mdelay(2);
-       sl811_write(SL811_INTRSTS, 0xff);
-       status = sl811_read(SL811_INTRSTS);
-
-       if (status & SL811_INTR_NOTPRESENT) {
-               /* Device is not present */
-               PDEBUG(0, "Device not present\n");
-               rh_status.wPortStatus &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE);
-               rh_status.wPortChange |= USB_PORT_STAT_C_CONNECTION;
-               sl811_write(SL811_INTR, SL811_INTR_INSRMV);
-               return 0;
-       }
-
-       /* Send SOF to address 0, endpoint 0. */
-       sl811_write(SL811_LEN_B, 0);
-       sl811_write(SL811_PIDEP_B, PIDEP(USB_PID_SOF, 0));
-       sl811_write(SL811_DEV_B, 0x00);
-       sl811_write(SL811_SOFLOW, SL811_12M_LOW);
-
-       if (status & SL811_INTR_SPEED_FULL) {
-               /* full speed device connect directly to root hub */
-               PDEBUG (0, "Full speed Device attached\n");
-
-               sl811_write(SL811_CTRL1, SL811_CTRL1_RESET);
-               mdelay(20);
-               sl811_write(SL811_CTRL2, SL811_CTL2_HOST | SL811_12M_HI);
-               sl811_write(SL811_CTRL1, SL811_CTRL1_SOF);
-
-               /* start the SOF or EOP */
-               sl811_write(SL811_CTRL_B, SL811_USB_CTRL_ARM);
-               rh_status.wPortStatus |= USB_PORT_STAT_CONNECTION;
-               rh_status.wPortStatus &= ~USB_PORT_STAT_LOW_SPEED;
-               mdelay(2);
-               sl811_write(SL811_INTRSTS, 0xff);
-       } else {
-               /* slow speed device connect directly to root-hub */
-               PDEBUG(0, "Low speed Device attached\n");
-
-               sl811_write(SL811_CTRL1, SL811_CTRL1_RESET);
-               mdelay(20);
-               sl811_write(SL811_CTRL2, SL811_CTL2_HOST | SL811_CTL2_DSWAP | SL811_12M_HI);
-               sl811_write(SL811_CTRL1, SL811_CTRL1_SPEED_LOW | SL811_CTRL1_SOF);
-
-               /* start the SOF or EOP */
-               sl811_write(SL811_CTRL_B, SL811_USB_CTRL_ARM);
-               rh_status.wPortStatus |= USB_PORT_STAT_CONNECTION | USB_PORT_STAT_LOW_SPEED;
-               mdelay(2);
-               sl811_write(SL811_INTRSTS, 0xff);
-       }
-
-       rh_status.wPortChange |= USB_PORT_STAT_C_CONNECTION;
-       sl811_write(SL811_INTR, /*SL811_INTR_INSRMV*/SL811_INTR_DONE_A);
-
-       return 1;
-}
-
-int usb_lowlevel_init(void)
-{
-       root_hub_devnum = 0;
-       sl811_hc_reset();
-       return 0;
-}
-
-int usb_lowlevel_stop(void)
-{
-       sl811_hc_reset();
-       return 0;
-}
-
-static int calc_needed_buswidth(int bytes, int need_preamble)
-{
-       return !need_preamble ? bytes * 8 + 256 : 8 * 8 * bytes + 2048;
-}
-
-static int sl811_send_packet(struct usb_device *dev, unsigned long pipe, __u8 *buffer, int len)
-{
-       __u8 ctrl = SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE;
-       __u16 status = 0;
-       int err = 0, time_start = get_timer(0);
-       int need_preamble = !(rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED) &&
-               usb_pipeslow(pipe);
-
-       if (len > 239)
-               return -1;
-
-       if (usb_pipeout(pipe))
-               ctrl |= SL811_USB_CTRL_DIR_OUT;
-       if (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)))
-               ctrl |= SL811_USB_CTRL_TOGGLE_1;
-       if (need_preamble)
-               ctrl |= SL811_USB_CTRL_PREAMBLE;
-
-       sl811_write(SL811_INTRSTS, 0xff);
-
-       while (err < 3) {
-               sl811_write(SL811_ADDR_A, 0x10);
-               sl811_write(SL811_LEN_A, len);
-               if (usb_pipeout(pipe) && len)
-                       sl811_write_buf(0x10, buffer, len);
-
-               if (!(rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED) &&
-                   sl811_read(SL811_SOFCNTDIV)*64 < calc_needed_buswidth(len, need_preamble))
-                       ctrl |= SL811_USB_CTRL_SOF;
-               else
-                       ctrl &= ~SL811_USB_CTRL_SOF;
-
-               sl811_write(SL811_CTRL_A, ctrl);
-               while (!(sl811_read(SL811_INTRSTS) & SL811_INTR_DONE_A)) {
-                       if (5*CONFIG_SYS_HZ < get_timer(time_start)) {
-                               printf("USB transmit timed out\n");
-                               return -USB_ST_CRC_ERR;
-                       }
-               }
-
-               sl811_write(SL811_INTRSTS, 0xff);
-               status = sl811_read(SL811_STS_A);
-
-               if (status & SL811_USB_STS_ACK) {
-                       int remainder = sl811_read(SL811_CNT_A);
-                       if (remainder) {
-                               PDEBUG(0, "usb transfer remainder = %d\n", remainder);
-                               len -= remainder;
-                       }
-                       if (usb_pipein(pipe) && len)
-                               sl811_read_buf(0x10, buffer, len);
-                       return len;
-               }
-
-               if ((status & SL811_USB_STS_NAK) == SL811_USB_STS_NAK)
-                       continue;
-
-               PDEBUG(0, "usb transfer error %#x\n", (int)status);
-               err++;
-       }
-
-       err = 0;
-
-       if (status & SL811_USB_STS_ERROR)
-               err |= USB_ST_BUF_ERR;
-       if (status & SL811_USB_STS_TIMEOUT)
-               err |= USB_ST_CRC_ERR;
-       if (status & SL811_USB_STS_STALL)
-               err |= USB_ST_STALLED;
-
-       return -err;
-}
-
-int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-                   int len)
-{
-       int dir_out = usb_pipeout(pipe);
-       int ep = usb_pipeendpoint(pipe);
-       int max = usb_maxpacket(dev, pipe);
-       int done = 0;
-
-       PDEBUG(7, "dev = %ld pipe = %ld buf = %p size = %d dir_out = %d\n",
-              usb_pipedevice(pipe), usb_pipeendpoint(pipe), buffer, len, dir_out);
-
-       dev->status = 0;
-
-       sl811_write(SL811_DEV_A, usb_pipedevice(pipe));
-       sl811_write(SL811_PIDEP_A, PIDEP(!dir_out ? USB_PID_IN : USB_PID_OUT, ep));
-       while (done < len) {
-               int res = sl811_send_packet(dev, pipe, (__u8*)buffer+done,
-                                           max > len - done ? len - done : max);
-               if (res < 0) {
-                       dev->status = -res;
-                       return res;
-               }
-
-               if (!dir_out && res < max) /* short packet */
-                       break;
-
-               done += res;
-               usb_dotoggle(dev, ep, dir_out);
-       }
-
-       dev->act_len = done;
-
-       return 0;
-}
-
-int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-                      int len,struct devrequest *setup)
-{
-       int done = 0;
-       int devnum = usb_pipedevice(pipe);
-       int ep = usb_pipeendpoint(pipe);
-
-       dev->status = 0;
-
-       if (devnum == root_hub_devnum)
-               return sl811_rh_submit_urb(dev, pipe, buffer, len, setup);
-
-       PDEBUG(7, "dev = %d pipe = %ld buf = %p size = %d rt = %#x req = %#x bus = %i\n",
-              devnum, ep, buffer, len, (int)setup->requesttype,
-              (int)setup->request, sl811_read(SL811_SOFCNTDIV)*64);
-
-       sl811_write(SL811_DEV_A, devnum);
-       sl811_write(SL811_PIDEP_A, PIDEP(USB_PID_SETUP, ep));
-       /* setup phase */
-       usb_settoggle(dev, ep, 1, 0);
-       if (sl811_send_packet(dev, usb_sndctrlpipe(dev, ep),
-                             (__u8*)setup, sizeof(*setup)) == sizeof(*setup)) {
-               int dir_in = usb_pipein(pipe);
-               int max = usb_maxpacket(dev, pipe);
-
-               /* data phase */
-               sl811_write(SL811_PIDEP_A,
-                           PIDEP(dir_in ? USB_PID_IN : USB_PID_OUT, ep));
-               usb_settoggle(dev, ep, usb_pipeout(pipe), 1);
-               while (done < len) {
-                       int res = sl811_send_packet(dev, pipe, (__u8*)buffer+done,
-                                                   max > len - done ? len - done : max);
-                       if (res < 0) {
-                               PDEBUG(0, "status data failed!\n");
-                               dev->status = -res;
-                               return 0;
-                       }
-                       done += res;
-                       usb_dotoggle(dev, ep, usb_pipeout(pipe));
-                       if (dir_in && res < max) /* short packet */
-                               break;
-               }
-
-               /* status phase */
-               sl811_write(SL811_PIDEP_A,
-                           PIDEP(!dir_in ? USB_PID_IN : USB_PID_OUT, ep));
-               usb_settoggle(dev, ep, !usb_pipeout(pipe), 1);
-               if (sl811_send_packet(dev,
-                                     !dir_in ? usb_rcvctrlpipe(dev, ep) :
-                                     usb_sndctrlpipe(dev, ep),
-                                     0, 0) < 0) {
-                       PDEBUG(0, "status phase failed!\n");
-                       dev->status = -1;
-               }
-       } else {
-               PDEBUG(0, "setup phase failed!\n");
-               dev->status = -1;
-       }
-
-       dev->act_len = done;
-
-       return done;
-}
-
-int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-                  int len, int interval)
-{
-       PDEBUG(0, "dev = %p pipe = %#lx buf = %p size = %d int = %d\n", dev, pipe,
-              buffer, len, interval);
-       return -1;
-}
-
-/*
- * SL811 Virtual Root Hub
- */
-
-/* Device descriptor */
-static __u8 sl811_rh_dev_des[] =
-{
-       0x12,       /*  __u8  bLength; */
-       0x01,       /*  __u8  bDescriptorType; Device */
-       0x10,       /*  __u16 bcdUSB; v1.1 */
-       0x01,
-       0x09,       /*  __u8  bDeviceClass; HUB_CLASSCODE */
-       0x00,       /*  __u8  bDeviceSubClass; */
-       0x00,       /*  __u8  bDeviceProtocol; */
-       0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
-       0x00,       /*  __u16 idVendor; */
-       0x00,
-       0x00,       /*  __u16 idProduct; */
-       0x00,
-       0x00,       /*  __u16 bcdDevice; */
-       0x00,
-       0x00,       /*  __u8  iManufacturer; */
-       0x02,       /*  __u8  iProduct; */
-       0x01,       /*  __u8  iSerialNumber; */
-       0x01        /*  __u8  bNumConfigurations; */
-};
-
-/* Configuration descriptor */
-static __u8 sl811_rh_config_des[] =
-{
-       0x09,       /*  __u8  bLength; */
-       0x02,       /*  __u8  bDescriptorType; Configuration */
-       0x19,       /*  __u16 wTotalLength; */
-       0x00,
-       0x01,       /*  __u8  bNumInterfaces; */
-       0x01,       /*  __u8  bConfigurationValue; */
-       0x00,       /*  __u8  iConfiguration; */
-       0x40,       /*  __u8  bmAttributes;
-                   Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup,
-                   4..0: resvd */
-       0x00,       /*  __u8  MaxPower; */
-
-       /* interface */
-       0x09,       /*  __u8  if_bLength; */
-       0x04,       /*  __u8  if_bDescriptorType; Interface */
-       0x00,       /*  __u8  if_bInterfaceNumber; */
-       0x00,       /*  __u8  if_bAlternateSetting; */
-       0x01,       /*  __u8  if_bNumEndpoints; */
-       0x09,       /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
-       0x00,       /*  __u8  if_bInterfaceSubClass; */
-       0x00,       /*  __u8  if_bInterfaceProtocol; */
-       0x00,       /*  __u8  if_iInterface; */
-
-       /* endpoint */
-       0x07,       /*  __u8  ep_bLength; */
-       0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
-       0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
-       0x03,       /*  __u8  ep_bmAttributes; Interrupt */
-       0x08,       /*  __u16 ep_wMaxPacketSize; */
-       0x00,
-       0xff        /*  __u8  ep_bInterval; 255 ms */
-};
-
-/* root hub class descriptor*/
-static __u8 sl811_rh_hub_des[] =
-{
-       0x09,                   /*  __u8  bLength; */
-       0x29,                   /*  __u8  bDescriptorType; Hub-descriptor */
-       0x01,                   /*  __u8  bNbrPorts; */
-       0x00,                   /* __u16  wHubCharacteristics; */
-       0x00,
-       0x50,                   /*  __u8  bPwrOn2pwrGood; 2ms */
-       0x00,                   /*  __u8  bHubContrCurrent; 0 mA */
-       0xfc,                   /*  __u8  DeviceRemovable; *** 7 Ports max *** */
-       0xff                    /*  __u8  PortPwrCtrlMask; *** 7 ports max *** */
-};
-
-/*
- * helper routine for returning string descriptors in UTF-16LE
- * input can actually be ISO-8859-1; ASCII is its 7-bit subset
- */
-static int ascii2utf (char *s, u8 *utf, int utfmax)
-{
-       int retval;
-
-       for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) {
-               *utf++ = *s++;
-               *utf++ = 0;
-       }
-       return retval;
-}
-
-/*
- * root_hub_string is used by each host controller's root hub code,
- * so that they're identified consistently throughout the system.
- */
-static int usb_root_hub_string (int id, int serial, char *type, __u8 *data, int len)
-{
-       char buf [30];
-
-       /* assert (len > (2 * (sizeof (buf) + 1)));
-          assert (strlen (type) <= 8);*/
-
-       /* language ids */
-       if (id == 0) {
-               *data++ = 4; *data++ = 3;       /* 4 bytes data */
-               *data++ = 0; *data++ = 0;       /* some language id */
-               return 4;
-
-       /* serial number */
-       } else if (id == 1) {
-               sprintf (buf, "%#x", serial);
-
-       /* product description */
-       } else if (id == 2) {
-               sprintf (buf, "USB %s Root Hub", type);
-
-       /* id 3 == vendor description */
-
-       /* unsupported IDs --> "stall" */
-       } else
-           return 0;
-
-       ascii2utf (buf, data + 2, len - 2);
-       data [0] = 2 + strlen(buf) * 2;
-       data [1] = 3;
-       return data [0];
-}
-
-/* helper macro */
-#define OK(x)  len = (x); break
-
-/*
- * This function handles all USB request to the the virtual root hub
- */
-static int sl811_rh_submit_urb(struct usb_device *usb_dev, unsigned long pipe,
-                              void *data, int buf_len, struct devrequest *cmd)
-{
-       __u8 data_buf[16];
-       __u8 *bufp = data_buf;
-       int len = 0;
-       int status = 0;
-
-       __u16 bmRType_bReq;
-       __u16 wValue;
-       __u16 wIndex;
-       __u16 wLength;
-
-       if (usb_pipeint(pipe)) {
-               PDEBUG(0, "interrupt transfer unimplemented!\n");
-               return 0;
-       }
-
-       bmRType_bReq  = cmd->requesttype | (cmd->request << 8);
-       wValue        = le16_to_cpu (cmd->value);
-       wIndex        = le16_to_cpu (cmd->index);
-       wLength       = le16_to_cpu (cmd->length);
-
-       PDEBUG(5, "submit rh urb, req = %d(%x) val = %#x index = %#x len=%d\n",
-              bmRType_bReq, bmRType_bReq, wValue, wIndex, wLength);
-
-       /* Request Destination:
-                  without flags: Device,
-                  USB_RECIP_INTERFACE: interface,
-                  USB_RECIP_ENDPOINT: endpoint,
-                  USB_TYPE_CLASS means HUB here,
-                  USB_RECIP_OTHER | USB_TYPE_CLASS  almost ever means HUB_PORT here
-       */
-       switch (bmRType_bReq) {
-       case RH_GET_STATUS:
-               *(__u16 *)bufp = cpu_to_le16(1);
-               OK(2);
-
-       case RH_GET_STATUS | USB_RECIP_INTERFACE:
-               *(__u16 *)bufp = cpu_to_le16(0);
-               OK(2);
-
-       case RH_GET_STATUS | USB_RECIP_ENDPOINT:
-               *(__u16 *)bufp = cpu_to_le16(0);
-               OK(2);
-
-       case RH_GET_STATUS | USB_TYPE_CLASS:
-               *(__u32 *)bufp = cpu_to_le32(0);
-               OK(4);
-
-       case RH_GET_STATUS | USB_RECIP_OTHER | USB_TYPE_CLASS:
-               *(__u32 *)bufp = cpu_to_le32(rh_status.wPortChange<<16 | rh_status.wPortStatus);
-               OK(4);
-
-       case RH_CLEAR_FEATURE | USB_RECIP_ENDPOINT:
-               switch (wValue) {
-               case 1:
-                       OK(0);
-               }
-               break;
-
-       case RH_CLEAR_FEATURE | USB_TYPE_CLASS:
-               switch (wValue) {
-               case C_HUB_LOCAL_POWER:
-                       OK(0);
-
-               case C_HUB_OVER_CURRENT:
-                       OK(0);
-               }
-               break;
-
-       case RH_CLEAR_FEATURE | USB_RECIP_OTHER | USB_TYPE_CLASS:
-               switch (wValue) {
-               case USB_PORT_FEAT_ENABLE:
-                       rh_status.wPortStatus &= ~USB_PORT_STAT_ENABLE;
-                       OK(0);
-
-               case USB_PORT_FEAT_SUSPEND:
-                       rh_status.wPortStatus &= ~USB_PORT_STAT_SUSPEND;
-                       OK(0);
-
-               case USB_PORT_FEAT_POWER:
-                       rh_status.wPortStatus &= ~USB_PORT_STAT_POWER;
-                       OK(0);
-
-               case USB_PORT_FEAT_C_CONNECTION:
-                       rh_status.wPortChange &= ~USB_PORT_STAT_C_CONNECTION;
-                       OK(0);
-
-               case USB_PORT_FEAT_C_ENABLE:
-                       rh_status.wPortChange &= ~USB_PORT_STAT_C_ENABLE;
-                       OK(0);
-
-               case USB_PORT_FEAT_C_SUSPEND:
-                       rh_status.wPortChange &= ~USB_PORT_STAT_C_SUSPEND;
-                       OK(0);
-
-               case USB_PORT_FEAT_C_OVER_CURRENT:
-                       rh_status.wPortChange &= ~USB_PORT_STAT_C_OVERCURRENT;
-                       OK(0);
-
-               case USB_PORT_FEAT_C_RESET:
-                       rh_status.wPortChange &= ~USB_PORT_STAT_C_RESET;
-                       OK(0);
-               }
-               break;
-
-       case RH_SET_FEATURE | USB_RECIP_OTHER | USB_TYPE_CLASS:
-               switch (wValue) {
-               case USB_PORT_FEAT_SUSPEND:
-                       rh_status.wPortStatus |= USB_PORT_STAT_SUSPEND;
-                       OK(0);
-
-               case USB_PORT_FEAT_RESET:
-                       rh_status.wPortStatus |= USB_PORT_STAT_RESET;
-                       rh_status.wPortChange = 0;
-                       rh_status.wPortChange |= USB_PORT_STAT_C_RESET;
-                       rh_status.wPortStatus &= ~USB_PORT_STAT_RESET;
-                       rh_status.wPortStatus |= USB_PORT_STAT_ENABLE;
-                       OK(0);
-
-               case USB_PORT_FEAT_POWER:
-                       rh_status.wPortStatus |= USB_PORT_STAT_POWER;
-                       OK(0);
-
-               case USB_PORT_FEAT_ENABLE:
-                       rh_status.wPortStatus |= USB_PORT_STAT_ENABLE;
-                       OK(0);
-               }
-               break;
-
-       case RH_SET_ADDRESS:
-               root_hub_devnum = wValue;
-               OK(0);
-
-       case RH_GET_DESCRIPTOR:
-               switch ((wValue & 0xff00) >> 8) {
-               case USB_DT_DEVICE:
-                       len = sizeof(sl811_rh_dev_des);
-                       bufp = sl811_rh_dev_des;
-                       OK(len);
-
-               case USB_DT_CONFIG:
-                       len = sizeof(sl811_rh_config_des);
-                       bufp = sl811_rh_config_des;
-                       OK(len);
-
-               case USB_DT_STRING:
-                       len = usb_root_hub_string(wValue & 0xff, (int)(long)0,  "SL811HS", data, wLength);
-                       if (len > 0) {
-                               bufp = data;
-                               OK(len);
-                       }
-
-               default:
-                       status = -32;
-               }
-               break;
-
-       case RH_GET_DESCRIPTOR | USB_TYPE_CLASS:
-               len = sizeof(sl811_rh_hub_des);
-               bufp = sl811_rh_hub_des;
-               OK(len);
-
-       case RH_GET_CONFIGURATION:
-               bufp[0] = 0x01;
-               OK(1);
-
-       case RH_SET_CONFIGURATION:
-               OK(0);
-
-       default:
-               PDEBUG(1, "unsupported root hub command\n");
-               status = -32;
-       }
-
-       len = min(len, buf_len);
-       if (data != bufp)
-               memcpy(data, bufp, len);
-
-       PDEBUG(5, "len = %d, status = %d\n", len, status);
-
-       usb_dev->status = status;
-       usb_dev->act_len = len;
-
-       return status == 0 ? len : status;
-}
diff --git a/drivers/usb/usb_ehci.h b/drivers/usb/usb_ehci.h
deleted file mode 100644 (file)
index b3c1d5d..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-/*-
- * Copyright (c) 2007-2008, Juniper Networks, Inc.
- * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it>
- * All rights reserved.
- *
- * 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 version 2 of
- * the License.
- *
- * 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_EHCI_H
-#define USB_EHCI_H
-
-#if !defined(CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS)
-#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS     2
-#endif
-
-/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */
-#define DeviceRequest \
-       ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE) << 8)
-
-#define DeviceOutRequest \
-       ((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE) << 8)
-
-#define InterfaceRequest \
-       ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
-
-#define EndpointRequest \
-       ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
-
-#define EndpointOutRequest \
-       ((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
-
-/*
- * Register Space.
- */
-struct ehci_hccr {
-       uint32_t cr_capbase;
-#define HC_LENGTH(p)           (((p) >> 0) & 0x00ff)
-#define HC_VERSION(p)          (((p) >> 16) & 0xffff)
-       uint32_t cr_hcsparams;
-#define HCS_PPC(p)             ((p) & (1 << 4))
-#define HCS_INDICATOR(p)       ((p) & (1 << 16)) /* Port indicators */
-#define HCS_N_PORTS(p)         (((p) >> 0) & 0xf)
-       uint32_t cr_hccparams;
-       uint8_t cr_hcsp_portrt[8];
-} __attribute__ ((packed));
-
-struct ehci_hcor {
-       uint32_t or_usbcmd;
-#define CMD_PARK       (1 << 11)               /* enable "park" */
-#define CMD_PARK_CNT(c)        (((c) >> 8) & 3)        /* how many transfers to park */
-#define CMD_ASE                (1 << 5)                /* async schedule enable */
-#define CMD_LRESET     (1 << 7)                /* partial reset */
-#define CMD_IAAD       (1 << 5)                /* "doorbell" interrupt */
-#define CMD_PSE                (1 << 4)                /* periodic schedule enable */
-#define CMD_RESET      (1 << 1)                /* reset HC not bus */
-#define CMD_RUN                (1 << 0)                /* start/stop HC */
-       uint32_t or_usbsts;
-#define        STD_ASS         (1 << 15)
-#define STS_HALT       (1 << 12)
-       uint32_t or_usbintr;
-       uint32_t or_frindex;
-       uint32_t or_ctrldssegment;
-       uint32_t or_periodiclistbase;
-       uint32_t or_asynclistaddr;
-       uint32_t _reserved_[9];
-       uint32_t or_configflag;
-#define FLAG_CF                (1 << 0)        /* true:  we'll support "high speed" */
-       uint32_t or_portsc[CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS];
-       uint32_t or_systune;
-} __attribute__ ((packed));
-
-#define USBMODE                0x68            /* USB Device mode */
-#define USBMODE_SDIS   (1 << 3)        /* Stream disable */
-#define USBMODE_BE     (1 << 2)        /* BE/LE endiannes select */
-#define USBMODE_CM_HC  (3 << 0)        /* host controller mode */
-#define USBMODE_CM_IDLE        (0 << 0)        /* idle state */
-
-/* Interface descriptor */
-struct usb_linux_interface_descriptor {
-       unsigned char   bLength;
-       unsigned char   bDescriptorType;
-       unsigned char   bInterfaceNumber;
-       unsigned char   bAlternateSetting;
-       unsigned char   bNumEndpoints;
-       unsigned char   bInterfaceClass;
-       unsigned char   bInterfaceSubClass;
-       unsigned char   bInterfaceProtocol;
-       unsigned char   iInterface;
-} __attribute__ ((packed));
-
-/* Configuration descriptor information.. */
-struct usb_linux_config_descriptor {
-       unsigned char   bLength;
-       unsigned char   bDescriptorType;
-       unsigned short  wTotalLength;
-       unsigned char   bNumInterfaces;
-       unsigned char   bConfigurationValue;
-       unsigned char   iConfiguration;
-       unsigned char   bmAttributes;
-       unsigned char   MaxPower;
-} __attribute__ ((packed));
-
-#if defined CONFIG_EHCI_DESC_BIG_ENDIAN
-#define        ehci_readl(x)           (*((volatile u32 *)(x)))
-#define ehci_writel(a, b)      (*((volatile u32 *)(a)) = ((volatile u32)b))
-#else
-#define ehci_readl(x)          cpu_to_le32((*((volatile u32 *)(x))))
-#define ehci_writel(a, b)      (*((volatile u32 *)(a)) = \
-                                       cpu_to_le32(((volatile u32)b)))
-#endif
-
-#if defined CONFIG_EHCI_MMIO_BIG_ENDIAN
-#define hc32_to_cpu(x)         be32_to_cpu((x))
-#define cpu_to_hc32(x)         cpu_to_be32((x))
-#else
-#define hc32_to_cpu(x)         le32_to_cpu((x))
-#define cpu_to_hc32(x)         cpu_to_le32((x))
-#endif
-
-#define EHCI_PS_WKOC_E         (1 << 22)       /* RW wake on over current */
-#define EHCI_PS_WKDSCNNT_E     (1 << 21)       /* RW wake on disconnect */
-#define EHCI_PS_WKCNNT_E       (1 << 20)       /* RW wake on connect */
-#define EHCI_PS_PO             (1 << 13)       /* RW port owner */
-#define EHCI_PS_PP             (1 << 12)       /* RW,RO port power */
-#define EHCI_PS_LS             (3 << 10)       /* RO line status */
-#define EHCI_PS_PR             (1 << 8)        /* RW port reset */
-#define EHCI_PS_SUSP           (1 << 7)        /* RW suspend */
-#define EHCI_PS_FPR            (1 << 6)        /* RW force port resume */
-#define EHCI_PS_OCC            (1 << 5)        /* RWC over current change */
-#define EHCI_PS_OCA            (1 << 4)        /* RO over current active */
-#define EHCI_PS_PEC            (1 << 3)        /* RWC port enable change */
-#define EHCI_PS_PE             (1 << 2)        /* RW port enable */
-#define EHCI_PS_CSC            (1 << 1)        /* RWC connect status change */
-#define EHCI_PS_CS             (1 << 0)        /* RO connect status */
-#define EHCI_PS_CLEAR          (EHCI_PS_OCC | EHCI_PS_PEC | EHCI_PS_CSC)
-
-#define EHCI_PS_IS_LOWSPEED(x) (((x) & EHCI_PS_LS) == (1 << 10))
-
-/*
- * Schedule Interface Space.
- *
- * IMPORTANT: Software must ensure that no interface data structure
- * reachable by the EHCI host controller spans a 4K page boundary!
- *
- * Periodic transfers (i.e. isochronous and interrupt transfers) are
- * not supported.
- */
-
-/* Queue Element Transfer Descriptor (qTD). */
-struct qTD {
-       uint32_t qt_next;
-#define        QT_NEXT_TERMINATE       1
-       uint32_t qt_altnext;
-       uint32_t qt_token;
-       uint32_t qt_buffer[5];
-};
-
-/* Queue Head (QH). */
-struct QH {
-       uint32_t qh_link;
-#define        QH_LINK_TERMINATE       1
-#define        QH_LINK_TYPE_ITD        0
-#define        QH_LINK_TYPE_QH         2
-#define        QH_LINK_TYPE_SITD       4
-#define        QH_LINK_TYPE_FSTN       6
-       uint32_t qh_endpt1;
-       uint32_t qh_endpt2;
-       uint32_t qh_curtd;
-       struct qTD qh_overlay;
-       /*
-        * Add dummy fill value to make the size of this struct
-        * aligned to 32 bytes
-        */
-       uint8_t fill[16];
-};
-
-/* Low level init functions */
-int ehci_hcd_init(void);
-int ehci_hcd_stop(void);
-
-#endif /* USB_EHCI_H */
diff --git a/drivers/usb/usb_ehci_core.c b/drivers/usb/usb_ehci_core.c
deleted file mode 100644 (file)
index 4dbfb66..0000000
+++ /dev/null
@@ -1,882 +0,0 @@
-/*-
- * Copyright (c) 2007-2008, Juniper Networks, Inc.
- * Copyright (c) 2008, Excito Elektronik i SkÃ¥ne AB
- * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it>
- *
- * All rights reserved.
- *
- * 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 version 2 of
- * the License.
- *
- * 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 <asm/byteorder.h>
-#include <usb.h>
-#include <asm/io.h>
-#include <malloc.h>
-#include "usb_ehci.h"
-
-int rootdev;
-struct ehci_hccr *hccr;        /* R/O registers, not need for volatile */
-volatile struct ehci_hcor *hcor;
-
-static uint16_t portreset;
-static struct QH qh_list __attribute__((aligned(32)));
-
-static struct descriptor {
-       struct usb_hub_descriptor hub;
-       struct usb_device_descriptor device;
-       struct usb_linux_config_descriptor config;
-       struct usb_linux_interface_descriptor interface;
-       struct usb_endpoint_descriptor endpoint;
-}  __attribute__ ((packed)) descriptor = {
-       {
-               0x8,            /* bDescLength */
-               0x29,           /* bDescriptorType: hub descriptor */
-               2,              /* bNrPorts -- runtime modified */
-               0,              /* wHubCharacteristics */
-               0xff,           /* bPwrOn2PwrGood */
-               0,              /* bHubCntrCurrent */
-               {},             /* Device removable */
-               {}              /* at most 7 ports! XXX */
-       },
-       {
-               0x12,           /* bLength */
-               1,              /* bDescriptorType: UDESC_DEVICE */
-               0x0002,         /* bcdUSB: v2.0 */
-               9,              /* bDeviceClass: UDCLASS_HUB */
-               0,              /* bDeviceSubClass: UDSUBCLASS_HUB */
-               1,              /* bDeviceProtocol: UDPROTO_HSHUBSTT */
-               64,             /* bMaxPacketSize: 64 bytes */
-               0x0000,         /* idVendor */
-               0x0000,         /* idProduct */
-               0x0001,         /* bcdDevice */
-               1,              /* iManufacturer */
-               2,              /* iProduct */
-               0,              /* iSerialNumber */
-               1               /* bNumConfigurations: 1 */
-       },
-       {
-               0x9,
-               2,              /* bDescriptorType: UDESC_CONFIG */
-               cpu_to_le16(0x19),
-               1,              /* bNumInterface */
-               1,              /* bConfigurationValue */
-               0,              /* iConfiguration */
-               0x40,           /* bmAttributes: UC_SELF_POWER */
-               0               /* bMaxPower */
-       },
-       {
-               0x9,            /* bLength */
-               4,              /* bDescriptorType: UDESC_INTERFACE */
-               0,              /* bInterfaceNumber */
-               0,              /* bAlternateSetting */
-               1,              /* bNumEndpoints */
-               9,              /* bInterfaceClass: UICLASS_HUB */
-               0,              /* bInterfaceSubClass: UISUBCLASS_HUB */
-               0,              /* bInterfaceProtocol: UIPROTO_HSHUBSTT */
-               0               /* iInterface */
-       },
-       {
-               0x7,            /* bLength */
-               5,              /* bDescriptorType: UDESC_ENDPOINT */
-               0x81,           /* bEndpointAddress:
-                                * UE_DIR_IN | EHCI_INTR_ENDPT
-                                */
-               3,              /* bmAttributes: UE_INTERRUPT */
-               8, 0,           /* wMaxPacketSize */
-               255             /* bInterval */
-       },
-};
-
-#if defined(CONFIG_EHCI_IS_TDI)
-#define ehci_is_TDI()  (1)
-#else
-#define ehci_is_TDI()  (0)
-#endif
-
-#if defined(CONFIG_EHCI_DCACHE)
-/*
- * Routines to handle (flush/invalidate) the dcache for the QH and qTD
- * structures and data buffers. This is needed on platforms using this
- * EHCI support with dcache enabled.
- */
-static void flush_invalidate(u32 addr, int size, int flush)
-{
-       if (flush)
-               flush_dcache_range(addr, addr + size);
-       else
-               invalidate_dcache_range(addr, addr + size);
-}
-
-static void cache_qtd(struct qTD *qtd, int flush)
-{
-       u32 *ptr = (u32 *)qtd->qt_buffer[0];
-       int len = (qtd->qt_token & 0x7fff0000) >> 16;
-
-       flush_invalidate((u32)qtd, sizeof(struct qTD), flush);
-       if (ptr && len)
-               flush_invalidate((u32)ptr, len, flush);
-}
-
-
-static inline struct QH *qh_addr(struct QH *qh)
-{
-       return (struct QH *)((u32)qh & 0xffffffe0);
-}
-
-static void cache_qh(struct QH *qh, int flush)
-{
-       struct qTD *qtd;
-       struct qTD *next;
-       static struct qTD *first_qtd;
-
-       /*
-        * Walk the QH list and flush/invalidate all entries
-        */
-       while (1) {
-               flush_invalidate((u32)qh_addr(qh), sizeof(struct QH), flush);
-               if ((u32)qh & QH_LINK_TYPE_QH)
-                       break;
-               qh = qh_addr(qh);
-               qh = (struct QH *)qh->qh_link;
-       }
-       qh = qh_addr(qh);
-
-       /*
-        * Save first qTD pointer, needed for invalidating pass on this QH
-        */
-       if (flush)
-               first_qtd = qtd = (struct qTD *)(*(u32 *)&qh->qh_overlay &
-                                                0xffffffe0);
-       else
-               qtd = first_qtd;
-
-       /*
-        * Walk the qTD list and flush/invalidate all entries
-        */
-       while (1) {
-               if (qtd == NULL)
-                       break;
-               cache_qtd(qtd, flush);
-               next = (struct qTD *)((u32)qtd->qt_next & 0xffffffe0);
-               if (next == qtd)
-                       break;
-               qtd = next;
-       }
-}
-
-static inline void ehci_flush_dcache(struct QH *qh)
-{
-       cache_qh(qh, 1);
-}
-
-static inline void ehci_invalidate_dcache(struct QH *qh)
-{
-       cache_qh(qh, 0);
-}
-#else /* CONFIG_EHCI_DCACHE */
-/*
- *
- */
-static inline void ehci_flush_dcache(struct QH *qh)
-{
-}
-
-static inline void ehci_invalidate_dcache(struct QH *qh)
-{
-}
-#endif /* CONFIG_EHCI_DCACHE */
-
-static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec)
-{
-       uint32_t result;
-       do {
-               result = ehci_readl(ptr);
-               if (result == ~(uint32_t)0)
-                       return -1;
-               result &= mask;
-               if (result == done)
-                       return 0;
-               udelay(1);
-               usec--;
-       } while (usec > 0);
-       return -1;
-}
-
-static void ehci_free(void *p, size_t sz)
-{
-
-}
-
-static int ehci_reset(void)
-{
-       uint32_t cmd;
-       uint32_t tmp;
-       uint32_t *reg_ptr;
-       int ret = 0;
-
-       cmd = ehci_readl(&hcor->or_usbcmd);
-       cmd |= CMD_RESET;
-       ehci_writel(&hcor->or_usbcmd, cmd);
-       ret = handshake((uint32_t *)&hcor->or_usbcmd, CMD_RESET, 0, 250 * 1000);
-       if (ret < 0) {
-               printf("EHCI fail to reset\n");
-               goto out;
-       }
-
-       if (ehci_is_TDI()) {
-               reg_ptr = (uint32_t *)((u8 *)hcor + USBMODE);
-               tmp = ehci_readl(reg_ptr);
-               tmp |= USBMODE_CM_HC;
-#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN)
-               tmp |= USBMODE_BE;
-#endif
-               ehci_writel(reg_ptr, tmp);
-       }
-out:
-       return ret;
-}
-
-static void *ehci_alloc(size_t sz, size_t align)
-{
-       static struct QH qh __attribute__((aligned(32)));
-       static struct qTD td[3] __attribute__((aligned (32)));
-       static int ntds;
-       void *p;
-
-       switch (sz) {
-       case sizeof(struct QH):
-               p = &qh;
-               ntds = 0;
-               break;
-       case sizeof(struct qTD):
-               if (ntds == 3) {
-                       debug("out of TDs\n");
-                       return NULL;
-               }
-               p = &td[ntds];
-               ntds++;
-               break;
-       default:
-               debug("unknown allocation size\n");
-               return NULL;
-       }
-
-       memset(p, sz, 0);
-       return p;
-}
-
-static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
-{
-       uint32_t addr, delta, next;
-       int idx;
-
-       addr = (uint32_t) buf;
-       idx = 0;
-       while (idx < 5) {
-               td->qt_buffer[idx] = cpu_to_hc32(addr);
-               next = (addr + 4096) & ~4095;
-               delta = next - addr;
-               if (delta >= sz)
-                       break;
-               sz -= delta;
-               addr = next;
-               idx++;
-       }
-
-       if (idx == 5) {
-               debug("out of buffer pointers (%u bytes left)\n", sz);
-               return -1;
-       }
-
-       return 0;
-}
-
-static int
-ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
-                  int length, struct devrequest *req)
-{
-       struct QH *qh;
-       struct qTD *td;
-       volatile struct qTD *vtd;
-       unsigned long ts;
-       uint32_t *tdp;
-       uint32_t endpt, token, usbsts;
-       uint32_t c, toggle;
-       uint32_t cmd;
-       int ret = 0;
-
-       debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe,
-             buffer, length, req);
-       if (req != NULL)
-               debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n",
-                     req->request, req->request,
-                     req->requesttype, req->requesttype,
-                     le16_to_cpu(req->value), le16_to_cpu(req->value),
-                     le16_to_cpu(req->index));
-
-       qh = ehci_alloc(sizeof(struct QH), 32);
-       if (qh == NULL) {
-               debug("unable to allocate QH\n");
-               return -1;
-       }
-       qh->qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH);
-       c = (usb_pipespeed(pipe) != USB_SPEED_HIGH &&
-            usb_pipeendpoint(pipe) == 0) ? 1 : 0;
-       endpt = (8 << 28) |
-           (c << 27) |
-           (usb_maxpacket(dev, pipe) << 16) |
-           (0 << 15) |
-           (1 << 14) |
-           (usb_pipespeed(pipe) << 12) |
-           (usb_pipeendpoint(pipe) << 8) |
-           (0 << 7) | (usb_pipedevice(pipe) << 0);
-       qh->qh_endpt1 = cpu_to_hc32(endpt);
-       endpt = (1 << 30) |
-           (dev->portnr << 23) |
-           (dev->parent->devnum << 16) | (0 << 8) | (0 << 0);
-       qh->qh_endpt2 = cpu_to_hc32(endpt);
-       qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
-       qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
-
-       td = NULL;
-       tdp = &qh->qh_overlay.qt_next;
-
-       toggle =
-           usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
-
-       if (req != NULL) {
-               td = ehci_alloc(sizeof(struct qTD), 32);
-               if (td == NULL) {
-                       debug("unable to allocate SETUP td\n");
-                       goto fail;
-               }
-               td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
-               td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
-               token = (0 << 31) |
-                   (sizeof(*req) << 16) |
-                   (0 << 15) | (0 << 12) | (3 << 10) | (2 << 8) | (0x80 << 0);
-               td->qt_token = cpu_to_hc32(token);
-               if (ehci_td_buffer(td, req, sizeof(*req)) != 0) {
-                       debug("unable construct SETUP td\n");
-                       ehci_free(td, sizeof(*td));
-                       goto fail;
-               }
-               *tdp = cpu_to_hc32((uint32_t) td);
-               tdp = &td->qt_next;
-               toggle = 1;
-       }
-
-       if (length > 0 || req == NULL) {
-               td = ehci_alloc(sizeof(struct qTD), 32);
-               if (td == NULL) {
-                       debug("unable to allocate DATA td\n");
-                       goto fail;
-               }
-               td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
-               td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
-               token = (toggle << 31) |
-                   (length << 16) |
-                   ((req == NULL ? 1 : 0) << 15) |
-                   (0 << 12) |
-                   (3 << 10) |
-                   ((usb_pipein(pipe) ? 1 : 0) << 8) | (0x80 << 0);
-               td->qt_token = cpu_to_hc32(token);
-               if (ehci_td_buffer(td, buffer, length) != 0) {
-                       debug("unable construct DATA td\n");
-                       ehci_free(td, sizeof(*td));
-                       goto fail;
-               }
-               *tdp = cpu_to_hc32((uint32_t) td);
-               tdp = &td->qt_next;
-       }
-
-       if (req != NULL) {
-               td = ehci_alloc(sizeof(struct qTD), 32);
-               if (td == NULL) {
-                       debug("unable to allocate ACK td\n");
-                       goto fail;
-               }
-               td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
-               td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
-               token = (toggle << 31) |
-                   (0 << 16) |
-                   (1 << 15) |
-                   (0 << 12) |
-                   (3 << 10) |
-                   ((usb_pipein(pipe) ? 0 : 1) << 8) | (0x80 << 0);
-               td->qt_token = cpu_to_hc32(token);
-               *tdp = cpu_to_hc32((uint32_t) td);
-               tdp = &td->qt_next;
-       }
-
-       qh_list.qh_link = cpu_to_hc32((uint32_t) qh | QH_LINK_TYPE_QH);
-
-       /* Flush dcache */
-       ehci_flush_dcache(&qh_list);
-
-       usbsts = ehci_readl(&hcor->or_usbsts);
-       ehci_writel(&hcor->or_usbsts, (usbsts & 0x3f));
-
-       /* Enable async. schedule. */
-       cmd = ehci_readl(&hcor->or_usbcmd);
-       cmd |= CMD_ASE;
-       ehci_writel(&hcor->or_usbcmd, cmd);
-
-       ret = handshake((uint32_t *)&hcor->or_usbsts, STD_ASS, STD_ASS,
-                       100 * 1000);
-       if (ret < 0) {
-               printf("EHCI fail timeout STD_ASS set\n");
-               goto fail;
-       }
-
-       /* Wait for TDs to be processed. */
-       ts = get_timer(0);
-       vtd = td;
-       do {
-               /* Invalidate dcache */
-               ehci_invalidate_dcache(&qh_list);
-               token = hc32_to_cpu(vtd->qt_token);
-               if (!(token & 0x80))
-                       break;
-       } while (get_timer(ts) < CONFIG_SYS_HZ);
-
-       /* Disable async schedule. */
-       cmd = ehci_readl(&hcor->or_usbcmd);
-       cmd &= ~CMD_ASE;
-       ehci_writel(&hcor->or_usbcmd, cmd);
-
-       ret = handshake((uint32_t *)&hcor->or_usbsts, STD_ASS, 0,
-                       100 * 1000);
-       if (ret < 0) {
-               printf("EHCI fail timeout STD_ASS reset\n");
-               goto fail;
-       }
-
-       qh_list.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH);
-
-       token = hc32_to_cpu(qh->qh_overlay.qt_token);
-       if (!(token & 0x80)) {
-               debug("TOKEN=%#x\n", token);
-               switch (token & 0xfc) {
-               case 0:
-                       toggle = token >> 31;
-                       usb_settoggle(dev, usb_pipeendpoint(pipe),
-                                      usb_pipeout(pipe), toggle);
-                       dev->status = 0;
-                       break;
-               case 0x40:
-                       dev->status = USB_ST_STALLED;
-                       break;
-               case 0xa0:
-               case 0x20:
-                       dev->status = USB_ST_BUF_ERR;
-                       break;
-               case 0x50:
-               case 0x10:
-                       dev->status = USB_ST_BABBLE_DET;
-                       break;
-               default:
-                       dev->status = USB_ST_CRC_ERR;
-                       break;
-               }
-               dev->act_len = length - ((token >> 16) & 0x7fff);
-       } else {
-               dev->act_len = 0;
-               debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n",
-                     dev->devnum, ehci_readl(&hcor->or_usbsts),
-                     ehci_readl(&hcor->or_portsc[0]),
-                     ehci_readl(&hcor->or_portsc[1]));
-       }
-
-       return (dev->status != USB_ST_NOT_PROC) ? 0 : -1;
-
-fail:
-       td = (void *)hc32_to_cpu(qh->qh_overlay.qt_next);
-       while (td != (void *)QT_NEXT_TERMINATE) {
-               qh->qh_overlay.qt_next = td->qt_next;
-               ehci_free(td, sizeof(*td));
-               td = (void *)hc32_to_cpu(qh->qh_overlay.qt_next);
-       }
-       ehci_free(qh, sizeof(*qh));
-       return -1;
-}
-
-static inline int min3(int a, int b, int c)
-{
-
-       if (b < a)
-               a = b;
-       if (c < a)
-               a = c;
-       return a;
-}
-
-int
-ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
-                int length, struct devrequest *req)
-{
-       uint8_t tmpbuf[4];
-       u16 typeReq;
-       void *srcptr = NULL;
-       int len, srclen;
-       uint32_t reg;
-       uint32_t *status_reg;
-
-       if (le16_to_cpu(req->index) >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) {
-               printf("The request port(%d) is not configured\n",
-                       le16_to_cpu(req->index) - 1);
-               return -1;
-       }
-       status_reg = (uint32_t *)&hcor->or_portsc[
-                                               le16_to_cpu(req->index) - 1];
-       srclen = 0;
-
-       debug("req=%u (%#x), type=%u (%#x), value=%u, index=%u\n",
-             req->request, req->request,
-             req->requesttype, req->requesttype,
-             le16_to_cpu(req->value), le16_to_cpu(req->index));
-
-       typeReq = req->request << 8 | req->requesttype;
-
-       switch (le16_to_cpu(typeReq)) {
-       case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
-               switch (le16_to_cpu(req->value) >> 8) {
-               case USB_DT_DEVICE:
-                       debug("USB_DT_DEVICE request\n");
-                       srcptr = &descriptor.device;
-                       srclen = 0x12;
-                       break;
-               case USB_DT_CONFIG:
-                       debug("USB_DT_CONFIG config\n");
-                       srcptr = &descriptor.config;
-                       srclen = 0x19;
-                       break;
-               case USB_DT_STRING:
-                       debug("USB_DT_STRING config\n");
-                       switch (le16_to_cpu(req->value) & 0xff) {
-                       case 0: /* Language */
-                               srcptr = "\4\3\1\0";
-                               srclen = 4;
-                               break;
-                       case 1: /* Vendor */
-                               srcptr = "\16\3u\0-\0b\0o\0o\0t\0";
-                               srclen = 14;
-                               break;
-                       case 2: /* Product */
-                               srcptr = "\52\3E\0H\0C\0I\0 "
-                                        "\0H\0o\0s\0t\0 "
-                                        "\0C\0o\0n\0t\0r\0o\0l\0l\0e\0r\0";
-                               srclen = 42;
-                               break;
-                       default:
-                               debug("unknown value DT_STRING %x\n",
-                                       le16_to_cpu(req->value));
-                               goto unknown;
-                       }
-                       break;
-               default:
-                       debug("unknown value %x\n", le16_to_cpu(req->value));
-                       goto unknown;
-               }
-               break;
-       case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8):
-               switch (le16_to_cpu(req->value) >> 8) {
-               case USB_DT_HUB:
-                       debug("USB_DT_HUB config\n");
-                       srcptr = &descriptor.hub;
-                       srclen = 0x8;
-                       break;
-               default:
-                       debug("unknown value %x\n", le16_to_cpu(req->value));
-                       goto unknown;
-               }
-               break;
-       case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8):
-               debug("USB_REQ_SET_ADDRESS\n");
-               rootdev = le16_to_cpu(req->value);
-               break;
-       case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
-               debug("USB_REQ_SET_CONFIGURATION\n");
-               /* Nothing to do */
-               break;
-       case USB_REQ_GET_STATUS | ((USB_DIR_IN | USB_RT_HUB) << 8):
-               tmpbuf[0] = 1;  /* USB_STATUS_SELFPOWERED */
-               tmpbuf[1] = 0;
-               srcptr = tmpbuf;
-               srclen = 2;
-               break;
-       case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8):
-               memset(tmpbuf, 0, 4);
-               reg = ehci_readl(status_reg);
-               if (reg & EHCI_PS_CS)
-                       tmpbuf[0] |= USB_PORT_STAT_CONNECTION;
-               if (reg & EHCI_PS_PE)
-                       tmpbuf[0] |= USB_PORT_STAT_ENABLE;
-               if (reg & EHCI_PS_SUSP)
-                       tmpbuf[0] |= USB_PORT_STAT_SUSPEND;
-               if (reg & EHCI_PS_OCA)
-                       tmpbuf[0] |= USB_PORT_STAT_OVERCURRENT;
-               if (reg & EHCI_PS_PR &&
-                   (portreset & (1 << le16_to_cpu(req->index)))) {
-                       int ret;
-                       /* force reset to complete */
-                       reg = reg & ~(EHCI_PS_PR | EHCI_PS_CLEAR);
-                       ehci_writel(status_reg, reg);
-                       ret = handshake(status_reg, EHCI_PS_PR, 0, 2 * 1000);
-                       if (!ret)
-                               tmpbuf[0] |= USB_PORT_STAT_RESET;
-                       else
-                               printf("port(%d) reset error\n",
-                                       le16_to_cpu(req->index) - 1);
-               }
-               if (reg & EHCI_PS_PP)
-                       tmpbuf[1] |= USB_PORT_STAT_POWER >> 8;
-
-               if (ehci_is_TDI()) {
-                       switch ((reg >> 26) & 3) {
-                       case 0:
-                               break;
-                       case 1:
-                               tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8;
-                               break;
-                       case 2:
-                       default:
-                               tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
-                               break;
-                       }
-               } else {
-                       tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
-               }
-
-               if (reg & EHCI_PS_CSC)
-                       tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION;
-               if (reg & EHCI_PS_PEC)
-                       tmpbuf[2] |= USB_PORT_STAT_C_ENABLE;
-               if (reg & EHCI_PS_OCC)
-                       tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT;
-               if (portreset & (1 << le16_to_cpu(req->index)))
-                       tmpbuf[2] |= USB_PORT_STAT_C_RESET;
-
-               srcptr = tmpbuf;
-               srclen = 4;
-               break;
-       case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
-               reg = ehci_readl(status_reg);
-               reg &= ~EHCI_PS_CLEAR;
-               switch (le16_to_cpu(req->value)) {
-               case USB_PORT_FEAT_ENABLE:
-                       reg |= EHCI_PS_PE;
-                       ehci_writel(status_reg, reg);
-                       break;
-               case USB_PORT_FEAT_POWER:
-                       if (HCS_PPC(ehci_readl(&hccr->cr_hcsparams))) {
-                               reg |= EHCI_PS_PP;
-                               ehci_writel(status_reg, reg);
-                       }
-                       break;
-               case USB_PORT_FEAT_RESET:
-                       if ((reg & (EHCI_PS_PE | EHCI_PS_CS)) == EHCI_PS_CS &&
-                           !ehci_is_TDI() &&
-                           EHCI_PS_IS_LOWSPEED(reg)) {
-                               /* Low speed device, give up ownership. */
-                               debug("port %d low speed --> companion\n",
-                                     req->index - 1);
-                               reg |= EHCI_PS_PO;
-                               ehci_writel(status_reg, reg);
-                               break;
-                       } else {
-                               reg |= EHCI_PS_PR;
-                               reg &= ~EHCI_PS_PE;
-                               ehci_writel(status_reg, reg);
-                               /*
-                                * caller must wait, then call GetPortStatus
-                                * usb 2.0 specification say 50 ms resets on
-                                * root
-                                */
-                               wait_ms(50);
-                               portreset |= 1 << le16_to_cpu(req->index);
-                       }
-                       break;
-               default:
-                       debug("unknown feature %x\n", le16_to_cpu(req->value));
-                       goto unknown;
-               }
-               /* unblock posted writes */
-               ehci_readl(&hcor->or_usbcmd);
-               break;
-       case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
-               reg = ehci_readl(status_reg);
-               switch (le16_to_cpu(req->value)) {
-               case USB_PORT_FEAT_ENABLE:
-                       reg &= ~EHCI_PS_PE;
-                       break;
-               case USB_PORT_FEAT_C_ENABLE:
-                       reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_PE;
-                       break;
-               case USB_PORT_FEAT_POWER:
-                       if (HCS_PPC(ehci_readl(&hccr->cr_hcsparams)))
-                               reg = reg & ~(EHCI_PS_CLEAR | EHCI_PS_PP);
-               case USB_PORT_FEAT_C_CONNECTION:
-                       reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_CSC;
-                       break;
-               case USB_PORT_FEAT_OVER_CURRENT:
-                       reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_OCC;
-                       break;
-               case USB_PORT_FEAT_C_RESET:
-                       portreset &= ~(1 << le16_to_cpu(req->index));
-                       break;
-               default:
-                       debug("unknown feature %x\n", le16_to_cpu(req->value));
-                       goto unknown;
-               }
-               ehci_writel(status_reg, reg);
-               /* unblock posted write */
-               ehci_readl(&hcor->or_usbcmd);
-               break;
-       default:
-               debug("Unknown request\n");
-               goto unknown;
-       }
-
-       wait_ms(1);
-       len = min3(srclen, le16_to_cpu(req->length), length);
-       if (srcptr != NULL && len > 0)
-               memcpy(buffer, srcptr, len);
-       else
-               debug("Len is 0\n");
-
-       dev->act_len = len;
-       dev->status = 0;
-       return 0;
-
-unknown:
-       debug("requesttype=%x, request=%x, value=%x, index=%x, length=%x\n",
-             req->requesttype, req->request, le16_to_cpu(req->value),
-             le16_to_cpu(req->index), le16_to_cpu(req->length));
-
-       dev->act_len = 0;
-       dev->status = USB_ST_STALLED;
-       return -1;
-}
-
-int usb_lowlevel_stop(void)
-{
-       return ehci_hcd_stop();
-}
-
-int usb_lowlevel_init(void)
-{
-       uint32_t reg;
-       uint32_t cmd;
-
-       if (ehci_hcd_init() != 0)
-               return -1;
-
-       /* EHCI spec section 4.1 */
-       if (ehci_reset() != 0)
-               return -1;
-
-#if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET)
-       if (ehci_hcd_init() != 0)
-               return -1;
-#endif
-
-       /* Set head of reclaim list */
-       memset(&qh_list, 0, sizeof(qh_list));
-       qh_list.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH);
-       qh_list.qh_endpt1 = cpu_to_hc32((1 << 15) | (USB_SPEED_HIGH << 12));
-       qh_list.qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE);
-       qh_list.qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
-       qh_list.qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
-       qh_list.qh_overlay.qt_token = cpu_to_hc32(0x40);
-
-       /* Set async. queue head pointer. */
-       ehci_writel(&hcor->or_asynclistaddr, (uint32_t)&qh_list);
-
-       reg = ehci_readl(&hccr->cr_hcsparams);
-       descriptor.hub.bNbrPorts = HCS_N_PORTS(reg);
-       printf("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts);
-       /* Port Indicators */
-       if (HCS_INDICATOR(reg))
-               descriptor.hub.wHubCharacteristics |= 0x80;
-       /* Port Power Control */
-       if (HCS_PPC(reg))
-               descriptor.hub.wHubCharacteristics |= 0x01;
-
-       /* Start the host controller. */
-       cmd = ehci_readl(&hcor->or_usbcmd);
-       /*
-        * Philips, Intel, and maybe others need CMD_RUN before the
-        * root hub will detect new devices (why?); NEC doesn't
-        */
-       cmd &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
-       cmd |= CMD_RUN;
-       ehci_writel(&hcor->or_usbcmd, cmd);
-
-       /* take control over the ports */
-       cmd = ehci_readl(&hcor->or_configflag);
-       cmd |= FLAG_CF;
-       ehci_writel(&hcor->or_configflag, cmd);
-       /* unblock posted write */
-       cmd = ehci_readl(&hcor->or_usbcmd);
-       wait_ms(5);
-       reg = HC_VERSION(ehci_readl(&hccr->cr_capbase));
-       printf("USB EHCI %x.%02x\n", reg >> 8, reg & 0xff);
-
-       rootdev = 0;
-
-       return 0;
-}
-
-int
-submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-               int length)
-{
-
-       if (usb_pipetype(pipe) != PIPE_BULK) {
-               debug("non-bulk pipe (type=%lu)", usb_pipetype(pipe));
-               return -1;
-       }
-       return ehci_submit_async(dev, pipe, buffer, length, NULL);
-}
-
-int
-submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-                  int length, struct devrequest *setup)
-{
-
-       if (usb_pipetype(pipe) != PIPE_CONTROL) {
-               debug("non-control pipe (type=%lu)", usb_pipetype(pipe));
-               return -1;
-       }
-
-       if (usb_pipedevice(pipe) == rootdev) {
-               if (rootdev == 0)
-                       dev->speed = USB_SPEED_HIGH;
-               return ehci_submit_root(dev, pipe, buffer, length, setup);
-       }
-       return ehci_submit_async(dev, pipe, buffer, length, setup);
-}
-
-int
-submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-              int length, int interval)
-{
-
-       debug("dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d",
-             dev, pipe, buffer, length, interval);
-       return -1;
-}
diff --git a/drivers/usb/usb_ehci_core.h b/drivers/usb/usb_ehci_core.h
deleted file mode 100644 (file)
index 39e5c5e..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*-
- * Copyright (c) 2007-2008, Juniper Networks, Inc.
- * Copyright (c) 2008, Excito Elektronik i SkÃ¥ne AB
- * All rights reserved.
- *
- * 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 version 2 of
- * the License.
- *
- * 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_EHCI_CORE_H
-#define USB_EHCI_CORE_H
-
-extern int rootdev;
-extern struct ehci_hccr *hccr;
-extern volatile struct ehci_hcor *hcor;
-
-#endif
diff --git a/drivers/usb/usb_ehci_fsl.c b/drivers/usb/usb_ehci_fsl.c
deleted file mode 100644 (file)
index 81d5d21..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * (C) Copyright 2008, Excito Elektronik i Sk=E5ne AB
- *
- * Author: Tor Krill tor@excito.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., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-#include <common.h>
-#include <pci.h>
-#include <usb.h>
-#include <mpc83xx.h>
-#include <asm/io.h>
-#include <asm/bitops.h>
-
-#include "usb_ehci.h"
-#include "usb_ehci_fsl.h"
-#include "usb_ehci_core.h"
-
-/*
- * Create the appropriate control structures to manage
- * a new EHCI host controller.
- *
- * Excerpts from linux ehci fsl driver.
- */
-int ehci_hcd_init(void)
-{
-       volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
-       uint32_t addr, temp;
-
-       addr = (uint32_t)&(im->usb[0]);
-       hccr = (struct ehci_hccr *)(addr + FSL_SKIP_PCI);
-       hcor = (struct ehci_hcor *)((uint32_t) hccr +
-                       HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
-
-       /* Configure clock */
-       clrsetbits_be32(&(im->clk.sccr), MPC83XX_SCCR_USB_MASK,
-                       MPC83XX_SCCR_USB_DRCM_11);
-
-       /* Confgure interface. */
-       temp = in_be32((void *)(addr + FSL_SOC_USB_CTRL));
-       out_be32((void *)(addr + FSL_SOC_USB_CTRL), temp
-                | REFSEL_16MHZ | UTMI_PHY_EN);
-
-       /* Wait for clock to stabilize */
-       do {
-               temp = in_be32((void *)(addr + FSL_SOC_USB_CTRL));
-               udelay(1000);
-       } while (!(temp & PHY_CLK_VALID));
-
-       /* Set to Host mode */
-       temp = in_le32((void *)(addr + FSL_SOC_USB_USBMODE));
-       out_le32((void *)(addr + FSL_SOC_USB_USBMODE), temp | CM_HOST);
-
-       out_be32((void *)(addr + FSL_SOC_USB_SNOOP1), SNOOP_SIZE_2GB);
-       out_be32((void *)(addr + FSL_SOC_USB_SNOOP2),
-                0x80000000 | SNOOP_SIZE_2GB);
-
-       /* Init phy */
-       /* TODO: handle different phys? */
-       out_le32(&(hcor->or_portsc[0]), PORT_PTS_UTMI);
-
-       /* Enable interface. */
-       temp = in_be32((void *)(addr + FSL_SOC_USB_CTRL));
-       out_be32((void *)(addr + FSL_SOC_USB_CTRL), temp | USB_EN);
-
-       out_be32((void *)(addr + FSL_SOC_USB_PRICTRL), 0x0000000c);
-       out_be32((void *)(addr + FSL_SOC_USB_AGECNTTHRSH), 0x00000040);
-       out_be32((void *)(addr + FSL_SOC_USB_SICTRL), 0x00000001);
-
-       /* Enable interface. */
-       temp = in_be32((void *)(addr + FSL_SOC_USB_CTRL));
-       out_be32((void *)(addr + FSL_SOC_USB_CTRL), temp | USB_EN);
-
-       temp = in_le32((void *)(addr + FSL_SOC_USB_USBMODE));
-
-       return 0;
-}
-
-/*
- * Destroy the appropriate control structures corresponding
- * the the EHCI host controller.
- */
-int ehci_hcd_stop(void)
-{
-       return 0;
-}
diff --git a/drivers/usb/usb_ehci_fsl.h b/drivers/usb/usb_ehci_fsl.h
deleted file mode 100644 (file)
index c429af1..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2005 freescale semiconductor
- * Copyright (c) 2005 MontaVista Software
- * Copyright (c) 2008 Excito Elektronik i Sk=E5ne AB
- *
- * 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 _EHCI_FSL_H
-#define _EHCI_FSL_H
-
-/* Global offsets */
-#define FSL_SKIP_PCI           0x100
-
-/* offsets for the non-ehci registers in the FSL SOC USB controller */
-#define FSL_SOC_USB_ULPIVP     0x170
-#define FSL_SOC_USB_PORTSC1    0x184
-#define PORT_PTS_MSK           (3 << 30)
-#define PORT_PTS_UTMI          (0 << 30)
-#define PORT_PTS_ULPI          (2 << 30)
-#define PORT_PTS_SERIAL                (3 << 30)
-#define PORT_PTS_PTW           (1 << 28)
-
-/* USBMODE Register bits */
-#define CM_IDLE                        (0 << 0)
-#define CM_RESERVED            (1 << 0)
-#define CM_DEVICE              (2 << 0)
-#define CM_HOST                        (3 << 0)
-#define USBMODE_RESERVED_2     (0 << 2)
-#define SLOM                   (1 << 3)
-#define SDIS                   (1 << 4)
-
-/* CONTROL Register bits */
-#define ULPI_INT_EN            (1 << 0)
-#define WU_INT_EN              (1 << 1)
-#define USB_EN                 (1 << 2)
-#define LSF_EN                 (1 << 3)
-#define KEEP_OTG_ON            (1 << 4)
-#define OTG_PORT               (1 << 5)
-#define REFSEL_12MHZ           (0 << 6)
-#define REFSEL_16MHZ           (1 << 6)
-#define REFSEL_48MHZ           (2 << 6)
-#define PLL_RESET              (1 << 8)
-#define UTMI_PHY_EN            (1 << 9)
-#define PHY_CLK_SEL_UTMI       (0 << 10)
-#define PHY_CLK_SEL_ULPI       (1 << 10)
-#define CLKIN_SEL_USB_CLK      (0 << 11)
-#define CLKIN_SEL_USB_CLK2     (1 << 11)
-#define CLKIN_SEL_SYS_CLK      (2 << 11)
-#define CLKIN_SEL_SYS_CLK2     (3 << 11)
-#define RESERVED_18            (0 << 13)
-#define RESERVED_17            (0 << 14)
-#define RESERVED_16            (0 << 15)
-#define WU_INT                 (1 << 16)
-#define PHY_CLK_VALID          (1 << 17)
-
-#define FSL_SOC_USB_PORTSC2    0x188
-#define FSL_SOC_USB_USBMODE    0x1a8
-#define FSL_SOC_USB_SNOOP1     0x400   /* NOTE: big-endian */
-#define FSL_SOC_USB_SNOOP2     0x404   /* NOTE: big-endian */
-#define FSL_SOC_USB_AGECNTTHRSH        0x408   /* NOTE: big-endian */
-#define FSL_SOC_USB_PRICTRL    0x40c   /* NOTE: big-endian */
-#define FSL_SOC_USB_SICTRL     0x410   /* NOTE: big-endian */
-#define FSL_SOC_USB_CTRL       0x500   /* NOTE: big-endian */
-#define SNOOP_SIZE_2GB         0x1e
-
-/* System Clock Control Register */
-#define MPC83XX_SCCR_USB_MASK          0x00f00000
-#define MPC83XX_SCCR_USB_DRCM_11       0x00300000
-#define MPC83XX_SCCR_USB_DRCM_01       0x00100000
-#define MPC83XX_SCCR_USB_DRCM_10       0x00200000
-
-#endif /* _EHCI_FSL_H */
diff --git a/drivers/usb/usb_ehci_ixp.c b/drivers/usb/usb_ehci_ixp.c
deleted file mode 100644 (file)
index 25c18c1..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * (C) Copyright 2008, Michael Trimarchi <trimarchimichael@yahoo.it>
- *
- * Author: Michael Trimarchi <trimarchimichael@yahoo.it>
- * This code is based on ehci freescale driver
- *
- * 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 <usb.h>
-#include "usb_ehci.h"
-#include "usb_ehci_core.h"
-/*
- * Create the appropriate control structures to manage
- * a new EHCI host controller.
- */
-int ehci_hcd_init(void)
-{
-       hccr = (struct ehci_hccr *)(0xcd000100);
-       hcor = (struct ehci_hcor *)((uint32_t) hccr
-                       + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
-
-       printf("IXP4XX init hccr %x and hcor %x hc_length %d\n",
-               (uint32_t)hccr, (uint32_t)hcor,
-               (uint32_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
-       return 0;
-}
-
-/*
- * Destroy the appropriate control structures corresponding
- * the the EHCI host controller.
- */
-int ehci_hcd_stop(void)
-{
-       return 0;
-}
diff --git a/drivers/usb/usb_ehci_pci.c b/drivers/usb/usb_ehci_pci.c
deleted file mode 100644 (file)
index 3e7143c..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*-
- * Copyright (c) 2007-2008, Juniper Networks, Inc.
- * All rights reserved.
- *
- * 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 version 2 of
- * the License.
- *
- * 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 <pci.h>
-#include <usb.h>
-#include "usb_ehci.h"
-#include "usb_ehci_core.h"
-
-#ifdef CONFIG_PCI_EHCI_DEVICE
-static struct pci_device_id ehci_pci_ids[] = {
-       /* Please add supported PCI EHCI controller ids here */
-       {0, 0}
-};
-#endif
-
-/*
- * Create the appropriate control structures to manage
- * a new EHCI host controller.
- */
-int ehci_hcd_init(void)
-{
-       pci_dev_t pdev;
-       uint32_t addr;
-
-       pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVICE);
-       if (pdev == -1) {
-               printf("EHCI host controller not found\n");
-               return -1;
-       }
-
-       pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &addr);
-       hccr = (struct ehci_hccr *)addr;
-       hcor = (struct ehci_hcor *)((uint32_t) hccr +
-                       HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
-
-       return 0;
-}
-
-/*
- * Destroy the appropriate control structures corresponding
- * the the EHCI host controller.
- */
-int ehci_hcd_stop(void)
-{
-       return 0;
-}
diff --git a/drivers/usb/usb_ehci_vct.c b/drivers/usb/usb_ehci_vct.c
deleted file mode 100644 (file)
index 89daaaf..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * (C) Copyright 2009 Stefan Roese <sr@denx.de>, DENX Software Engineering
- *
- * 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 <usb.h>
-
-#include "usb_ehci.h"
-#include "usb_ehci_core.h"
-
-int vct_ehci_hcd_init(u32 *hccr, u32 *hcor);
-
-/*
- * Create the appropriate control structures to manage
- * a new EHCI host controller.
- */
-int ehci_hcd_init(void)
-{
-       int ret;
-       u32 vct_hccr;
-       u32 vct_hcor;
-
-       /*
-        * Init VCT specific stuff
-        */
-       ret = vct_ehci_hcd_init(&vct_hccr, &vct_hcor);
-       if (ret)
-               return ret;
-
-       hccr = (struct ehci_hccr *)vct_hccr;
-       hcor = (struct ehci_hcor *)vct_hcor;
-
-       return 0;
-}
-
-/*
- * Destroy the appropriate control structures corresponding
- * the the EHCI host controller.
- */
-int ehci_hcd_stop(void)
-{
-       return 0;
-}
diff --git a/drivers/usb/usb_ohci.c b/drivers/usb/usb_ohci.c
deleted file mode 100644 (file)
index 0bbee0f..0000000
+++ /dev/null
@@ -1,2015 +0,0 @@
-/*
- * URB OHCI HCD (Host Controller Driver) for USB on the AT91RM9200 and PCI bus.
- *
- * Interrupt support is added. Now, it has been tested
- * on ULI1575 chip and works well with USB keyboard.
- *
- * (C) Copyright 2007
- * Zhang Wei, Freescale Semiconductor, Inc. <wei.zhang@freescale.com>
- *
- * (C) Copyright 2003
- * Gary Jennejohn, DENX Software Engineering <gj@denx.de>
- *
- * Note: Much of this code has been derived from Linux 2.4
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell
- *
- * Modified for the MP2USB by (C) Copyright 2005 Eric Benard
- * ebenard@eukrea.com - based on s3c24x0's driver
- *
- * 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
- *
- */
-/*
- * IMPORTANT NOTES
- * 1 - Read doc/README.generic_usb_ohci
- * 2 - this driver is intended for use with USB Mass Storage Devices
- *     (BBB) and USB keyboard. There is NO support for Isochronous pipes!
- * 2 - when running on a PQFP208 AT91RM9200, define CONFIG_AT91C_PQFP_UHPBUG
- *     to activate workaround for bug #41 or this driver will NOT work!
- */
-
-#include <common.h>
-#include <asm/byteorder.h>
-
-#if defined(CONFIG_PCI_OHCI)
-# include <pci.h>
-#if !defined(CONFIG_PCI_OHCI_DEVNO)
-#define CONFIG_PCI_OHCI_DEVNO  0
-#endif
-#endif
-
-#include <malloc.h>
-#include <usb.h>
-#include "usb_ohci.h"
-
-#ifdef CONFIG_AT91RM9200
-#include <asm/arch/hardware.h> /* needed for AT91_USB_HOST_BASE */
-#endif
-
-#if defined(CONFIG_ARM920T) || \
-    defined(CONFIG_S3C2400) || \
-    defined(CONFIG_S3C2410) || \
-    defined(CONFIG_S3C6400) || \
-    defined(CONFIG_440EP) || \
-    defined(CONFIG_PCI_OHCI) || \
-    defined(CONFIG_MPC5200) || \
-    defined(CONFIG_SYS_OHCI_USE_NPS)
-# define OHCI_USE_NPS          /* force NoPowerSwitching mode */
-#endif
-
-#undef OHCI_VERBOSE_DEBUG      /* not always helpful */
-#undef DEBUG
-#undef SHOW_INFO
-#undef OHCI_FILL_TRACE
-
-/* For initializing controller (mask in an HCFS mode too) */
-#define OHCI_CONTROL_INIT \
-       (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
-
-/*
- * e.g. PCI controllers need this
- */
-#ifdef CONFIG_SYS_OHCI_SWAP_REG_ACCESS
-# define readl(a) __swap_32(*((volatile u32 *)(a)))
-# define writel(a, b) (*((volatile u32 *)(b)) = __swap_32((volatile u32)a))
-#else
-# define readl(a) (*((volatile u32 *)(a)))
-# define writel(a, b) (*((volatile u32 *)(b)) = ((volatile u32)a))
-#endif /* CONFIG_SYS_OHCI_SWAP_REG_ACCESS */
-
-#define min_t(type, x, y) \
-                   ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
-
-#ifdef CONFIG_PCI_OHCI
-static struct pci_device_id ohci_pci_ids[] = {
-       {0x10b9, 0x5237},       /* ULI1575 PCI OHCI module ids */
-       {0x1033, 0x0035},       /* NEC PCI OHCI module ids */
-       {0x1131, 0x1561},       /* Philips 1561 PCI OHCI module ids */
-       /* Please add supported PCI OHCI controller ids here */
-       {0, 0}
-};
-#endif
-
-#ifdef CONFIG_PCI_EHCI_DEVNO
-static struct pci_device_id ehci_pci_ids[] = {
-       {0x1131, 0x1562},       /* Philips 1562 PCI EHCI module ids */
-       /* Please add supported PCI EHCI controller ids here */
-       {0, 0}
-};
-#endif
-
-#ifdef DEBUG
-#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg)
-#else
-#define dbg(format, arg...) do {} while (0)
-#endif /* DEBUG */
-#define err(format, arg...) printf("ERROR: " format "\n", ## arg)
-#ifdef SHOW_INFO
-#define info(format, arg...) printf("INFO: " format "\n", ## arg)
-#else
-#define info(format, arg...) do {} while (0)
-#endif
-
-#ifdef CONFIG_SYS_OHCI_BE_CONTROLLER
-# define m16_swap(x) cpu_to_be16(x)
-# define m32_swap(x) cpu_to_be32(x)
-#else
-# define m16_swap(x) cpu_to_le16(x)
-# define m32_swap(x) cpu_to_le32(x)
-#endif /* CONFIG_SYS_OHCI_BE_CONTROLLER */
-
-/* global ohci_t */
-static ohci_t gohci;
-/* this must be aligned to a 256 byte boundary */
-struct ohci_hcca ghcca[1];
-/* a pointer to the aligned storage */
-struct ohci_hcca *phcca;
-/* this allocates EDs for all possible endpoints */
-struct ohci_device ohci_dev;
-/* device which was disconnected */
-struct usb_device *devgone;
-
-static inline u32 roothub_a(struct ohci *hc)
-       { return readl(&hc->regs->roothub.a); }
-static inline u32 roothub_b(struct ohci *hc)
-       { return readl(&hc->regs->roothub.b); }
-static inline u32 roothub_status(struct ohci *hc)
-       { return readl(&hc->regs->roothub.status); }
-static inline u32 roothub_portstatus(struct ohci *hc, int i)
-       { return readl(&hc->regs->roothub.portstatus[i]); }
-
-/* forward declaration */
-static int hc_interrupt(void);
-static void td_submit_job(struct usb_device *dev, unsigned long pipe,
-                         void *buffer, int transfer_len,
-                         struct devrequest *setup, urb_priv_t *urb,
-                         int interval);
-
-/*-------------------------------------------------------------------------*
- * URB support functions
- *-------------------------------------------------------------------------*/
-
-/* free HCD-private data associated with this URB */
-
-static void urb_free_priv(urb_priv_t *urb)
-{
-       int             i;
-       int             last;
-       struct td       *td;
-
-       last = urb->length - 1;
-       if (last >= 0) {
-               for (i = 0; i <= last; i++) {
-                       td = urb->td[i];
-                       if (td) {
-                               td->usb_dev = NULL;
-                               urb->td[i] = NULL;
-                       }
-               }
-       }
-       free(urb);
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef DEBUG
-static int sohci_get_current_frame_number(struct usb_device *dev);
-
-/* debug| print the main components of an URB
- * small: 0) header + data packets 1) just header */
-
-static void pkt_print(urb_priv_t *purb, struct usb_device *dev,
-                     unsigned long pipe, void *buffer, int transfer_len,
-                     struct devrequest *setup, char *str, int small)
-{
-       dbg("%s URB:[%4x] dev:%2lu,ep:%2lu-%c,type:%s,len:%d/%d stat:%#lx",
-                       str,
-                       sohci_get_current_frame_number(dev),
-                       usb_pipedevice(pipe),
-                       usb_pipeendpoint(pipe),
-                       usb_pipeout(pipe)? 'O': 'I',
-                       usb_pipetype(pipe) < 2 ? \
-                               (usb_pipeint(pipe)? "INTR": "ISOC"): \
-                               (usb_pipecontrol(pipe)? "CTRL": "BULK"),
-                       (purb ? purb->actual_length : 0),
-                       transfer_len, dev->status);
-#ifdef OHCI_VERBOSE_DEBUG
-       if (!small) {
-               int i, len;
-
-               if (usb_pipecontrol(pipe)) {
-                       printf(__FILE__ ": cmd(8):");
-                       for (i = 0; i < 8 ; i++)
-                               printf(" %02x", ((__u8 *) setup) [i]);
-                       printf("\n");
-               }
-               if (transfer_len > 0 && buffer) {
-                       printf(__FILE__ ": data(%d/%d):",
-                               (purb ? purb->actual_length : 0),
-                               transfer_len);
-                       len = usb_pipeout(pipe)? transfer_len:
-                                       (purb ? purb->actual_length : 0);
-                       for (i = 0; i < 16 && i < len; i++)
-                               printf(" %02x", ((__u8 *) buffer) [i]);
-                       printf("%s\n", i < len? "...": "");
-               }
-       }
-#endif
-}
-
-/* just for debugging; prints non-empty branches of the int ed tree
- * inclusive iso eds */
-void ep_print_int_eds(ohci_t *ohci, char *str)
-{
-       int i, j;
-        __u32 *ed_p;
-       for (i = 0; i < 32; i++) {
-               j = 5;
-               ed_p = &(ohci->hcca->int_table [i]);
-               if (*ed_p == 0)
-                   continue;
-               printf(__FILE__ ": %s branch int %2d(%2x):", str, i, i);
-               while (*ed_p != 0 && j--) {
-                       ed_t *ed = (ed_t *)m32_swap(ed_p);
-                       printf(" ed: %4x;", ed->hwINFO);
-                       ed_p = &ed->hwNextED;
-               }
-               printf("\n");
-       }
-}
-
-static void ohci_dump_intr_mask(char *label, __u32 mask)
-{
-       dbg("%s: 0x%08x%s%s%s%s%s%s%s%s%s",
-               label,
-               mask,
-               (mask & OHCI_INTR_MIE) ? " MIE" : "",
-               (mask & OHCI_INTR_OC) ? " OC" : "",
-               (mask & OHCI_INTR_RHSC) ? " RHSC" : "",
-               (mask & OHCI_INTR_FNO) ? " FNO" : "",
-               (mask & OHCI_INTR_UE) ? " UE" : "",
-               (mask & OHCI_INTR_RD) ? " RD" : "",
-               (mask & OHCI_INTR_SF) ? " SF" : "",
-               (mask & OHCI_INTR_WDH) ? " WDH" : "",
-               (mask & OHCI_INTR_SO) ? " SO" : ""
-               );
-}
-
-static void maybe_print_eds(char *label, __u32 value)
-{
-       ed_t *edp = (ed_t *)value;
-
-       if (value) {
-               dbg("%s %08x", label, value);
-               dbg("%08x", edp->hwINFO);
-               dbg("%08x", edp->hwTailP);
-               dbg("%08x", edp->hwHeadP);
-               dbg("%08x", edp->hwNextED);
-       }
-}
-
-static char *hcfs2string(int state)
-{
-       switch (state) {
-       case OHCI_USB_RESET:    return "reset";
-       case OHCI_USB_RESUME:   return "resume";
-       case OHCI_USB_OPER:     return "operational";
-       case OHCI_USB_SUSPEND:  return "suspend";
-       }
-       return "?";
-}
-
-/* dump control and status registers */
-static void ohci_dump_status(ohci_t *controller)
-{
-       struct ohci_regs        *regs = controller->regs;
-       __u32                   temp;
-
-       temp = readl(&regs->revision) & 0xff;
-       if (temp != 0x10)
-               dbg("spec %d.%d", (temp >> 4), (temp & 0x0f));
-
-       temp = readl(&regs->control);
-       dbg("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp,
-               (temp & OHCI_CTRL_RWE) ? " RWE" : "",
-               (temp & OHCI_CTRL_RWC) ? " RWC" : "",
-               (temp & OHCI_CTRL_IR) ? " IR" : "",
-               hcfs2string(temp & OHCI_CTRL_HCFS),
-               (temp & OHCI_CTRL_BLE) ? " BLE" : "",
-               (temp & OHCI_CTRL_CLE) ? " CLE" : "",
-               (temp & OHCI_CTRL_IE) ? " IE" : "",
-               (temp & OHCI_CTRL_PLE) ? " PLE" : "",
-               temp & OHCI_CTRL_CBSR
-               );
-
-       temp = readl(&regs->cmdstatus);
-       dbg("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp,
-               (temp & OHCI_SOC) >> 16,
-               (temp & OHCI_OCR) ? " OCR" : "",
-               (temp & OHCI_BLF) ? " BLF" : "",
-               (temp & OHCI_CLF) ? " CLF" : "",
-               (temp & OHCI_HCR) ? " HCR" : ""
-               );
-
-       ohci_dump_intr_mask("intrstatus", readl(&regs->intrstatus));
-       ohci_dump_intr_mask("intrenable", readl(&regs->intrenable));
-
-       maybe_print_eds("ed_periodcurrent", readl(&regs->ed_periodcurrent));
-
-       maybe_print_eds("ed_controlhead", readl(&regs->ed_controlhead));
-       maybe_print_eds("ed_controlcurrent", readl(&regs->ed_controlcurrent));
-
-       maybe_print_eds("ed_bulkhead", readl(&regs->ed_bulkhead));
-       maybe_print_eds("ed_bulkcurrent", readl(&regs->ed_bulkcurrent));
-
-       maybe_print_eds("donehead", readl(&regs->donehead));
-}
-
-static void ohci_dump_roothub(ohci_t *controller, int verbose)
-{
-       __u32                   temp, ndp, i;
-
-       temp = roothub_a(controller);
-       ndp = (temp & RH_A_NDP);
-#ifdef CONFIG_AT91C_PQFP_UHPBUG
-       ndp = (ndp == 2) ? 1:0;
-#endif
-       if (verbose) {
-               dbg("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp,
-                       ((temp & RH_A_POTPGT) >> 24) & 0xff,
-                       (temp & RH_A_NOCP) ? " NOCP" : "",
-                       (temp & RH_A_OCPM) ? " OCPM" : "",
-                       (temp & RH_A_DT) ? " DT" : "",
-                       (temp & RH_A_NPS) ? " NPS" : "",
-                       (temp & RH_A_PSM) ? " PSM" : "",
-                       ndp
-                       );
-               temp = roothub_b(controller);
-               dbg("roothub.b: %08x PPCM=%04x DR=%04x",
-                       temp,
-                       (temp & RH_B_PPCM) >> 16,
-                       (temp & RH_B_DR)
-                       );
-               temp = roothub_status(controller);
-               dbg("roothub.status: %08x%s%s%s%s%s%s",
-                       temp,
-                       (temp & RH_HS_CRWE) ? " CRWE" : "",
-                       (temp & RH_HS_OCIC) ? " OCIC" : "",
-                       (temp & RH_HS_LPSC) ? " LPSC" : "",
-                       (temp & RH_HS_DRWE) ? " DRWE" : "",
-                       (temp & RH_HS_OCI) ? " OCI" : "",
-                       (temp & RH_HS_LPS) ? " LPS" : ""
-                       );
-       }
-
-       for (i = 0; i < ndp; i++) {
-               temp = roothub_portstatus(controller, i);
-               dbg("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s",
-                       i,
-                       temp,
-                       (temp & RH_PS_PRSC) ? " PRSC" : "",
-                       (temp & RH_PS_OCIC) ? " OCIC" : "",
-                       (temp & RH_PS_PSSC) ? " PSSC" : "",
-                       (temp & RH_PS_PESC) ? " PESC" : "",
-                       (temp & RH_PS_CSC) ? " CSC" : "",
-
-                       (temp & RH_PS_LSDA) ? " LSDA" : "",
-                       (temp & RH_PS_PPS) ? " PPS" : "",
-                       (temp & RH_PS_PRS) ? " PRS" : "",
-                       (temp & RH_PS_POCI) ? " POCI" : "",
-                       (temp & RH_PS_PSS) ? " PSS" : "",
-
-                       (temp & RH_PS_PES) ? " PES" : "",
-                       (temp & RH_PS_CCS) ? " CCS" : ""
-                       );
-       }
-}
-
-static void ohci_dump(ohci_t *controller, int verbose)
-{
-       dbg("OHCI controller usb-%s state", controller->slot_name);
-
-       /* dumps some of the state we know about */
-       ohci_dump_status(controller);
-       if (verbose)
-               ep_print_int_eds(controller, "hcca");
-       dbg("hcca frame #%04x", controller->hcca->frame_no);
-       ohci_dump_roothub(controller, 1);
-}
-#endif /* DEBUG */
-
-/*-------------------------------------------------------------------------*
- * Interface functions (URB)
- *-------------------------------------------------------------------------*/
-
-/* get a transfer request */
-
-int sohci_submit_job(urb_priv_t *urb, struct devrequest *setup)
-{
-       ohci_t *ohci;
-       ed_t *ed;
-       urb_priv_t *purb_priv = urb;
-       int i, size = 0;
-       struct usb_device *dev = urb->dev;
-       unsigned long pipe = urb->pipe;
-       void *buffer = urb->transfer_buffer;
-       int transfer_len = urb->transfer_buffer_length;
-       int interval = urb->interval;
-
-       ohci = &gohci;
-
-       /* when controller's hung, permit only roothub cleanup attempts
-        * such as powering down ports */
-       if (ohci->disabled) {
-               err("sohci_submit_job: EPIPE");
-               return -1;
-       }
-
-       /* we're about to begin a new transaction here so mark the
-        * URB unfinished */
-       urb->finished = 0;
-
-       /* every endpoint has a ed, locate and fill it */
-       ed = ep_add_ed(dev, pipe, interval, 1);
-       if (!ed) {
-               err("sohci_submit_job: ENOMEM");
-               return -1;
-       }
-
-       /* for the private part of the URB we need the number of TDs (size) */
-       switch (usb_pipetype(pipe)) {
-       case PIPE_BULK: /* one TD for every 4096 Byte */
-               size = (transfer_len - 1) / 4096 + 1;
-               break;
-       case PIPE_CONTROL:/* 1 TD for setup, 1 for ACK and 1 for every 4096 B */
-               size = (transfer_len == 0)? 2:
-                                       (transfer_len - 1) / 4096 + 3;
-               break;
-       case PIPE_INTERRUPT: /* 1 TD */
-               size = 1;
-               break;
-       }
-
-       ed->purb = urb;
-
-       if (size >= (N_URB_TD - 1)) {
-               err("need %d TDs, only have %d", size, N_URB_TD);
-               return -1;
-       }
-       purb_priv->pipe = pipe;
-
-       /* fill the private part of the URB */
-       purb_priv->length = size;
-       purb_priv->ed = ed;
-       purb_priv->actual_length = 0;
-
-       /* allocate the TDs */
-       /* note that td[0] was allocated in ep_add_ed */
-       for (i = 0; i < size; i++) {
-               purb_priv->td[i] = td_alloc(dev);
-               if (!purb_priv->td[i]) {
-                       purb_priv->length = i;
-                       urb_free_priv(purb_priv);
-                       err("sohci_submit_job: ENOMEM");
-                       return -1;
-               }
-       }
-
-       if (ed->state == ED_NEW || (ed->state & ED_DEL)) {
-               urb_free_priv(purb_priv);
-               err("sohci_submit_job: EINVAL");
-               return -1;
-       }
-
-       /* link the ed into a chain if is not already */
-       if (ed->state != ED_OPER)
-               ep_link(ohci, ed);
-
-       /* fill the TDs and link it to the ed */
-       td_submit_job(dev, pipe, buffer, transfer_len,
-                     setup, purb_priv, interval);
-
-       return 0;
-}
-
-static inline int sohci_return_job(struct ohci *hc, urb_priv_t *urb)
-{
-       struct ohci_regs *regs = hc->regs;
-
-       switch (usb_pipetype(urb->pipe)) {
-       case PIPE_INTERRUPT:
-               /* implicitly requeued */
-               if (urb->dev->irq_handle &&
-                               (urb->dev->irq_act_len = urb->actual_length)) {
-                       writel(OHCI_INTR_WDH, &regs->intrenable);
-                       readl(&regs->intrenable); /* PCI posting flush */
-                       urb->dev->irq_handle(urb->dev);
-                       writel(OHCI_INTR_WDH, &regs->intrdisable);
-                       readl(&regs->intrdisable); /* PCI posting flush */
-               }
-               urb->actual_length = 0;
-               td_submit_job(
-                               urb->dev,
-                               urb->pipe,
-                               urb->transfer_buffer,
-                               urb->transfer_buffer_length,
-                               NULL,
-                               urb,
-                               urb->interval);
-               break;
-       case PIPE_CONTROL:
-       case PIPE_BULK:
-               break;
-       default:
-               return 0;
-       }
-       return 1;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef DEBUG
-/* tell us the current USB frame number */
-
-static int sohci_get_current_frame_number(struct usb_device *usb_dev)
-{
-       ohci_t *ohci = &gohci;
-
-       return m16_swap(ohci->hcca->frame_no);
-}
-#endif
-
-/*-------------------------------------------------------------------------*
- * ED handling functions
- *-------------------------------------------------------------------------*/
-
-/* search for the right branch to insert an interrupt ed into the int tree
- * do some load ballancing;
- * returns the branch and
- * sets the interval to interval = 2^integer (ld (interval)) */
-
-static int ep_int_ballance(ohci_t *ohci, int interval, int load)
-{
-       int i, branch = 0;
-
-       /* search for the least loaded interrupt endpoint
-        * branch of all 32 branches
-        */
-       for (i = 0; i < 32; i++)
-               if (ohci->ohci_int_load [branch] > ohci->ohci_int_load [i])
-                       branch = i;
-
-       branch = branch % interval;
-       for (i = branch; i < 32; i += interval)
-               ohci->ohci_int_load [i] += load;
-
-       return branch;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*  2^int( ld (inter)) */
-
-static int ep_2_n_interval(int inter)
-{
-       int i;
-       for (i = 0; ((inter >> i) > 1) && (i < 5); i++);
-       return 1 << i;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* the int tree is a binary tree
- * in order to process it sequentially the indexes of the branches have to
- * be mapped the mapping reverses the bits of a word of num_bits length */
-static int ep_rev(int num_bits, int word)
-{
-       int i, wout = 0;
-
-       for (i = 0; i < num_bits; i++)
-               wout |= (((word >> i) & 1) << (num_bits - i - 1));
-       return wout;
-}
-
-/*-------------------------------------------------------------------------*
- * ED handling functions
- *-------------------------------------------------------------------------*/
-
-/* link an ed into one of the HC chains */
-
-static int ep_link(ohci_t *ohci, ed_t *edi)
-{
-       volatile ed_t *ed = edi;
-       int int_branch;
-       int i;
-       int inter;
-       int interval;
-       int load;
-       __u32 *ed_p;
-
-       ed->state = ED_OPER;
-       ed->int_interval = 0;
-
-       switch (ed->type) {
-       case PIPE_CONTROL:
-               ed->hwNextED = 0;
-               if (ohci->ed_controltail == NULL)
-                       writel(ed, &ohci->regs->ed_controlhead);
-               else
-                       ohci->ed_controltail->hwNextED =
-                                                  m32_swap((unsigned long)ed);
-
-               ed->ed_prev = ohci->ed_controltail;
-               if (!ohci->ed_controltail && !ohci->ed_rm_list[0] &&
-                       !ohci->ed_rm_list[1] && !ohci->sleeping) {
-                       ohci->hc_control |= OHCI_CTRL_CLE;
-                       writel(ohci->hc_control, &ohci->regs->control);
-               }
-               ohci->ed_controltail = edi;
-               break;
-
-       case PIPE_BULK:
-               ed->hwNextED = 0;
-               if (ohci->ed_bulktail == NULL)
-                       writel(ed, &ohci->regs->ed_bulkhead);
-               else
-                       ohci->ed_bulktail->hwNextED =
-                                                  m32_swap((unsigned long)ed);
-
-               ed->ed_prev = ohci->ed_bulktail;
-               if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] &&
-                       !ohci->ed_rm_list[1] && !ohci->sleeping) {
-                       ohci->hc_control |= OHCI_CTRL_BLE;
-                       writel(ohci->hc_control, &ohci->regs->control);
-               }
-               ohci->ed_bulktail = edi;
-               break;
-
-       case PIPE_INTERRUPT:
-               load = ed->int_load;
-               interval = ep_2_n_interval(ed->int_period);
-               ed->int_interval = interval;
-               int_branch = ep_int_ballance(ohci, interval, load);
-               ed->int_branch = int_branch;
-
-               for (i = 0; i < ep_rev(6, interval); i += inter) {
-                       inter = 1;
-                       for (ed_p = &(ohci->hcca->int_table[\
-                                               ep_rev(5, i) + int_branch]);
-                               (*ed_p != 0) &&
-                               (((ed_t *)ed_p)->int_interval >= interval);
-                               ed_p = &(((ed_t *)ed_p)->hwNextED))
-                                       inter = ep_rev(6,
-                                                ((ed_t *)ed_p)->int_interval);
-                       ed->hwNextED = *ed_p;
-                       *ed_p = m32_swap((unsigned long)ed);
-               }
-               break;
-       }
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* scan the periodic table to find and unlink this ED */
-static void periodic_unlink(struct ohci *ohci, volatile struct ed *ed,
-                           unsigned index, unsigned period)
-{
-       for (; index < NUM_INTS; index += period) {
-               __u32   *ed_p = &ohci->hcca->int_table [index];
-
-               /* ED might have been unlinked through another path */
-               while (*ed_p != 0) {
-                       if (((struct ed *)
-                                       m32_swap((unsigned long)ed_p)) == ed) {
-                               *ed_p = ed->hwNextED;
-                               break;
-                       }
-                       ed_p = &(((struct ed *)
-                                    m32_swap((unsigned long)ed_p))->hwNextED);
-               }
-       }
-}
-
-/* unlink an ed from one of the HC chains.
- * just the link to the ed is unlinked.
- * the link from the ed still points to another operational ed or 0
- * so the HC can eventually finish the processing of the unlinked ed */
-
-static int ep_unlink(ohci_t *ohci, ed_t *edi)
-{
-       volatile ed_t *ed = edi;
-       int i;
-
-       ed->hwINFO |= m32_swap(OHCI_ED_SKIP);
-
-       switch (ed->type) {
-       case PIPE_CONTROL:
-               if (ed->ed_prev == NULL) {
-                       if (!ed->hwNextED) {
-                               ohci->hc_control &= ~OHCI_CTRL_CLE;
-                               writel(ohci->hc_control, &ohci->regs->control);
-                       }
-                       writel(m32_swap(*((__u32 *)&ed->hwNextED)),
-                               &ohci->regs->ed_controlhead);
-               } else {
-                       ed->ed_prev->hwNextED = ed->hwNextED;
-               }
-               if (ohci->ed_controltail == ed) {
-                       ohci->ed_controltail = ed->ed_prev;
-               } else {
-                       ((ed_t *)m32_swap(
-                           *((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev;
-               }
-               break;
-
-       case PIPE_BULK:
-               if (ed->ed_prev == NULL) {
-                       if (!ed->hwNextED) {
-                               ohci->hc_control &= ~OHCI_CTRL_BLE;
-                               writel(ohci->hc_control, &ohci->regs->control);
-                       }
-                       writel(m32_swap(*((__u32 *)&ed->hwNextED)),
-                              &ohci->regs->ed_bulkhead);
-               } else {
-                       ed->ed_prev->hwNextED = ed->hwNextED;
-               }
-               if (ohci->ed_bulktail == ed) {
-                       ohci->ed_bulktail = ed->ed_prev;
-               } else {
-                       ((ed_t *)m32_swap(
-                            *((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev;
-               }
-               break;
-
-       case PIPE_INTERRUPT:
-               periodic_unlink(ohci, ed, 0, 1);
-               for (i = ed->int_branch; i < 32; i += ed->int_interval)
-                   ohci->ohci_int_load[i] -= ed->int_load;
-               break;
-       }
-       ed->state = ED_UNLINK;
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* add/reinit an endpoint; this should be done once at the
- * usb_set_configuration command, but the USB stack is a little bit
- * stateless so we do it at every transaction if the state of the ed
- * is ED_NEW then a dummy td is added and the state is changed to
- * ED_UNLINK in all other cases the state is left unchanged the ed
- * info fields are setted anyway even though most of them should not
- * change
- */
-static ed_t *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe,
-                       int interval, int load)
-{
-       td_t *td;
-       ed_t *ed_ret;
-       volatile ed_t *ed;
-
-       ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint(pipe) << 1) |
-                       (usb_pipecontrol(pipe)? 0: usb_pipeout(pipe))];
-
-       if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) {
-               err("ep_add_ed: pending delete");
-               /* pending delete request */
-               return NULL;
-       }
-
-       if (ed->state == ED_NEW) {
-               /* dummy td; end of td list for ed */
-               td = td_alloc(usb_dev);
-               ed->hwTailP = m32_swap((unsigned long)td);
-               ed->hwHeadP = ed->hwTailP;
-               ed->state = ED_UNLINK;
-               ed->type = usb_pipetype(pipe);
-               ohci_dev.ed_cnt++;
-       }
-
-       ed->hwINFO = m32_swap(usb_pipedevice(pipe)
-                       | usb_pipeendpoint(pipe) << 7
-                       | (usb_pipeisoc(pipe)? 0x8000: 0)
-                       | (usb_pipecontrol(pipe)? 0: \
-                                          (usb_pipeout(pipe)? 0x800: 0x1000))
-                       | usb_pipeslow(pipe) << 13
-                       | usb_maxpacket(usb_dev, pipe) << 16);
-
-       if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) {
-               ed->int_period = interval;
-               ed->int_load = load;
-       }
-
-       return ed_ret;
-}
-
-/*-------------------------------------------------------------------------*
- * TD handling functions
- *-------------------------------------------------------------------------*/
-
-/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
-
-static void td_fill(ohci_t *ohci, unsigned int info,
-       void *data, int len,
-       struct usb_device *dev, int index, urb_priv_t *urb_priv)
-{
-       volatile td_t  *td, *td_pt;
-#ifdef OHCI_FILL_TRACE
-       int i;
-#endif
-
-       if (index > urb_priv->length) {
-               err("index > length");
-               return;
-       }
-       /* use this td as the next dummy */
-       td_pt = urb_priv->td [index];
-       td_pt->hwNextTD = 0;
-
-       /* fill the old dummy TD */
-       td = urb_priv->td [index] =
-                            (td_t *)(m32_swap(urb_priv->ed->hwTailP) & ~0xf);
-
-       td->ed = urb_priv->ed;
-       td->next_dl_td = NULL;
-       td->index = index;
-       td->data = (__u32)data;
-#ifdef OHCI_FILL_TRACE
-       if (usb_pipebulk(urb_priv->pipe) && usb_pipeout(urb_priv->pipe)) {
-               for (i = 0; i < len; i++)
-               printf("td->data[%d] %#2x ", i, ((unsigned char *)td->data)[i]);
-               printf("\n");
-       }
-#endif
-       if (!len)
-               data = 0;
-
-       td->hwINFO = m32_swap(info);
-       td->hwCBP = m32_swap((unsigned long)data);
-       if (data)
-               td->hwBE = m32_swap((unsigned long)(data + len - 1));
-       else
-               td->hwBE = 0;
-
-       td->hwNextTD = m32_swap((unsigned long)td_pt);
-
-       /* append to queue */
-       td->ed->hwTailP = td->hwNextTD;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* prepare all TDs of a transfer */
-
-static void td_submit_job(struct usb_device *dev, unsigned long pipe,
-                         void *buffer, int transfer_len,
-                         struct devrequest *setup, urb_priv_t *urb,
-                         int interval)
-{
-       ohci_t *ohci = &gohci;
-       int data_len = transfer_len;
-       void *data;
-       int cnt = 0;
-       __u32 info = 0;
-       unsigned int toggle = 0;
-
-       /* OHCI handles the DATA-toggles itself, we just use the USB-toggle
-        * bits for reseting */
-       if (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) {
-               toggle = TD_T_TOGGLE;
-       } else {
-               toggle = TD_T_DATA0;
-               usb_settoggle(dev, usb_pipeendpoint(pipe),
-                               usb_pipeout(pipe), 1);
-       }
-       urb->td_cnt = 0;
-       if (data_len)
-               data = buffer;
-       else
-               data = 0;
-
-       switch (usb_pipetype(pipe)) {
-       case PIPE_BULK:
-               info = usb_pipeout(pipe)?
-                       TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ;
-               while (data_len > 4096) {
-                       td_fill(ohci, info | (cnt? TD_T_TOGGLE:toggle),
-                               data, 4096, dev, cnt, urb);
-                       data += 4096; data_len -= 4096; cnt++;
-               }
-               info = usb_pipeout(pipe)?
-                       TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ;
-               td_fill(ohci, info | (cnt? TD_T_TOGGLE:toggle), data,
-                       data_len, dev, cnt, urb);
-               cnt++;
-
-               if (!ohci->sleeping) {
-                       /* start bulk list */
-                       writel(OHCI_BLF, &ohci->regs->cmdstatus);
-               }
-               break;
-
-       case PIPE_CONTROL:
-               /* Setup phase */
-               info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
-               td_fill(ohci, info, setup, 8, dev, cnt++, urb);
-
-               /* Optional Data phase */
-               if (data_len > 0) {
-                       info = usb_pipeout(pipe)?
-                               TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 :
-                               TD_CC | TD_R | TD_DP_IN | TD_T_DATA1;
-                       /* NOTE:  mishandles transfers >8K, some >4K */
-                       td_fill(ohci, info, data, data_len, dev, cnt++, urb);
-               }
-
-               /* Status phase */
-               info = usb_pipeout(pipe)?
-                       TD_CC | TD_DP_IN | TD_T_DATA1:
-                       TD_CC | TD_DP_OUT | TD_T_DATA1;
-               td_fill(ohci, info, data, 0, dev, cnt++, urb);
-
-               if (!ohci->sleeping) {
-                       /* start Control list */
-                       writel(OHCI_CLF, &ohci->regs->cmdstatus);
-               }
-               break;
-
-       case PIPE_INTERRUPT:
-               info = usb_pipeout(urb->pipe)?
-                       TD_CC | TD_DP_OUT | toggle:
-                       TD_CC | TD_R | TD_DP_IN | toggle;
-               td_fill(ohci, info, data, data_len, dev, cnt++, urb);
-               break;
-       }
-       if (urb->length != cnt)
-               dbg("TD LENGTH %d != CNT %d", urb->length, cnt);
-}
-
-/*-------------------------------------------------------------------------*
- * Done List handling functions
- *-------------------------------------------------------------------------*/
-
-/* calculate the transfer length and update the urb */
-
-static void dl_transfer_length(td_t *td)
-{
-       __u32 tdINFO, tdBE, tdCBP;
-       urb_priv_t *lurb_priv = td->ed->purb;
-
-       tdINFO = m32_swap(td->hwINFO);
-       tdBE   = m32_swap(td->hwBE);
-       tdCBP  = m32_swap(td->hwCBP);
-
-       if (!(usb_pipecontrol(lurb_priv->pipe) &&
-           ((td->index == 0) || (td->index == lurb_priv->length - 1)))) {
-               if (tdBE != 0) {
-                       if (td->hwCBP == 0)
-                               lurb_priv->actual_length += tdBE - td->data + 1;
-                       else
-                               lurb_priv->actual_length += tdCBP - td->data;
-               }
-       }
-}
-
-/*-------------------------------------------------------------------------*/
-static void check_status(td_t *td_list)
-{
-       urb_priv_t *lurb_priv = td_list->ed->purb;
-       int        urb_len    = lurb_priv->length;
-       __u32      *phwHeadP  = &td_list->ed->hwHeadP;
-       int        cc;
-
-       cc = TD_CC_GET(m32_swap(td_list->hwINFO));
-       if (cc) {
-               err(" USB-error: %s (%x)", cc_to_string[cc], cc);
-
-               if (*phwHeadP & m32_swap(0x1)) {
-                       if (lurb_priv &&
-                           ((td_list->index + 1) < urb_len)) {
-                               *phwHeadP =
-                                       (lurb_priv->td[urb_len - 1]->hwNextTD &\
-                                                       m32_swap(0xfffffff0)) |
-                                                  (*phwHeadP & m32_swap(0x2));
-
-                               lurb_priv->td_cnt += urb_len -
-                                                    td_list->index - 1;
-                       } else
-                               *phwHeadP &= m32_swap(0xfffffff2);
-               }
-#ifdef CONFIG_MPC5200
-               td_list->hwNextTD = 0;
-#endif
-       }
-}
-
-/* replies to the request have to be on a FIFO basis so
- * we reverse the reversed done-list */
-static td_t *dl_reverse_done_list(ohci_t *ohci)
-{
-       __u32 td_list_hc;
-       td_t *td_rev = NULL;
-       td_t *td_list = NULL;
-
-       td_list_hc = m32_swap(ohci->hcca->done_head) & 0xfffffff0;
-       ohci->hcca->done_head = 0;
-
-       while (td_list_hc) {
-               td_list = (td_t *)td_list_hc;
-               check_status(td_list);
-               td_list->next_dl_td = td_rev;
-               td_rev = td_list;
-               td_list_hc = m32_swap(td_list->hwNextTD) & 0xfffffff0;
-       }
-       return td_list;
-}
-
-/*-------------------------------------------------------------------------*/
-/*-------------------------------------------------------------------------*/
-
-static void finish_urb(ohci_t *ohci, urb_priv_t *urb, int status)
-{
-       if ((status & (ED_OPER | ED_UNLINK)) && (urb->state != URB_DEL))
-               urb->finished = sohci_return_job(ohci, urb);
-       else
-               dbg("finish_urb: strange.., ED state %x, \n", status);
-}
-
-/*
- * Used to take back a TD from the host controller. This would normally be
- * called from within dl_done_list, however it may be called directly if the
- * HC no longer sees the TD and it has not appeared on the donelist (after
- * two frames).  This bug has been observed on ZF Micro systems.
- */
-static int takeback_td(ohci_t *ohci, td_t *td_list)
-{
-       ed_t *ed;
-       int cc;
-       int stat = 0;
-       /* urb_t *urb; */
-       urb_priv_t *lurb_priv;
-       __u32 tdINFO, edHeadP, edTailP;
-
-       tdINFO = m32_swap(td_list->hwINFO);
-
-       ed = td_list->ed;
-       lurb_priv = ed->purb;
-
-       dl_transfer_length(td_list);
-
-       lurb_priv->td_cnt++;
-
-       /* error code of transfer */
-       cc = TD_CC_GET(tdINFO);
-       if (cc) {
-               err("USB-error: %s (%x)", cc_to_string[cc], cc);
-               stat = cc_to_error[cc];
-       }
-
-       /* see if this done list makes for all TD's of current URB,
-       * and mark the URB finished if so */
-       if (lurb_priv->td_cnt == lurb_priv->length)
-               finish_urb(ohci, lurb_priv, ed->state);
-
-       dbg("dl_done_list: processing TD %x, len %x\n",
-               lurb_priv->td_cnt, lurb_priv->length);
-
-       if (ed->state != ED_NEW && (!usb_pipeint(lurb_priv->pipe))) {
-               edHeadP = m32_swap(ed->hwHeadP) & 0xfffffff0;
-               edTailP = m32_swap(ed->hwTailP);
-
-               /* unlink eds if they are not busy */
-               if ((edHeadP == edTailP) && (ed->state == ED_OPER))
-                       ep_unlink(ohci, ed);
-       }
-       return stat;
-}
-
-static int dl_done_list(ohci_t *ohci)
-{
-       int stat = 0;
-       td_t    *td_list = dl_reverse_done_list(ohci);
-
-       while (td_list) {
-               td_t    *td_next = td_list->next_dl_td;
-               stat = takeback_td(ohci, td_list);
-               td_list = td_next;
-       }
-       return stat;
-}
-
-/*-------------------------------------------------------------------------*
- * Virtual Root Hub
- *-------------------------------------------------------------------------*/
-
-/* Device descriptor */
-static __u8 root_hub_dev_des[] =
-{
-       0x12,       /*  __u8  bLength; */
-       0x01,       /*  __u8  bDescriptorType; Device */
-       0x10,       /*  __u16 bcdUSB; v1.1 */
-       0x01,
-       0x09,       /*  __u8  bDeviceClass; HUB_CLASSCODE */
-       0x00,       /*  __u8  bDeviceSubClass; */
-       0x00,       /*  __u8  bDeviceProtocol; */
-       0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
-       0x00,       /*  __u16 idVendor; */
-       0x00,
-       0x00,       /*  __u16 idProduct; */
-       0x00,
-       0x00,       /*  __u16 bcdDevice; */
-       0x00,
-       0x00,       /*  __u8  iManufacturer; */
-       0x01,       /*  __u8  iProduct; */
-       0x00,       /*  __u8  iSerialNumber; */
-       0x01        /*  __u8  bNumConfigurations; */
-};
-
-/* Configuration descriptor */
-static __u8 root_hub_config_des[] =
-{
-       0x09,       /*  __u8  bLength; */
-       0x02,       /*  __u8  bDescriptorType; Configuration */
-       0x19,       /*  __u16 wTotalLength; */
-       0x00,
-       0x01,       /*  __u8  bNumInterfaces; */
-       0x01,       /*  __u8  bConfigurationValue; */
-       0x00,       /*  __u8  iConfiguration; */
-       0x40,       /*  __u8  bmAttributes;
-        Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
-       0x00,       /*  __u8  MaxPower; */
-
-       /* interface */
-       0x09,       /*  __u8  if_bLength; */
-       0x04,       /*  __u8  if_bDescriptorType; Interface */
-       0x00,       /*  __u8  if_bInterfaceNumber; */
-       0x00,       /*  __u8  if_bAlternateSetting; */
-       0x01,       /*  __u8  if_bNumEndpoints; */
-       0x09,       /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
-       0x00,       /*  __u8  if_bInterfaceSubClass; */
-       0x00,       /*  __u8  if_bInterfaceProtocol; */
-       0x00,       /*  __u8  if_iInterface; */
-
-       /* endpoint */
-       0x07,       /*  __u8  ep_bLength; */
-       0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
-       0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
-       0x03,       /*  __u8  ep_bmAttributes; Interrupt */
-       0x02,       /*  __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
-       0x00,
-       0xff        /*  __u8  ep_bInterval; 255 ms */
-};
-
-static unsigned char root_hub_str_index0[] =
-{
-       0x04,                   /*  __u8  bLength; */
-       0x03,                   /*  __u8  bDescriptorType; String-descriptor */
-       0x09,                   /*  __u8  lang ID */
-       0x04,                   /*  __u8  lang ID */
-};
-
-static unsigned char root_hub_str_index1[] =
-{
-       28,                     /*  __u8  bLength; */
-       0x03,                   /*  __u8  bDescriptorType; String-descriptor */
-       'O',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       'H',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       'C',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       'I',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       ' ',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       'R',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       'o',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       'o',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       't',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       ' ',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       'H',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       'u',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-       'b',                    /*  __u8  Unicode */
-       0,                              /*  __u8  Unicode */
-};
-
-/* Hub class-specific descriptor is constructed dynamically */
-
-/*-------------------------------------------------------------------------*/
-
-#define OK(x)                  len = (x); break
-#ifdef DEBUG
-#define WR_RH_STAT(x)          {info("WR:status %#8x", (x)); writel((x), \
-                                               &gohci.regs->roothub.status); }
-#define WR_RH_PORTSTAT(x)      {info("WR:portstatus[%d] %#8x", wIndex-1, \
-               (x)); writel((x), &gohci.regs->roothub.portstatus[wIndex-1]); }
-#else
-#define WR_RH_STAT(x)          writel((x), &gohci.regs->roothub.status)
-#define WR_RH_PORTSTAT(x)      writel((x), \
-                                   &gohci.regs->roothub.portstatus[wIndex-1])
-#endif
-#define RD_RH_STAT             roothub_status(&gohci)
-#define RD_RH_PORTSTAT         roothub_portstatus(&gohci, wIndex-1)
-
-/* request to virtual root hub */
-
-int rh_check_port_status(ohci_t *controller)
-{
-       __u32 temp, ndp, i;
-       int res;
-
-       res = -1;
-       temp = roothub_a(controller);
-       ndp = (temp & RH_A_NDP);
-#ifdef CONFIG_AT91C_PQFP_UHPBUG
-       ndp = (ndp == 2) ? 1:0;
-#endif
-       for (i = 0; i < ndp; i++) {
-               temp = roothub_portstatus(controller, i);
-               /* check for a device disconnect */
-               if (((temp & (RH_PS_PESC | RH_PS_CSC)) ==
-                       (RH_PS_PESC | RH_PS_CSC)) &&
-                       ((temp & RH_PS_CCS) == 0)) {
-                       res = i;
-                       break;
-               }
-       }
-       return res;
-}
-
-static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
-               void *buffer, int transfer_len, struct devrequest *cmd)
-{
-       void *data = buffer;
-       int leni = transfer_len;
-       int len = 0;
-       int stat = 0;
-       __u32 datab[4];
-       __u8 *data_buf = (__u8 *)datab;
-       __u16 bmRType_bReq;
-       __u16 wValue;
-       __u16 wIndex;
-       __u16 wLength;
-
-#ifdef DEBUG
-pkt_print(NULL, dev, pipe, buffer, transfer_len,
-         cmd, "SUB(rh)", usb_pipein(pipe));
-#else
-       wait_ms(1);
-#endif
-       if (usb_pipeint(pipe)) {
-               info("Root-Hub submit IRQ: NOT implemented");
-               return 0;
-       }
-
-       bmRType_bReq  = cmd->requesttype | (cmd->request << 8);
-       wValue        = le16_to_cpu(cmd->value);
-       wIndex        = le16_to_cpu(cmd->index);
-       wLength       = le16_to_cpu(cmd->length);
-
-       info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x",
-               dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength);
-
-       switch (bmRType_bReq) {
-       /* Request Destination:
-          without flags: Device,
-          RH_INTERFACE: interface,
-          RH_ENDPOINT: endpoint,
-          RH_CLASS means HUB here,
-          RH_OTHER | RH_CLASS  almost ever means HUB_PORT here
-       */
-
-       case RH_GET_STATUS:
-               *(__u16 *) data_buf = cpu_to_le16(1);
-               OK(2);
-       case RH_GET_STATUS | RH_INTERFACE:
-               *(__u16 *) data_buf = cpu_to_le16(0);
-               OK(2);
-       case RH_GET_STATUS | RH_ENDPOINT:
-               *(__u16 *) data_buf = cpu_to_le16(0);
-               OK(2);
-       case RH_GET_STATUS | RH_CLASS:
-               *(__u32 *) data_buf = cpu_to_le32(
-                               RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE));
-               OK(4);
-       case RH_GET_STATUS | RH_OTHER | RH_CLASS:
-               *(__u32 *) data_buf = cpu_to_le32(RD_RH_PORTSTAT);
-               OK(4);
-
-       case RH_CLEAR_FEATURE | RH_ENDPOINT:
-               switch (wValue) {
-               case (RH_ENDPOINT_STALL):
-                       OK(0);
-               }
-               break;
-
-       case RH_CLEAR_FEATURE | RH_CLASS:
-               switch (wValue) {
-               case RH_C_HUB_LOCAL_POWER:
-                       OK(0);
-               case (RH_C_HUB_OVER_CURRENT):
-                       WR_RH_STAT(RH_HS_OCIC);
-                       OK(0);
-               }
-               break;
-
-       case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
-               switch (wValue) {
-               case (RH_PORT_ENABLE):        WR_RH_PORTSTAT(RH_PS_CCS);  OK(0);
-               case (RH_PORT_SUSPEND):       WR_RH_PORTSTAT(RH_PS_POCI); OK(0);
-               case (RH_PORT_POWER):         WR_RH_PORTSTAT(RH_PS_LSDA); OK(0);
-               case (RH_C_PORT_CONNECTION):  WR_RH_PORTSTAT(RH_PS_CSC);  OK(0);
-               case (RH_C_PORT_ENABLE):      WR_RH_PORTSTAT(RH_PS_PESC); OK(0);
-               case (RH_C_PORT_SUSPEND):     WR_RH_PORTSTAT(RH_PS_PSSC); OK(0);
-               case (RH_C_PORT_OVER_CURRENT):WR_RH_PORTSTAT(RH_PS_OCIC); OK(0);
-               case (RH_C_PORT_RESET):       WR_RH_PORTSTAT(RH_PS_PRSC); OK(0);
-               }
-               break;
-
-       case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
-               switch (wValue) {
-               case (RH_PORT_SUSPEND):
-                       WR_RH_PORTSTAT(RH_PS_PSS);  OK(0);
-               case (RH_PORT_RESET): /* BUG IN HUP CODE *********/
-                       if (RD_RH_PORTSTAT & RH_PS_CCS)
-                               WR_RH_PORTSTAT(RH_PS_PRS);
-                       OK(0);
-               case (RH_PORT_POWER):
-                       WR_RH_PORTSTAT(RH_PS_PPS);
-                       wait_ms(100);
-                       OK(0);
-               case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/
-                       if (RD_RH_PORTSTAT & RH_PS_CCS)
-                               WR_RH_PORTSTAT(RH_PS_PES);
-                       OK(0);
-               }
-               break;
-
-       case RH_SET_ADDRESS:
-               gohci.rh.devnum = wValue;
-               OK(0);
-
-       case RH_GET_DESCRIPTOR:
-               switch ((wValue & 0xff00) >> 8) {
-               case (0x01): /* device descriptor */
-                       len = min_t(unsigned int,
-                                       leni,
-                                       min_t(unsigned int,
-                                       sizeof(root_hub_dev_des),
-                                       wLength));
-                       data_buf = root_hub_dev_des; OK(len);
-               case (0x02): /* configuration descriptor */
-                       len = min_t(unsigned int,
-                                       leni,
-                                       min_t(unsigned int,
-                                       sizeof(root_hub_config_des),
-                                       wLength));
-                       data_buf = root_hub_config_des; OK(len);
-               case (0x03): /* string descriptors */
-                       if (wValue == 0x0300) {
-                               len = min_t(unsigned int,
-                                               leni,
-                                               min_t(unsigned int,
-                                               sizeof(root_hub_str_index0),
-                                               wLength));
-                               data_buf = root_hub_str_index0;
-                               OK(len);
-                       }
-                       if (wValue == 0x0301) {
-                               len = min_t(unsigned int,
-                                               leni,
-                                               min_t(unsigned int,
-                                               sizeof(root_hub_str_index1),
-                                               wLength));
-                               data_buf = root_hub_str_index1;
-                               OK(len);
-               }
-               default:
-                       stat = USB_ST_STALLED;
-               }
-               break;
-
-       case RH_GET_DESCRIPTOR | RH_CLASS:
-       {
-               __u32 temp = roothub_a(&gohci);
-
-               data_buf [0] = 9;               /* min length; */
-               data_buf [1] = 0x29;
-               data_buf [2] = temp & RH_A_NDP;
-#ifdef CONFIG_AT91C_PQFP_UHPBUG
-               data_buf [2] = (data_buf [2] == 2) ? 1:0;
-#endif
-               data_buf [3] = 0;
-               if (temp & RH_A_PSM)    /* per-port power switching? */
-                       data_buf [3] |= 0x1;
-               if (temp & RH_A_NOCP)   /* no overcurrent reporting? */
-                       data_buf [3] |= 0x10;
-               else if (temp & RH_A_OCPM)/* per-port overcurrent reporting? */
-                       data_buf [3] |= 0x8;
-
-               /* corresponds to data_buf[4-7] */
-               datab [1] = 0;
-               data_buf [5] = (temp & RH_A_POTPGT) >> 24;
-               temp = roothub_b(&gohci);
-               data_buf [7] = temp & RH_B_DR;
-               if (data_buf [2] < 7) {
-                       data_buf [8] = 0xff;
-               } else {
-                       data_buf [0] += 2;
-                       data_buf [8] = (temp & RH_B_DR) >> 8;
-                       data_buf [10] = data_buf [9] = 0xff;
-               }
-
-               len = min_t(unsigned int, leni,
-                           min_t(unsigned int, data_buf [0], wLength));
-               OK(len);
-       }
-
-       case RH_GET_CONFIGURATION:      *(__u8 *) data_buf = 0x01; OK(1);
-
-       case RH_SET_CONFIGURATION:      WR_RH_STAT(0x10000); OK(0);
-
-       default:
-               dbg("unsupported root hub command");
-               stat = USB_ST_STALLED;
-       }
-
-#ifdef DEBUG
-       ohci_dump_roothub(&gohci, 1);
-#else
-       wait_ms(1);
-#endif
-
-       len = min_t(int, len, leni);
-       if (data != data_buf)
-           memcpy(data, data_buf, len);
-       dev->act_len = len;
-       dev->status = stat;
-
-#ifdef DEBUG
-       pkt_print(NULL, dev, pipe, buffer,
-                 transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/);
-#else
-       wait_ms(1);
-#endif
-
-       return stat;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* common code for handling submit messages - used for all but root hub */
-/* accesses. */
-int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-               int transfer_len, struct devrequest *setup, int interval)
-{
-       int stat = 0;
-       int maxsize = usb_maxpacket(dev, pipe);
-       int timeout;
-       urb_priv_t *urb;
-
-       urb = malloc(sizeof(urb_priv_t));
-       memset(urb, 0, sizeof(urb_priv_t));
-
-       urb->dev = dev;
-       urb->pipe = pipe;
-       urb->transfer_buffer = buffer;
-       urb->transfer_buffer_length = transfer_len;
-       urb->interval = interval;
-
-       /* device pulled? Shortcut the action. */
-       if (devgone == dev) {
-               dev->status = USB_ST_CRC_ERR;
-               return 0;
-       }
-
-#ifdef DEBUG
-       urb->actual_length = 0;
-       pkt_print(urb, dev, pipe, buffer, transfer_len,
-                 setup, "SUB", usb_pipein(pipe));
-#else
-       wait_ms(1);
-#endif
-       if (!maxsize) {
-               err("submit_common_message: pipesize for pipe %lx is zero",
-                       pipe);
-               return -1;
-       }
-
-       if (sohci_submit_job(urb, setup) < 0) {
-               err("sohci_submit_job failed");
-               return -1;
-       }
-
-#if 0
-       wait_ms(10);
-       /* ohci_dump_status(&gohci); */
-#endif
-
-       /* allow more time for a BULK device to react - some are slow */
-#define BULK_TO         5000   /* timeout in milliseconds */
-       if (usb_pipebulk(pipe))
-               timeout = BULK_TO;
-       else
-               timeout = 100;
-
-       /* wait for it to complete */
-       for (;;) {
-               /* check whether the controller is done */
-               stat = hc_interrupt();
-               if (stat < 0) {
-                       stat = USB_ST_CRC_ERR;
-                       break;
-               }
-
-               /* NOTE: since we are not interrupt driven in U-Boot and always
-                * handle only one URB at a time, we cannot assume the
-                * transaction finished on the first successful return from
-                * hc_interrupt().. unless the flag for current URB is set,
-                * meaning that all TD's to/from device got actually
-                * transferred and processed. If the current URB is not
-                * finished we need to re-iterate this loop so as
-                * hc_interrupt() gets called again as there needs to be some
-                * more TD's to process still */
-               if ((stat >= 0) && (stat != 0xff) && (urb->finished)) {
-                       /* 0xff is returned for an SF-interrupt */
-                       break;
-               }
-
-               if (--timeout) {
-                       wait_ms(1);
-                       if (!urb->finished)
-                               dbg("*");
-
-               } else {
-                       err("CTL:TIMEOUT ");
-                       dbg("submit_common_msg: TO status %x\n", stat);
-                       urb->finished = 1;
-                       stat = USB_ST_CRC_ERR;
-                       break;
-               }
-       }
-
-       dev->status = stat;
-       dev->act_len = transfer_len;
-
-#ifdef DEBUG
-       pkt_print(urb, dev, pipe, buffer, transfer_len,
-                 setup, "RET(ctlr)", usb_pipein(pipe));
-#else
-       wait_ms(1);
-#endif
-
-       /* free TDs in urb_priv */
-       if (!usb_pipeint(pipe))
-               urb_free_priv(urb);
-       return 0;
-}
-
-/* submit routines called from usb.c */
-int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-               int transfer_len)
-{
-       info("submit_bulk_msg");
-       return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0);
-}
-
-int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-               int transfer_len, struct devrequest *setup)
-{
-       int maxsize = usb_maxpacket(dev, pipe);
-
-       info("submit_control_msg");
-#ifdef DEBUG
-       pkt_print(NULL, dev, pipe, buffer, transfer_len,
-                 setup, "SUB", usb_pipein(pipe));
-#else
-       wait_ms(1);
-#endif
-       if (!maxsize) {
-               err("submit_control_message: pipesize for pipe %lx is zero",
-                       pipe);
-               return -1;
-       }
-       if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) {
-               gohci.rh.dev = dev;
-               /* root hub - redirect */
-               return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len,
-                       setup);
-       }
-
-       return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0);
-}
-
-int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-               int transfer_len, int interval)
-{
-       info("submit_int_msg");
-       return submit_common_msg(dev, pipe, buffer, transfer_len, NULL,
-                       interval);
-}
-
-/*-------------------------------------------------------------------------*
- * HC functions
- *-------------------------------------------------------------------------*/
-
-/* reset the HC and BUS */
-
-static int hc_reset(ohci_t *ohci)
-{
-#ifdef CONFIG_PCI_EHCI_DEVNO
-       pci_dev_t pdev;
-#endif
-       int timeout = 30;
-       int smm_timeout = 50; /* 0,5 sec */
-
-       dbg("%s\n", __FUNCTION__);
-
-#ifdef CONFIG_PCI_EHCI_DEVNO
-       /*
-        *  Some multi-function controllers (e.g. ISP1562) allow root hub
-        * resetting via EHCI registers only.
-        */
-       pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVNO);
-       if (pdev != -1) {
-               u32 base;
-               int timeout = 1000;
-
-               pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &base);
-               writel(readl(base + EHCI_USBCMD_OFF) | EHCI_USBCMD_HCRESET,
-                       base + EHCI_USBCMD_OFF);
-
-               while (readl(base + EHCI_USBCMD_OFF) & EHCI_USBCMD_HCRESET) {
-                       if (timeout-- <= 0) {
-                               printf("USB RootHub reset timed out!");
-                               break;
-                       }
-                       udelay(1);
-               }
-       } else
-               printf("No EHCI func at %d index!\n", CONFIG_PCI_EHCI_DEVNO);
-#endif
-       if (readl(&ohci->regs->control) & OHCI_CTRL_IR) {
-               /* SMM owns the HC */
-               writel(OHCI_OCR, &ohci->regs->cmdstatus);/* request ownership */
-               info("USB HC TakeOver from SMM");
-               while (readl(&ohci->regs->control) & OHCI_CTRL_IR) {
-                       wait_ms(10);
-                       if (--smm_timeout == 0) {
-                               err("USB HC TakeOver failed!");
-                               return -1;
-                       }
-               }
-       }
-
-       /* Disable HC interrupts */
-       writel(OHCI_INTR_MIE, &ohci->regs->intrdisable);
-
-       dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;\n",
-               ohci->slot_name,
-               readl(&ohci->regs->control));
-
-       /* Reset USB (needed by some controllers) */
-       ohci->hc_control = 0;
-       writel(ohci->hc_control, &ohci->regs->control);
-
-       /* HC Reset requires max 10 us delay */
-       writel(OHCI_HCR,  &ohci->regs->cmdstatus);
-       while ((readl(&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
-               if (--timeout == 0) {
-                       err("USB HC reset timed out!");
-                       return -1;
-               }
-               udelay(1);
-       }
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* Start an OHCI controller, set the BUS operational
- * enable interrupts
- * connect the virtual root hub */
-
-static int hc_start(ohci_t *ohci)
-{
-       __u32 mask;
-       unsigned int fminterval;
-
-       ohci->disabled = 1;
-
-       /* Tell the controller where the control and bulk lists are
-        * The lists are empty now. */
-
-       writel(0, &ohci->regs->ed_controlhead);
-       writel(0, &ohci->regs->ed_bulkhead);
-
-       writel((__u32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */
-
-       fminterval = 0x2edf;
-       writel((fminterval * 9) / 10, &ohci->regs->periodicstart);
-       fminterval |= ((((fminterval - 210) * 6) / 7) << 16);
-       writel(fminterval, &ohci->regs->fminterval);
-       writel(0x628, &ohci->regs->lsthresh);
-
-       /* start controller operations */
-       ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
-       ohci->disabled = 0;
-       writel(ohci->hc_control, &ohci->regs->control);
-
-       /* disable all interrupts */
-       mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD |
-                       OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC |
-                       OHCI_INTR_OC | OHCI_INTR_MIE);
-       writel(mask, &ohci->regs->intrdisable);
-       /* clear all interrupts */
-       mask &= ~OHCI_INTR_MIE;
-       writel(mask, &ohci->regs->intrstatus);
-       /* Choose the interrupts we care about now  - but w/o MIE */
-       mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO;
-       writel(mask, &ohci->regs->intrenable);
-
-#ifdef OHCI_USE_NPS
-       /* required for AMD-756 and some Mac platforms */
-       writel((roothub_a(ohci) | RH_A_NPS) & ~RH_A_PSM,
-               &ohci->regs->roothub.a);
-       writel(RH_HS_LPSC, &ohci->regs->roothub.status);
-#endif /* OHCI_USE_NPS */
-
-#define mdelay(n) ({unsigned long msec = (n); while (msec--) udelay(1000); })
-       /* POTPGT delay is bits 24-31, in 2 ms units. */
-       mdelay((roothub_a(ohci) >> 23) & 0x1fe);
-
-       /* connect the virtual root hub */
-       ohci->rh.devnum = 0;
-
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* Poll USB interrupt. */
-void usb_event_poll(void)
-{
-       hc_interrupt();
-}
-
-/* an interrupt happens */
-
-static int hc_interrupt(void)
-{
-       ohci_t *ohci = &gohci;
-       struct ohci_regs *regs = ohci->regs;
-       int ints;
-       int stat = -1;
-
-       if ((ohci->hcca->done_head != 0) &&
-                               !(m32_swap(ohci->hcca->done_head) & 0x01)) {
-               ints =  OHCI_INTR_WDH;
-       } else {
-               ints = readl(&regs->intrstatus);
-               if (ints == ~(u32)0) {
-                       ohci->disabled++;
-                       err("%s device removed!", ohci->slot_name);
-                       return -1;
-               } else {
-                       ints &= readl(&regs->intrenable);
-                       if (ints == 0) {
-                               dbg("hc_interrupt: returning..\n");
-                               return 0xff;
-                       }
-               }
-       }
-
-       /* dbg("Interrupt: %x frame: %x", ints,
-                                       le16_to_cpu(ohci->hcca->frame_no)); */
-
-       if (ints & OHCI_INTR_RHSC)
-               stat = 0xff;
-
-       if (ints & OHCI_INTR_UE) {
-               ohci->disabled++;
-               err("OHCI Unrecoverable Error, controller usb-%s disabled",
-                       ohci->slot_name);
-               /* e.g. due to PCI Master/Target Abort */
-
-#ifdef DEBUG
-               ohci_dump(ohci, 1);
-#else
-               wait_ms(1);
-#endif
-               /* FIXME: be optimistic, hope that bug won't repeat often. */
-               /* Make some non-interrupt context restart the controller. */
-               /* Count and limit the retries though; either hardware or */
-               /* software errors can go forever... */
-               hc_reset(ohci);
-               return -1;
-       }
-
-       if (ints & OHCI_INTR_WDH) {
-               wait_ms(1);
-               writel(OHCI_INTR_WDH, &regs->intrdisable);
-               (void)readl(&regs->intrdisable); /* flush */
-               stat = dl_done_list(&gohci);
-               writel(OHCI_INTR_WDH, &regs->intrenable);
-               (void)readl(&regs->intrdisable); /* flush */
-       }
-
-       if (ints & OHCI_INTR_SO) {
-               dbg("USB Schedule overrun\n");
-               writel(OHCI_INTR_SO, &regs->intrenable);
-               stat = -1;
-       }
-
-       /* FIXME:  this assumes SOF (1/ms) interrupts don't get lost... */
-       if (ints & OHCI_INTR_SF) {
-               unsigned int frame = m16_swap(ohci->hcca->frame_no) & 1;
-               wait_ms(1);
-               writel(OHCI_INTR_SF, &regs->intrdisable);
-               if (ohci->ed_rm_list[frame] != NULL)
-                       writel(OHCI_INTR_SF, &regs->intrenable);
-               stat = 0xff;
-       }
-
-       writel(ints, &regs->intrstatus);
-       return stat;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*-------------------------------------------------------------------------*/
-
-/* De-allocate all resources.. */
-
-static void hc_release_ohci(ohci_t *ohci)
-{
-       dbg("USB HC release ohci usb-%s", ohci->slot_name);
-
-       if (!ohci->disabled)
-               hc_reset(ohci);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * low level initalisation routine, called from usb.c
- */
-static char ohci_inited = 0;
-
-int usb_lowlevel_init(void)
-{
-#ifdef CONFIG_PCI_OHCI
-       pci_dev_t pdev;
-#endif
-
-#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT
-       /* cpu dependant init */
-       if (usb_cpu_init())
-               return -1;
-#endif
-
-#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT
-       /*  board dependant init */
-       if (usb_board_init())
-               return -1;
-#endif
-       memset(&gohci, 0, sizeof(ohci_t));
-
-       /* align the storage */
-       if ((__u32)&ghcca[0] & 0xff) {
-               err("HCCA not aligned!!");
-               return -1;
-       }
-       phcca = &ghcca[0];
-       info("aligned ghcca %p", phcca);
-       memset(&ohci_dev, 0, sizeof(struct ohci_device));
-       if ((__u32)&ohci_dev.ed[0] & 0x7) {
-               err("EDs not aligned!!");
-               return -1;
-       }
-       memset(gtd, 0, sizeof(td_t) * (NUM_TD + 1));
-       if ((__u32)gtd & 0x7) {
-               err("TDs not aligned!!");
-               return -1;
-       }
-       ptd = gtd;
-       gohci.hcca = phcca;
-       memset(phcca, 0, sizeof(struct ohci_hcca));
-
-       gohci.disabled = 1;
-       gohci.sleeping = 0;
-       gohci.irq = -1;
-#ifdef CONFIG_PCI_OHCI
-       pdev = pci_find_devices(ohci_pci_ids, CONFIG_PCI_OHCI_DEVNO);
-
-       if (pdev != -1) {
-               u16 vid, did;
-               u32 base;
-               pci_read_config_word(pdev, PCI_VENDOR_ID, &vid);
-               pci_read_config_word(pdev, PCI_DEVICE_ID, &did);
-               printf("OHCI pci controller (%04x, %04x) found @(%d:%d:%d)\n",
-                               vid, did, (pdev >> 16) & 0xff,
-                               (pdev >> 11) & 0x1f, (pdev >> 8) & 0x7);
-               pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &base);
-               printf("OHCI regs address 0x%08x\n", base);
-               gohci.regs = (struct ohci_regs *)base;
-       } else
-               return -1;
-#else
-       gohci.regs = (struct ohci_regs *)CONFIG_SYS_USB_OHCI_REGS_BASE;
-#endif
-
-       gohci.flags = 0;
-       gohci.slot_name = CONFIG_SYS_USB_OHCI_SLOT_NAME;
-
-       if (hc_reset (&gohci) < 0) {
-               hc_release_ohci (&gohci);
-               err ("can't reset usb-%s", gohci.slot_name);
-#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT
-               /* board dependant cleanup */
-               usb_board_init_fail();
-#endif
-
-#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT
-               /* cpu dependant cleanup */
-               usb_cpu_init_fail();
-#endif
-               return -1;
-       }
-
-       if (hc_start(&gohci) < 0) {
-               err("can't start usb-%s", gohci.slot_name);
-               hc_release_ohci(&gohci);
-               /* Initialization failed */
-#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT
-               /* board dependant cleanup */
-               usb_board_stop();
-#endif
-
-#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT
-               /* cpu dependant cleanup */
-               usb_cpu_stop();
-#endif
-               return -1;
-       }
-
-#ifdef DEBUG
-       ohci_dump(&gohci, 1);
-#else
-       wait_ms(1);
-#endif
-       ohci_inited = 1;
-       return 0;
-}
-
-int usb_lowlevel_stop(void)
-{
-       /* this gets called really early - before the controller has */
-       /* even been initialized! */
-       if (!ohci_inited)
-               return 0;
-       /* TODO release any interrupts, etc. */
-       /* call hc_release_ohci() here ? */
-       hc_reset(&gohci);
-
-#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT
-       /* board dependant cleanup */
-       if (usb_board_stop())
-               return -1;
-#endif
-
-#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT
-       /* cpu dependant cleanup */
-       if (usb_cpu_stop())
-               return -1;
-#endif
-       /* This driver is no longer initialised. It needs a new low-level
-        * init (board/cpu) before it can be used again. */
-       ohci_inited = 0;
-       return 0;
-}
diff --git a/drivers/usb/usb_ohci.h b/drivers/usb/usb_ohci.h
deleted file mode 100644 (file)
index a547337..0000000
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
- * URB OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
- *
- * usb-ohci.h
- */
-
-/* functions for doing board or CPU specific setup/cleanup */
-extern int usb_board_init(void);
-extern int usb_board_stop(void);
-extern int usb_board_init_fail(void);
-
-extern int usb_cpu_init(void);
-extern int usb_cpu_stop(void);
-extern int usb_cpu_init_fail(void);
-
-
-static int cc_to_error[16] = {
-
-/* mapping of the OHCI CC status to error codes */
-       /* No  Error  */               0,
-       /* CRC Error  */               USB_ST_CRC_ERR,
-       /* Bit Stuff  */               USB_ST_BIT_ERR,
-       /* Data Togg  */               USB_ST_CRC_ERR,
-       /* Stall      */               USB_ST_STALLED,
-       /* DevNotResp */               -1,
-       /* PIDCheck   */               USB_ST_BIT_ERR,
-       /* UnExpPID   */               USB_ST_BIT_ERR,
-       /* DataOver   */               USB_ST_BUF_ERR,
-       /* DataUnder  */               USB_ST_BUF_ERR,
-       /* reservd    */               -1,
-       /* reservd    */               -1,
-       /* BufferOver */               USB_ST_BUF_ERR,
-       /* BuffUnder  */               USB_ST_BUF_ERR,
-       /* Not Access */               -1,
-       /* Not Access */               -1
-};
-
-static const char *cc_to_string[16] = {
-       "No Error",
-       "CRC: Last data packet from endpoint contained a CRC error.",
-       "BITSTUFFING: Last data packet from endpoint contained a bit " \
-                    "stuffing violation",
-       "DATATOGGLEMISMATCH: Last packet from endpoint had data toggle PID\n" \
-                    "that did not match the expected value.",
-       "STALL: TD was moved to the Done Queue because the endpoint returned" \
-                    " a STALL PID",
-       "DEVICENOTRESPONDING: Device did not respond to token (IN) or did\n" \
-                    "not provide a handshake (OUT)",
-       "PIDCHECKFAILURE: Check bits on PID from endpoint failed on data PID\n"\
-                    "(IN) or handshake (OUT)",
-       "UNEXPECTEDPID: Receive PID was not valid when encountered or PID\n" \
-                    "value is not defined.",
-       "DATAOVERRUN: The amount of data returned by the endpoint exceeded\n" \
-                    "either the size of the maximum data packet allowed\n" \
-                    "from the endpoint (found in MaximumPacketSize field\n" \
-                    "of ED) or the remaining buffer size.",
-       "DATAUNDERRUN: The endpoint returned less than MaximumPacketSize\n" \
-                    "and that amount was not sufficient to fill the\n" \
-                    "specified buffer",
-       "reserved1",
-       "reserved2",
-       "BUFFEROVERRUN: During an IN, HC received data from endpoint faster\n" \
-                    "than it could be written to system memory",
-       "BUFFERUNDERRUN: During an OUT, HC could not retrieve data from\n" \
-                    "system memory fast enough to keep up with data USB " \
-                    "data rate.",
-       "NOT ACCESSED: This code is set by software before the TD is placed" \
-                    "on a list to be processed by the HC.(1)",
-       "NOT ACCESSED: This code is set by software before the TD is placed" \
-                    "on a list to be processed by the HC.(2)",
-};
-
-/* ED States */
-
-#define ED_NEW         0x00
-#define ED_UNLINK      0x01
-#define ED_OPER                0x02
-#define ED_DEL         0x04
-#define ED_URB_DEL     0x08
-
-/* usb_ohci_ed */
-struct ed {
-       __u32 hwINFO;
-       __u32 hwTailP;
-       __u32 hwHeadP;
-       __u32 hwNextED;
-
-       struct ed *ed_prev;
-       __u8 int_period;
-       __u8 int_branch;
-       __u8 int_load;
-       __u8 int_interval;
-       __u8 state;
-       __u8 type;
-       __u16 last_iso;
-       struct ed *ed_rm_list;
-
-       struct usb_device *usb_dev;
-       void *purb;
-       __u32 unused[2];
-} __attribute((aligned(16)));
-typedef struct ed ed_t;
-
-
-/* TD info field */
-#define TD_CC      0xf0000000
-#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
-#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
-#define TD_EC      0x0C000000
-#define TD_T       0x03000000
-#define TD_T_DATA0  0x02000000
-#define TD_T_DATA1  0x03000000
-#define TD_T_TOGGLE 0x00000000
-#define TD_R       0x00040000
-#define TD_DI      0x00E00000
-#define TD_DI_SET(X) (((X) & 0x07)<< 21)
-#define TD_DP      0x00180000
-#define TD_DP_SETUP 0x00000000
-#define TD_DP_IN    0x00100000
-#define TD_DP_OUT   0x00080000
-
-#define TD_ISO     0x00010000
-#define TD_DEL     0x00020000
-
-/* CC Codes */
-#define TD_CC_NOERROR     0x00
-#define TD_CC_CRC         0x01
-#define TD_CC_BITSTUFFING  0x02
-#define TD_CC_DATATOGGLEM  0x03
-#define TD_CC_STALL       0x04
-#define TD_DEVNOTRESP     0x05
-#define TD_PIDCHECKFAIL           0x06
-#define TD_UNEXPECTEDPID   0x07
-#define TD_DATAOVERRUN    0x08
-#define TD_DATAUNDERRUN           0x09
-#define TD_BUFFEROVERRUN   0x0C
-#define TD_BUFFERUNDERRUN  0x0D
-#define TD_NOTACCESSED    0x0F
-
-
-#define MAXPSW 1
-
-struct td {
-       __u32 hwINFO;
-       __u32 hwCBP;            /* Current Buffer Pointer */
-       __u32 hwNextTD;         /* Next TD Pointer */
-       __u32 hwBE;             /* Memory Buffer End Pointer */
-
-/* #ifndef CONFIG_MPC5200 /\* this seems wrong *\/ */
-       __u16 hwPSW[MAXPSW];
-/* #endif */
-       __u8 unused;
-       __u8 index;
-       struct ed *ed;
-       struct td *next_dl_td;
-       struct usb_device *usb_dev;
-       int transfer_len;
-       __u32 data;
-
-       __u32 unused2[2];
-} __attribute((aligned(32)));
-typedef struct td td_t;
-
-#define OHCI_ED_SKIP   (1 << 14)
-
-/*
- * The HCCA (Host Controller Communications Area) is a 256 byte
- * structure defined in the OHCI spec. that the host controller is
- * told the base address of.  It must be 256-byte aligned.
- */
-
-#define NUM_INTS 32    /* part of the OHCI standard */
-struct ohci_hcca {
-       __u32   int_table[NUM_INTS];    /* Interrupt ED table */
-#if defined(CONFIG_MPC5200)
-       __u16   pad1;                   /* set to 0 on each frame_no change */
-       __u16   frame_no;               /* current frame number */
-#else
-       __u16   frame_no;               /* current frame number */
-       __u16   pad1;                   /* set to 0 on each frame_no change */
-#endif
-       __u32   done_head;              /* info returned for an interrupt */
-       u8              reserved_for_hc[116];
-} __attribute((aligned(256)));
-
-
-/*
- * Maximum number of root hub ports.
- */
-#ifndef CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS
-# error "CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS undefined!"
-#endif
-
-/*
- * This is the structure of the OHCI controller's memory mapped I/O
- * region.  This is Memory Mapped I/O. You must use the readl() and
- * writel() macros defined in asm/io.h to access these!!
- */
-struct ohci_regs {
-       /* control and status registers */
-       __u32   revision;
-       __u32   control;
-       __u32   cmdstatus;
-       __u32   intrstatus;
-       __u32   intrenable;
-       __u32   intrdisable;
-       /* memory pointers */
-       __u32   hcca;
-       __u32   ed_periodcurrent;
-       __u32   ed_controlhead;
-       __u32   ed_controlcurrent;
-       __u32   ed_bulkhead;
-       __u32   ed_bulkcurrent;
-       __u32   donehead;
-       /* frame counters */
-       __u32   fminterval;
-       __u32   fmremaining;
-       __u32   fmnumber;
-       __u32   periodicstart;
-       __u32   lsthresh;
-       /* Root hub ports */
-       struct  ohci_roothub_regs {
-               __u32   a;
-               __u32   b;
-               __u32   status;
-               __u32   portstatus[CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS];
-       } roothub;
-} __attribute((aligned(32)));
-
-/* Some EHCI controls */
-#define EHCI_USBCMD_OFF                0x20
-#define EHCI_USBCMD_HCRESET    (1 << 1)
-
-/* OHCI CONTROL AND STATUS REGISTER MASKS */
-
-/*
- * HcControl (control) register masks
- */
-#define OHCI_CTRL_CBSR (3 << 0)        /* control/bulk service ratio */
-#define OHCI_CTRL_PLE  (1 << 2)        /* periodic list enable */
-#define OHCI_CTRL_IE   (1 << 3)        /* isochronous enable */
-#define OHCI_CTRL_CLE  (1 << 4)        /* control list enable */
-#define OHCI_CTRL_BLE  (1 << 5)        /* bulk list enable */
-#define OHCI_CTRL_HCFS (3 << 6)        /* host controller functional state */
-#define OHCI_CTRL_IR   (1 << 8)        /* interrupt routing */
-#define OHCI_CTRL_RWC  (1 << 9)        /* remote wakeup connected */
-#define OHCI_CTRL_RWE  (1 << 10)       /* remote wakeup enable */
-
-/* pre-shifted values for HCFS */
-#      define OHCI_USB_RESET   (0 << 6)
-#      define OHCI_USB_RESUME  (1 << 6)
-#      define OHCI_USB_OPER    (2 << 6)
-#      define OHCI_USB_SUSPEND (3 << 6)
-
-/*
- * HcCommandStatus (cmdstatus) register masks
- */
-#define OHCI_HCR       (1 << 0)        /* host controller reset */
-#define OHCI_CLF       (1 << 1)        /* control list filled */
-#define OHCI_BLF       (1 << 2)        /* bulk list filled */
-#define OHCI_OCR       (1 << 3)        /* ownership change request */
-#define OHCI_SOC       (3 << 16)       /* scheduling overrun count */
-
-/*
- * masks used with interrupt registers:
- * HcInterruptStatus (intrstatus)
- * HcInterruptEnable (intrenable)
- * HcInterruptDisable (intrdisable)
- */
-#define OHCI_INTR_SO   (1 << 0)        /* scheduling overrun */
-#define OHCI_INTR_WDH  (1 << 1)        /* writeback of done_head */
-#define OHCI_INTR_SF   (1 << 2)        /* start frame */
-#define OHCI_INTR_RD   (1 << 3)        /* resume detect */
-#define OHCI_INTR_UE   (1 << 4)        /* unrecoverable error */
-#define OHCI_INTR_FNO  (1 << 5)        /* frame number overflow */
-#define OHCI_INTR_RHSC (1 << 6)        /* root hub status change */
-#define OHCI_INTR_OC   (1 << 30)       /* ownership change */
-#define OHCI_INTR_MIE  (1 << 31)       /* master interrupt enable */
-
-
-/* Virtual Root HUB */
-struct virt_root_hub {
-       int devnum; /* Address of Root Hub endpoint */
-       void *dev;  /* was urb */
-       void *int_addr;
-       int send;
-       int interval;
-};
-
-/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */
-
-/* destination of request */
-#define RH_INTERFACE              0x01
-#define RH_ENDPOINT               0x02
-#define RH_OTHER                  0x03
-
-#define RH_CLASS                  0x20
-#define RH_VENDOR                 0x40
-
-/* Requests: bRequest << 8 | bmRequestType */
-#define RH_GET_STATUS          0x0080
-#define RH_CLEAR_FEATURE       0x0100
-#define RH_SET_FEATURE         0x0300
-#define RH_SET_ADDRESS         0x0500
-#define RH_GET_DESCRIPTOR      0x0680
-#define RH_SET_DESCRIPTOR      0x0700
-#define RH_GET_CONFIGURATION   0x0880
-#define RH_SET_CONFIGURATION   0x0900
-#define RH_GET_STATE           0x0280
-#define RH_GET_INTERFACE       0x0A80
-#define RH_SET_INTERFACE       0x0B00
-#define RH_SYNC_FRAME          0x0C80
-/* Our Vendor Specific Request */
-#define RH_SET_EP              0x2000
-
-
-/* Hub port features */
-#define RH_PORT_CONNECTION        0x00
-#define RH_PORT_ENABLE            0x01
-#define RH_PORT_SUSPEND                   0x02
-#define RH_PORT_OVER_CURRENT      0x03
-#define RH_PORT_RESET             0x04
-#define RH_PORT_POWER             0x08
-#define RH_PORT_LOW_SPEED         0x09
-
-#define RH_C_PORT_CONNECTION      0x10
-#define RH_C_PORT_ENABLE          0x11
-#define RH_C_PORT_SUSPEND         0x12
-#define RH_C_PORT_OVER_CURRENT    0x13
-#define RH_C_PORT_RESET                   0x14
-
-/* Hub features */
-#define RH_C_HUB_LOCAL_POWER      0x00
-#define RH_C_HUB_OVER_CURRENT     0x01
-
-#define RH_DEVICE_REMOTE_WAKEUP           0x00
-#define RH_ENDPOINT_STALL         0x01
-
-#define RH_ACK                    0x01
-#define RH_REQ_ERR                -1
-#define RH_NACK                           0x00
-
-
-/* OHCI ROOT HUB REGISTER MASKS */
-
-/* roothub.portstatus [i] bits */
-#define RH_PS_CCS           0x00000001         /* current connect status */
-#define RH_PS_PES           0x00000002         /* port enable status*/
-#define RH_PS_PSS           0x00000004         /* port suspend status */
-#define RH_PS_POCI          0x00000008         /* port over current indicator */
-#define RH_PS_PRS           0x00000010         /* port reset status */
-#define RH_PS_PPS           0x00000100         /* port power status */
-#define RH_PS_LSDA          0x00000200         /* low speed device attached */
-#define RH_PS_CSC           0x00010000         /* connect status change */
-#define RH_PS_PESC          0x00020000         /* port enable status change */
-#define RH_PS_PSSC          0x00040000         /* port suspend status change */
-#define RH_PS_OCIC          0x00080000         /* over current indicator change */
-#define RH_PS_PRSC          0x00100000         /* port reset status change */
-
-/* roothub.status bits */
-#define RH_HS_LPS           0x00000001         /* local power status */
-#define RH_HS_OCI           0x00000002         /* over current indicator */
-#define RH_HS_DRWE          0x00008000         /* device remote wakeup enable */
-#define RH_HS_LPSC          0x00010000         /* local power status change */
-#define RH_HS_OCIC          0x00020000         /* over current indicator change */
-#define RH_HS_CRWE          0x80000000         /* clear remote wakeup enable */
-
-/* roothub.b masks */
-#define RH_B_DR                0x0000ffff              /* device removable flags */
-#define RH_B_PPCM      0xffff0000              /* port power control mask */
-
-/* roothub.a masks */
-#define RH_A_NDP       (0xff << 0)             /* number of downstream ports */
-#define RH_A_PSM       (1 << 8)                /* power switching mode */
-#define RH_A_NPS       (1 << 9)                /* no power switching */
-#define RH_A_DT                (1 << 10)               /* device type (mbz) */
-#define RH_A_OCPM      (1 << 11)               /* over current protection mode */
-#define RH_A_NOCP      (1 << 12)               /* no over current protection */
-#define RH_A_POTPGT    (0xff << 24)            /* power on to power good time */
-
-/* urb */
-#define N_URB_TD 48
-typedef struct
-{
-       ed_t *ed;
-       __u16 length;   /* number of tds associated with this request */
-       __u16 td_cnt;   /* number of tds already serviced */
-       struct usb_device *dev;
-       int   state;
-       unsigned long pipe;
-       void *transfer_buffer;
-       int transfer_buffer_length;
-       int interval;
-       int actual_length;
-       int finished;
-       td_t *td[N_URB_TD];     /* list pointer to all corresponding TDs associated with this request */
-} urb_priv_t;
-#define URB_DEL 1
-
-/*
- * This is the full ohci controller description
- *
- * Note how the "proper" USB information is just
- * a subset of what the full implementation needs. (Linus)
- */
-
-
-typedef struct ohci {
-       struct ohci_hcca *hcca;         /* hcca */
-       /*dma_addr_t hcca_dma;*/
-
-       int irq;
-       int disabled;                   /* e.g. got a UE, we're hung */
-       int sleeping;
-       unsigned long flags;            /* for HC bugs */
-
-       struct ohci_regs *regs; /* OHCI controller's memory */
-
-       int ohci_int_load[32];   /* load of the 32 Interrupt Chains (for load balancing)*/
-       ed_t *ed_rm_list[2];     /* lists of all endpoints to be removed */
-       ed_t *ed_bulktail;       /* last endpoint of bulk list */
-       ed_t *ed_controltail;    /* last endpoint of control list */
-       int intrstatus;
-       __u32 hc_control;               /* copy of the hc control reg */
-       struct usb_device *dev[32];
-       struct virt_root_hub rh;
-
-       const char      *slot_name;
-} ohci_t;
-
-#define NUM_EDS 8              /* num of preallocated endpoint descriptors */
-
-struct ohci_device {
-       ed_t    ed[NUM_EDS];
-       int ed_cnt;
-};
-
-/* hcd */
-/* endpoint */
-static int ep_link(ohci_t * ohci, ed_t * ed);
-static int ep_unlink(ohci_t * ohci, ed_t * ed);
-static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned long pipe,
-               int interval, int load);
-
-/*-------------------------------------------------------------------------*/
-
-/* we need more TDs than EDs */
-#define NUM_TD 64
-
-/* +1 so we can align the storage */
-td_t gtd[NUM_TD+1];
-/* pointers to aligned storage */
-td_t *ptd;
-
-/* TDs ... */
-static inline struct td *
-td_alloc (struct usb_device *usb_dev)
-{
-       int i;
-       struct td       *td;
-
-       td = NULL;
-       for (i = 0; i < NUM_TD; i++)
-       {
-               if (ptd[i].usb_dev == NULL)
-               {
-                       td = &ptd[i];
-                       td->usb_dev = usb_dev;
-                       break;
-               }
-       }
-
-       return td;
-}
-
-static inline void
-ed_free (struct ed *ed)
-{
-       ed->usb_dev = NULL;
-}
diff --git a/drivers/usb/usbdcore.c b/drivers/usb/usbdcore.c
deleted file mode 100644 (file)
index 53ed669..0000000
+++ /dev/null
@@ -1,683 +0,0 @@
-/*
- * (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)
-{
-       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(%zu) 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/usb/usbdcore_ep0.c b/drivers/usb/usbdcore_ep0.c
deleted file mode 100644 (file)
index f6e017d..0000000
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- * (C) Copyright 2003
- * Gerry Hamel, geh@ti.com, Texas Instruments
- *
- * (C) Copyright 2006
- * Bryan O'Donoghue, deckard@CodeHermit.ie
- *
- * 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
- *
- * As alluded to above, a simple callback cdc_recv_setup has been implemented
- * in the usb_device data structure to facilicate passing
- * Common Device Class packets to a function driver.
- *
- * XXX
- */
-
-#include <common.h>
-#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 = (char*)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.
- */
-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;
-       }
-       length = max_length;
-
-       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 = (char*)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;
-
-               }
-               dbg_ep0(3, "copied device configuration, actual_length: 0x%x", urb->actual_length);
-               break;
-
-       case USB_DESCRIPTOR_TYPE_CONFIGURATION:
-               {
-                       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;
-                       }
-                       dbg_ep0(0, "attempt to copy %d bytes to urb\n",cpu_to_le16(configuration_descriptor->wTotalLength));
-                       copy_config (urb, configuration_descriptor,
-
-                                       cpu_to_le16(configuration_descriptor->wTotalLength),
-                                    max);
-               }
-
-               break;
-
-       case USB_DESCRIPTOR_TYPE_STRING:
-               {
-                       struct usb_string_descriptor *string_descriptor;
-                       if (!(string_descriptor = usbd_get_string (index))) {
-                               serial_printf("Invalid string index %d\n", index);
-                               return -1;
-                       }
-                       dbg_ep0(3, "string_descriptor: %p length %d", string_descriptor, string_descriptor->bLength);
-                       copy_config (urb, string_descriptor, string_descriptor->bLength, max);
-               }
-               break;
-       case USB_DESCRIPTOR_TYPE_INTERFACE:
-       serial_printf("USB_DESCRIPTOR_TYPE_INTERFACE - error not implemented\n");
-               return -1;
-       case USB_DESCRIPTOR_TYPE_ENDPOINT:
-               serial_printf("USB_DESCRIPTOR_TYPE_ENDPOINT - error not implemented\n");
-               return -1;
-       case USB_DESCRIPTOR_TYPE_HID:
-               {
-                       serial_printf("USB_DESCRIPTOR_TYPE_HID - error not implemented\n");
-                       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:
-               {
-                       serial_printf("USB_DESCRIPTOR_TYPE_REPORT - error not implemented\n");
-                       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;
-       case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
-               {
-                       /* If a USB device supports both a full speed and low speed operation
-                        * we must send a Device_Qualifier descriptor here
-                        */
-                       return -1;
-               }
-       default:
-               return -1;
-       }
-
-
-       dbg_ep0 (1, "urb: buffer: %p buffer_length: %2d actual_length: %2d tx_packetSize: %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) {
-               if(device->device_state <= STATE_CONFIGURED){
-                       /*      Attempt to handle a CDC specific request if we are
-                        *      in the configured state.
-                        */
-                       return device->cdc_recv_setup(request,urb);
-               }
-               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:
-                       serial_printf("get config %d\n", device->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); */
-
-                       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 */
-                       device->configuration = le16_to_cpu(request->wValue) & 0xff;
-
-                       /* 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;
-}
diff --git a/drivers/usb/usbdcore_mpc8xx.c b/drivers/usb/usbdcore_mpc8xx.c
deleted file mode 100644 (file)
index 0e311ad..0000000
+++ /dev/null
@@ -1,1398 +0,0 @@
-/*
- * Copyright (C) 2006 by Bryan O'Donoghue, CodeHermit
- * bodonoghue@CodeHermit.ie
- *
- * References
- * DasUBoot/drivers/usb/usbdcore_omap1510.c, for design and implementation
- * ideas.
- *
- * 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.
- *
- */
-
-/*
- * Notes :
- * 1.  #define __SIMULATE_ERROR__ to inject a CRC error into every 2nd TX
- *             packet to force the USB re-transmit protocol.
- *
- * 2.  #define __DEBUG_UDC__ to switch on debug tracing to serial console
- *     be careful that tracing doesn't create Hiesen-bugs with respect to
- *     response timeouts to control requests.
- *
- * 3.  This driver should be able to support any higher level driver that
- *     that wants to do either of the two standard UDC implementations
- *     Control-Bulk-Interrupt or  Bulk-IN/Bulk-Out standards. Hence
- *     gserial and cdc_acm should work with this code.
- *
- * 4.  NAK events never actually get raised at all, the documentation
- *     is just wrong !
- *
- * 5.  For some reason, cbd_datlen is *always* +2 the value it should be.
- *     this means that having an RX cbd of 16 bytes is not possible, since
- *     the same size is reported for 14 bytes received as 16 bytes received
- *     until we can find out why this happens, RX cbds must be limited to 8
- *     bytes. TODO: check errata for this behaviour.
- *
- * 6.  Right now this code doesn't support properly powering up with the USB
- *     cable attached to the USB host my development board the Adder87x doesn't
- *     have a pull-up fitted to allow this, so it is necessary to power the
- *     board and *then* attached the USB cable to the host. However somebody
- *     with a different design in their board may be able to keep the cable
- *     constantly connected and simply enable/disable a pull-up  re
- *     figure 31.1 in MPC885RM.pdf instead of having to power up the board and
- *     then attach the cable !
- *
- */
-#include <common.h>
-#include <config.h>
-#include <commproc.h>
-#include "usbdcore.h"
-#include "usbdcore_mpc8xx.h"
-#include "usbdcore_ep0.h"
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#define ERR(fmt, args...)\
-       serial_printf("ERROR : [%s] %s:%d: "fmt,\
-                               __FILE__,__FUNCTION__,__LINE__, ##args)
-#ifdef __DEBUG_UDC__
-#define DBG(fmt,args...)\
-               serial_printf("[%s] %s:%d: "fmt,\
-                               __FILE__,__FUNCTION__,__LINE__, ##args)
-#else
-#define DBG(fmt,args...)
-#endif
-
-/* Static Data */
-#ifdef __SIMULATE_ERROR__
-static char err_poison_test = 0;
-#endif
-static struct mpc8xx_ep ep_ref[MAX_ENDPOINTS];
-static u32 address_base = STATE_NOT_READY;
-static mpc8xx_udc_state_t udc_state = 0;
-static struct usb_device_instance *udc_device = 0;
-static volatile usb_epb_t *endpoints[MAX_ENDPOINTS];
-static volatile cbd_t *tx_cbd[TX_RING_SIZE];
-static volatile cbd_t *rx_cbd[RX_RING_SIZE];
-static volatile immap_t *immr = 0;
-static volatile cpm8xx_t *cp = 0;
-static volatile usb_pram_t *usb_paramp = 0;
-static volatile usb_t *usbp = 0;
-static int rx_ct = 0;
-static int tx_ct = 0;
-
-/* Static Function Declarations */
-static void mpc8xx_udc_state_transition_up (usb_device_state_t initial,
-                                           usb_device_state_t final);
-static void mpc8xx_udc_state_transition_down (usb_device_state_t initial,
-                                             usb_device_state_t final);
-static void mpc8xx_udc_stall (unsigned int ep);
-static void mpc8xx_udc_flush_tx_fifo (int epid);
-static void mpc8xx_udc_flush_rx_fifo (void);
-static void mpc8xx_udc_clear_rxbd (volatile cbd_t * rx_cbdp);
-static void mpc8xx_udc_init_tx (struct usb_endpoint_instance *epi,
-                               struct urb *tx_urb);
-static void mpc8xx_udc_dump_request (struct usb_device_request *request);
-static void mpc8xx_udc_clock_init (volatile immap_t * immr,
-                                  volatile cpm8xx_t * cp);
-static int mpc8xx_udc_ep_tx (struct usb_endpoint_instance *epi);
-static int mpc8xx_udc_epn_rx (unsigned int epid, volatile cbd_t * rx_cbdp);
-static void mpc8xx_udc_ep0_rx (volatile cbd_t * rx_cbdp);
-static void mpc8xx_udc_cbd_init (void);
-static void mpc8xx_udc_endpoint_init (void);
-static void mpc8xx_udc_cbd_attach (int ep, uchar tx_size, uchar rx_size);
-static u32 mpc8xx_udc_alloc (u32 data_size, u32 alignment);
-static int mpc8xx_udc_ep0_rx_setup (volatile cbd_t * rx_cbdp);
-static void mpc8xx_udc_set_nak (unsigned int ep);
-static short mpc8xx_udc_handle_txerr (void);
-static void mpc8xx_udc_advance_rx (volatile cbd_t ** rx_cbdp, int epid);
-
-/******************************************************************************
-                              Global Linkage
- *****************************************************************************/
-
-/* udc_init
- *
- * Do initial bus gluing
- */
-int udc_init (void)
-{
-       /* Init various pointers */
-       immr = (immap_t *) CONFIG_SYS_IMMR;
-       cp = (cpm8xx_t *) & (immr->im_cpm);
-       usb_paramp = (usb_pram_t *) & (cp->cp_dparam[PROFF_USB]);
-       usbp = (usb_t *) & (cp->cp_scc[0]);
-
-       memset (ep_ref, 0x00, (sizeof (struct mpc8xx_ep) * MAX_ENDPOINTS));
-
-       udc_device = 0;
-       udc_state = STATE_NOT_READY;
-
-       usbp->usmod = 0x00;
-       usbp->uscom = 0;
-
-       /* Set USB Frame #0, Respond at Address & Get a clock source  */
-       usbp->usaddr = 0x00;
-       mpc8xx_udc_clock_init (immr, cp);
-
-       /* PA15, PA14 as perhiperal USBRXD and USBOE */
-       immr->im_ioport.iop_padir &= ~0x0003;
-       immr->im_ioport.iop_papar |= 0x0003;
-
-       /* PC11/PC10 as peripheral USBRXP USBRXN */
-       immr->im_ioport.iop_pcso |= 0x0030;
-
-       /* PC7/PC6 as perhiperal USBTXP and USBTXN */
-       immr->im_ioport.iop_pcdir |= 0x0300;
-       immr->im_ioport.iop_pcpar |= 0x0300;
-
-       /* Set the base address */
-       address_base = (u32) (cp->cp_dpmem + CPM_USB_BASE);
-
-       /* Initialise endpoints and circular buffers */
-       mpc8xx_udc_endpoint_init ();
-       mpc8xx_udc_cbd_init ();
-
-       /* Assign allocated Dual Port Endpoint descriptors */
-       usb_paramp->ep0ptr = (u32) endpoints[0];
-       usb_paramp->ep1ptr = (u32) endpoints[1];
-       usb_paramp->ep2ptr = (u32) endpoints[2];
-       usb_paramp->ep3ptr = (u32) endpoints[3];
-       usb_paramp->frame_n = 0;
-
-       DBG ("ep0ptr=0x%08x ep1ptr=0x%08x ep2ptr=0x%08x ep3ptr=0x%08x\n",
-            usb_paramp->ep0ptr, usb_paramp->ep1ptr, usb_paramp->ep2ptr,
-            usb_paramp->ep3ptr);
-
-       return 0;
-}
-
-/* udc_irq
- *
- * Poll for whatever events may have occured
- */
-void udc_irq (void)
-{
-       int epid = 0;
-       volatile cbd_t *rx_cbdp = 0;
-       volatile cbd_t *rx_cbdp_base = 0;
-
-       if (udc_state != STATE_READY) {
-               return;
-       }
-
-       if (usbp->usber & USB_E_BSY) {
-               /* This shouldn't happen. If it does then it's a bug ! */
-               usbp->usber |= USB_E_BSY;
-               mpc8xx_udc_flush_rx_fifo ();
-       }
-
-       /* Scan all RX/Bidirectional Endpoints for RX data. */
-       for (epid = 0; epid < MAX_ENDPOINTS; epid++) {
-               if (!ep_ref[epid].prx) {
-                       continue;
-               }
-               rx_cbdp = rx_cbdp_base = ep_ref[epid].prx;
-
-               do {
-                       if (!(rx_cbdp->cbd_sc & RX_BD_E)) {
-
-                               if (rx_cbdp->cbd_sc & 0x1F) {
-                                       /* Corrupt data discard it.
-                                        * Controller has NAK'd this packet.
-                                        */
-                                       mpc8xx_udc_clear_rxbd (rx_cbdp);
-
-                               } else {
-                                       if (!epid) {
-                                               mpc8xx_udc_ep0_rx (rx_cbdp);
-
-                                       } else {
-                                               /* Process data */
-                                               mpc8xx_udc_set_nak (epid);
-                                               mpc8xx_udc_epn_rx (epid, rx_cbdp);
-                                               mpc8xx_udc_clear_rxbd (rx_cbdp);
-                                       }
-                               }
-
-                               /* Advance RX CBD pointer */
-                               mpc8xx_udc_advance_rx (&rx_cbdp, epid);
-                               ep_ref[epid].prx = rx_cbdp;
-                       } else {
-                               /* Advance RX CBD pointer */
-                               mpc8xx_udc_advance_rx (&rx_cbdp, epid);
-                       }
-
-               } while (rx_cbdp != rx_cbdp_base);
-       }
-
-       /* Handle TX events as appropiate, the correct place to do this is
-        * in a tx routine. Perhaps TX on epn was pre-empted by ep0
-        */
-
-       if (usbp->usber & USB_E_TXB) {
-               usbp->usber |= USB_E_TXB;
-       }
-
-       if (usbp->usber & (USB_TX_ERRMASK)) {
-               mpc8xx_udc_handle_txerr ();
-       }
-
-       /* Switch to the default state, respond at the default address */
-       if (usbp->usber & USB_E_RESET) {
-               usbp->usber |= USB_E_RESET;
-               usbp->usaddr = 0x00;
-               udc_device->device_state = STATE_DEFAULT;
-       }
-
-       /* if(usbp->usber&USB_E_IDLE){
-          We could suspend here !
-          usbp->usber|=USB_E_IDLE;
-          DBG("idle state change\n");
-          }
-          if(usbp->usbs){
-          We could resume here when IDLE is deasserted !
-          Not worth doing, so long as we are self powered though.
-          }
-       */
-
-       return;
-}
-
-/* udc_endpoint_write
- *
- * Write some data to an endpoint
- */
-int udc_endpoint_write (struct usb_endpoint_instance *epi)
-{
-       int ep = 0;
-       short epid = 1, unnak = 0, ret = 0;
-
-       if (udc_state != STATE_READY) {
-               ERR ("invalid udc_state != STATE_READY!\n");
-               return -1;
-       }
-
-       if (!udc_device || !epi) {
-               return -1;
-       }
-
-       if (udc_device->device_state != STATE_CONFIGURED) {
-               return -1;
-       }
-
-       ep = epi->endpoint_address & 0x03;
-       if (ep >= MAX_ENDPOINTS) {
-               return -1;
-       }
-
-       /* Set NAK for all RX endpoints during TX */
-       for (epid = 1; epid < MAX_ENDPOINTS; epid++) {
-
-               /* Don't set NAK on DATA IN/CONTROL endpoints */
-               if (ep_ref[epid].sc & USB_DIR_IN) {
-                       continue;
-               }
-
-               if (!(usbp->usep[epid] & (USEP_THS_NAK | USEP_RHS_NAK))) {
-                       unnak |= 1 << epid;
-               }
-
-               mpc8xx_udc_set_nak (epid);
-       }
-
-       mpc8xx_udc_init_tx (&udc_device->bus->endpoint_array[ep],
-                           epi->tx_urb);
-       ret = mpc8xx_udc_ep_tx (&udc_device->bus->endpoint_array[ep]);
-
-       /* Remove temporary NAK */
-       for (epid = 1; epid < MAX_ENDPOINTS; epid++) {
-               if (unnak & (1 << epid)) {
-                       udc_unset_nak (epid);
-               }
-       }
-
-       return ret;
-}
-
-/* mpc8xx_udc_assign_urb
- *
- * Associate a given urb to an endpoint TX or RX transmit/receive buffers
- */
-static int mpc8xx_udc_assign_urb (int ep, char direction)
-{
-       struct usb_endpoint_instance *epi = 0;
-
-       if (ep >= MAX_ENDPOINTS) {
-               goto err;
-       }
-       epi = &udc_device->bus->endpoint_array[ep];
-       if (!epi) {
-               goto err;
-       }
-
-       if (!ep_ref[ep].urb) {
-               ep_ref[ep].urb = usbd_alloc_urb (udc_device, udc_device->bus->endpoint_array);
-               if (!ep_ref[ep].urb) {
-                       goto err;
-               }
-       } else {
-               ep_ref[ep].urb->actual_length = 0;
-       }
-
-       switch (direction) {
-       case USB_DIR_IN:
-               epi->tx_urb = ep_ref[ep].urb;
-               break;
-       case USB_DIR_OUT:
-               epi->rcv_urb = ep_ref[ep].urb;
-               break;
-       default:
-               goto err;
-       }
-       return 0;
-
-      err:
-       udc_state = STATE_ERROR;
-       return -1;
-}
-
-/* udc_setup_ep
- *
- * Associate U-Boot software endpoints to mpc8xx endpoint parameter ram
- * Isochronous endpoints aren't yet supported!
- */
-void udc_setup_ep (struct usb_device_instance *device, unsigned int ep,
-                  struct usb_endpoint_instance *epi)
-{
-       uchar direction = 0;
-       int ep_attrib = 0;
-
-       if (epi && (ep < MAX_ENDPOINTS)) {
-
-               if (ep == 0) {
-                       if (epi->rcv_attributes != USB_ENDPOINT_XFER_CONTROL
-                           || epi->tx_attributes !=
-                           USB_ENDPOINT_XFER_CONTROL) {
-
-                               /* ep0 must be a control endpoint */
-                               udc_state = STATE_ERROR;
-                               return;
-
-                       }
-                       if (!(ep_ref[ep].sc & EP_ATTACHED)) {
-                               mpc8xx_udc_cbd_attach (ep, epi->tx_packetSize,
-                                                      epi->rcv_packetSize);
-                       }
-                       usbp->usep[ep] = 0x0000;
-                       return;
-               }
-
-               if ((epi->endpoint_address & USB_ENDPOINT_DIR_MASK)
-                   == USB_DIR_IN) {
-
-                       direction = 1;
-                       ep_attrib = epi->tx_attributes;
-                       epi->rcv_packetSize = 0;
-                       ep_ref[ep].sc |= USB_DIR_IN;
-               } else {
-
-                       direction = 0;
-                       ep_attrib = epi->rcv_attributes;
-                       epi->tx_packetSize = 0;
-                       ep_ref[ep].sc &= ~USB_DIR_IN;
-               }
-
-               if (mpc8xx_udc_assign_urb (ep, epi->endpoint_address
-                                          & USB_ENDPOINT_DIR_MASK)) {
-                       return;
-               }
-
-               switch (ep_attrib) {
-               case USB_ENDPOINT_XFER_CONTROL:
-                       if (!(ep_ref[ep].sc & EP_ATTACHED)) {
-                               mpc8xx_udc_cbd_attach (ep,
-                                                      epi->tx_packetSize,
-                                                      epi->rcv_packetSize);
-                       }
-                       usbp->usep[ep] = ep << 12;
-                       epi->rcv_urb = epi->tx_urb = ep_ref[ep].urb;
-
-                       break;
-               case USB_ENDPOINT_XFER_BULK:
-               case USB_ENDPOINT_XFER_INT:
-                       if (!(ep_ref[ep].sc & EP_ATTACHED)) {
-                               if (direction) {
-                                       mpc8xx_udc_cbd_attach (ep,
-                                                              epi->tx_packetSize,
-                                                              0);
-                               } else {
-                                       mpc8xx_udc_cbd_attach (ep,
-                                                              0,
-                                                              epi->rcv_packetSize);
-                               }
-                       }
-                       usbp->usep[ep] = (ep << 12) | ((ep_attrib) << 8);
-
-                       break;
-               case USB_ENDPOINT_XFER_ISOC:
-               default:
-                       serial_printf ("Error endpoint attrib %d>3\n", ep_attrib);
-                       udc_state = STATE_ERROR;
-                       break;
-               }
-       }
-
-}
-
-/* udc_connect
- *
- * Move state, switch on the USB
- */
-void udc_connect (void)
-{
-       /* Enable pull-up resistor on D+
-        * TODO: fit a pull-up resistor to drive SE0 for > 2.5us
-        */
-
-       if (udc_state != STATE_ERROR) {
-               udc_state = STATE_READY;
-               usbp->usmod |= USMOD_EN;
-       }
-}
-
-/* udc_disconnect
- *
- * Disconnect is not used but, is included for completeness
- */
-void udc_disconnect (void)
-{
-       /* Disable pull-up resistor on D-
-        * TODO: fix a pullup resistor to control this
-        */
-
-       if (udc_state != STATE_ERROR) {
-               udc_state = STATE_NOT_READY;
-       }
-       usbp->usmod &= ~USMOD_EN;
-}
-
-/* udc_enable
- *
- * Grab an EP0 URB, register interest in a subset of USB events
- */
-void udc_enable (struct usb_device_instance *device)
-{
-       if (udc_state == STATE_ERROR) {
-               return;
-       }
-
-       udc_device = device;
-
-       if (!ep_ref[0].urb) {
-               ep_ref[0].urb = usbd_alloc_urb (device, device->bus->endpoint_array);
-       }
-
-       /* Register interest in all events except SOF, enable transceiver */
-       usbp->usber = 0x03FF;
-       usbp->usbmr = 0x02F7;
-
-       return;
-}
-
-/* udc_disable
- *
- * disable the currently hooked device
- */
-void udc_disable (void)
-{
-       int i = 0;
-
-       if (udc_state == STATE_ERROR) {
-               DBG ("Won't disable UDC. udc_state==STATE_ERROR !\n");
-               return;
-       }
-
-       udc_device = 0;
-
-       for (; i < MAX_ENDPOINTS; i++) {
-               if (ep_ref[i].urb) {
-                       usbd_dealloc_urb (ep_ref[i].urb);
-                       ep_ref[i].urb = 0;
-               }
-       }
-
-       usbp->usbmr = 0x00;
-       usbp->usmod = ~USMOD_EN;
-       udc_state = STATE_NOT_READY;
-}
-
-/* udc_startup_events
- *
- * Enable the specified device
- */
-void udc_startup_events (struct usb_device_instance *device)
-{
-       udc_enable (device);
-       if (udc_state == STATE_READY) {
-               usbd_device_event_irq (device, DEVICE_CREATE, 0);
-       }
-}
-
-/* udc_set_nak
- *
- * Allow upper layers to signal lower layers should not accept more RX data
- *
- */
-void udc_set_nak (int epid)
-{
-       if (epid) {
-               mpc8xx_udc_set_nak (epid);
-       }
-}
-
-/* udc_unset_nak
- *
- * Suspend sending of NAK tokens for DATA OUT tokens on a given endpoint.
- * Switch off NAKing on this endpoint to accept more data output from host.
- *
- */
-void udc_unset_nak (int epid)
-{
-       if (epid > MAX_ENDPOINTS) {
-               return;
-       }
-
-       if (usbp->usep[epid] & (USEP_THS_NAK | USEP_RHS_NAK)) {
-               usbp->usep[epid] &= ~(USEP_THS_NAK | USEP_RHS_NAK);
-               __asm__ ("eieio");
-       }
-}
-
-/******************************************************************************
-                             Static Linkage
-******************************************************************************/
-
-/* 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.
- *
- */
-
-static void mpc8xx_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 mpc8xx_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;
-               }
-       }
-}
-
-/* mpc8xx_udc_stall
- *
- * Force returning of STALL tokens on the given endpoint. Protocol or function
- * STALL conditions are permissable here
- */
-static void mpc8xx_udc_stall (unsigned int ep)
-{
-       usbp->usep[ep] |= STALL_BITMASK;
-}
-
-/* mpc8xx_udc_set_nak
- *
- * Force returning of NAK responses for the given endpoint as a kind of very
- * simple flow control
- */
-static void mpc8xx_udc_set_nak (unsigned int ep)
-{
-       usbp->usep[ep] |= NAK_BITMASK;
-       __asm__ ("eieio");
-}
-
-/* mpc8xx_udc_handle_txerr
- *
- * Handle errors relevant to TX. Return a status code to allow calling
- * indicative of what if anything happened
- */
-static short mpc8xx_udc_handle_txerr ()
-{
-       short ep = 0, ret = 0;
-
-       for (; ep < TX_RING_SIZE; ep++) {
-               if (usbp->usber & (0x10 << ep)) {
-
-                       /* Timeout or underrun */
-                       if (tx_cbd[ep]->cbd_sc & 0x06) {
-                               ret = 1;
-                               mpc8xx_udc_flush_tx_fifo (ep);
-
-                       } else {
-                               if (usbp->usep[ep] & STALL_BITMASK) {
-                                       if (!ep) {
-                                               usbp->usep[ep] &= ~STALL_BITMASK;
-                                       }
-                               }       /* else NAK */
-                       }
-                       usbp->usber |= (0x10 << ep);
-               }
-       }
-       return ret;
-}
-
-/* mpc8xx_udc_advance_rx
- *
- * Advance cbd rx
- */
-static void mpc8xx_udc_advance_rx (volatile cbd_t ** rx_cbdp, int epid)
-{
-       if ((*rx_cbdp)->cbd_sc & RX_BD_W) {
-               *rx_cbdp = (volatile cbd_t *) (endpoints[epid]->rbase + CONFIG_SYS_IMMR);
-
-       } else {
-               (*rx_cbdp)++;
-       }
-}
-
-
-/* mpc8xx_udc_flush_tx_fifo
- *
- * Flush a given TX fifo. Assumes one tx cbd per endpoint
- */
-static void mpc8xx_udc_flush_tx_fifo (int epid)
-{
-       volatile cbd_t *tx_cbdp = 0;
-
-       if (epid > MAX_ENDPOINTS) {
-               return;
-       }
-
-       /* TX stop */
-       immr->im_cpm.cp_cpcr = ((epid << 2) | 0x1D01);
-       __asm__ ("eieio");
-       while (immr->im_cpm.cp_cpcr & 0x01);
-
-       usbp->uscom = 0x40 | 0;
-
-       /* reset ring */
-       tx_cbdp = (cbd_t *) (endpoints[epid]->tbptr + CONFIG_SYS_IMMR);
-       tx_cbdp->cbd_sc = (TX_BD_I | TX_BD_W);
-
-
-       endpoints[epid]->tptr = endpoints[epid]->tbase;
-       endpoints[epid]->tstate = 0x00;
-       endpoints[epid]->tbcnt = 0x00;
-
-       /* TX start */
-       immr->im_cpm.cp_cpcr = ((epid << 2) | 0x2D01);
-       __asm__ ("eieio");
-       while (immr->im_cpm.cp_cpcr & 0x01);
-
-       return;
-}
-
-/* mpc8xx_udc_flush_rx_fifo
- *
- * For the sake of completeness of the namespace, it seems like
- * a good-design-decision (tm) to include mpc8xx_udc_flush_rx_fifo();
- * If RX_BD_E is true => a driver bug either here or in an upper layer
- * not polling frequently enough. If RX_BD_E is true we have told the host
- * we have accepted data but, the CPM found it had no-where to put that data
- * which needless to say would be a bad thing.
- */
-static void mpc8xx_udc_flush_rx_fifo ()
-{
-       int i = 0;
-
-       for (i = 0; i < RX_RING_SIZE; i++) {
-               if (!(rx_cbd[i]->cbd_sc & RX_BD_E)) {
-                       ERR ("buf %p used rx data len = 0x%x sc=0x%x!\n",
-                            rx_cbd[i], rx_cbd[i]->cbd_datlen,
-                            rx_cbd[i]->cbd_sc);
-
-               }
-       }
-       ERR ("BUG : Input over-run\n");
-}
-
-/* mpc8xx_udc_clear_rxbd
- *
- * Release control of RX CBD to CP.
- */
-static void mpc8xx_udc_clear_rxbd (volatile cbd_t * rx_cbdp)
-{
-       rx_cbdp->cbd_datlen = 0x0000;
-       rx_cbdp->cbd_sc = ((rx_cbdp->cbd_sc & RX_BD_W) | (RX_BD_E | RX_BD_I));
-       __asm__ ("eieio");
-}
-
-/* mpc8xx_udc_tx_irq
- *
- * Parse for tx timeout, control RX or USB reset/busy conditions
- * Return -1 on timeout, -2 on fatal error, else return zero
- */
-static int mpc8xx_udc_tx_irq (int ep)
-{
-       int i = 0;
-
-       if (usbp->usber & (USB_TX_ERRMASK)) {
-               if (mpc8xx_udc_handle_txerr ()) {
-                       /* Timeout, controlling function must retry send */
-                       return -1;
-               }
-       }
-
-       if (usbp->usber & (USB_E_RESET | USB_E_BSY)) {
-               /* Fatal, abandon TX transaction */
-               return -2;
-       }
-
-       if (usbp->usber & USB_E_RXB) {
-               for (i = 0; i < RX_RING_SIZE; i++) {
-                       if (!(rx_cbd[i]->cbd_sc & RX_BD_E)) {
-                               if ((rx_cbd[i] == ep_ref[0].prx) || ep) {
-                                       return -2;
-                               }
-                       }
-               }
-       }
-
-       return 0;
-}
-
-/* mpc8xx_udc_ep_tx
- *
- * Transmit in a re-entrant fashion outbound USB packets.
- * Implement retry/timeout mechanism described in USB specification
- * Toggle DATA0/DATA1 pids as necessary
- * Introduces non-standard tx_retry. The USB standard has no scope for slave
- * devices to give up TX, however tx_retry stops us getting stuck in an endless
- * TX loop.
- */
-static int mpc8xx_udc_ep_tx (struct usb_endpoint_instance *epi)
-{
-       struct urb *urb = epi->tx_urb;
-       volatile cbd_t *tx_cbdp = 0;
-       unsigned int ep = 0, pkt_len = 0, x = 0, tx_retry = 0;
-       int ret = 0;
-
-       if (!epi || (epi->endpoint_address & 0x03) >= MAX_ENDPOINTS || !urb) {
-               return -1;
-       }
-
-       ep = epi->endpoint_address & 0x03;
-       tx_cbdp = (cbd_t *) (endpoints[ep]->tbptr + CONFIG_SYS_IMMR);
-
-       if (tx_cbdp->cbd_sc & TX_BD_R || usbp->usber & USB_E_TXB) {
-               mpc8xx_udc_flush_tx_fifo (ep);
-               usbp->usber |= USB_E_TXB;
-       };
-
-       while (tx_retry++ < 100) {
-               ret = mpc8xx_udc_tx_irq (ep);
-               if (ret == -1) {
-                       /* ignore timeout here */
-               } else if (ret == -2) {
-                       /* Abandon TX */
-                       mpc8xx_udc_flush_tx_fifo (ep);
-                       return -1;
-               }
-
-               tx_cbdp = (cbd_t *) (endpoints[ep]->tbptr + CONFIG_SYS_IMMR);
-               while (tx_cbdp->cbd_sc & TX_BD_R) {
-               };
-               tx_cbdp->cbd_sc = (tx_cbdp->cbd_sc & TX_BD_W);
-
-               pkt_len = urb->actual_length - epi->sent;
-
-               if (pkt_len > epi->tx_packetSize || pkt_len > EP_MAX_PKT) {
-                       pkt_len = MIN (epi->tx_packetSize, EP_MAX_PKT);
-               }
-
-               for (x = 0; x < pkt_len; x++) {
-                       *((unsigned char *) (tx_cbdp->cbd_bufaddr + x)) =
-                               urb->buffer[epi->sent + x];
-               }
-               tx_cbdp->cbd_datlen = pkt_len;
-               tx_cbdp->cbd_sc |= (CBD_TX_BITMASK | ep_ref[ep].pid);
-               __asm__ ("eieio");
-
-#ifdef __SIMULATE_ERROR__
-               if (++err_poison_test == 2) {
-                       err_poison_test = 0;
-                       tx_cbdp->cbd_sc &= ~TX_BD_TC;
-               }
-#endif
-
-               usbp->uscom = (USCOM_STR | ep);
-
-               while (!(usbp->usber & USB_E_TXB)) {
-                       ret = mpc8xx_udc_tx_irq (ep);
-                       if (ret == -1) {
-                               /* TX timeout */
-                               break;
-                       } else if (ret == -2) {
-                               if (usbp->usber & USB_E_TXB) {
-                                       usbp->usber |= USB_E_TXB;
-                               }
-                               mpc8xx_udc_flush_tx_fifo (ep);
-                               return -1;
-                       }
-               };
-
-               if (usbp->usber & USB_E_TXB) {
-                       usbp->usber |= USB_E_TXB;
-               }
-
-               /* ACK must be present <= 18bit times from TX */
-               if (ret == -1) {
-                       continue;
-               }
-
-               /* TX ACK : USB 2.0 8.7.2, Toggle PID, Advance TX */
-               epi->sent += pkt_len;
-               epi->last = MIN (urb->actual_length - epi->sent, epi->tx_packetSize);
-               TOGGLE_TX_PID (ep_ref[ep].pid);
-
-               if (epi->sent >= epi->tx_urb->actual_length) {
-
-                       epi->tx_urb->actual_length = 0;
-                       epi->sent = 0;
-
-                       if (ep_ref[ep].sc & EP_SEND_ZLP) {
-                               ep_ref[ep].sc &= ~EP_SEND_ZLP;
-                       } else {
-                               return 0;
-                       }
-               }
-       }
-
-       ERR ("TX fail, endpoint 0x%x tx bytes 0x%x/0x%x\n", ep, epi->sent,
-            epi->tx_urb->actual_length);
-
-       return -1;
-}
-
-/* mpc8xx_udc_dump_request
- *
- * Dump a control request to console
- */
-static void mpc8xx_udc_dump_request (struct usb_device_request *request)
-{
-       DBG ("bmRequestType:%02x bRequest:%02x wValue:%04x "
-            "wIndex:%04x wLength:%04x ?\n",
-            request->bmRequestType,
-            request->bRequest,
-            request->wValue, request->wIndex, request->wLength);
-
-       return;
-}
-
-/* mpc8xx_udc_ep0_rx_setup
- *
- * Decode received ep0 SETUP packet. return non-zero on error
- */
-static int mpc8xx_udc_ep0_rx_setup (volatile cbd_t * rx_cbdp)
-{
-       unsigned int x = 0;
-       struct urb *purb = ep_ref[0].urb;
-       struct usb_endpoint_instance *epi =
-               &udc_device->bus->endpoint_array[0];
-
-       for (; x < rx_cbdp->cbd_datlen; x++) {
-               *(((unsigned char *) &ep_ref[0].urb->device_request) + x) =
-                       *((unsigned char *) (rx_cbdp->cbd_bufaddr + x));
-       }
-
-       mpc8xx_udc_clear_rxbd (rx_cbdp);
-
-       if (ep0_recv_setup (purb)) {
-               mpc8xx_udc_dump_request (&purb->device_request);
-               return -1;
-       }
-
-       if ((purb->device_request.bmRequestType & USB_REQ_DIRECTION_MASK)
-           == USB_REQ_HOST2DEVICE) {
-
-               switch (purb->device_request.bRequest) {
-               case USB_REQ_SET_ADDRESS:
-                       /* Send the Status OUT ZLP */
-                       ep_ref[0].pid = TX_BD_PID_DATA1;
-                       purb->actual_length = 0;
-                       mpc8xx_udc_init_tx (epi, purb);
-                       mpc8xx_udc_ep_tx (epi);
-
-                       /* Move to the addressed state */
-                       usbp->usaddr = udc_device->address;
-                       mpc8xx_udc_state_transition_up (udc_device->device_state,
-                                                       STATE_ADDRESSED);
-                       return 0;
-
-               case USB_REQ_SET_CONFIGURATION:
-                       if (!purb->device_request.wValue) {
-                               /* Respond at default address */
-                               usbp->usaddr = 0x00;
-                               mpc8xx_udc_state_transition_down (udc_device->device_state,
-                                                                 STATE_ADDRESSED);
-                       } else {
-                               /* TODO: Support multiple configurations */
-                               mpc8xx_udc_state_transition_up (udc_device->device_state,
-                                                               STATE_CONFIGURED);
-                               for (x = 1; x < MAX_ENDPOINTS; x++) {
-                                       if ((udc_device->bus->endpoint_array[x].endpoint_address & USB_ENDPOINT_DIR_MASK)
-                                           == USB_DIR_IN) {
-                                               ep_ref[x].pid = TX_BD_PID_DATA0;
-                                       } else {
-                                               ep_ref[x].pid = RX_BD_PID_DATA0;
-                                       }
-                                       /* Set configuration must unstall endpoints */
-                                       usbp->usep[x] &= ~STALL_BITMASK;
-                               }
-                       }
-                       break;
-               default:
-                       /* CDC/Vendor specific */
-                       break;
-               }
-
-               /* Send ZLP as ACK in Status OUT phase */
-               ep_ref[0].pid = TX_BD_PID_DATA1;
-               purb->actual_length = 0;
-               mpc8xx_udc_init_tx (epi, purb);
-               mpc8xx_udc_ep_tx (epi);
-
-       } else {
-
-               if (purb->actual_length) {
-                       ep_ref[0].pid = TX_BD_PID_DATA1;
-                       mpc8xx_udc_init_tx (epi, purb);
-
-                       if (!(purb->actual_length % EP0_MAX_PACKET_SIZE)) {
-                               ep_ref[0].sc |= EP_SEND_ZLP;
-                       }
-
-                       if (purb->device_request.wValue ==
-                           USB_DESCRIPTOR_TYPE_DEVICE) {
-                               if (le16_to_cpu (purb->device_request.wLength)
-                                   > purb->actual_length) {
-                                       /* Send EP0_MAX_PACKET_SIZE bytes
-                                        * unless correct size requested.
-                                        */
-                                       if (purb->actual_length > epi->tx_packetSize) {
-                                               purb->actual_length = epi->tx_packetSize;
-                                       }
-                               }
-                       }
-                       mpc8xx_udc_ep_tx (epi);
-
-               } else {
-                       /* Corrupt SETUP packet? */
-                       ERR ("Zero length data or SETUP with DATA-IN phase ?\n");
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-/* mpc8xx_udc_init_tx
- *
- * Setup some basic parameters for a TX transaction
- */
-static void mpc8xx_udc_init_tx (struct usb_endpoint_instance *epi,
-                               struct urb *tx_urb)
-{
-       epi->sent = 0;
-       epi->last = 0;
-       epi->tx_urb = tx_urb;
-}
-
-/* mpc8xx_udc_ep0_rx
- *
- * Receive ep0/control USB data. Parse and possibly send a response.
- */
-static void mpc8xx_udc_ep0_rx (volatile cbd_t * rx_cbdp)
-{
-       if (rx_cbdp->cbd_sc & RX_BD_PID_SETUP) {
-
-               /* Unconditionally accept SETUP packets */
-               if (mpc8xx_udc_ep0_rx_setup (rx_cbdp)) {
-                       mpc8xx_udc_stall (0);
-               }
-
-       } else {
-
-               mpc8xx_udc_clear_rxbd (rx_cbdp);
-
-               if ((rx_cbdp->cbd_datlen - 2)) {
-                       /* SETUP with a DATA phase
-                        * outside of SETUP packet.
-                        * Reply with STALL.
-                        */
-                       mpc8xx_udc_stall (0);
-               }
-       }
-}
-
-/* mpc8xx_udc_epn_rx
- *
- * Receive some data from cbd into USB system urb data abstraction
- * Upper layers should NAK if there is insufficient RX data space
- */
-static int mpc8xx_udc_epn_rx (unsigned int epid, volatile cbd_t * rx_cbdp)
-{
-       struct usb_endpoint_instance *epi = 0;
-       struct urb *urb = 0;
-       unsigned int x = 0;
-
-       if (epid >= MAX_ENDPOINTS || !rx_cbdp->cbd_datlen) {
-               return 0;
-       }
-
-       /* USB 2.0 PDF section 8.6.4
-        * Discard data with invalid PID it is a resend.
-        */
-       if (ep_ref[epid].pid != (rx_cbdp->cbd_sc & 0xC0)) {
-               return 1;
-       }
-       TOGGLE_RX_PID (ep_ref[epid].pid);
-
-       epi = &udc_device->bus->endpoint_array[epid];
-       urb = epi->rcv_urb;
-
-       for (; x < (rx_cbdp->cbd_datlen - 2); x++) {
-               *((unsigned char *) (urb->buffer + urb->actual_length + x)) =
-                       *((unsigned char *) (rx_cbdp->cbd_bufaddr + x));
-       }
-
-       if (x) {
-               usbd_rcv_complete (epi, x, 0);
-               if (ep_ref[epid].urb->status == RECV_ERROR) {
-                       DBG ("RX error unset NAK\n");
-                       udc_unset_nak (epid);
-               }
-       }
-       return x;
-}
-
-/* mpc8xx_udc_clock_init
- *
- * Obtain a clock reference for Full Speed Signaling
- */
-static void mpc8xx_udc_clock_init (volatile immap_t * immr,
-                                  volatile cpm8xx_t * cp)
-{
-
-#if defined(CONFIG_SYS_USB_EXTC_CLK)
-
-       /* This has been tested with a 48MHz crystal on CLK6 */
-       switch (CONFIG_SYS_USB_EXTC_CLK) {
-       case 1:
-               immr->im_ioport.iop_papar |= 0x0100;
-               immr->im_ioport.iop_padir &= ~0x0100;
-               cp->cp_sicr |= 0x24;
-               break;
-       case 2:
-               immr->im_ioport.iop_papar |= 0x0200;
-               immr->im_ioport.iop_padir &= ~0x0200;
-               cp->cp_sicr |= 0x2D;
-               break;
-       case 3:
-               immr->im_ioport.iop_papar |= 0x0400;
-               immr->im_ioport.iop_padir &= ~0x0400;
-               cp->cp_sicr |= 0x36;
-               break;
-       case 4:
-               immr->im_ioport.iop_papar |= 0x0800;
-               immr->im_ioport.iop_padir &= ~0x0800;
-               cp->cp_sicr |= 0x3F;
-               break;
-       default:
-               udc_state = STATE_ERROR;
-               break;
-       }
-
-#elif defined(CONFIG_SYS_USB_BRGCLK)
-
-       /* This has been tested with brgclk == 50MHz */
-       int divisor = 0;
-
-       if (gd->cpu_clk < 48000000L) {
-               ERR ("brgclk is too slow for full-speed USB!\n");
-               udc_state = STATE_ERROR;
-               return;
-       }
-
-       /* Assume the brgclk is 'good enough', we want !(gd->cpu_clk%48MHz)
-        * but, can /probably/ live with close-ish alternative rates.
-        */
-       divisor = (gd->cpu_clk / 48000000L) - 1;
-       cp->cp_sicr &= ~0x0000003F;
-
-       switch (CONFIG_SYS_USB_BRGCLK) {
-       case 1:
-               cp->cp_brgc1 |= (divisor | CPM_BRG_EN);
-               cp->cp_sicr &= ~0x2F;
-               break;
-       case 2:
-               cp->cp_brgc2 |= (divisor | CPM_BRG_EN);
-               cp->cp_sicr |= 0x00000009;
-               break;
-       case 3:
-               cp->cp_brgc3 |= (divisor | CPM_BRG_EN);
-               cp->cp_sicr |= 0x00000012;
-               break;
-       case 4:
-               cp->cp_brgc4 = (divisor | CPM_BRG_EN);
-               cp->cp_sicr |= 0x0000001B;
-               break;
-       default:
-               udc_state = STATE_ERROR;
-               break;
-       }
-
-#else
-#error "CONFIG_SYS_USB_EXTC_CLK or CONFIG_SYS_USB_BRGCLK must be defined"
-#endif
-
-}
-
-/* mpc8xx_udc_cbd_attach
- *
- * attach a cbd to and endpoint
- */
-static void mpc8xx_udc_cbd_attach (int ep, uchar tx_size, uchar rx_size)
-{
-
-       if (!tx_cbd[ep] || !rx_cbd[ep] || ep >= MAX_ENDPOINTS) {
-               udc_state = STATE_ERROR;
-               return;
-       }
-
-       if (tx_size > USB_MAX_PKT || rx_size > USB_MAX_PKT ||
-           (!tx_size && !rx_size)) {
-               udc_state = STATE_ERROR;
-               return;
-       }
-
-       /* Attach CBD to appropiate Parameter RAM Endpoint data structure */
-       if (rx_size) {
-               endpoints[ep]->rbase = (u32) rx_cbd[rx_ct];
-               endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct];
-               rx_ct++;
-
-               if (!ep) {
-
-                       endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct];
-                       rx_cbd[rx_ct]->cbd_sc |= RX_BD_W;
-                       rx_ct++;
-
-               } else {
-                       rx_ct += 2;
-                       endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct];
-                       rx_cbd[rx_ct]->cbd_sc |= RX_BD_W;
-                       rx_ct++;
-               }
-
-               /* Where we expect to RX data on this endpoint */
-               ep_ref[ep].prx = rx_cbd[rx_ct - 1];
-       } else {
-
-               ep_ref[ep].prx = 0;
-               endpoints[ep]->rbase = 0;
-               endpoints[ep]->rbptr = 0;
-       }
-
-       if (tx_size) {
-               endpoints[ep]->tbase = (u32) tx_cbd[tx_ct];
-               endpoints[ep]->tbptr = (u32) tx_cbd[tx_ct];
-               tx_ct++;
-       } else {
-               endpoints[ep]->tbase = 0;
-               endpoints[ep]->tbptr = 0;
-       }
-
-       endpoints[ep]->tstate = 0;
-       endpoints[ep]->tbcnt = 0;
-       endpoints[ep]->mrblr = EP_MAX_PKT;
-       endpoints[ep]->rfcr = 0x18;
-       endpoints[ep]->tfcr = 0x18;
-       ep_ref[ep].sc |= EP_ATTACHED;
-
-       DBG ("ep %d rbase 0x%08x rbptr 0x%08x tbase 0x%08x tbptr 0x%08x prx = %p\n",
-               ep, endpoints[ep]->rbase, endpoints[ep]->rbptr,
-               endpoints[ep]->tbase, endpoints[ep]->tbptr,
-               ep_ref[ep].prx);
-
-       return;
-}
-
-/* mpc8xx_udc_cbd_init
- *
- * Allocate space for a cbd and allocate TX/RX data space
- */
-static void mpc8xx_udc_cbd_init (void)
-{
-       int i = 0;
-
-       for (; i < TX_RING_SIZE; i++) {
-               tx_cbd[i] = (cbd_t *)
-                       mpc8xx_udc_alloc (sizeof (cbd_t), sizeof (int));
-       }
-
-       for (i = 0; i < RX_RING_SIZE; i++) {
-               rx_cbd[i] = (cbd_t *)
-                       mpc8xx_udc_alloc (sizeof (cbd_t), sizeof (int));
-       }
-
-       for (i = 0; i < TX_RING_SIZE; i++) {
-               tx_cbd[i]->cbd_bufaddr =
-                       mpc8xx_udc_alloc (EP_MAX_PKT, sizeof (int));
-
-               tx_cbd[i]->cbd_sc = (TX_BD_I | TX_BD_W);
-               tx_cbd[i]->cbd_datlen = 0x0000;
-       }
-
-
-       for (i = 0; i < RX_RING_SIZE; i++) {
-               rx_cbd[i]->cbd_bufaddr =
-                       mpc8xx_udc_alloc (EP_MAX_PKT, sizeof (int));
-               rx_cbd[i]->cbd_sc = (RX_BD_I | RX_BD_E);
-               rx_cbd[i]->cbd_datlen = 0x0000;
-
-       }
-
-       return;
-}
-
-/* mpc8xx_udc_endpoint_init
- *
- * Attach an endpoint to some dpram
- */
-static void mpc8xx_udc_endpoint_init (void)
-{
-       int i = 0;
-
-       for (; i < MAX_ENDPOINTS; i++) {
-               endpoints[i] = (usb_epb_t *)
-                       mpc8xx_udc_alloc (sizeof (usb_epb_t), 32);
-       }
-}
-
-/* mpc8xx_udc_alloc
- *
- * Grab the address of some dpram
- */
-static u32 mpc8xx_udc_alloc (u32 data_size, u32 alignment)
-{
-       u32 retaddr = address_base;
-
-       while (retaddr % alignment) {
-               retaddr++;
-       }
-       address_base += data_size;
-
-       return retaddr;
-}
diff --git a/drivers/usb/usbdcore_omap1510.c b/drivers/usb/usbdcore_omap1510.c
deleted file mode 100644 (file)
index 6b7b61b..0000000
+++ /dev/null
@@ -1,1567 +0,0 @@
-/*
- * (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>
-#include <asm/io.h>
-#ifdef CONFIG_OMAP_SX1
-#include <i2c.h>
-#endif
-
-#include "usbdcore.h"
-#include "usbdcore_omap1510.h"
-#include "usbdcore_ep0.h"
-
-
-#define UDC_INIT_MDELAY                     80 /* Device settle delay */
-#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. */
-int 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);
-       }
-
-       return 0;
-}
-
-/* Start to initialize h/w stuff */
-int udc_init (void)
-{
-       u16 udc_rev;
-       uchar value;
-       ulong gpio;
-       int i;
-
-       /* Let the device settle down before we start */
-       for (i = 0; i < UDC_INIT_MDELAY; i++) udelay(1000);
-
-       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);
-
-#ifdef CONFIG_OMAP1510
-       /* This code was originally implemented for OMAP1510 and
-        * therefore is only applicable for OMAP1510 boards. For
-        * OMAP5912 or OMAP16xx the register APLL_CTRL does not
-        * exist and DPLL_CTRL is already configured.
-        */
-
-       /* Set and check APLL */
-       outw (0x0008, APLL_CTRL);
-       UDCREG (APLL_CTRL);
-       /* Set and check DPLL */
-       outw (0x2210, DPLL_CTRL);
-       UDCREG (DPLL_CTRL);
-#endif
-       /* Set and check SOFT
-        * The below line of code has been changed to perform a
-        * read-modify-write instead of a simple write for
-        * configuring the SOFT_REQ register. This allows the code
-        * to be compatible with OMAP5912 and OMAP16xx devices
-        */
-       outw ((1 << 4) | (1 << 3) | 1 | (inw(SOFT_REQ)), SOFT_REQ);
-
-       /* Short delay to wait for DPLL */
-       udelay (1000);
-
-       /* Print banner with device revision */
-       udc_rev = inw (UDC_REV) & 0xff;
-#ifdef CONFIG_OMAP1510
-       printf ("USB:   TI OMAP1510 USB function module rev %d.%d\n",
-               udc_rev >> 4, udc_rev & 0xf);
-#endif
-
-#ifdef CONFIG_OMAP1610
-       printf ("USB:   TI OMAP5912 USB function module rev %d.%d\n",
-               udc_rev >> 4, udc_rev & 0xf);
-#endif
-
-#ifdef CONFIG_OMAP_SX1
-       i2c_read (0x32, 0x04, 1, &value, 1);
-       value |= 0x04;
-       i2c_write (0x32, 0x04, 1, &value, 1);
-
-       i2c_read (0x32, 0x03, 1, &value, 1);
-       value |= 0x01;
-       i2c_write (0x32, 0x03, 1, &value, 1);
-
-       gpio = inl(GPIO_PIN_CONTROL_REG);
-       gpio |=  0x0002; /* A_IRDA_OFF */
-       gpio |=  0x0800; /* A_SWITCH   */
-       gpio |=  0x8000; /* A_USB_ON   */
-       outl (gpio, GPIO_PIN_CONTROL_REG);
-
-       gpio = inl(GPIO_DIR_CONTROL_REG);
-       gpio &= ~0x0002; /* A_IRDA_OFF */
-       gpio &= ~0x0800; /* A_SWITCH   */
-       gpio &= ~0x8000; /* A_USB_ON   */
-       outl (gpio, GPIO_DIR_CONTROL_REG);
-
-       gpio = inl(GPIO_DATA_OUTPUT_REG);
-       gpio |=  0x0002; /* A_IRDA_OFF */
-       gpio &= ~0x0800; /* A_SWITCH   */
-       gpio &= ~0x8000; /* A_USB_ON   */
-       outl (gpio, GPIO_DATA_OUTPUT_REG);
-#endif
-
-       /* 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);
-}
-
-/**
- * udc_irq - do pseudo interrupts
- */
-void udc_irq(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 ();
-       }
-}
-
-/* Flow control */
-void udc_set_nak(int epid)
-{
-       /* TODO: implement this functionality in omap1510 */
-}
-
-void udc_unset_nak (int epid)
-{
-       /* TODO: implement this functionality in omap1510 */
-}
diff --git a/include/usb/mpc8xx_udc.h b/include/usb/mpc8xx_udc.h
new file mode 100644 (file)
index 0000000..039d245
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2006 Bryan O'Donoghue, CodeHermit
+ * bodonoghue@codehermit.ie
+ *
+ *
+ * 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 <commproc.h>
+
+/* Mode Register */
+#define USMOD_EN       0x01
+#define USMOD_HOST     0x02
+#define USMOD_TEST     0x04
+#define USMOD_SFTE     0x08
+#define USMOD_RESUME   0x40
+#define USMOD_LSS      0x80
+
+/* Endpoint Registers */
+#define USEP_RHS_NORM  0x00
+#define USEP_RHS_IGNORE        0x01
+#define USEP_RHS_NAK   0x02
+#define USEP_RHS_STALL 0x03
+
+#define USEP_THS_NORM  0x00
+#define USEP_THS_IGNORE        0x04
+#define USEP_THS_NAK   0x08
+#define USEP_THS_STALL 0x0C
+
+#define USEP_RTE       0x10
+#define USEP_MF                0x20
+
+#define USEP_TM_CONTROL        0x00
+#define USEP_TM_INT    0x100
+#define USEP_TM_BULK   0x200
+#define USEP_TM_ISO    0x300
+
+/* Command Register */
+#define USCOM_EP0      0x00
+#define USCOM_EP1      0x01
+#define USCOM_EP2      0x02
+#define USCOM_EP3      0x03
+
+#define USCOM_FLUSH    0x40
+#define USCOM_STR      0x80
+
+/* Event Register */
+#define USB_E_RXB      0x0001
+#define USB_E_TXB      0x0002
+#define USB_E_BSY      0x0004
+#define USB_E_SOF      0x0008
+#define USB_E_TXE1     0x0010
+#define USB_E_TXE2     0x0020
+#define USB_E_TXE3     0x0040
+#define USB_E_TXE4     0x0080
+#define USB_TX_ERRMASK (USB_E_TXE1|USB_E_TXE2|USB_E_TXE3|USB_E_TXE4)
+#define USB_E_IDLE     0x0100
+#define USB_E_RESET    0x0200
+
+/* Mask Register */
+#define USBS_IDLE      0x01
+
+/* RX Buffer Descriptor */
+#define RX_BD_OV       0x02
+#define RX_BD_CR       0x04
+#define RX_BD_AB       0x08
+#define RX_BD_NO       0x10
+#define RX_BD_PID_DATA0        0x00
+#define RX_BD_PID_DATA1        0x40
+#define RX_BD_PID_SETUP        0x80
+#define RX_BD_F                0x400
+#define RX_BD_L                0x800
+#define RX_BD_I                0x1000
+#define RX_BD_W                0x2000
+#define RX_BD_E                0x8000
+
+/* Useful masks */
+#define RX_BD_PID_BITMASK (RX_BD_PID_DATA1 | RX_BD_PID_SETUP)
+#define STALL_BITMASK (USEP_THS_STALL | USEP_RHS_STALL)
+#define NAK_BITMASK (USEP_THS_NAK | USEP_RHS_NAK)
+#define CBD_TX_BITMASK (TX_BD_R | TX_BD_L | TX_BD_TC | TX_BD_I | TX_BD_CNF)
+
+/* TX Buffer Descriptor */
+#define TX_BD_UN       0x02
+#define TX_BD_TO       0x04
+#define TX_BD_NO_PID   0x00
+#define TX_BD_PID_DATA0        0x80
+#define TX_BD_PID_DATA1        0xC0
+#define TX_BD_CNF      0x200
+#define TX_BD_TC       0x400
+#define TX_BD_L                0x800
+#define TX_BD_I                0x1000
+#define TX_BD_W                0x2000
+#define TX_BD_R                0x8000
+
+/* Implementation specific defines */
+
+#define EP_MIN_PACKET_SIZE 0x08
+#define MAX_ENDPOINTS  0x04
+#define FIFO_SIZE      0x10
+#define EP_MAX_PKT     FIFO_SIZE
+#define TX_RING_SIZE   0x04
+#define RX_RING_SIZE   0x06
+#define USB_MAX_PKT    0x40
+#define TOGGLE_TX_PID(x) x= ((~x)&0x40)|0x80
+#define TOGGLE_RX_PID(x) x^= 0x40
+#define EP_ATTACHED    0x01    /* Endpoint has a urb attached or not */
+#define EP_SEND_ZLP    0x02    /* Send ZLP y/n ? */
+
+#define PROFF_USB      0x00000000
+#define CPM_USB_BASE   0x00000A00
+
+/* UDC device defines */
+#define EP0_MAX_PACKET_SIZE    EP_MAX_PKT
+#define UDC_OUT_ENDPOINT       0x02
+#define UDC_OUT_PACKET_SIZE    EP_MIN_PACKET_SIZE
+#define UDC_IN_ENDPOINT                0x03
+#define UDC_IN_PACKET_SIZE     EP_MIN_PACKET_SIZE
+#define UDC_INT_ENDPOINT       0x01
+#define UDC_INT_PACKET_SIZE    UDC_IN_PACKET_SIZE
+#define UDC_BULK_PACKET_SIZE   EP_MIN_PACKET_SIZE
+
+struct mpc8xx_ep {
+       struct urb * urb;
+       unsigned char pid;
+       unsigned char sc;
+       volatile cbd_t * prx;
+};
+
+typedef struct mpc8xx_usb{
+       char usmod;     /* Mode Register */
+       char usaddr;    /* Slave Address Register */
+       char uscom;     /* Command Register */
+       char res1;      /* Reserved */
+       ushort usep[4];
+       ulong res2;     /* Reserved */
+       ushort usber;   /* Event Register */
+       ushort res3;    /* Reserved */
+       ushort usbmr;   /* Mask Register */
+       char res4;      /* Reserved */
+       char usbs;      /* Status Register */
+       char res5[8];   /* Reserved */
+}usb_t;
+
+typedef struct mpc8xx_parameter_ram{
+       ushort ep0ptr;  /* Endpoint Pointer Register 0 */
+       ushort ep1ptr;  /* Endpoint Pointer Register 1 */
+       ushort ep2ptr;  /* Endpoint Pointer Register 2 */
+       ushort ep3ptr;  /* Endpoint Pointer Register 3 */
+       uint rstate;    /* Receive state */
+       uint rptr;      /* Receive internal data pointer */
+       ushort frame_n; /* Frame number */
+       ushort rbcnt;   /* Receive byte count */
+       uint rtemp;     /* Receive temp cp use only */
+       uint rxusb;     /* Rx Data Temp */
+       ushort rxuptr;  /* Rx microcode return address temp */
+}usb_pram_t;
+
+typedef struct endpoint_parameter_block_pointer{
+       ushort rbase;   /* RxBD base address */
+       ushort tbase;   /* TxBD base address */
+       char rfcr;      /* Rx Function code */
+       char tfcr;      /* Tx Function code */
+       ushort mrblr;   /* Maximum Receive Buffer Length */
+       ushort rbptr;   /* RxBD pointer Next Buffer Descriptor */
+       ushort tbptr;   /* TxBD pointer Next Buffer Descriptor  */
+       ulong tstate;   /* Transmit internal state */
+       ulong tptr;     /* Transmit internal data pointer */
+       ushort tcrc;    /* Transmit temp CRC */
+       ushort tbcnt;   /* Transmit internal bye count */
+       ulong ttemp;    /* Tx temp */
+       ushort txuptr;  /* Tx microcode return address */
+       ushort res1;    /* Reserved */
+}usb_epb_t;
+
+typedef enum mpc8xx_udc_state{
+       STATE_NOT_READY,
+       STATE_ERROR,
+       STATE_READY,
+}mpc8xx_udc_state_t;
+
+/* Declarations */
+int udc_init(void);
+void udc_irq(void);
+int udc_endpoint_write(struct usb_endpoint_instance *endpoint);
+void udc_setup_ep(struct usb_device_instance *device, unsigned int ep,
+                 struct usb_endpoint_instance *endpoint);
+void udc_connect(void);
+void udc_disconnect(void);
+void udc_enable(struct usb_device_instance *device);
+void udc_disable(void);
+void udc_startup_events(struct usb_device_instance *device);
+
+/* Flow control */
+void udc_set_nak(int epid);
+void udc_unset_nak (int epid);
diff --git a/include/usb/omap1510_udc.h b/include/usb/omap1510_udc.h
new file mode 100644 (file)
index 0000000..ece0e95
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * (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)
+
+/* OMAP Endpoint parameters */
+#define EP0_MAX_PACKET_SIZE 64
+#define UDC_OUT_ENDPOINT 2
+#define UDC_OUT_PACKET_SIZE 64
+#define UDC_IN_ENDPOINT        1
+#define UDC_IN_PACKET_SIZE 64
+#define UDC_INT_ENDPOINT 5
+#define UDC_INT_PACKET_SIZE    16
+#define UDC_BULK_PACKET_SIZE 16
+
+void udc_irq (void);
+/* Flow control */
+void udc_set_nak(int epid);
+void udc_unset_nak (int epid);
+
+/* Higher level functions for abstracting away from specific device */
+int 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/usbdcore.h b/include/usbdcore.h
deleted file mode 100644 (file)
index 206dbbc..0000000
+++ /dev/null
@@ -1,666 +0,0 @@
-/*
- * (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
-
-/*
- * 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);
-
-       /* Do cdc device specific control requests */
-       int (*cdc_recv_setup)(struct usb_device_request *request, struct urb *urb);
-
-       /* 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
deleted file mode 100644 (file)
index 3bec106..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * (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_mpc8xx.h b/include/usbdcore_mpc8xx.h
deleted file mode 100644 (file)
index 039d245..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2006 Bryan O'Donoghue, CodeHermit
- * bodonoghue@codehermit.ie
- *
- *
- * 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 <commproc.h>
-
-/* Mode Register */
-#define USMOD_EN       0x01
-#define USMOD_HOST     0x02
-#define USMOD_TEST     0x04
-#define USMOD_SFTE     0x08
-#define USMOD_RESUME   0x40
-#define USMOD_LSS      0x80
-
-/* Endpoint Registers */
-#define USEP_RHS_NORM  0x00
-#define USEP_RHS_IGNORE        0x01
-#define USEP_RHS_NAK   0x02
-#define USEP_RHS_STALL 0x03
-
-#define USEP_THS_NORM  0x00
-#define USEP_THS_IGNORE        0x04
-#define USEP_THS_NAK   0x08
-#define USEP_THS_STALL 0x0C
-
-#define USEP_RTE       0x10
-#define USEP_MF                0x20
-
-#define USEP_TM_CONTROL        0x00
-#define USEP_TM_INT    0x100
-#define USEP_TM_BULK   0x200
-#define USEP_TM_ISO    0x300
-
-/* Command Register */
-#define USCOM_EP0      0x00
-#define USCOM_EP1      0x01
-#define USCOM_EP2      0x02
-#define USCOM_EP3      0x03
-
-#define USCOM_FLUSH    0x40
-#define USCOM_STR      0x80
-
-/* Event Register */
-#define USB_E_RXB      0x0001
-#define USB_E_TXB      0x0002
-#define USB_E_BSY      0x0004
-#define USB_E_SOF      0x0008
-#define USB_E_TXE1     0x0010
-#define USB_E_TXE2     0x0020
-#define USB_E_TXE3     0x0040
-#define USB_E_TXE4     0x0080
-#define USB_TX_ERRMASK (USB_E_TXE1|USB_E_TXE2|USB_E_TXE3|USB_E_TXE4)
-#define USB_E_IDLE     0x0100
-#define USB_E_RESET    0x0200
-
-/* Mask Register */
-#define USBS_IDLE      0x01
-
-/* RX Buffer Descriptor */
-#define RX_BD_OV       0x02
-#define RX_BD_CR       0x04
-#define RX_BD_AB       0x08
-#define RX_BD_NO       0x10
-#define RX_BD_PID_DATA0        0x00
-#define RX_BD_PID_DATA1        0x40
-#define RX_BD_PID_SETUP        0x80
-#define RX_BD_F                0x400
-#define RX_BD_L                0x800
-#define RX_BD_I                0x1000
-#define RX_BD_W                0x2000
-#define RX_BD_E                0x8000
-
-/* Useful masks */
-#define RX_BD_PID_BITMASK (RX_BD_PID_DATA1 | RX_BD_PID_SETUP)
-#define STALL_BITMASK (USEP_THS_STALL | USEP_RHS_STALL)
-#define NAK_BITMASK (USEP_THS_NAK | USEP_RHS_NAK)
-#define CBD_TX_BITMASK (TX_BD_R | TX_BD_L | TX_BD_TC | TX_BD_I | TX_BD_CNF)
-
-/* TX Buffer Descriptor */
-#define TX_BD_UN       0x02
-#define TX_BD_TO       0x04
-#define TX_BD_NO_PID   0x00
-#define TX_BD_PID_DATA0        0x80
-#define TX_BD_PID_DATA1        0xC0
-#define TX_BD_CNF      0x200
-#define TX_BD_TC       0x400
-#define TX_BD_L                0x800
-#define TX_BD_I                0x1000
-#define TX_BD_W                0x2000
-#define TX_BD_R                0x8000
-
-/* Implementation specific defines */
-
-#define EP_MIN_PACKET_SIZE 0x08
-#define MAX_ENDPOINTS  0x04
-#define FIFO_SIZE      0x10
-#define EP_MAX_PKT     FIFO_SIZE
-#define TX_RING_SIZE   0x04
-#define RX_RING_SIZE   0x06
-#define USB_MAX_PKT    0x40
-#define TOGGLE_TX_PID(x) x= ((~x)&0x40)|0x80
-#define TOGGLE_RX_PID(x) x^= 0x40
-#define EP_ATTACHED    0x01    /* Endpoint has a urb attached or not */
-#define EP_SEND_ZLP    0x02    /* Send ZLP y/n ? */
-
-#define PROFF_USB      0x00000000
-#define CPM_USB_BASE   0x00000A00
-
-/* UDC device defines */
-#define EP0_MAX_PACKET_SIZE    EP_MAX_PKT
-#define UDC_OUT_ENDPOINT       0x02
-#define UDC_OUT_PACKET_SIZE    EP_MIN_PACKET_SIZE
-#define UDC_IN_ENDPOINT                0x03
-#define UDC_IN_PACKET_SIZE     EP_MIN_PACKET_SIZE
-#define UDC_INT_ENDPOINT       0x01
-#define UDC_INT_PACKET_SIZE    UDC_IN_PACKET_SIZE
-#define UDC_BULK_PACKET_SIZE   EP_MIN_PACKET_SIZE
-
-struct mpc8xx_ep {
-       struct urb * urb;
-       unsigned char pid;
-       unsigned char sc;
-       volatile cbd_t * prx;
-};
-
-typedef struct mpc8xx_usb{
-       char usmod;     /* Mode Register */
-       char usaddr;    /* Slave Address Register */
-       char uscom;     /* Command Register */
-       char res1;      /* Reserved */
-       ushort usep[4];
-       ulong res2;     /* Reserved */
-       ushort usber;   /* Event Register */
-       ushort res3;    /* Reserved */
-       ushort usbmr;   /* Mask Register */
-       char res4;      /* Reserved */
-       char usbs;      /* Status Register */
-       char res5[8];   /* Reserved */
-}usb_t;
-
-typedef struct mpc8xx_parameter_ram{
-       ushort ep0ptr;  /* Endpoint Pointer Register 0 */
-       ushort ep1ptr;  /* Endpoint Pointer Register 1 */
-       ushort ep2ptr;  /* Endpoint Pointer Register 2 */
-       ushort ep3ptr;  /* Endpoint Pointer Register 3 */
-       uint rstate;    /* Receive state */
-       uint rptr;      /* Receive internal data pointer */
-       ushort frame_n; /* Frame number */
-       ushort rbcnt;   /* Receive byte count */
-       uint rtemp;     /* Receive temp cp use only */
-       uint rxusb;     /* Rx Data Temp */
-       ushort rxuptr;  /* Rx microcode return address temp */
-}usb_pram_t;
-
-typedef struct endpoint_parameter_block_pointer{
-       ushort rbase;   /* RxBD base address */
-       ushort tbase;   /* TxBD base address */
-       char rfcr;      /* Rx Function code */
-       char tfcr;      /* Tx Function code */
-       ushort mrblr;   /* Maximum Receive Buffer Length */
-       ushort rbptr;   /* RxBD pointer Next Buffer Descriptor */
-       ushort tbptr;   /* TxBD pointer Next Buffer Descriptor  */
-       ulong tstate;   /* Transmit internal state */
-       ulong tptr;     /* Transmit internal data pointer */
-       ushort tcrc;    /* Transmit temp CRC */
-       ushort tbcnt;   /* Transmit internal bye count */
-       ulong ttemp;    /* Tx temp */
-       ushort txuptr;  /* Tx microcode return address */
-       ushort res1;    /* Reserved */
-}usb_epb_t;
-
-typedef enum mpc8xx_udc_state{
-       STATE_NOT_READY,
-       STATE_ERROR,
-       STATE_READY,
-}mpc8xx_udc_state_t;
-
-/* Declarations */
-int udc_init(void);
-void udc_irq(void);
-int udc_endpoint_write(struct usb_endpoint_instance *endpoint);
-void udc_setup_ep(struct usb_device_instance *device, unsigned int ep,
-                 struct usb_endpoint_instance *endpoint);
-void udc_connect(void);
-void udc_disconnect(void);
-void udc_enable(struct usb_device_instance *device);
-void udc_disable(void);
-void udc_startup_events(struct usb_device_instance *device);
-
-/* Flow control */
-void udc_set_nak(int epid);
-void udc_unset_nak (int epid);
diff --git a/include/usbdcore_omap1510.h b/include/usbdcore_omap1510.h
deleted file mode 100644 (file)
index ece0e95..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * (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)
-
-/* OMAP Endpoint parameters */
-#define EP0_MAX_PACKET_SIZE 64
-#define UDC_OUT_ENDPOINT 2
-#define UDC_OUT_PACKET_SIZE 64
-#define UDC_IN_ENDPOINT        1
-#define UDC_IN_PACKET_SIZE 64
-#define UDC_INT_ENDPOINT 5
-#define UDC_INT_PACKET_SIZE    16
-#define UDC_BULK_PACKET_SIZE 16
-
-void udc_irq (void);
-/* Flow control */
-void udc_set_nak(int epid);
-void udc_unset_nak (int epid);
-
-/* Higher level functions for abstracting away from specific device */
-int 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/usbdevice.h b/include/usbdevice.h
new file mode 100644 (file)
index 0000000..206dbbc
--- /dev/null
@@ -0,0 +1,666 @@
+/*
+ * (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
+
+/*
+ * 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);
+
+       /* Do cdc device specific control requests */
+       int (*cdc_recv_setup)(struct usb_device_request *request, struct urb *urb);
+
+       /* 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