[brcm2708] adds target used by rapsberry pi
authorblogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Tue, 24 Jul 2012 20:39:17 +0000 (20:39 +0000)
committerblogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Tue, 24 Jul 2012 20:39:17 +0000 (20:39 +0000)
Add support for Raspberry Pi / brcm2708 / 2835

Signed-off-by: Ian Ridge <ianridge [at] gmail.com>
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@32825 3c298f89-4303-0410-b956-a3cf2f4a3e73

20 files changed:
package/brcm2708-gpu-fw/Makefile [new file with mode: 0644]
target/linux/brcm2708/Makefile [new file with mode: 0644]
target/linux/brcm2708/base-files/etc/config/network [new file with mode: 0644]
target/linux/brcm2708/base-files/etc/inittab [new file with mode: 0644]
target/linux/brcm2708/config-3.3 [new file with mode: 0644]
target/linux/brcm2708/image/Config.in [new file with mode: 0644]
target/linux/brcm2708/image/Makefile [new file with mode: 0644]
target/linux/brcm2708/image/cmdline.txt [new file with mode: 0644]
target/linux/brcm2708/image/gen_rpi_sdcard_img.sh [new file with mode: 0755]
target/linux/brcm2708/modules.mk [new file with mode: 0644]
target/linux/brcm2708/patches-3.3/0001-Add-dwc_otg-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-3.3/0002-Main-bcm2708-linux-port.patch [new file with mode: 0644]
target/linux/brcm2708/patches-3.3/0003-bcm2708-watchdog-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-3.3/0004-bcm2708-framebuffer-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-3.3/0005-bcm2708-vchiq-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-3.3/0006-Allow-mac-address-to-be-set-in-smsc95xx.patch [new file with mode: 0644]
target/linux/brcm2708/patches-3.3/0007-Fix-headers-for-vchiq-vcos-to-be-GPLv2.patch [new file with mode: 0644]
target/linux/brcm2708/patches-3.3/0500-rpi-patches-geaf792a-9efb4705.patch [new file with mode: 0644]
target/linux/brcm2708/patches-3.3/0510-fix_divdi3.patch [new file with mode: 0644]
target/linux/brcm2708/profiles/100-RaspberryPi.mk [new file with mode: 0644]

diff --git a/package/brcm2708-gpu-fw/Makefile b/package/brcm2708-gpu-fw/Makefile
new file mode 100644 (file)
index 0000000..45c727c
--- /dev/null
@@ -0,0 +1,46 @@
+# 
+# Copyright (C) 2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=brcm2708-gpu-fw
+PKG_REV:=29ce6bcf278e7e79cd8a2b84c6aa9db9864ca91d
+PKG_VERSION:=20120529
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=git://github.com/raspberrypi/firmware.git
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=$(PKG_REV)
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/brcm2708-gpu-fw
+  SECTION:=boot
+  CATEGORY:=Boot Loaders
+  DEPENDS:=@TARGET_brcm2708
+  TITLE:=brcm2708-gpu-fw
+  DEFAULT:=y if (TARGET_brcm2708)
+endef
+
+define Package/brcm2708-gpu-fw/description
+ GPU and kernel boot firmware for brcm2708. 
+endef
+
+define Build/Compile
+endef
+
+define Build/InstallDev
+       $(INSTALL_DIR) $(BUILD_DIR)/brcm2708-gpu-fw-boot
+       $(CP) $(PKG_BUILD_DIR)/boot/* $(BUILD_DIR)/brcm2708-gpu-fw-boot
+endef
+
+$(eval $(call BuildPackage,brcm2708-gpu-fw))
+
diff --git a/target/linux/brcm2708/Makefile b/target/linux/brcm2708/Makefile
new file mode 100644 (file)
index 0000000..91207e9
--- /dev/null
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/host.mk
+
+ARCH:=arm
+BOARD:=brcm2708
+BOARDNAME:=Broadcom BCM2708/BCM2835
+FEATURES:=ext4 audio usb usbgadget display gpio
+MAINTAINER:=Ian Ridge <ianridge[at]gmail.com>
+
+LINUX_VERSION:=3.3.8
+
+include $(INCLUDE_DIR)/target.mk
+DEFAULT_PACKAGES += brcm2708-gpu-fw kmod-usb-hid kmod-sound-core kmod-sound-arm-bcm2835
+
+define Target/Description
+       Build firmware image for Broadcom BCM2708/BCM2835 SoC devices.
+       Currently produces SD Card image for Raspberry Pi.
+endef
+
+CFLAGS:=-pipe -march=armv6 -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=softfp -marm
+
+$(eval $(call BuildTarget))
diff --git a/target/linux/brcm2708/base-files/etc/config/network b/target/linux/brcm2708/base-files/etc/config/network
new file mode 100644 (file)
index 0000000..1d5ded3
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright (C) 2006 OpenWrt.org
+
+config interface loopback
+       option ifname   lo
+       option proto    static
+       option ipaddr   127.0.0.1
+       option netmask  255.0.0.0
+
+config interface lan
+       option ifname   eth0
+       option proto    static
+       option ipaddr   192.168.1.1
+       option netmask  255.255.255.0
diff --git a/target/linux/brcm2708/base-files/etc/inittab b/target/linux/brcm2708/base-files/etc/inittab
new file mode 100644 (file)
index 0000000..d9d571e
--- /dev/null
@@ -0,0 +1,5 @@
+::sysinit:/etc/init.d/rcS S boot
+::shutdown:/etc/init.d/rcS K shutdown
+tts/0::askfirst:/bin/ash --login
+ttyAMA0::askfirst:/bin/ash --login
+tty1::askfirst:/bin/ash --login
diff --git a/target/linux/brcm2708/config-3.3 b/target/linux/brcm2708/config-3.3
new file mode 100644 (file)
index 0000000..ae1f599
--- /dev/null
@@ -0,0 +1,308 @@
+# CONFIG_AIO is not set
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_BCM2708=y
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
+CONFIG_ARM=y
+CONFIG_ARM_AMBA=y
+CONFIG_ARM_CPU_SUSPEND=y
+# CONFIG_ARM_ERRATA_326103 is not set
+# CONFIG_ARM_ERRATA_364296 is not set
+CONFIG_ARM_ERRATA_411920=y
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_NR_BANKS=8
+# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_UNWIND=y
+CONFIG_AVERAGE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_GENERIC=m
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BCM2708_GPIO=y
+# CONFIG_BCM2708_NOL2CACHE is not set
+CONFIG_BCM2708_VCHIQ=y
+CONFIG_BCM2708_VCMEM=y
+CONFIG_BCM2708_WDT=y
+CONFIG_BCMA_POSSIBLE=y
+CONFIG_BINFMT_MISC=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rootwait"
+CONFIG_CMDLINE_FROM_BOOTLOADER=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_HAS_PMU=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_PM=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_USE_DOMAINS=y
+CONFIG_CPU_V6=y
+CONFIG_CRC16=y
+CONFIG_CRYPTO_AEAD2=m
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_ALGAPI2=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_HASH2=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=m
+# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
+CONFIG_CRYPTO_PCOMP2=m
+CONFIG_CRYPTO_RNG2=m
+CONFIG_CRYPTO_WORKQUEUE=m
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_DEVTMPFS=y
+CONFIG_DNOTIFY=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_EEPROM_93CX6=m
+CONFIG_ELF_CORE=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_FB=y
+# CONFIG_FB_ARMCLCD is not set
+CONFIG_FB_BCM2708=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_WMT_GE_ROPS is not set
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FIRMWARE_IN_KERNEL=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x16=y
+CONFIG_FONT_8x8=y
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_FPE_NWFPE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FREEZER=y
+CONFIG_FS_MBCACHE=y
+CONFIG_FS_POSIX_ACL=y
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GENERIC_ACL=y
+CONFIG_GENERIC_ATOMIC64=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_PL061 is not set
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HAMRADIO is not set
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAVE_AOUT=y
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+CONFIG_HAVE_IRQ_WORK=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_SPARSE_IRQ=y
+CONFIG_HW_CONSOLE=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INPUT=y
+CONFIG_INPUT_AD714X=m
+CONFIG_INPUT_ADXL34X=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_CMA3000=m
+CONFIG_INPUT_FF_MEMLESS=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_POWERMATE=m
+CONFIG_INPUT_UINPUT=m
+CONFIG_IOSCHED_CFQ=y
+CONFIG_IWMC3200TOP=m
+# CONFIG_IWMC3200TOP_DEBUG is not set
+# CONFIG_IWMC3200TOP_DEBUGFS is not set
+CONFIG_JBD2=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_XZ is not set
+CONFIG_KTIME_SCALAR=y
+CONFIG_LCD_CLASS_DEVICE=m
+# CONFIG_LCD_PLATFORM is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_MACH_BCM2708=y
+CONFIG_MAC_PARTITION=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MAX_RAW_DEVS=256
+# CONFIG_MFD_T7L66XB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_BCM2708 is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_BCM2708=y
+CONFIG_MMC_SDHCI_BCM2708_DMA=y
+CONFIG_MMC_SDHCI_IO_ACCESSORS=y
+CONFIG_MMC_SDHCI_PLTFM=y
+# CONFIG_MTD is not set
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_MACH_MEMORY_H=y
+CONFIG_NEED_PER_CPU_KM=y
+CONFIG_NLS=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NO_HZ=y
+CONFIG_OABI_COMPAT=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PDA_POWER is not set
+CONFIG_PERF_USE_VMALLOC=y
+CONFIG_PM=y
+CONFIG_PM_CLK=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_PREEMPT_RCU is not set
+CONFIG_PRINTK_TIME=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_RAW_DRIVER=y
+CONFIG_SCSI=y
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_PROC_FS is not set
+# CONFIG_SERIAL_8250 is not set
+# CONFIG_SERIAL_AMBA_PL010 is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIO=m
+CONFIG_SERIO_RAW=m
+CONFIG_SERIO_SERPORT=m
+# CONFIG_SQUASHFS is not set
+CONFIG_SSB=m
+CONFIG_SSB_BLOCKIO=y
+CONFIG_SSB_SDIOHOST_POSSIBLE=y
+# CONFIG_STAGING is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+# CONFIG_TEXTSEARCH is not set
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_UID16 is not set
+CONFIG_UIO=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+CONFIG_USB=y
+CONFIG_USB_ACM=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_APPLEDISPLAY=m
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_XHCI is not set
+CONFIG_USB_COMMON=y
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICE_CLASS=y
+CONFIG_USB_DWCOTG=y
+CONFIG_USB_EMI26=m
+CONFIG_USB_EMI62=m
+CONFIG_USB_FTDI_ELAN=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_IOWARRIOR=m
+CONFIG_USB_ISIGHTFW=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LD=m
+CONFIG_USB_LED=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LIBUSUAL=y
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_MON=m
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_RIO500=m
+CONFIG_USB_SEVSEG=m
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_ENE_UB6250=m
+CONFIG_USB_STORAGE_ONETOUCH=m
+CONFIG_USB_STORAGE_REALTEK=m
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_TRANCEVIBRATOR=m
+# CONFIG_USB_U132_HCD is not set
+CONFIG_USB_UAS=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_YUREX=m
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_VFP=y
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZONE_DMA_FLAG=0
diff --git a/target/linux/brcm2708/image/Config.in b/target/linux/brcm2708/image/Config.in
new file mode 100644 (file)
index 0000000..b9bea86
--- /dev/null
@@ -0,0 +1,5 @@
+config BRCM2708_SD_BOOT_PARTSIZE
+       int "Boot (SD Card) filesystem partition size (in MB)"
+       depends TARGET_brcm2708
+       default 20
+
diff --git a/target/linux/brcm2708/image/Makefile b/target/linux/brcm2708/image/Makefile
new file mode 100644 (file)
index 0000000..a8dbef1
--- /dev/null
@@ -0,0 +1,46 @@
+# 
+# Copyright (C) 2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/image.mk
+include $(INCLUDE_DIR)/host.mk
+
+define Image/Prepare
+       cp $(LINUX_DIR)/arch/arm/boot/Image $(KDIR)/Image
+endef
+
+FAT32_BLOCK_SIZE=1024
+FAT32_BLOCKS=$(shell echo $$(($(CONFIG_BRCM2708_SD_BOOT_PARTSIZE)*1024*1024/$(FAT32_BLOCK_SIZE))))
+
+define Image/Build/RaspberryPi
+       rm -f $(KDIR)/boot.img
+
+       mkdosfs $(KDIR)/boot.img -C $(FAT32_BLOCKS)
+       # Raspberry Pi has no bootloader, instead the GPU loads and starts the kernel
+       mcopy -i $(KDIR)/boot.img $(BUILD_DIR)/brcm2708-gpu-fw-boot/arm128_start.elf ::
+       mcopy -i $(KDIR)/boot.img $(BUILD_DIR)/brcm2708-gpu-fw-boot/arm192_start.elf ::
+       mcopy -i $(KDIR)/boot.img $(BUILD_DIR)/brcm2708-gpu-fw-boot/arm224_start.elf ::
+       mcopy -i $(KDIR)/boot.img $(BUILD_DIR)/brcm2708-gpu-fw-boot/bootcode.bin ::
+       mcopy -i $(KDIR)/boot.img $(BUILD_DIR)/brcm2708-gpu-fw-boot/COPYING.linux ::
+       mcopy -i $(KDIR)/boot.img $(BUILD_DIR)/brcm2708-gpu-fw-boot/LICENCE.broadcom ::
+       mcopy -i $(KDIR)/boot.img $(BUILD_DIR)/brcm2708-gpu-fw-boot/loader.bin ::
+       mcopy -i $(KDIR)/boot.img $(BUILD_DIR)/brcm2708-gpu-fw-boot/arm$(2)_start.elf ::start.elf  #Copy file for memory/gpu division
+       mcopy -i $(KDIR)/boot.img cmdline.txt ::
+       mcopy -i $(KDIR)/boot.img $(KDIR)/Image ::kernel.img  # Copy OpenWrt built kernel
+       ./gen_rpi_sdcard_img.sh $(BIN_DIR)/$(IMG_PREFIX)-sdcard-vfat-$(1)_$(2).img $(KDIR)/boot.img $(KDIR)/root.$(1) \
+               $(CONFIG_BRCM2708_SD_BOOT_PARTSIZE) $(CONFIG_TARGET_ROOTFS_PARTSIZE)
+endef
+
+define Image/Build
+       $(CP) $(KDIR)/root.$(1) $(BIN_DIR)/$(IMG_PREFIX)-$(1).img
+       $(CP) $(KDIR)/Image $(BIN_DIR)/$(IMG_PREFIX)-Image
+
+       $(call Image/Build/RaspberryPi,$(1),128)
+       $(call Image/Build/RaspberryPi,$(1),192)
+       $(call Image/Build/RaspberryPi,$(1),224)
+endef
+
+$(eval $(call BuildImage))
diff --git a/target/linux/brcm2708/image/cmdline.txt b/target/linux/brcm2708/image/cmdline.txt
new file mode 100644 (file)
index 0000000..516f270
--- /dev/null
@@ -0,0 +1 @@
+dwc_otg.lpm_enable=0 rpitestmode=1 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait
diff --git a/target/linux/brcm2708/image/gen_rpi_sdcard_img.sh b/target/linux/brcm2708/image/gen_rpi_sdcard_img.sh
new file mode 100755 (executable)
index 0000000..c3287d2
--- /dev/null
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+set -x 
+[ $# == 5 ] || {
+    echo "SYNTAX: $0 <file> <bootfs image> <rootfs image> <bootfs size> <rootfs size>"
+    exit 1
+}
+
+OUTPUT="$1"
+BOOTFS="$2"
+ROOTFS="$3"
+BOOTFSSIZE="$4"
+ROOTFSSIZE="$5"
+
+head=4
+sect=63
+
+set `ptgen -o $OUTPUT -h $head -s $sect -t c -p ${BOOTFSSIZE}M -t 83 -p ${ROOTFSSIZE}M`
+
+BOOTOFFSET="$(($1 / 512))"
+BOOTSIZE="$(($2 / 512))"
+ROOTFSOFFSET="$(($3 / 512))"
+ROOTFSSIZE="$(($4 / 512))"
+
+dd bs=512 if="$BOOTFS" of="$OUTPUT" seek="$BOOTOFFSET" conv=notrunc
+dd bs=512 if="$ROOTFS" of="$OUTPUT" seek="$ROOTFSOFFSET" conv=notrunc
+
+
+
diff --git a/target/linux/brcm2708/modules.mk b/target/linux/brcm2708/modules.mk
new file mode 100644 (file)
index 0000000..e8a2bff
--- /dev/null
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define KernelPackage/sound-arm-bcm2835
+  TITLE:=Broadcom 2708,2835 SoC sound support
+  KCONFIG:= \
+       CONFIG_SND_ARM=y \
+       CONFIG_SND_BCM2835 \
+       CONFIG_SND_ARMAACI=n
+  FILES:= \
+       $(LINUX_DIR)/sound/arm/snd-bcm2835.ko
+  AUTOLOAD:=$(call AutoLoad,68,snd-bcm2835)
+  DEPENDS:=@TARGET_brcm2708
+  $(call AddDepends/sound)
+endef
+
+define KernelPackage/sound-arm-bcm2835/description
+  This package contains the Broadcom 2708/2835 sound driver
+endef
+
+$(eval $(call KernelPackage,sound-arm-bcm2835))
+
diff --git a/target/linux/brcm2708/patches-3.3/0001-Add-dwc_otg-driver.patch b/target/linux/brcm2708/patches-3.3/0001-Add-dwc_otg-driver.patch
new file mode 100644 (file)
index 0000000..2e7bcf0
--- /dev/null
@@ -0,0 +1,43253 @@
+From c2eaacd30565604bbf776ca6e83c9889ea87ea74 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Tue, 17 Jan 2012 19:14:08 +0000
+Subject: [PATCH 1/7] Add dwc_otg driver
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+---
+ drivers/usb/Makefile                               |    1 +
+ drivers/usb/core/generic.c                         |    1 +
+ drivers/usb/core/hub.c                             |   52 +-
+ drivers/usb/core/message.c                         |   79 +
+ drivers/usb/core/otg_whitelist.h                   |  172 +-
+ drivers/usb/gadget/Kconfig                         |   28 +
+ drivers/usb/gadget/file_storage.c                  |   70 +-
+ drivers/usb/host/Kconfig                           |   13 +
+ drivers/usb/host/Makefile                          |    2 +
+ drivers/usb/host/dwc_common_port/Makefile          |   44 +
+ drivers/usb/host/dwc_common_port/Makefile.linux    |   36 +
+ drivers/usb/host/dwc_common_port/doc/doxygen.cfg   |  270 +
+ .../html/dir_c13d72e45af28cdc461a5f284d3d36fc.html |   81 +
+ .../usb/host/dwc_common_port/doc/html/dirs.html    |   22 +
+ .../usb/host/dwc_common_port/doc/html/doxygen.css  |  358 ++
+ .../host/dwc_common_port/doc/html/dwc__cc_8h.html  |  709 +++
+ .../dwc_common_port/doc/html/dwc__crypto_8c.html   |  435 ++
+ .../dwc_common_port/doc/html/dwc__crypto_8h.html   |  618 +++
+ .../host/dwc_common_port/doc/html/dwc__dh_8h.html  |  166 +
+ .../dwc_common_port/doc/html/dwc__list_8h.html     | 1844 +++++++
+ .../dwc_common_port/doc/html/dwc__modpow_8h.html   |   48 +
+ .../dwc_common_port/doc/html/dwc__notifier_8h.html |  306 ++
+ .../host/dwc_common_port/doc/html/dwc__os_8h.html  | 3090 +++++++++++
+ .../usb/host/dwc_common_port/doc/html/files.html   |   34 +
+ .../usb/host/dwc_common_port/doc/html/globals.html |  163 +
+ .../dwc_common_port/doc/html/globals_defs.html     |   41 +
+ .../dwc_common_port/doc/html/globals_func.html     |  153 +
+ .../dwc_common_port/doc/html/globals_type.html     |   41 +
+ .../usb/host/dwc_common_port/doc/html/index.html   |    8 +
+ .../usb/host/dwc_common_port/doc/html/main.html    |   45 +
+ .../usb/host/dwc_common_port/doc/html/pages.html   |   23 +
+ drivers/usb/host/dwc_common_port/doc/html/tabs.css |  102 +
+ .../usb/host/dwc_common_port/doc/html/todo.html    |   23 +
+ .../usb/host/dwc_common_port/doc/html/tree.html    |   90 +
+ drivers/usb/host/dwc_common_port/dwc_cc.c          |  506 ++
+ drivers/usb/host/dwc_common_port/dwc_cc.h          |  209 +
+ .../usb/host/dwc_common_port/dwc_common_linux.c    | 1247 +++++
+ drivers/usb/host/dwc_common_port/dwc_crypto.c      |  306 ++
+ drivers/usb/host/dwc_common_port/dwc_crypto.h      |  103 +
+ drivers/usb/host/dwc_common_port/dwc_dh.c          |  286 ++
+ drivers/usb/host/dwc_common_port/dwc_dh.h          |   98 +
+ drivers/usb/host/dwc_common_port/dwc_list.h        |  616 +++
+ drivers/usb/host/dwc_common_port/dwc_mem.c         |  172 +
+ drivers/usb/host/dwc_common_port/dwc_modpow.c      |  622 +++
+ drivers/usb/host/dwc_common_port/dwc_modpow.h      |   26 +
+ drivers/usb/host/dwc_common_port/dwc_notifier.c    |  256 +
+ drivers/usb/host/dwc_common_port/dwc_notifier.h    |  112 +
+ drivers/usb/host/dwc_common_port/dwc_os.h          |  924 ++++
+ drivers/usb/host/dwc_common_port/usb.h             |  850 +++
+ drivers/usb/host/dwc_otg/Makefile                  |   78 +
+ drivers/usb/host/dwc_otg/doc/doxygen.cfg           |  224 +
+ drivers/usb/host/dwc_otg/doc/html/annotated.html   |  120 +
+ drivers/usb/host/dwc_otg/doc/html/doxygen.css      |  358 ++
+ .../dwc_otg/doc/html/dummy__audio_8c-source.html   | 1550 ++++++
+ .../doc/html/dwc__cfi__common_8h-source.html       |  115 +
+ .../host/dwc_otg/doc/html/dwc__cfi__common_8h.html |  119 +
+ .../dwc_otg/doc/html/dwc__otg__attr_8c-source.html |  828 +++
+ .../host/dwc_otg/doc/html/dwc__otg__attr_8c.html   |  485 ++
+ .../dwc_otg/doc/html/dwc__otg__attr_8h-source.html |  105 +
+ .../host/dwc_otg/doc/html/dwc__otg__attr_8h.html   |  116 +
+ .../dwc_otg/doc/html/dwc__otg__cfi_8c-source.html  | 1724 +++++++
+ .../host/dwc_otg/doc/html/dwc__otg__cfi_8c.html    |   36 +
+ .../dwc_otg/doc/html/dwc__otg__cfi_8h-source.html  |  299 ++
+ .../host/dwc_otg/doc/html/dwc__otg__cfi_8h.html    |  302 ++
+ .../dwc_otg/doc/html/dwc__otg__cil_8c-source.html  | 4922 ++++++++++++++++++
+ .../host/dwc_otg/doc/html/dwc__otg__cil_8c.html    | 3103 +++++++++++
+ .../dwc_otg/doc/html/dwc__otg__cil_8h-source.html  |  709 +++
+ .../host/dwc_otg/doc/html/dwc__otg__cil_8h.html    | 1844 +++++++
+ .../doc/html/dwc__otg__cil__intr_8c-source.html    |  742 +++
+ .../dwc_otg/doc/html/dwc__otg__cil__intr_8c.html   |  645 +++
+ .../doc/html/dwc__otg__core__if_8h-source.html     |  365 ++
+ .../dwc_otg/doc/html/dwc__otg__core__if_8h.html    | 1730 +++++++
+ .../dwc_otg/doc/html/dwc__otg__dbg_8h-source.html  |  100 +
+ .../host/dwc_otg/doc/html/dwc__otg__dbg_8h.html    |  133 +
+ .../doc/html/dwc__otg__driver_8c-source.html       | 1079 ++++
+ .../host/dwc_otg/doc/html/dwc__otg__driver_8c.html |  719 +++
+ .../doc/html/dwc__otg__driver_8h-source.html       |  110 +
+ .../host/dwc_otg/doc/html/dwc__otg__driver_8h.html |   50 +
+ .../dwc_otg/doc/html/dwc__otg__hcd_8c-source.html  | 2946 +++++++++++
+ .../host/dwc_otg/doc/html/dwc__otg__hcd_8c.html    | 1837 +++++++
+ .../dwc_otg/doc/html/dwc__otg__hcd_8h-source.html  |  517 ++
+ .../host/dwc_otg/doc/html/dwc__otg__hcd_8h.html    | 1310 +++++
+ .../doc/html/dwc__otg__hcd__ddma_8c-source.html    | 1070 ++++
+ .../dwc_otg/doc/html/dwc__otg__hcd__ddma_8c.html   |  311 ++
+ .../doc/html/dwc__otg__hcd__if_8h-source.html      |  191 +
+ .../dwc_otg/doc/html/dwc__otg__hcd__if_8h.html     | 1381 +++++
+ .../doc/html/dwc__otg__hcd__intr_8c-source.html    | 1873 +++++++
+ .../dwc_otg/doc/html/dwc__otg__hcd__intr_8c.html   | 1252 +++++
+ .../doc/html/dwc__otg__hcd__linux_8c-source.html   |  726 +++
+ .../dwc_otg/doc/html/dwc__otg__hcd__linux_8c.html  |  514 ++
+ .../doc/html/dwc__otg__hcd__queue_8c-source.html   |  633 +++
+ .../dwc_otg/doc/html/dwc__otg__hcd__queue_8c.html  |  667 +++
+ .../dwc_otg/doc/html/dwc__otg__pcd_8c-source.html  | 1851 +++++++
+ .../host/dwc_otg/doc/html/dwc__otg__pcd_8c.html    | 1343 +++++
+ .../dwc_otg/doc/html/dwc__otg__pcd_8h-source.html  |  171 +
+ .../host/dwc_otg/doc/html/dwc__otg__pcd_8h.html    |  254 +
+ .../doc/html/dwc__otg__pcd__if_8h-source.html      |  174 +
+ .../dwc_otg/doc/html/dwc__otg__pcd__if_8h.html     |  976 ++++
+ .../doc/html/dwc__otg__pcd__intr_8c-source.html    | 3629 +++++++++++++
+ .../dwc_otg/doc/html/dwc__otg__pcd__intr_8c.html   | 1599 ++++++
+ .../doc/html/dwc__otg__pcd__linux_8c-source.html   |  997 ++++
+ .../dwc_otg/doc/html/dwc__otg__pcd__linux_8c.html  |  796 +++
+ .../dwc_otg/doc/html/dwc__otg__regs_8h-source.html | 1260 +++++
+ .../host/dwc_otg/doc/html/dwc__otg__regs_8h.html   | 1468 ++++++
+ drivers/usb/host/dwc_otg/doc/html/files.html       |   52 +
+ drivers/usb/host/dwc_otg/doc/html/functions.html   |   82 +
+ .../usb/host/dwc_otg/doc/html/functions_0x62.html  |   99 +
+ .../usb/host/dwc_otg/doc/html/functions_0x63.html  |  110 +
+ .../usb/host/dwc_otg/doc/html/functions_0x64.html  |  158 +
+ .../usb/host/dwc_otg/doc/html/functions_0x65.html  |  109 +
+ .../usb/host/dwc_otg/doc/html/functions_0x66.html  |   81 +
+ .../usb/host/dwc_otg/doc/html/functions_0x67.html  |   95 +
+ .../usb/host/dwc_otg/doc/html/functions_0x68.html  |  119 +
+ .../usb/host/dwc_otg/doc/html/functions_0x69.html  |  121 +
+ .../usb/host/dwc_otg/doc/html/functions_0x6c.html  |   74 +
+ .../usb/host/dwc_otg/doc/html/functions_0x6d.html  |   79 +
+ .../usb/host/dwc_otg/doc/html/functions_0x6e.html  |   99 +
+ .../usb/host/dwc_otg/doc/html/functions_0x6f.html  |  101 +
+ .../usb/host/dwc_otg/doc/html/functions_0x70.html  |  144 +
+ .../usb/host/dwc_otg/doc/html/functions_0x71.html  |   71 +
+ .../usb/host/dwc_otg/doc/html/functions_0x72.html  |  141 +
+ .../usb/host/dwc_otg/doc/html/functions_0x73.html  |  128 +
+ .../usb/host/dwc_otg/doc/html/functions_0x74.html  |   88 +
+ .../usb/host/dwc_otg/doc/html/functions_0x75.html  |   78 +
+ .../usb/host/dwc_otg/doc/html/functions_0x76.html  |   65 +
+ .../usb/host/dwc_otg/doc/html/functions_0x77.html  |   79 +
+ .../usb/host/dwc_otg/doc/html/functions_0x78.html  |   77 +
+ .../usb/host/dwc_otg/doc/html/functions_func.html  |   36 +
+ .../usb/host/dwc_otg/doc/html/functions_vars.html  |   82 +
+ .../host/dwc_otg/doc/html/functions_vars_0x62.html |   99 +
+ .../host/dwc_otg/doc/html/functions_vars_0x63.html |  110 +
+ .../host/dwc_otg/doc/html/functions_vars_0x64.html |  157 +
+ .../host/dwc_otg/doc/html/functions_vars_0x65.html |  109 +
+ .../host/dwc_otg/doc/html/functions_vars_0x66.html |   81 +
+ .../host/dwc_otg/doc/html/functions_vars_0x67.html |   95 +
+ .../host/dwc_otg/doc/html/functions_vars_0x68.html |  119 +
+ .../host/dwc_otg/doc/html/functions_vars_0x69.html |  121 +
+ .../host/dwc_otg/doc/html/functions_vars_0x6c.html |   74 +
+ .../host/dwc_otg/doc/html/functions_vars_0x6d.html |   79 +
+ .../host/dwc_otg/doc/html/functions_vars_0x6e.html |   99 +
+ .../host/dwc_otg/doc/html/functions_vars_0x6f.html |  101 +
+ .../host/dwc_otg/doc/html/functions_vars_0x70.html |  144 +
+ .../host/dwc_otg/doc/html/functions_vars_0x71.html |   71 +
+ .../host/dwc_otg/doc/html/functions_vars_0x72.html |  141 +
+ .../host/dwc_otg/doc/html/functions_vars_0x73.html |  128 +
+ .../host/dwc_otg/doc/html/functions_vars_0x74.html |   88 +
+ .../host/dwc_otg/doc/html/functions_vars_0x75.html |   78 +
+ .../host/dwc_otg/doc/html/functions_vars_0x76.html |   65 +
+ .../host/dwc_otg/doc/html/functions_vars_0x77.html |   79 +
+ .../host/dwc_otg/doc/html/functions_vars_0x78.html |   77 +
+ drivers/usb/host/dwc_otg/doc/html/globals.html     |   87 +
+ .../usb/host/dwc_otg/doc/html/globals_0x61.html    |   76 +
+ .../usb/host/dwc_otg/doc/html/globals_0x62.html    |   83 +
+ .../usb/host/dwc_otg/doc/html/globals_0x63.html    |  100 +
+ .../usb/host/dwc_otg/doc/html/globals_0x64.html    |  686 +++
+ .../usb/host/dwc_otg/doc/html/globals_0x65.html    |   78 +
+ .../usb/host/dwc_otg/doc/html/globals_0x66.html    |   87 +
+ .../usb/host/dwc_otg/doc/html/globals_0x67.html    |   93 +
+ .../usb/host/dwc_otg/doc/html/globals_0x68.html    |  129 +
+ .../usb/host/dwc_otg/doc/html/globals_0x69.html    |   76 +
+ .../usb/host/dwc_otg/doc/html/globals_0x6b.html    |   69 +
+ .../usb/host/dwc_otg/doc/html/globals_0x6d.html    |   84 +
+ .../usb/host/dwc_otg/doc/html/globals_0x6e.html    |   68 +
+ .../usb/host/dwc_otg/doc/html/globals_0x6f.html    |   73 +
+ .../usb/host/dwc_otg/doc/html/globals_0x70.html    |   84 +
+ .../usb/host/dwc_otg/doc/html/globals_0x71.html    |   70 +
+ .../usb/host/dwc_otg/doc/html/globals_0x72.html    |   94 +
+ .../usb/host/dwc_otg/doc/html/globals_0x73.html    |   85 +
+ .../usb/host/dwc_otg/doc/html/globals_0x74.html    |   68 +
+ .../usb/host/dwc_otg/doc/html/globals_0x75.html    |   80 +
+ .../usb/host/dwc_otg/doc/html/globals_0x76.html    |   75 +
+ .../usb/host/dwc_otg/doc/html/globals_0x77.html    |   74 +
+ .../usb/host/dwc_otg/doc/html/globals_defs.html    |   68 +
+ .../host/dwc_otg/doc/html/globals_defs_0x61.html   |   64 +
+ .../host/dwc_otg/doc/html/globals_defs_0x62.html   |   71 +
+ .../host/dwc_otg/doc/html/globals_defs_0x63.html   |   74 +
+ .../host/dwc_otg/doc/html/globals_defs_0x64.html   |  241 +
+ .../host/dwc_otg/doc/html/globals_defs_0x66.html   |   71 +
+ .../host/dwc_otg/doc/html/globals_defs_0x67.html   |   62 +
+ .../host/dwc_otg/doc/html/globals_defs_0x68.html   |   63 +
+ .../host/dwc_otg/doc/html/globals_defs_0x69.html   |   62 +
+ .../host/dwc_otg/doc/html/globals_defs_0x6d.html   |   76 +
+ .../host/dwc_otg/doc/html/globals_defs_0x6e.html   |   62 +
+ .../host/dwc_otg/doc/html/globals_defs_0x6f.html   |   67 +
+ .../host/dwc_otg/doc/html/globals_defs_0x72.html   |   66 +
+ .../host/dwc_otg/doc/html/globals_defs_0x73.html   |   63 +
+ .../host/dwc_otg/doc/html/globals_defs_0x75.html   |   64 +
+ .../host/dwc_otg/doc/html/globals_defs_0x76.html   |   68 +
+ .../usb/host/dwc_otg/doc/html/globals_enum.html    |   44 +
+ .../usb/host/dwc_otg/doc/html/globals_eval.html    |   43 +
+ .../usb/host/dwc_otg/doc/html/globals_func.html    |   77 +
+ .../host/dwc_otg/doc/html/globals_func_0x61.html   |   70 +
+ .../host/dwc_otg/doc/html/globals_func_0x62.html   |   68 +
+ .../host/dwc_otg/doc/html/globals_func_0x63.html   |   77 +
+ .../host/dwc_otg/doc/html/globals_func_0x64.html   |  427 ++
+ .../host/dwc_otg/doc/html/globals_func_0x65.html   |   73 +
+ .../host/dwc_otg/doc/html/globals_func_0x66.html   |   72 +
+ .../host/dwc_otg/doc/html/globals_func_0x67.html   |   78 +
+ .../host/dwc_otg/doc/html/globals_func_0x68.html   |  101 +
+ .../host/dwc_otg/doc/html/globals_func_0x69.html   |   71 +
+ .../host/dwc_otg/doc/html/globals_func_0x6b.html   |   66 +
+ .../host/dwc_otg/doc/html/globals_func_0x6d.html   |   66 +
+ .../host/dwc_otg/doc/html/globals_func_0x70.html   |   78 +
+ .../host/dwc_otg/doc/html/globals_func_0x71.html   |   67 +
+ .../host/dwc_otg/doc/html/globals_func_0x72.html   |   80 +
+ .../host/dwc_otg/doc/html/globals_func_0x73.html   |   77 +
+ .../host/dwc_otg/doc/html/globals_func_0x75.html   |   73 +
+ .../host/dwc_otg/doc/html/globals_func_0x76.html   |   65 +
+ .../host/dwc_otg/doc/html/globals_func_0x77.html   |   70 +
+ .../usb/host/dwc_otg/doc/html/globals_type.html    |  175 +
+ .../usb/host/dwc_otg/doc/html/globals_vars.html    |  120 +
+ drivers/usb/host/dwc_otg/doc/html/index.html       |    8 +
+ .../dwc_otg/doc/html/linux module attributes.html  |  130 +
+ drivers/usb/host/dwc_otg/doc/html/main.html        |   21 +
+ .../host/dwc_otg/doc/html/module parameters.html   |  189 +
+ drivers/usb/host/dwc_otg/doc/html/pages.html       |   27 +
+ .../html/struct__ddma__align__buffer__setup.html   |   46 +
+ .../html/struct__ddma__concat__buffer__setup.html  |   46 +
+ .../struct__ddma__concat__buffer__setup__hdr.html  |   49 +
+ .../doc/html/struct__ddma__sg__buffer__setup.html  |   57 +
+ .../doc/html/struct__rx__fifo__size__setup.html    |   43 +
+ .../doc/html/struct__tx__fifo__size__setup.html    |   46 +
+ .../doc/html/structcfi__all__features__header.html |   75 +
+ .../dwc_otg/doc/html/structcfi__dma__buff.html     |   41 +
+ .../usb/host/dwc_otg/doc/html/structcfi__ep.html   |   69 +
+ .../doc/html/structcfi__feature__desc__header.html |   60 +
+ .../usb/host/dwc_otg/doc/html/structcfi__ops.html  |   64 +
+ .../host/dwc_otg/doc/html/structcfi__string.html   |   48 +
+ .../doc/html/structcfi__usb__ctrlrequest.html      |   58 +
+ .../usb/host/dwc_otg/doc/html/structcfiobject.html |   62 +
+ .../usb/host/dwc_otg/doc/html/structdwc__ep.html   |  192 +
+ .../usb/host/dwc_otg/doc/html/structdwc__hc.html   |  345 ++
+ .../doc/html/structdwc__otg__cil__callbacks.html   |   70 +
+ .../html/structdwc__otg__core__global__regs.html   |  557 ++
+ .../dwc_otg/doc/html/structdwc__otg__core__if.html |  190 +
+ .../doc/html/structdwc__otg__core__params.html     |  606 +++
+ .../doc/html/structdwc__otg__dev__dma__desc.html   |   50 +
+ .../html/structdwc__otg__dev__global__regs.html    |  441 ++
+ .../dwc_otg/doc/html/structdwc__otg__dev__if.html  |  142 +
+ .../html/structdwc__otg__dev__in__ep__regs.html    |  221 +
+ .../html/structdwc__otg__dev__out__ep__regs.html   |  221 +
+ .../dwc_otg/doc/html/structdwc__otg__device.html   |   64 +
+ .../structdwc__otg__driver__module__params.html    |  146 +
+ .../dwc_otg/doc/html/structdwc__otg__hc__regs.html |  200 +
+ .../host/dwc_otg/doc/html/structdwc__otg__hcd.html |  377 ++
+ .../html/structdwc__otg__hcd__function__ops.html   |   53 +
+ .../structdwc__otg__hcd__iso__packet__desc.html    |   47 +
+ .../doc/html/structdwc__otg__hcd__pipe__info.html  |   50 +
+ .../dwc_otg/doc/html/structdwc__otg__hcd__urb.html |   80 +
+ .../doc/html/structdwc__otg__host__dma__desc.html  |   50 +
+ .../html/structdwc__otg__host__global__regs.html   |  219 +
+ .../dwc_otg/doc/html/structdwc__otg__host__if.html |   66 +
+ .../host/dwc_otg/doc/html/structdwc__otg__pcd.html |  152 +
+ .../dwc_otg/doc/html/structdwc__otg__pcd__ep.html  |   77 +
+ .../html/structdwc__otg__pcd__function__ops.html   |   73 +
+ .../doc/html/structdwc__otg__pcd__request.html     |   64 +
+ .../host/dwc_otg/doc/html/structdwc__otg__qh.html  |  228 +
+ .../host/dwc_otg/doc/html/structdwc__otg__qtd.html |  157 +
+ .../dwc_otg/doc/html/structgadget__wrapper.html    |   53 +
+ .../dwc_otg/doc/html/structiso__pkt__info.html     |   49 +
+ .../doc/html/structwrapper__priv__data.html        |   38 +
+ .../usb/host/dwc_otg/doc/html/structzero__dev.html |   56 +
+ drivers/usb/host/dwc_otg/doc/html/tabs.css         |  102 +
+ drivers/usb/host/dwc_otg/doc/html/todo.html        |  262 +
+ drivers/usb/host/dwc_otg/doc/html/tree.html        |  201 +
+ .../host/dwc_otg/doc/html/uniondaint__data.html    |  131 +
+ .../usb/host/dwc_otg/doc/html/uniondcfg__data.html |   74 +
+ .../usb/host/dwc_otg/doc/html/uniondctl__data.html |   96 +
+ .../host/dwc_otg/doc/html/uniondepctl__data.html   |  139 +
+ .../host/dwc_otg/doc/html/uniondeptsiz0__data.html |   69 +
+ .../host/dwc_otg/doc/html/uniondeptsiz__data.html  |   63 +
+ .../dwc_otg/doc/html/uniondev__dma__desc__sts.html |  140 +
+ .../doc/html/uniondevice__grxsts__data.html        |   62 +
+ .../host/dwc_otg/doc/html/uniondiepint__data.html  |   90 +
+ .../host/dwc_otg/doc/html/uniondoepint__data.html  |   98 +
+ .../usb/host/dwc_otg/doc/html/uniondsts__data.html |   68 +
+ .../host/dwc_otg/doc/html/uniondthrctl__data.html  |  178 +
+ .../host/dwc_otg/doc/html/uniondtknq1__data.html   |   86 +
+ .../host/dwc_otg/doc/html/uniondtxfsts__data.html  |   56 +
+ ...otg__hcd_1_1dwc__otg__hcd__internal__flags.html |   66 +
+ .../host/dwc_otg/doc/html/unionfifosize__data.html |   56 +
+ .../host/dwc_otg/doc/html/uniongahbcfg__data.html  |   66 +
+ .../host/dwc_otg/doc/html/uniongi2cctl__data.html  |   72 +
+ .../host/dwc_otg/doc/html/uniongintmsk__data.html  |  114 +
+ .../host/dwc_otg/doc/html/uniongintsts__data.html  |  114 +
+ .../host/dwc_otg/doc/html/unionglpmctl__data.html  |  178 +
+ .../host/dwc_otg/doc/html/uniongnptxsts__data.html |   69 +
+ .../host/dwc_otg/doc/html/uniongotgctl__data.html  |   80 +
+ .../host/dwc_otg/doc/html/uniongotgint__data.html  |   79 +
+ .../host/dwc_otg/doc/html/uniongrstctl__data.html  |  249 +
+ .../host/dwc_otg/doc/html/uniongusbcfg__data.html  |   98 +
+ .../host/dwc_otg/doc/html/unionhaint__data.html    |   93 +
+ .../host/dwc_otg/doc/html/unionhaintmsk__data.html |   93 +
+ .../host/dwc_otg/doc/html/unionhcchar__data.html   |  123 +
+ .../host/dwc_otg/doc/html/unionhcdma__data.html    |   78 +
+ .../usb/host/dwc_otg/doc/html/unionhcfg__data.html |   72 +
+ .../host/dwc_otg/doc/html/unionhcint__data.html    |   95 +
+ .../host/dwc_otg/doc/html/unionhcintmsk__data.html |   82 +
+ .../host/dwc_otg/doc/html/unionhcsplt__data.html   |   63 +
+ .../host/dwc_otg/doc/html/unionhctsiz__data.html   |  105 +
+ .../usb/host/dwc_otg/doc/html/unionhfir__data.html |   54 +
+ .../host/dwc_otg/doc/html/unionhfnum__data.html    |   54 +
+ .../doc/html/unionhost__dma__desc__sts.html        |  123 +
+ .../dwc_otg/doc/html/unionhost__grxsts__data.html  |   60 +
+ .../host/dwc_otg/doc/html/unionhprt0__data.html    |   82 +
+ .../host/dwc_otg/doc/html/unionhptxsts__data.html  |   62 +
+ .../host/dwc_otg/doc/html/unionhwcfg1__data.html   |   84 +
+ .../host/dwc_otg/doc/html/unionhwcfg2__data.html   |   82 +
+ .../host/dwc_otg/doc/html/unionhwcfg3__data.html   |   76 +
+ .../host/dwc_otg/doc/html/unionhwcfg4__data.html   |   80 +
+ .../host/dwc_otg/doc/html/unionpcgcctl__data.html  |   78 +
+ drivers/usb/host/dwc_otg/dummy_audio.c             | 1575 ++++++
+ drivers/usb/host/dwc_otg/dwc_cfi_common.h          |  142 +
+ drivers/usb/host/dwc_otg/dwc_otg_attr.c            | 1316 +++++
+ drivers/usb/host/dwc_otg/dwc_otg_attr.h            |   88 +
+ drivers/usb/host/dwc_otg/dwc_otg_cfi.c             | 1876 +++++++
+ drivers/usb/host/dwc_otg/dwc_otg_cfi.h             |  319 ++
+ drivers/usb/host/dwc_otg/dwc_otg_cil.c             | 5410 ++++++++++++++++++++
+ drivers/usb/host/dwc_otg/dwc_otg_cil.h             | 1143 +++++
+ drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c        |  846 +++
+ drivers/usb/host/dwc_otg/dwc_otg_core_if.h         |  641 +++
+ drivers/usb/host/dwc_otg/dwc_otg_dbg.h             |  113 +
+ drivers/usb/host/dwc_otg/dwc_otg_driver.c          | 1577 ++++++
+ drivers/usb/host/dwc_otg/dwc_otg_driver.h          |  101 +
+ drivers/usb/host/dwc_otg/dwc_otg_hcd.c             | 3330 ++++++++++++
+ drivers/usb/host/dwc_otg/dwc_otg_hcd.h             |  804 +++
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c        | 1106 ++++
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h          |  393 ++
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c        | 2065 ++++++++
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c       |  840 +++
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c       |  732 +++
+ drivers/usb/host/dwc_otg/dwc_otg_pcd.c             | 2067 ++++++++
+ drivers/usb/host/dwc_otg/dwc_otg_pcd.h             |  216 +
+ drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h          |  333 ++
+ drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c        | 4077 +++++++++++++++
+ drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c       | 1288 +++++
+ drivers/usb/host/dwc_otg/dwc_otg_regs.h            | 2237 ++++++++
+ drivers/usb/host/dwc_otg/test/Makefile             |   16 +
+ drivers/usb/host/dwc_otg/test/dwc_otg_test.pm      |  337 ++
+ drivers/usb/host/dwc_otg/test/test_mod_param.pl    |  133 +
+ drivers/usb/host/dwc_otg/test/test_sysfs.pl        |  193 +
+ 341 files changed, 124762 insertions(+), 59 deletions(-)
+ create mode 100644 drivers/usb/host/dwc_common_port/Makefile
+ create mode 100644 drivers/usb/host/dwc_common_port/Makefile.linux
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/doxygen.cfg
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dir_c13d72e45af28cdc461a5f284d3d36fc.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dirs.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/doxygen.css
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dwc__cc_8h.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dwc__crypto_8c.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dwc__crypto_8h.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dwc__dh_8h.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dwc__list_8h.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dwc__modpow_8h.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dwc__notifier_8h.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dwc__os_8h.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/files.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/globals.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/globals_defs.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/globals_func.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/globals_type.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/index.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/main.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/pages.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/tabs.css
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/todo.html
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/html/tree.html
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_cc.c
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_cc.h
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_linux.c
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_crypto.c
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_crypto.h
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_dh.c
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_dh.h
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_list.h
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_mem.c
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_modpow.c
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_modpow.h
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_notifier.c
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_notifier.h
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_os.h
+ create mode 100644 drivers/usb/host/dwc_common_port/usb.h
+ create mode 100644 drivers/usb/host/dwc_otg/Makefile
+ create mode 100644 drivers/usb/host/dwc_otg/doc/doxygen.cfg
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/annotated.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/doxygen.css
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dummy__audio_8c-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__cfi__common_8h-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__cfi__common_8h.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__attr_8c-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__attr_8c.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__attr_8h-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__attr_8h.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cfi_8c-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cfi_8c.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cfi_8h-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cfi_8h.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cil_8c-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cil_8c.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cil_8h-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cil_8h.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cil__intr_8c-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cil__intr_8c.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__core__if_8h-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__core__if_8h.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__dbg_8h-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__dbg_8h.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__driver_8c-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__driver_8c.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__driver_8h-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__driver_8h.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd_8c-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd_8c.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd_8h-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd_8h.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__ddma_8c-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__ddma_8c.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__if_8h-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__if_8h.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__intr_8c-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__intr_8c.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__linux_8c-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__linux_8c.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__queue_8c-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__queue_8c.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd_8c-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd_8c.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd_8h-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd_8h.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd__if_8h-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd__if_8h.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd__intr_8c-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd__intr_8c.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd__linux_8c-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd__linux_8c.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__regs_8h-source.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__regs_8h.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/files.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x62.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x63.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x64.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x65.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x66.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x67.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x68.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x69.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x6c.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x6d.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x6e.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x6f.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x70.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x71.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x72.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x73.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x74.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x75.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x76.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x77.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x78.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_func.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x62.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x63.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x64.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x65.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x66.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x67.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x68.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x69.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x6c.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x6d.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x6e.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x6f.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x70.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x71.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x72.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x73.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x74.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x75.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x76.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x77.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x78.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x61.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x62.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x63.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x64.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x65.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x66.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x67.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x68.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x69.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x6b.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x6d.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x6e.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x6f.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x70.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x71.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x72.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x73.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x74.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x75.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x76.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x77.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x61.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x62.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x63.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x64.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x66.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x67.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x68.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x69.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x6d.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x6e.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x6f.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x72.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x73.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x75.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x76.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_enum.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_eval.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x61.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x62.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x63.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x64.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x65.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x66.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x67.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x68.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x69.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x6b.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x6d.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x70.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x71.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x72.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x73.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x75.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x76.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x77.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_type.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_vars.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/index.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/linux module attributes.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/main.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/module parameters.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/pages.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/struct__ddma__align__buffer__setup.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/struct__ddma__concat__buffer__setup.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/struct__ddma__concat__buffer__setup__hdr.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/struct__ddma__sg__buffer__setup.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/struct__rx__fifo__size__setup.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/struct__tx__fifo__size__setup.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structcfi__all__features__header.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structcfi__dma__buff.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structcfi__ep.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structcfi__feature__desc__header.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structcfi__ops.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structcfi__string.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structcfi__usb__ctrlrequest.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structcfiobject.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__ep.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__hc.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__cil__callbacks.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__core__global__regs.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__core__if.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__core__params.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__dev__dma__desc.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__dev__global__regs.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__dev__if.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__dev__in__ep__regs.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__dev__out__ep__regs.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__device.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__driver__module__params.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__hc__regs.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__hcd.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__hcd__function__ops.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__hcd__iso__packet__desc.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__hcd__pipe__info.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__hcd__urb.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__host__dma__desc.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__host__global__regs.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__host__if.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__pcd.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__pcd__ep.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__pcd__function__ops.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__pcd__request.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__qh.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__qtd.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structgadget__wrapper.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structiso__pkt__info.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structwrapper__priv__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/structzero__dev.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/tabs.css
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/todo.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/tree.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondaint__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondcfg__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondctl__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondepctl__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondeptsiz0__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondeptsiz__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondev__dma__desc__sts.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondevice__grxsts__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondiepint__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondoepint__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondsts__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondthrctl__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondtknq1__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondtxfsts__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondwc__otg__hcd_1_1dwc__otg__hcd__internal__flags.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionfifosize__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniongahbcfg__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniongi2cctl__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniongintmsk__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniongintsts__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionglpmctl__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniongnptxsts__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniongotgctl__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniongotgint__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniongrstctl__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniongusbcfg__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhaint__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhaintmsk__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhcchar__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhcdma__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhcfg__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhcint__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhcintmsk__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhcsplt__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhctsiz__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhfir__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhfnum__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhost__dma__desc__sts.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhost__grxsts__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhprt0__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhptxsts__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhwcfg1__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhwcfg2__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhwcfg3__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhwcfg4__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionpcgcctl__data.html
+ create mode 100644 drivers/usb/host/dwc_otg/dummy_audio.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_cfi_common.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cfi.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cfi.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_core_if.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_dbg.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_driver.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_driver.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_regs.h
+ create mode 100644 drivers/usb/host/dwc_otg/test/Makefile
+ create mode 100644 drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
+ create mode 100644 drivers/usb/host/dwc_otg/test/test_mod_param.pl
+ create mode 100644 drivers/usb/host/dwc_otg/test/test_sysfs.pl
+
+--- a/drivers/usb/Makefile
++++ b/drivers/usb/Makefile
+@@ -25,6 +25,7 @@ obj-$(CONFIG_USB_U132_HCD)   += host/
+ obj-$(CONFIG_USB_R8A66597_HCD)        += host/
+ obj-$(CONFIG_USB_HWA_HCD)     += host/
+ obj-$(CONFIG_USB_ISP1760_HCD) += host/
++obj-$(CONFIG_USB_DWCOTG)      += host/
+ obj-$(CONFIG_USB_IMX21_HCD)   += host/
+ obj-$(CONFIG_USB_FSL_MPH_DR_OF)       += host/
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -149,6 +149,7 @@ int usb_choose_configuration(struct usb_
+               dev_warn(&udev->dev,
+                       "no configuration chosen from %d choice%s\n",
+                       num_configs, plural(num_configs));
++              dev_warn(&udev->dev, "No support over %dmA\n", udev->bus_mA);
+       }
+       return i;
+ }
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1075,6 +1075,8 @@ static int hub_configure(struct usb_hub
+       INIT_WORK(&hub->tt.clear_work, hub_tt_work);
+       switch (hdev->descriptor.bDeviceProtocol) {
+       case USB_HUB_PR_FS:
++              dev_dbg(hub_dev, "TT with no hub-specific protocol - "
++                      "no TT\n");             
+               break;
+       case USB_HUB_PR_HS_SINGLE_TT:
+               dev_dbg(hub_dev, "Single TT\n");
+@@ -1091,6 +1093,7 @@ static int hub_configure(struct usb_hub
+               hub->tt.hub = hdev;
+               break;
+       case USB_HUB_PR_SS:
++              dev_dbg(hub_dev, "USB 3.0 hub - no TT\n");
+               /* USB 3.0 hubs don't have a TT */
+               break;
+       default:
+@@ -1719,6 +1722,12 @@ static inline void announce_device(struc
+ #endif
+ #ifdef        CONFIG_USB_OTG
++
++static int enable_whitelist;
++module_param(enable_whitelist, bool, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(enable_whitelist,
++               "only recognize devices in OTG whitelist if true");
++
+ #include "otg_whitelist.h"
+ #endif
+@@ -1773,9 +1782,15 @@ static int usb_enumerate_device_otg(stru
+                                       dev_info(&udev->dev,
+                                               "can't set HNP mode: %d\n",
+                                               err);
++                                      dev_printk(KERN_CRIT, &udev->dev,
++                                              "Not Connected/Responding\n");
++
+                                       bus->b_hnp_enable = 0;
++                              } else {
++                                      dev_info(&udev->dev,
++                                              "HNP Not Supported\n");
+                               }
+-                      }
++                        }
+               }
+       }
+@@ -1784,12 +1799,27 @@ static int usb_enumerate_device_otg(stru
+               /* Maybe it can talk to us, though we can't talk to it.
+                * (Includes HNP test device.)
+                */
+-              if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
++              if (udev->bus->b_hnp_enable || udev->bus->is_b_host ||
++                  udev->descriptor.idVendor == 0x1a0a) {
+                       err = usb_port_suspend(udev, PMSG_SUSPEND);
+-                      if (err < 0)
++                      if (err < 0) {
+                               dev_dbg(&udev->dev, "HNP fail, %d\n", err);
++                      } else {
++                          /* Return Connection Refused(ECONNREFUSED)
++                           * instead of No Device(ENODEV) so that the
++                           * retry loop in hub_port_connect_change() is
++                           * exited without disabling the port
++                           */
++                          err = -ECONNREFUSED;
++                          goto fail;
++                      }
+               }
+-              err = -ENOTSUPP;
++              //err = -ENOTSUPP;
++              /* Return Not Connected (ENOTCONN) instead of No
++               * Device(ENODEV) so that the retry loop in
++               * hub_port_connect_change() is exited
++               */
++              err = -ENOTCONN;
+               goto fail;
+       }
+ fail:
+@@ -2980,7 +3010,9 @@ hub_port_init (struct usb_hub *hub, stru
+                               buf->bMaxPacketSize0 = 0;
+                               r = usb_control_msg(udev, usb_rcvaddr0pipe(),
+                                       USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+-                                      USB_DT_DEVICE << 8, 0,
++                                      USB_DT_DEVICE << 8,
++                                      //USB_DT_DEVICE << 64, // DWC patch suggestion!
++                                      0,
+                                       buf, GET_DESCRIPTOR_BUFSIZE,
+                                       initial_descriptor_timeout);
+                               switch (buf->bMaxPacketSize0) {
+@@ -3426,8 +3458,10 @@ loop:
+               release_devnum(udev);
+               hub_free_dev(udev);
+               usb_put_dev(udev);
+-              if ((status == -ENOTCONN) || (status == -ENOTSUPP))
+-                      break;
++              if (status == -ENOTCONN || status == -ENOTSUPP ||
++                      status == -ECONNREFUSED)
++                      // break; //DWC patch
++                      return;
+       }
+       if (hub->hdev->parent ||
+                       !hcd->driver->port_handed_over ||
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1837,6 +1837,85 @@ free_interfaces:
+       if (cp->string == NULL &&
+                       !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
+               cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
++/* Uncomment this define to enable the HS Electrical Test support */
++#define DWC_HS_ELECT_TST 1
++#ifdef DWC_HS_ELECT_TST
++              /* Here we implement the HS Electrical Test support. The
++               * tester uses a vendor ID of 0x1A0A to indicate we should
++               * run a special test sequence. The product ID tells us
++               * which sequence to run. We invoke the test sequence by
++               * sending a non-standard SetFeature command to our root
++               * hub port. Our dwc_otg_hcd_hub_control() routine will
++               * recognize the command and perform the desired test
++               * sequence.
++               */
++              if (dev->descriptor.idVendor == 0x1A0A) {
++                      /* HSOTG Electrical Test */
++                      dev_warn(&dev->dev, "VID from HSOTG Electrical Test Fixture\n");
++
++                      if (dev->bus && dev->bus->root_hub) {
++                              struct usb_device *hdev = dev->bus->root_hub;
++                              dev_warn(&dev->dev, "Got PID 0x%x\n", dev->descriptor.idProduct);
++
++                              switch (dev->descriptor.idProduct) {
++                              case 0x0101:    /* TEST_SE0_NAK */
++                                      dev_warn(&dev->dev, "TEST_SE0_NAK\n");
++                                      usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
++                                                      USB_REQ_SET_FEATURE, USB_RT_PORT,
++                                                      USB_PORT_FEAT_TEST, 0x300, NULL, 0, HZ);
++                                      break;
++
++                              case 0x0102:    /* TEST_J */
++                                      dev_warn(&dev->dev, "TEST_J\n");
++                                      usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
++                                                      USB_REQ_SET_FEATURE, USB_RT_PORT,
++                                                      USB_PORT_FEAT_TEST, 0x100, NULL, 0, HZ);
++                                      break;
++
++                              case 0x0103:    /* TEST_K */
++                                      dev_warn(&dev->dev, "TEST_K\n");
++                                      usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
++                                                      USB_REQ_SET_FEATURE, USB_RT_PORT,
++                                                      USB_PORT_FEAT_TEST, 0x200, NULL, 0, HZ);
++                                      break;
++
++                              case 0x0104:    /* TEST_PACKET */
++                                      dev_warn(&dev->dev, "TEST_PACKET\n");
++                                      usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
++                                                      USB_REQ_SET_FEATURE, USB_RT_PORT,
++                                                      USB_PORT_FEAT_TEST, 0x400, NULL, 0, HZ);
++                                      break;
++
++                              case 0x0105:    /* TEST_FORCE_ENABLE */
++                                      dev_warn(&dev->dev, "TEST_FORCE_ENABLE\n");
++                                      usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
++                                                      USB_REQ_SET_FEATURE, USB_RT_PORT,
++                                                      USB_PORT_FEAT_TEST, 0x500, NULL, 0, HZ);
++                                      break;
++
++                              case 0x0106:    /* HS_HOST_PORT_SUSPEND_RESUME */
++                                      dev_warn(&dev->dev, "HS_HOST_PORT_SUSPEND_RESUME\n");
++                                      usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
++                                                      USB_REQ_SET_FEATURE, USB_RT_PORT,
++                                                      USB_PORT_FEAT_TEST, 0x600, NULL, 0, 40 * HZ);
++                                      break;
++
++                              case 0x0107:    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
++                                      dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup\n");
++                                      usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
++                                                      USB_REQ_SET_FEATURE, USB_RT_PORT,
++                                                      USB_PORT_FEAT_TEST, 0x700, NULL, 0, 40 * HZ);
++                                      break;
++
++                              case 0x0108:    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
++                                      dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute\n");
++                                      usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
++                                                      USB_REQ_SET_FEATURE, USB_RT_PORT,
++                                                      USB_PORT_FEAT_TEST, 0x800, NULL, 0, 40 * HZ);
++                              }
++                      }
++              }
++#endif /* DWC_HS_ELECT_TST */
+       /* Now that all the interfaces are set up, register them
+        * to trigger binding of drivers to interfaces.  probe()
+--- a/drivers/usb/core/otg_whitelist.h
++++ b/drivers/usb/core/otg_whitelist.h
+@@ -19,33 +19,82 @@
+ static struct usb_device_id whitelist_table [] = {
+ /* hubs are optional in OTG, but very handy ... */
++#define CERT_WITHOUT_HUBS
++#if defined(CERT_WITHOUT_HUBS)
++{ USB_DEVICE( 0x0000, 0x0000 ), }, /* Root HUB Only*/
++#else
+ { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), },
+ { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), },
++{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 2), },
++#endif
+ #ifdef        CONFIG_USB_PRINTER              /* ignoring nonstatic linkage! */
+ /* FIXME actually, printers are NOT supposed to use device classes;
+  * they're supposed to use interface classes...
+  */
+-{ USB_DEVICE_INFO(7, 1, 1) },
+-{ USB_DEVICE_INFO(7, 1, 2) },
+-{ USB_DEVICE_INFO(7, 1, 3) },
++//{ USB_DEVICE_INFO(7, 1, 1) },
++//{ USB_DEVICE_INFO(7, 1, 2) },
++//{ USB_DEVICE_INFO(7, 1, 3) },
+ #endif
+ #ifdef        CONFIG_USB_NET_CDCETHER
+ /* Linux-USB CDC Ethernet gadget */
+-{ USB_DEVICE(0x0525, 0xa4a1), },
++//{ USB_DEVICE(0x0525, 0xa4a1), },
+ /* Linux-USB CDC Ethernet + RNDIS gadget */
+-{ USB_DEVICE(0x0525, 0xa4a2), },
++//{ USB_DEVICE(0x0525, 0xa4a2), },
+ #endif
+ #if   defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE)
+ /* gadget zero, for testing */
+-{ USB_DEVICE(0x0525, 0xa4a0), },
++//{ USB_DEVICE(0x0525, 0xa4a0), },
+ #endif
++   
++/* OPT Tester */
++{ USB_DEVICE( 0x1a0a, 0x0101 ), }, /* TEST_SE0_NAK */
++{ USB_DEVICE( 0x1a0a, 0x0102 ), }, /* Test_J */
++{ USB_DEVICE( 0x1a0a, 0x0103 ), }, /* Test_K */
++{ USB_DEVICE( 0x1a0a, 0x0104 ), }, /* Test_PACKET */
++{ USB_DEVICE( 0x1a0a, 0x0105 ), }, /* Test_FORCE_ENABLE */
++{ USB_DEVICE( 0x1a0a, 0x0106 ), }, /* HS_PORT_SUSPEND_RESUME  */
++{ USB_DEVICE( 0x1a0a, 0x0107 ), }, /* SINGLE_STEP_GET_DESCRIPTOR setup */
++{ USB_DEVICE( 0x1a0a, 0x0108 ), }, /* SINGLE_STEP_GET_DESCRIPTOR execute */
++
++/* Sony cameras */        
++{ USB_DEVICE_VER(0x054c,0x0010,0x0410, 0x0500), },
++   
++/* Memory Devices */
++//{ USB_DEVICE( 0x0781, 0x5150 ), }, /* SanDisk */
++//{ USB_DEVICE( 0x05DC, 0x0080 ), }, /* Lexar */
++//{ USB_DEVICE( 0x4146, 0x9281 ), }, /* IOMEGA */
++//{ USB_DEVICE( 0x067b, 0x2507 ), }, /* Hammer 20GB External HD  */
++{ USB_DEVICE( 0x0EA0, 0x2168 ), }, /* Ours Technology Inc. (BUFFALO ClipDrive)*/
++//{ USB_DEVICE( 0x0457, 0x0150 ), }, /* Silicon Integrated Systems Corp. */
++
++/* HP Printers */
++//{ USB_DEVICE( 0x03F0, 0x1102 ), }, /* HP Photosmart 245 */
++//{ USB_DEVICE( 0x03F0, 0x1302 ), }, /* HP Photosmart 370 Series */
++
++/* Speakers */
++//{ USB_DEVICE( 0x0499, 0x3002 ), }, /* YAMAHA YST-MS35D USB Speakers */
++//{ USB_DEVICE( 0x0672, 0x1041 ), }, /* Labtec USB Headset */
+ { }   /* Terminating entry */
+ };
++static inline void report_errors(struct usb_device *dev)
++{
++      /* OTG MESSAGE: report errors here, customize to match your product */
++      dev_info(&dev->dev, "device Vendor:%04x Product:%04x is not supported\n",
++               le16_to_cpu(dev->descriptor.idVendor),
++               le16_to_cpu(dev->descriptor.idProduct));
++        if (USB_CLASS_HUB == dev->descriptor.bDeviceClass){
++                dev_printk(KERN_CRIT, &dev->dev, "Unsupported Hub Topology\n");
++        } else {        
++                dev_printk(KERN_CRIT, &dev->dev, "Attached Device is not Supported\n");
++        }
++}
++
++
+ static int is_targeted(struct usb_device *dev)
+ {
+       struct usb_device_id    *id = whitelist_table;
+@@ -55,58 +104,83 @@ static int is_targeted(struct usb_device
+               return 1;
+       /* HNP test device is _never_ targeted (see OTG spec 6.6.6) */
+-      if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a &&
+-           le16_to_cpu(dev->descriptor.idProduct) == 0xbadd))
+-              return 0;
++      if (dev->descriptor.idVendor == 0x1a0a && 
++            dev->descriptor.idProduct == 0xbadd) {
++                return 0;
++      } else if (!enable_whitelist) {
++              return 1;
++        } else {
+-      /* NOTE: can't use usb_match_id() since interface caches
+-       * aren't set up yet. this is cut/paste from that code.
+-       */
+-      for (id = whitelist_table; id->match_flags; id++) {
+-              if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
+-                  id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
+-                      continue;
+-
+-              if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
+-                  id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
+-                      continue;
+-
+-              /* No need to test id->bcdDevice_lo != 0, since 0 is never
+-                 greater than any unsigned number. */
+-              if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
+-                  (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
+-                      continue;
+-
+-              if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
+-                  (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
+-                      continue;
+-
+-              if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
+-                  (id->bDeviceClass != dev->descriptor.bDeviceClass))
+-                      continue;
+-
+-              if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
+-                  (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
+-                      continue;
+-
+-              if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
+-                  (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
+-                      continue;
++#ifdef DEBUG
++                dev_dbg(&dev->dev, "device V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n",
++                        dev->descriptor.idVendor,
++                        dev->descriptor.idProduct,
++                        dev->descriptor.bDeviceClass,
++                        dev->descriptor.bDeviceSubClass,
++                        dev->descriptor.bDeviceProtocol);
++#endif
+               return 1;
++              /* NOTE: can't use usb_match_id() since interface caches
++               * aren't set up yet. this is cut/paste from that code.
++               */
++              for (id = whitelist_table; id->match_flags; id++) {
++#ifdef DEBUG
++                      dev_dbg(&dev->dev, 
++                              "ID: V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n",
++                              id->idVendor,
++                              id->idProduct,
++                              id->bDeviceClass,
++                              id->bDeviceSubClass,
++                              id->bDeviceProtocol);
++#endif                              
++
++                      if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
++                          id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
++                              continue;
++
++                      if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
++                          id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
++                              continue;
++
++                      /* No need to test id->bcdDevice_lo != 0, since 0 is never
++                         greater than any unsigned number. */
++                      if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
++                          (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
++                              continue;
++
++                      if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
++                          (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
++                              continue;
++
++                      if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
++                          (id->bDeviceClass != dev->descriptor.bDeviceClass))
++                              continue;
++
++                      if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
++                          (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
++                              continue;
++
++                      if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
++                          (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
++                              continue;
++
++                      return 1;
++              }
+       }
+       /* add other match criteria here ... */
+-
+-      /* OTG MESSAGE: report errors here, customize to match your product */
+-      dev_err(&dev->dev, "device v%04x p%04x is not supported\n",
+-              le16_to_cpu(dev->descriptor.idVendor),
+-              le16_to_cpu(dev->descriptor.idProduct));
+ #ifdef        CONFIG_USB_OTG_WHITELIST
++      report_errors(dev);
+       return 0;
+ #else
+-      return 1;
++      if (enable_whitelist) {
++              report_errors(dev);
++              return 0;
++      } else {
++              return 1;
++      }
+ #endif
+ }
+--- a/drivers/usb/gadget/Kconfig
++++ b/drivers/usb/gadget/Kconfig
+@@ -536,6 +536,34 @@ config USB_GADGET_SUPERSPEED
+       bool
+       depends on USB_GADGET_DUALSPEED
++config USB_GADGET_SNPS_DWC_OTG
++      boolean "Synopsys Driver for DWC_otg Controller"
++      depends on USB && EXPERIMENTAL
++      select USB_OTG
++      select USB_GADGET_DUALSPEED
++      help
++         Selects the Synopsys Driver for the DWC_otg Controller.
++
++config USB_DWC_OTG_LPM
++      boolean "Enable LPM support"
++      depends on USB && EXPERIMENTAL
++      help
++         Enables LPM support.
++
++config USB_GADGET_SNPS_DWC_OTG
++      boolean "Synopsys Driver for DWC_otg Controller"
++      depends on USB && EXPERIMENTAL
++      select USB_OTG
++      select USB_GADGET_DUALSPEED
++      help
++         Selects the Synopsys Driver for the DWC_otg Controller.
++
++config USB_DWC_OTG_LPM
++      boolean "Enable LPM support"
++      depends on USB && EXPERIMENTAL
++      help
++         Enables LPM support.
++
+ #
+ # USB Gadget Drivers
+ #
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -573,8 +573,37 @@ config_desc = {
+       .iConfiguration =       FSG_STRING_CONFIG,
+       .bmAttributes =         USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+       .bMaxPower =            CONFIG_USB_GADGET_VBUS_DRAW / 2,
++        //.bMaxPower =                0, //unused suggestion by DWC patch
+ };
++#ifdef CONFIG_USB_DWC_OTG_LPM
++#define USB_DEVICE_CAPABILITY_20_EXTENSION    0x02
++#define USB_20_EXT_LPM                                0x02
++typedef struct usb_dev_cap_20_ext_desc {
++      __u8 bLength;
++      __u8 bDescriptorType;
++      __u8 bDevCapabilityType;
++      __le32 bmAttributes;
++} __attribute__ ((__packed__)) usb_dev_cap_20_ext_desc_t;
++
++static struct usb_bos_20_ext_desc {
++      struct usb_bos_descriptor bos_desc;
++      struct usb_dev_cap_20_ext_desc dev_cap_20_ext_desc;
++} __attribute__ ((__packed__)) bos_20_ext_desc = {
++      {
++              .bLength =              sizeof(struct usb_bos_descriptor),
++              .bDescriptorType =      USB_DT_BOS,
++              .wTotalLength =         sizeof(struct usb_bos_20_ext_desc),
++              .bNumDeviceCaps =       1,
++      },
++      {
++              .bLength =              sizeof(struct usb_dev_cap_20_ext_desc),
++              .bDescriptorType =      USB_DT_DEVICE_CAPABILITY,
++              .bDevCapabilityType =   USB_DEVICE_CAPABILITY_20_EXTENSION,
++              .bmAttributes =         USB_20_EXT_LPM,
++      },
++};
++#endif
+ static struct usb_qualifier_descriptor
+ dev_qualifier = {
+@@ -989,6 +1018,24 @@ get_config:
+                       if (gadget_is_superspeed(fsg->gadget))
+                               value = populate_bos(fsg, req->buf);
+                       break;
++#ifdef CONFIG_USB_DWC_OTG_LPM
++              case USB_DT_BOS:
++                      /* When the PCD has LPM enabled set the LPM
++                       * Feature bit to 1 when not enabled set the
++                       * bit to 0. */
++                      if (usb_gadget_test_lpm_support(fsg->gadget)) {
++                              VDBG(fsg, "LPM support enabled in DWC UDC PCD\n");
++                              bos_20_ext_desc.dev_cap_20_ext_desc.bmAttributes |= USB_20_EXT_LPM;
++                      } else {
++                              VDBG(fsg, "LPM support disabled in DWC UDC PCD\n");
++                              bos_20_ext_desc.dev_cap_20_ext_desc.bmAttributes &= ~USB_20_EXT_LPM;
++                      }
++                      DBG(fsg, "sending BOS descriptor to host\n");
++                      value = sizeof bos_20_ext_desc;
++                      memcpy(req->buf, &bos_20_ext_desc, value);
++                      break;
++#endif
++
+               }
+               break;
+@@ -2650,6 +2697,9 @@ static int received_cbw(struct fsg_dev *
+                       fsg_set_halt(fsg, fsg->bulk_out);
+                       halt_bulk_in_endpoint(fsg);
+               }
++              fsg->bulk_in->ops->set_halt(fsg->bulk_in, 3);
++              fsg_set_halt(fsg, fsg->bulk_out);
++              fsg->bulk_out->ops->set_halt(fsg->bulk_out, 3);
+               return -EINVAL;
+       }
+@@ -3011,7 +3061,8 @@ static void handle_exception(struct fsg_
+                * bulk endpoint, clear the halt now.  (The SuperH UDC
+                * requires this.) */
+               if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
+-                      usb_ep_clear_halt(fsg->bulk_in);
++                      //usb_ep_clear_halt(fsg->bulk_in); //DWC patch:
++                      fsg->bulk_in->ops->set_halt(fsg->bulk_in, 2);
+               if (transport_is_bbb()) {
+                       if (fsg->ep0_req_tag == exception_req_tag)
+@@ -3085,6 +3136,9 @@ static int fsg_main_thread(void *fsg_)
+        * that expects a __user pointer and it will work okay. */
+       set_fs(get_ds());
++      /* Setting this thread high priority */
++      set_user_nice(current, -20);
++
+       /* The main loop */
+       while (fsg->state != FSG_STATE_TERMINATED) {
+               if (exception_in_progress(fsg) || signal_pending(current)) {
+@@ -3232,6 +3286,13 @@ static int __init check_parameters(struc
+               gcnum = usb_gadget_controller_number(fsg->gadget);
+               if (gcnum >= 0)
+                       mod_data.release = 0x0300 + gcnum;
++              else if (gadget_is_dwc_otg(fsg->gadget)) {
++                      mod_data.release = __constant_cpu_to_le16 (0x0200);
++                      mod_data.vendor  = __constant_cpu_to_le16 (0x053f);
++                      if (mod_data.product == DRIVER_PRODUCT_ID) {
++                              mod_data.product  = __constant_cpu_to_le16 (0x0000);
++                      }
++              }
+               else {
+                       WARNING(fsg, "controller '%s' not recognized\n",
+                               fsg->gadget->name);
+@@ -3493,6 +3554,13 @@ static int __init fsg_bind(struct usb_ga
+       rc = -ENOMEM;
++#ifdef CONFIG_USB_DWC_OTG_LPM
++      /* When LPM is enabled, Inform the host that the remote wake
++       * up capability is supported. */
++      if (usb_gadget_test_lpm_support(fsg->gadget))
++              config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
++#endif
++
+       /* Allocate the request and buffer for endpoint 0 */
+       fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL);
+       if (!req)
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -571,6 +571,19 @@ config USB_HWA_HCD
+         To compile this driver a module, choose M here: the module
+         will be called "hwa-hc".
++config USB_DWCOTG
++      tristate "Synopsis DWC host support"
++      depends on USB
++      help
++        The Synopsis DWC controller is a dual-role
++        host/peripheral/OTG ("On The Go") USB controllers.
++
++        Enable this option to support this IP in host controller mode.
++        If unsure, say N.
++
++        To compile this driver as a module, choose M here: the
++        modules built will be called dwc_otg and dwc_common_port.
++
+ config USB_IMX21_HCD
+        tristate "i.MX21 HCD support"
+        depends on USB && ARM && ARCH_MXC
+--- a/drivers/usb/host/Makefile
++++ b/drivers/usb/host/Makefile
+@@ -33,6 +33,8 @@ obj-$(CONFIG_USB_U132_HCD)   += u132-hcd.o
+ obj-$(CONFIG_USB_R8A66597_HCD)        += r8a66597-hcd.o
+ obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o
+ obj-$(CONFIG_USB_HWA_HCD)     += hwa-hc.o
++
++obj-$(CONFIG_USB_DWCOTG)        += dwc_otg/ dwc_common_port/
+ obj-$(CONFIG_USB_IMX21_HCD)   += imx21-hcd.o
+ obj-$(CONFIG_USB_FSL_MPH_DR_OF)       += fsl-mph-dr-of.o
+ obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
+--- /dev/null
++++ b/drivers/usb/host/dwc_common_port/Makefile
+@@ -0,0 +1,44 @@
++#
++# Makefile for DWC_common library
++#
++
++ifneq ($(KERNELRELEASE),)
++
++#CPPFLAGS     += -DDEBUG_MEMORY
++
++CPPFLAGS      += -DDEBUG
++CPPFLAGS      += -DDWC_LINUX
++
++obj-$(CONFIG_USB_DWCOTG)      += dwc_common_port_lib.o
++dwc_common_port_lib-objs      := dwc_cc.o dwc_modpow.o dwc_dh.o \
++                                 dwc_crypto.o dwc_notifier.o \
++                                 dwc_common_linux.o dwc_mem.o
++
++kernrelwd := $(subst ., ,$(KERNELRELEASE))
++kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))
++
++ifneq ($(kernrel3),2.6.20)
++# grayg - I only know that we use EXTRA_CFLAGS in 2.6.31 actually
++EXTRA_CFLAGS += $(CPPFLAGS)
++endif
++
++else
++
++ifeq ($(DOXYGEN),)
++DOXYGEN               := $(DOXYGEN)
++endif
++
++default:
++      $(MAKE) -C$(KDIR) M=$(PWD) modules
++
++docs: $(wildcard *.[hc]) doc/doxygen.cfg
++      $(DOXYGEN) doc/doxygen.cfg
++
++tags: $(wildcard *.[hc])
++      $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
++
++endif
++
++clean:
++      rm -rf   *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers
++
+--- /dev/null
++++ b/drivers/usb/host/dwc_common_port/Makefile.linux
+@@ -0,0 +1,36 @@
++#
++# Makefile for DWC_common library
++#
++ifneq ($(KERNELRELEASE),)
++
++#CPPFLAGS     += -DDEBUG_MEMORY
++
++#CPPFLAGS     += -DDEBUG
++CPPFLAGS      += -DDWC_LINUX
++
++obj-m         := dwc_common_port_lib.o
++dwc_common_port_lib-objs      := dwc_cc.o dwc_modpow.o dwc_dh.o \
++                                 dwc_crypto.o dwc_notifier.o \
++                                 dwc_common_linux.o dwc_mem.o
++
++else
++
++
++ifeq ($(DOXYGEN),)
++DOXYGEN               := $(DOXYGEN)
++endif
++
++default:
++      $(MAKE) -C$(KDIR) M=$(PWD) modules
++
++docs: $(wildcard *.[hc]) doc/doxygen.cfg
++      $(DOXYGEN) doc/doxygen.cfg
++
++tags: $(wildcard *.[hc])
++      $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
++
++endif
++
++clean:
++      rm -rf   *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers
++
+--- /dev/null
++++ b/drivers/usb/host/dwc_common_port/dwc_cc.c
+@@ -0,0 +1,506 @@
++/* =========================================================================
++ * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_cc.c $
++ * $Revision: #1 $
++ * $Date: 2008/12/21 $
++ * $Change: 1156609 $
++ *
++ * Synopsys Portability Library Software and documentation
++ * (hereinafter, "Software") is an Unsupported proprietary work of
++ * Synopsys, Inc. unless otherwise expressly agreed to in writing
++ * between Synopsys and you.
++ *
++ * The Software IS NOT an item of Licensed Software or Licensed Product
++ * under any End User Software License Agreement or Agreement for
++ * Licensed Product with Synopsys or any supplement thereto. You are
++ * permitted to use and redistribute this Software in source and binary
++ * forms, with or without modification, provided that redistributions
++ * of source code must retain this notice. You may not view, use,
++ * disclose, copy or distribute this file or any information contained
++ * herein except pursuant to this license grant from Synopsys. If you
++ * do not agree with this notice, including the disclaimer below, then
++ * you are not authorized to use the Software.
++ *
++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
++ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
++ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
++ * DAMAGE.
++ * ========================================================================= */
++#include "dwc_cc.h"
++
++typedef struct dwc_cc
++{
++      uint32_t uid;
++      uint8_t chid[16];
++      uint8_t cdid[16];
++      uint8_t ck[16];
++      uint8_t *name;
++      uint8_t length;
++        DWC_CIRCLEQ_ENTRY(dwc_cc) list_entry;
++} dwc_cc_t;
++
++DWC_CIRCLEQ_HEAD(context_list, dwc_cc);
++
++/** The main structure for CC management.  */
++struct dwc_cc_if
++{
++      dwc_mutex_t *mutex;
++      char *filename;
++
++      unsigned is_host:1;
++
++      dwc_notifier_t *notifier;
++
++      struct context_list list;
++};
++
++#ifdef DEBUG
++static inline void dump_bytes(char *name, uint8_t *bytes, int len)
++{
++      int i;
++      DWC_PRINTF("%s: ", name);
++      for (i=0; i<len; i++) {
++              DWC_PRINTF("%02x ", bytes[i]);
++      }
++      DWC_PRINTF("\n");
++}
++#else
++#define dump_bytes(x...)
++#endif
++
++static dwc_cc_t *alloc_cc(uint8_t *name, uint32_t length)
++{
++      dwc_cc_t *cc = DWC_ALLOC(sizeof(dwc_cc_t));
++      if (!cc) {
++              return NULL;
++      }
++      DWC_MEMSET(cc, 0, sizeof(dwc_cc_t));
++
++      if (name) {
++              cc->length = length;
++              cc->name = DWC_ALLOC(length);
++              DWC_MEMCPY(cc->name, name, length);
++      }
++
++      return cc;
++}
++
++static void free_cc(dwc_cc_t *cc)
++{
++      if (cc->name) {
++              DWC_FREE(cc->name);
++      }
++      DWC_FREE(cc);
++}
++
++static uint32_t next_uid(dwc_cc_if_t *cc_if)
++{
++      uint32_t uid = 0;
++      dwc_cc_t *cc;
++      DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
++              if (cc->uid > uid) {
++                      uid = cc->uid;
++              }
++      }
++
++      if (uid == 0) {
++              uid = 255;
++      }
++
++      return uid + 1;
++}
++
++static dwc_cc_t *cc_find(dwc_cc_if_t *cc_if, uint32_t uid)
++{
++      dwc_cc_t *cc;
++      DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
++              if (cc->uid == uid) {
++                      return cc;
++              }
++      }
++      return NULL;
++}
++
++static unsigned int cc_data_size(dwc_cc_if_t *cc_if)
++{
++      unsigned int size = 0;
++      dwc_cc_t *cc;
++      DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
++              size += (48 + 1);
++              if (cc->name) {
++                      size += cc->length;
++              }
++      }
++      return size;
++}
++
++static uint32_t cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
++{
++      uint32_t uid = 0;
++      dwc_cc_t *cc;
++
++      DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
++              if (DWC_MEMCMP(cc->chid, chid, 16) == 0) {
++                      uid = cc->uid;
++                      break;
++              }
++      }
++      return uid;
++}
++static uint32_t cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
++{
++      uint32_t uid = 0;
++      dwc_cc_t *cc;
++
++      DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
++              if (DWC_MEMCMP(cc->cdid, cdid, 16) == 0) {
++                      uid = cc->uid;
++                      break;
++              }
++      }
++      return uid;
++}
++
++/* Internal cc_add */
++static int32_t cc_add(dwc_cc_if_t *cc_if, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
++{
++      dwc_cc_t *cc;
++      uint32_t uid;
++
++      if (cc_if->is_host) {
++              uid = cc_match_cdid(cc_if, cdid);
++      }
++      else {
++              uid = cc_match_chid(cc_if, chid);
++      }
++
++      if (uid) {
++              DWC_DEBUG("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length);
++              cc = cc_find(cc_if, uid);
++      }
++      else {
++              cc = alloc_cc(name, length);
++              cc->uid = next_uid(cc_if);
++              DWC_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry);
++      }
++
++      DWC_MEMCPY(&(cc->chid[0]), chid, 16);
++      DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
++      DWC_MEMCPY(&(cc->ck[0]), ck, 16);
++
++      DWC_DEBUG("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length);
++      dump_bytes("CHID", cc->chid, 16);
++      dump_bytes("CDID", cc->cdid, 16);
++      dump_bytes("CK", cc->ck, 16);
++      return cc->uid;
++}
++
++/* Internal cc_clear */
++static void cc_clear(dwc_cc_if_t *cc_if)
++{
++      while (!DWC_CIRCLEQ_EMPTY(&cc_if->list)) {
++              dwc_cc_t *cc = DWC_CIRCLEQ_FIRST(&cc_if->list);
++              DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
++              free_cc(cc);
++      }
++}
++
++dwc_cc_if_t *dwc_cc_if_alloc(dwc_notifier_t *notifier, unsigned is_host)
++{
++      dwc_cc_if_t *cc_if = NULL;
++
++      /* Allocate a common_cc_if structure */
++      cc_if = DWC_ALLOC(sizeof(dwc_cc_if_t));
++
++      if(!cc_if)
++              return NULL;
++
++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
++      DWC_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex);
++#else
++      cc_if->mutex = DWC_MUTEX_ALLOC();
++#endif
++      DWC_CIRCLEQ_INIT(&cc_if->list);
++      cc_if->is_host = is_host;
++      cc_if->notifier = notifier;
++      return cc_if;
++}
++
++void dwc_cc_if_free(dwc_cc_if_t *cc_if)
++{
++      DWC_MUTEX_FREE(cc_if->mutex);
++      cc_clear(cc_if);
++      DWC_FREE(cc_if);
++}
++
++static void cc_changed(dwc_cc_if_t *cc_if)
++{
++      if (cc_if->notifier) {
++              dwc_notify(cc_if->notifier, DWC_CC_LIST_CHANGED_NOTIFICATION, cc_if);
++      }
++}
++
++void dwc_cc_clear(dwc_cc_if_t *cc_if)
++{
++      DWC_MUTEX_LOCK(cc_if->mutex);
++      cc_clear(cc_if);
++      DWC_MUTEX_UNLOCK(cc_if->mutex);
++      cc_changed(cc_if);
++}
++
++int32_t dwc_cc_add(dwc_cc_if_t *cc_if, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
++{
++      uint32_t uid;
++
++      DWC_MUTEX_LOCK(cc_if->mutex);
++      uid = cc_add(cc_if, chid, cdid, ck, name, length);
++      DWC_MUTEX_UNLOCK(cc_if->mutex);
++      cc_changed(cc_if);
++
++      return uid;
++}
++
++void dwc_cc_change(dwc_cc_if_t *cc_if, int32_t id,
++                        uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
++{
++      dwc_cc_t* cc;
++
++      DWC_DEBUG("Change connection context %d", id);
++
++      DWC_MUTEX_LOCK(cc_if->mutex);
++      cc = cc_find(cc_if, id);
++      if (!cc) {
++              DWC_ERROR("Uid %d not found in cc list", id);
++              DWC_MUTEX_UNLOCK(cc_if->mutex);
++              return;
++      }
++
++      if (chid) {
++              DWC_MEMCPY(&(cc->chid[0]), chid, 16);
++      }
++      if (cdid) {
++              DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
++      }
++      if (ck) {
++              DWC_MEMCPY(&(cc->ck[0]), ck, 16);
++      }
++
++      if (name) {
++              if (cc->name) {
++                      DWC_FREE(cc->name);
++              }
++              cc->name = DWC_ALLOC(length);
++              cc->length = length;
++              DWC_MEMCPY(cc->name, name, length);
++      }
++
++      DWC_MUTEX_UNLOCK(cc_if->mutex);
++
++      cc_changed(cc_if);
++
++      DWC_DEBUG("Changed connection context id=%d\n", id);
++      dump_bytes("New CHID", cc->chid, 16);
++      dump_bytes("New CDID", cc->cdid, 16);
++      dump_bytes("New CK", cc->ck, 16);
++}
++
++void dwc_cc_remove(dwc_cc_if_t *cc_if, int32_t id)
++{
++      dwc_cc_t *cc;
++
++      DWC_DEBUG("Removing connection context %d", id);
++
++      DWC_MUTEX_LOCK(cc_if->mutex);
++      cc = cc_find(cc_if, id);
++      if (!cc) {
++              DWC_ERROR("Uid %d not found in cc list", id);
++              DWC_MUTEX_UNLOCK(cc_if->mutex);
++              return;
++      }
++
++      DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
++      DWC_MUTEX_UNLOCK(cc_if->mutex);
++      free_cc(cc);
++
++      cc_changed(cc_if);
++}
++
++uint8_t *dwc_cc_data_for_save(dwc_cc_if_t *cc_if, unsigned int *length)
++{
++      uint8_t *buf, *x;
++      uint8_t zero = 0;
++      dwc_cc_t *cc;
++
++      DWC_MUTEX_LOCK(cc_if->mutex);
++      *length = cc_data_size(cc_if);
++      if (!(*length)) {
++              DWC_MUTEX_UNLOCK(cc_if->mutex);
++              return NULL;
++      }
++
++      DWC_DEBUG("Creating data for saving (length=%d)", *length);
++
++      buf = DWC_ALLOC(*length);
++      if (!buf) {
++              *length = 0;
++              DWC_MUTEX_UNLOCK(cc_if->mutex);
++              return NULL;
++      }
++
++      x = buf;
++      DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
++              DWC_MEMCPY(x, cc->chid, 16);
++              x += 16;
++              DWC_MEMCPY(x, cc->cdid, 16);
++              x += 16;
++              DWC_MEMCPY(x, cc->ck, 16);
++              x += 16;
++              if (cc->name) {
++                      DWC_MEMCPY(x, &cc->length, 1);
++                      x += 1;
++                      DWC_MEMCPY(x, cc->name, cc->length);
++                      x += cc->length;
++              }
++              else {
++                      DWC_MEMCPY(x, &zero, 1);
++                      x += 1;
++              }
++      }
++      DWC_MUTEX_UNLOCK(cc_if->mutex);
++
++      return buf;
++}
++
++void dwc_cc_restore_from_data(dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length)
++{
++      uint8_t name_length;
++      uint8_t *name;
++      uint8_t *chid;
++      uint8_t *cdid;
++      uint8_t *ck;
++      uint32_t i = 0;
++
++      DWC_MUTEX_LOCK(cc_if->mutex);
++      cc_clear(cc_if);
++
++      while (i < length) {
++              chid = &data[i];
++              i += 16;
++              cdid = &data[i];
++              i += 16;
++              ck = &data[i];
++              i += 16;
++
++              name_length = data[i];
++              i ++;
++
++              if (name_length) {
++                      name = &data[i];
++                      i += name_length;
++              }
++              else {
++                      name = NULL;
++              }
++
++              /* check to see if we haven't overflown the buffer */
++              if (i > length) {
++                      DWC_ERROR("Data format error while attempting to load CCs "
++                                "(nlen=%d, iter=%d, buflen=%d).", name_length, i, length);
++                      break;
++              }
++
++              cc_add(cc_if, chid, cdid, ck, name, name_length);
++      }
++      DWC_MUTEX_UNLOCK(cc_if->mutex);
++
++      cc_changed(cc_if);
++}
++
++uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
++{
++      uint32_t uid = 0;
++
++      DWC_MUTEX_LOCK(cc_if->mutex);
++      uid = cc_match_chid(cc_if, chid);
++      DWC_MUTEX_UNLOCK(cc_if->mutex);
++      return uid;
++}
++uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
++{
++      uint32_t uid = 0;
++
++      DWC_MUTEX_LOCK(cc_if->mutex);
++      uid = cc_match_cdid(cc_if, cdid);
++      DWC_MUTEX_UNLOCK(cc_if->mutex);
++      return uid;
++}
++
++uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id)
++{
++      uint8_t *ck = NULL;
++      dwc_cc_t *cc;
++
++      DWC_MUTEX_LOCK(cc_if->mutex);
++      cc = cc_find(cc_if, id);
++      if (cc) {
++              ck = cc->ck;
++      }
++      DWC_MUTEX_UNLOCK(cc_if->mutex);
++
++      return ck;
++
++}
++
++uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id)
++{
++      uint8_t *retval = NULL;
++      dwc_cc_t *cc;
++
++      DWC_MUTEX_LOCK(cc_if->mutex);
++      cc = cc_find(cc_if, id);
++      if (cc) {
++              retval = cc->chid;
++      }
++      DWC_MUTEX_UNLOCK(cc_if->mutex);
++
++      return retval;
++}
++
++uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id)
++{
++      uint8_t *retval = NULL;
++      dwc_cc_t *cc;
++
++      DWC_MUTEX_LOCK(cc_if->mutex);
++      cc = cc_find(cc_if, id);
++      if (cc) {
++              retval = cc->cdid;
++      }
++      DWC_MUTEX_UNLOCK(cc_if->mutex);
++
++      return retval;
++}
++
++uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length)
++{
++      uint8_t *retval = NULL;
++      dwc_cc_t *cc;
++
++      DWC_MUTEX_LOCK(cc_if->mutex);
++      *length = 0;
++      cc = cc_find(cc_if, id);
++      if (cc) {
++              *length = cc->length;
++              retval = cc->name;
++      }
++      DWC_MUTEX_UNLOCK(cc_if->mutex);
++
++      return retval;
++}
+--- /dev/null
++++ b/drivers/usb/host/dwc_common_port/dwc_cc.h
+@@ -0,0 +1,209 @@
++/* =========================================================================
++ * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_cc.h $
++ * $Revision: #1 $
++ * $Date: 2008/12/21 $
++ * $Change: 1156609 $
++ *
++ * Synopsys Portability Library Software and documentation
++ * (hereinafter, "Software") is an Unsupported proprietary work of
++ * Synopsys, Inc. unless otherwise expressly agreed to in writing
++ * between Synopsys and you.
++ *
++ * The Software IS NOT an item of Licensed Software or Licensed Product
++ * under any End User Software License Agreement or Agreement for
++ * Licensed Product with Synopsys or any supplement thereto. You are
++ * permitted to use and redistribute this Software in source and binary
++ * forms, with or without modification, provided that redistributions
++ * of source code must retain this notice. You may not view, use,
++ * disclose, copy or distribute this file or any information contained
++ * herein except pursuant to this license grant from Synopsys. If you
++ * do not agree with this notice, including the disclaimer below, then
++ * you are not authorized to use the Software.
++ *
++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
++ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
++ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
++ * DAMAGE.
++ * ========================================================================= */
++#ifndef _DWC_CC_H_
++#define _DWC_CC_H_
++
++/** @file
++ *
++ * This file defines the Context Context library.
++ *
++ * The main data structure is dwc_cc_if_t which is returned by either the
++ * dwc_cc_if_alloc function or returned by the module to the user via a provided
++ * function. The data structure is opaque and should only be manipulated via the
++ * functions provied in this API.
++ *
++ * It manages a list of connection contexts and operations can be performed to
++ * add, remove, query, search, and change, those contexts.  Additionally,
++ * a dwc_notifier_t object can be requested from the manager so that
++ * the user can be notified whenever the context list has changed.
++ */
++
++#include "dwc_os.h"
++#include "dwc_list.h"
++#include "dwc_notifier.h"
++
++
++/* Notifications */
++#define DWC_CC_LIST_CHANGED_NOTIFICATION "DWC_CC_LIST_CHANGED_NOTIFICATION"
++
++struct dwc_cc_if;
++typedef struct dwc_cc_if dwc_cc_if_t;
++
++
++/** @name Connection Context Operations */
++/** @{ */
++
++/** This function allocates memory for a dwc_cc_if_t structure, initializes
++ * fields to default values, and returns a pointer to the structure or NULL on
++ * error. */
++extern dwc_cc_if_t *dwc_cc_if_alloc(dwc_notifier_t *notifier, unsigned is_host);
++
++/** Frees the memory for the specified CC structure allocated from
++ * dwc_cc_if_alloc(). */
++extern void dwc_cc_if_free(dwc_cc_if_t *cc_if);
++
++/** Removes all contexts from the connection context list */
++extern void dwc_cc_clear(dwc_cc_if_t *cc_if);
++
++/** Adds a connection context (CHID, CK, CDID, Name) to the connection context list.
++ * If a CHID already exists, the CK and name are overwritten.  Statistics are
++ * not overwritten.
++ *
++ * @param cc_if The cc_if structure.
++ * @param chid A pointer to the 16-byte CHID.  This value will be copied.
++ * @param ck A pointer to the 16-byte CK.  This value will be copied.
++ * @param cdid A pointer to the 16-byte CDID.  This value will be copied.
++ * @param name An optional host friendly name as defined in the association model
++ * spec.  Must be a UTF16-LE unicode string.  Can be NULL to indicated no name.
++ * @param length The length othe unicode string.
++ * @return A unique identifier used to refer to this context that is valid for
++ * as long as this context is still in the list. */
++extern int32_t dwc_cc_add(dwc_cc_if_t *cc_if, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length);
++
++/** Changes the CHID, CK, CDID, or Name values of a connection context in the
++ * list, preserving any accumulated statistics.  This would typically be called
++ * if the host decideds to change the context with a SET_CONNECTION request.
++ *
++ * @param cc_if The cc_if structure.
++ * @param id The identifier of the connection context.
++ * @param chid A pointer to the 16-byte CHID.  This value will be copied.  NULL
++ * indicates no change.
++ * @param cdid A pointer to the 16-byte CDID.  This value will be copied.  NULL
++ * indicates no change.
++ * @param ck A pointer to the 16-byte CK.  This value will be copied.  NULL
++ * indicates no change.
++ * @param name Host friendly name UTF16-LE.  NULL indicates no change.
++ * @param length Length of name. */
++extern void dwc_cc_change(dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length);
++
++/** Remove the specified connection context.
++ * @param cc_if The cc_if structure.
++ * @param id The identifier of the connection context to remove. */
++extern void dwc_cc_remove(dwc_cc_if_t *cc_if, int32_t id);
++
++/** Get a binary block of data for the connection context list and attributes.
++ * This data can be used by the OS specific driver to save the connection
++ * context list into non-volatile memory.
++ *
++ * @param cc_if The cc_if structure.
++ * @param length Return the length of the data buffer.
++ * @return A pointer to the data buffer.  The memory for this buffer should be freed with DWC_FREE() after use. */
++extern uint8_t *dwc_cc_data_for_save(dwc_cc_if_t *cc_if, unsigned int *length);
++
++/** Restore the connection context list from the binary data that was previously
++ * returned from a call to dwc_cc_data_for_save.  This can be used by the OS specific
++ * driver to load a connection context list from non-volatile memory.
++ *
++ * @param cc_if The cc_if structure.
++ * @param data The data bytes as returned from dwc_cc_data_for_save.
++ * @param length The length of the data. */
++extern void dwc_cc_restore_from_data(dwc_cc_if_t *cc_if, uint8_t *data, unsigned int length);
++
++/** Find the connection context from the specified CHID.
++ *
++ * @param cc_if The cc_if structure.
++ * @param chid A pointer to the CHID data.
++ * @return A non-zero identifier of the connection context if the CHID matches.
++ * Otherwise returns 0. */
++extern uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid);
++
++/** Find the connection context from the specified CDID.
++ *
++ * @param cc_if The cc_if structure.
++ * @param cdid A pointer to the CDID data.
++ * @return A non-zero identifier of the connection context if the CHID matches.
++ * Otherwise returns 0. */
++extern uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid);
++
++/** Retrieve the CK from the specified connection context.
++ *
++ * @param cc_if The cc_if structure.
++ * @param id The identifier of the connection context.
++ * @return A pointer to the CK data.  The memory does not need to be freed. */
++extern uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id);
++
++/** Retrieve the CHID from the specified connection context.
++ *
++ * @param cc_if The cc_if structure.
++ * @param id The identifier of the connection context.
++ * @return A pointer to the CHID data.  The memory does not need to be freed. */
++extern uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id);
++
++/** Retrieve the CDID from the specified connection context.
++ *
++ * @param cc_if The cc_if structure.
++ * @param id The identifier of the connection context.
++ * @return A pointer to the CDID data.  The memory does not need to be freed. */
++extern uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id);
++
++extern uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length);
++
++/** Checks a buffer for non-zero.
++ * @param id A pointer to a 16 byte buffer. 
++ * @return true if the 16 byte value is non-zero. */
++static inline unsigned dwc_assoc_is_not_zero_id(uint8_t *id) {
++      int i;
++      for (i=0; i<16; i++) {
++              if (id[i]) return 1;
++      }
++      return 0;
++}
++
++/** Checks a buffer for zero.
++ * @param id A pointer to a 16 byte buffer. 
++ * @return true if the 16 byte value is zero. */
++static inline unsigned dwc_assoc_is_zero_id(uint8_t *id) {
++      return !dwc_assoc_is_not_zero_id(id);
++}
++
++/** Prints an ASCII representation for the 16-byte chid, cdid, or ck, into
++ * buffer. */
++static inline int dwc_print_id_string(char *buffer, uint8_t *id) {
++      char *ptr = buffer;
++      int i;
++      for (i=0; i<16; i++) {
++              ptr += DWC_SPRINTF(ptr, "%02x", id[i]);
++              if (i < 15) {
++                      ptr += DWC_SPRINTF(ptr, " ");
++              }
++      }
++      return ptr - buffer;
++}
++
++/** @} */
++
++#endif /* _DWC_CC_H_ */
++
+--- /dev/null
++++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c
+@@ -0,0 +1,1247 @@
++#include "dwc_cc.h"
++#include "dwc_modpow.h"
++#include "dwc_dh.h"
++#include "dwc_crypto.h"
++#include "dwc_notifier.h"
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/kthread.h>
++
++MODULE_DESCRIPTION("DWC Common Library - Portable version");
++MODULE_AUTHOR("Synopsys Inc.");
++MODULE_LICENSE ("GPL");
++
++static int dwc_common_port_init_module(void)
++{
++      printk( KERN_DEBUG "Module dwc_common_port init\n" );
++#ifdef DEBUG_MEMORY
++      dwc_memory_debug_start();
++#endif
++      dwc_alloc_notification_manager();
++      return 0;
++}
++
++static void dwc_common_port_exit_module(void)
++{
++      printk( KERN_DEBUG "Module dwc_common_port exit\n" );
++      dwc_free_notification_manager();
++#ifdef DEBUG_MEMORY
++      dwc_memory_debug_stop();
++#endif
++}
++
++module_init(dwc_common_port_init_module);
++module_exit(dwc_common_port_exit_module);
++
++/* CC */
++EXPORT_SYMBOL(dwc_cc_if_alloc);
++EXPORT_SYMBOL(dwc_cc_if_free);
++EXPORT_SYMBOL(dwc_cc_clear);
++EXPORT_SYMBOL(dwc_cc_add);
++EXPORT_SYMBOL(dwc_cc_remove);
++EXPORT_SYMBOL(dwc_cc_change);
++EXPORT_SYMBOL(dwc_cc_data_for_save);
++EXPORT_SYMBOL(dwc_cc_restore_from_data);
++EXPORT_SYMBOL(dwc_cc_match_chid);
++EXPORT_SYMBOL(dwc_cc_match_cdid);
++EXPORT_SYMBOL(dwc_cc_ck);
++EXPORT_SYMBOL(dwc_cc_chid);
++EXPORT_SYMBOL(dwc_cc_cdid);
++EXPORT_SYMBOL(dwc_cc_name);
++
++#ifndef CONFIG_MACH_IPMATE
++/* Modpow */
++EXPORT_SYMBOL(dwc_modpow);
++/* DH */
++EXPORT_SYMBOL(dwc_dh_modpow);
++EXPORT_SYMBOL(dwc_dh_derive_keys);
++EXPORT_SYMBOL(dwc_dh_pk);
++#endif /* CONFIG_MACH_IPMATE  */
++/* Crypto */
++EXPORT_SYMBOL(dwc_wusb_aes_encrypt);
++EXPORT_SYMBOL(dwc_wusb_cmf);
++EXPORT_SYMBOL(dwc_wusb_prf);
++EXPORT_SYMBOL(dwc_wusb_fill_ccm_nonce);
++EXPORT_SYMBOL(dwc_wusb_gen_nonce);
++EXPORT_SYMBOL(dwc_wusb_gen_key);
++EXPORT_SYMBOL(dwc_wusb_gen_mic);
++
++
++/* Notification */
++EXPORT_SYMBOL(dwc_alloc_notification_manager);
++EXPORT_SYMBOL(dwc_free_notification_manager);
++EXPORT_SYMBOL(dwc_register_notifier);
++EXPORT_SYMBOL(dwc_unregister_notifier);
++EXPORT_SYMBOL(dwc_add_observer);
++EXPORT_SYMBOL(dwc_remove_observer);
++EXPORT_SYMBOL(dwc_notify);
++
++/* Memory Debugging Routines */
++#ifdef DEBUG_MEMORY
++EXPORT_SYMBOL(dwc_alloc_debug);
++EXPORT_SYMBOL(dwc_alloc_atomic_debug);
++EXPORT_SYMBOL(dwc_free_debug);
++EXPORT_SYMBOL(dwc_dma_alloc_debug);
++EXPORT_SYMBOL(dwc_dma_alloc_atomic_debug);
++EXPORT_SYMBOL(dwc_dma_free_debug);
++#endif
++
++/* OS-Level Implementations */
++
++/* This is the Linux kernel implementation of the DWC platform library. */
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/ctype.h>
++#include <linux/crypto.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++#include <linux/cdev.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/jiffies.h>
++#include <linux/list.h>
++#include <linux/pci.h>
++#include <linux/slab.h>
++#include <linux/stat.h>
++#include <linux/string.h>
++#include <linux/timer.h>
++#include <linux/version.h>
++#include <linux/usb.h>
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
++#include <linux/usb_gadget.h>
++#else
++#include <linux/usb/gadget.h>
++#endif
++#include <linux/random.h>
++#include <asm/io.h>
++#include <asm/page.h>
++#include <asm/uaccess.h>
++#include <asm/unaligned.h>
++#include <asm/page.h>
++#include <linux/scatterlist.h>
++
++/* MISC */
++
++void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
++{
++      return memset(dest, byte, size);
++}
++EXPORT_SYMBOL(DWC_MEMSET);
++
++void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
++{
++      return memcpy(dest, src, size);
++}
++EXPORT_SYMBOL(DWC_MEMCPY);
++
++void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
++{
++      return memmove(dest, src, size);
++}
++EXPORT_SYMBOL(DWC_MEMMOVE);
++
++int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
++{
++      return memcmp(m1, m2, size);
++}
++EXPORT_SYMBOL(DWC_MEMCMP);
++
++int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
++{
++      return strncmp(s1, s2, size);
++}
++EXPORT_SYMBOL(DWC_STRNCMP);
++
++int DWC_STRCMP(void *s1, void *s2)
++{
++      return strcmp(s1, s2);
++}
++EXPORT_SYMBOL(DWC_STRCMP);
++
++int DWC_STRLEN(char const *str)
++{
++      return strlen(str);
++}
++EXPORT_SYMBOL(DWC_STRLEN);
++
++char *DWC_STRCPY(char *to, const char *from)
++{
++      return strcpy(to, from);
++}
++EXPORT_SYMBOL(DWC_STRCPY);
++
++char *DWC_STRDUP(char const *str)
++{
++      int len = DWC_STRLEN(str) + 1;
++      char *new = DWC_ALLOC_ATOMIC(len);
++      if (!new) {
++              return NULL;
++      }
++      DWC_MEMCPY(new, str, len);
++      return new;
++}
++EXPORT_SYMBOL(DWC_STRDUP);
++
++int DWC_ATOI(char *str, int32_t *value)
++{
++      char *end = NULL;
++      *value = simple_strtol(str, &end, 0);
++      if (*end == '\0') {
++              return 0;
++      }
++      return -1;
++}
++EXPORT_SYMBOL(DWC_ATOI);
++
++int DWC_ATOUI(char *str, uint32_t *value)
++{
++      char *end = NULL;
++      *value = simple_strtoul(str, &end, 0);
++      if (*end == '\0') {
++              return 0;
++      }
++      return -1;
++}
++EXPORT_SYMBOL(DWC_ATOUI);
++
++
++/* From usbstring.c */
++int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
++{
++      int     count = 0;
++      u8      c;
++      u16     uchar;
++
++      /* this insists on correct encodings, though not minimal ones.
++       * BUT it currently rejects legit 4-byte UTF-8 code points,
++       * which need surrogate pairs.  (Unicode 3.1 can use them.)
++       */
++      while (len != 0 && (c = (u8) *s++) != 0) {
++              if (unlikely(c & 0x80)) {
++                      // 2-byte sequence:
++                      // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
++                      if ((c & 0xe0) == 0xc0) {
++                              uchar = (c & 0x1f) << 6;
++
++                              c = (u8) *s++;
++                              if ((c & 0xc0) != 0xc0)
++                                      goto fail;
++                              c &= 0x3f;
++                              uchar |= c;
++
++                      // 3-byte sequence (most CJKV characters):
++                      // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
++                      } else if ((c & 0xf0) == 0xe0) {
++                              uchar = (c & 0x0f) << 12;
++
++                              c = (u8) *s++;
++                              if ((c & 0xc0) != 0xc0)
++                                      goto fail;
++                              c &= 0x3f;
++                              uchar |= c << 6;
++
++                              c = (u8) *s++;
++                              if ((c & 0xc0) != 0xc0)
++                                      goto fail;
++                              c &= 0x3f;
++                              uchar |= c;
++
++                              /* no bogus surrogates */
++                              if (0xd800 <= uchar && uchar <= 0xdfff)
++                                      goto fail;
++
++                      // 4-byte sequence (surrogate pairs, currently rare):
++                      // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
++                      //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
++                      // (uuuuu = wwww + 1)
++                      // FIXME accept the surrogate code points (only)
++
++                      } else
++                              goto fail;
++              } else
++                      uchar = c;
++              put_unaligned (cpu_to_le16 (uchar), cp++);
++              count++;
++              len--;
++      }
++      return count;
++fail:
++      return -1;
++}
++EXPORT_SYMBOL(DWC_UTF8_TO_UTF16LE);
++
++/* dwc_debug.h */
++
++dwc_bool_t DWC_IN_IRQ(void)
++{
++      return in_irq();
++}
++EXPORT_SYMBOL(DWC_IN_IRQ);
++
++int DWC_IN_BH(void)
++{
++      return in_softirq();
++}
++EXPORT_SYMBOL(DWC_IN_BH);
++
++void DWC_VPRINTF(char *format, va_list args)
++{
++      vprintk(format, args);
++}
++EXPORT_SYMBOL(DWC_VPRINTF);
++
++int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
++{
++      return vsnprintf(str, size, format, args);
++}
++
++void DWC_PRINTF(char *format, ...)
++{
++      va_list args;
++      va_start(args, format);
++      DWC_VPRINTF(format, args);
++      va_end(args);
++}
++EXPORT_SYMBOL(DWC_PRINTF);
++
++int DWC_SPRINTF(char *buffer, char *format, ...)
++{
++      int retval;
++      va_list args;
++      va_start(args, format);
++      retval = vsprintf(buffer, format, args);
++      va_end(args);
++      return retval;
++}
++EXPORT_SYMBOL(DWC_SPRINTF);
++
++int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
++{
++      int retval;
++      va_list args;
++      va_start(args, format);
++      retval = vsnprintf(buffer, size, format, args);
++      va_end(args);
++      return retval;
++}
++EXPORT_SYMBOL(DWC_SNPRINTF);
++
++void __DWC_WARN(char *format, ...)
++{
++      va_list args;
++      va_start(args, format);
++      DWC_PRINTF(KERN_WARNING);
++      DWC_VPRINTF(format, args);
++      va_end(args);
++}
++EXPORT_SYMBOL(__DWC_WARN);
++
++void __DWC_ERROR(char *format, ...)
++{
++      va_list args;
++      va_start(args, format);
++      DWC_PRINTF(KERN_ERR);
++      DWC_VPRINTF(format, args);
++      va_end(args);
++}
++EXPORT_SYMBOL(__DWC_ERROR);
++
++void DWC_EXCEPTION(char *format, ...)
++{
++      va_list args;
++      va_start(args, format);
++      DWC_PRINTF(KERN_ERR);
++      DWC_VPRINTF(format, args);
++      va_end(args);
++      BUG_ON(1);
++}
++EXPORT_SYMBOL(DWC_EXCEPTION);
++
++#ifdef DEBUG
++void __DWC_DEBUG(char *format, ...)
++{
++      va_list args;
++      va_start(args, format);
++      DWC_PRINTF(KERN_DEBUG);
++      DWC_VPRINTF(format, args);
++      va_end(args);
++}
++EXPORT_SYMBOL(__DWC_DEBUG);
++#endif
++
++
++
++/* dwc_mem.h */
++
++#if 0
++dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
++                              uint32_t align,
++                              uint32_t alloc)
++{
++      struct dma_pool *pool = dma_pool_create("Pool", NULL,
++                                              size, align, alloc);
++      return (dwc_pool_t *)pool;
++}
++
++void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
++{
++      dma_pool_destroy((struct dma_pool *)pool);
++}
++
++void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, U64 *dma_addr)
++{
++      return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
++}
++
++void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, U64 *dma_addr)
++{
++      void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
++      memset();
++}
++
++void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
++{
++      dma_pool_free(pool, vaddr, daddr);
++}
++
++#endif
++
++void *__DWC_DMA_ALLOC(uint32_t size, dwc_dma_t *dma_addr)
++{
++      void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_KERNEL);
++      if (!buf) {
++              return NULL;
++      }
++      memset(buf, 0, (size_t)size);
++      return buf;
++}
++EXPORT_SYMBOL(__DWC_DMA_ALLOC);
++
++void __DWC_DMA_FREE(uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
++{
++      dma_free_coherent(NULL, size, virt_addr, dma_addr);
++}
++EXPORT_SYMBOL(__DWC_DMA_FREE);
++
++void *__DWC_DMA_ALLOC_ATOMIC(uint32_t size, dwc_dma_t *dma_addr)
++{
++      void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC);
++      if (!buf) {
++              return NULL;
++      }
++      memset(buf, 0, (size_t)size);
++      return buf;
++}
++EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC);
++
++void *__DWC_ALLOC(uint32_t size)
++{
++      return kzalloc(size, GFP_KERNEL);
++}
++EXPORT_SYMBOL(__DWC_ALLOC);
++
++void *__DWC_ALLOC_ATOMIC(uint32_t size)
++{
++      return kzalloc(size, GFP_ATOMIC);
++}
++EXPORT_SYMBOL(__DWC_ALLOC_ATOMIC);
++
++void __DWC_FREE(void *addr)
++{
++      kfree(addr);
++}
++EXPORT_SYMBOL(__DWC_FREE);
++
++/* dwc_crypto.h */
++
++void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
++{
++      get_random_bytes(buffer, length);
++}
++EXPORT_SYMBOL(DWC_RANDOM_BYTES);
++
++int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
++{
++      struct crypto_blkcipher *tfm;
++      struct blkcipher_desc desc;
++      struct scatterlist sgd;
++      struct scatterlist sgs;
++
++      tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
++      if (tfm == NULL) {
++              printk("failed to load transform for aes CBC\n");
++              return -1;
++      }
++
++      crypto_blkcipher_setkey(tfm, key, keylen);
++      crypto_blkcipher_set_iv(tfm, iv, 16);
++
++      sg_init_one(&sgd, out, messagelen);
++      sg_init_one(&sgs, message, messagelen);
++
++      desc.tfm = tfm;
++      desc.flags = 0;
++
++      if(crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
++              crypto_free_blkcipher(tfm);
++              DWC_ERROR("AES CBC encryption failed");
++              return -1;
++      }
++
++      crypto_free_blkcipher(tfm);
++      return 0;
++}
++EXPORT_SYMBOL(DWC_AES_CBC);
++
++int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
++{
++      struct crypto_hash *tfm;
++      struct hash_desc desc;
++      struct scatterlist sg;
++
++      tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
++      if (IS_ERR(tfm)) {
++              DWC_ERROR("Failed to load transform for sha256: %ld\n", PTR_ERR(tfm));
++              return 0;
++      }
++      desc.tfm = tfm;
++      desc.flags = 0;
++
++      sg_init_one(&sg, message, len);
++      crypto_hash_digest(&desc, &sg, len, out);
++      crypto_free_hash(tfm);
++
++      return 1;
++}
++EXPORT_SYMBOL(DWC_SHA256);
++
++int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
++                  uint8_t *key, uint32_t keylen, uint8_t *out)
++{
++      struct crypto_hash *tfm;
++      struct hash_desc desc;
++      struct scatterlist sg;
++
++      tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
++      if (IS_ERR(tfm)) {
++              DWC_ERROR("Failed to load transform for hmac(sha256): %ld\n", PTR_ERR(tfm));
++              return 0;
++      }
++      desc.tfm = tfm;
++      desc.flags = 0;
++
++      sg_init_one(&sg, message, messagelen);
++      crypto_hash_setkey(tfm, key, keylen);
++      crypto_hash_digest(&desc, &sg, messagelen, out);
++      crypto_free_hash(tfm);
++
++      return 1;
++}
++EXPORT_SYMBOL(DWC_HMAC_SHA256);
++
++/* Byte Ordering Conversions. */
++uint32_t DWC_CPU_TO_LE32(void *p)
++{
++#ifdef __LITTLE_ENDIAN
++      return *((uint32_t *)p);
++#else
++      uint8_t *u_p = (uint8_t *)p;
++
++      return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
++#endif
++}
++EXPORT_SYMBOL(DWC_CPU_TO_LE32);
++
++uint32_t DWC_CPU_TO_BE32(void *p)
++{
++#ifdef __BIG_ENDIAN
++      return *((uint32_t *)p);
++#else
++      uint8_t *u_p = (uint8_t *)p;
++
++      return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
++#endif
++}
++EXPORT_SYMBOL(DWC_CPU_TO_BE32);
++
++uint32_t DWC_LE32_TO_CPU(void *p)
++{
++#ifdef __LITTLE_ENDIAN
++      return *((uint32_t *)p);
++#else
++      uint8_t *u_p = (uint8_t *)p;
++
++      return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
++
++#endif
++}
++EXPORT_SYMBOL(DWC_LE32_TO_CPU);
++
++uint32_t DWC_BE32_TO_CPU(void *p)
++{
++#ifdef __BIG_ENDIAN
++      return *((uint32_t *)p);
++#else
++      uint8_t *u_p = (uint8_t *)p;
++
++      return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
++#endif
++}
++EXPORT_SYMBOL(DWC_BE32_TO_CPU);
++
++uint16_t DWC_CPU_TO_LE16(void *p)
++{
++#ifdef __LITTLE_ENDIAN
++      return *((uint16_t *)p);
++#else
++      uint8_t *u_p = (uint8_t *)p;
++      return (u_p[1] | (u_p[0] << 8));
++#endif
++}
++EXPORT_SYMBOL(DWC_CPU_TO_LE16);
++
++uint16_t DWC_CPU_TO_BE16(void *p)
++{
++#ifdef __BIG_ENDIAN
++      return *((uint16_t *)p);
++#else
++      uint8_t *u_p = (uint8_t *)p;
++      return (u_p[1] | (u_p[0] << 8));
++#endif
++}
++EXPORT_SYMBOL(DWC_CPU_TO_BE16);
++
++uint16_t DWC_LE16_TO_CPU(void *p)
++{
++#ifdef __LITTLE_ENDIAN
++      return *((uint16_t *)p);
++#else
++      uint8_t *u_p = (uint8_t *)p;
++      return (u_p[1] | (u_p[0] << 8));
++#endif
++}
++EXPORT_SYMBOL(DWC_LE16_TO_CPU);
++
++uint16_t DWC_BE16_TO_CPU(void *p)
++{
++#ifdef __BIG_ENDIAN
++      return *((uint16_t *p)p);
++#else
++      uint8_t *u_p = (uint8_t *)p;
++      return (u_p[1] | (u_p[0] << 8));
++#endif
++}
++EXPORT_SYMBOL(DWC_BE16_TO_CPU);
++
++
++/* Registers */
++
++uint32_t DWC_READ_REG32(uint32_t volatile *reg)
++{
++      return readl(reg);
++}
++EXPORT_SYMBOL(DWC_READ_REG32);
++
++#if 0
++uint64_t DWC_READ_REG64(uint64_t volatile *reg)
++{
++}
++#endif
++
++void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value)
++{
++      writel(value, reg);
++}
++EXPORT_SYMBOL(DWC_WRITE_REG32);
++
++#if 0
++void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value)
++{
++}
++#endif
++
++void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)
++{
++      writel( (readl(reg) & ~clear_mask) | set_mask, reg );
++}
++EXPORT_SYMBOL(DWC_MODIFY_REG32);
++
++#if 0
++void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t value)
++{
++}
++#endif
++
++
++
++/* Threading */
++
++typedef struct work_container
++{
++      dwc_work_callback_t cb;
++      void *data;
++      dwc_workq_t *wq;
++      char *name;
++
++#ifdef DEBUG
++      DWC_CIRCLEQ_ENTRY(work_container) entry;
++#endif
++
++      struct delayed_work work;
++} work_container_t;
++
++#ifdef DEBUG
++DWC_CIRCLEQ_HEAD(work_container_queue, work_container);
++#endif
++
++struct dwc_workq
++{
++      struct workqueue_struct *wq;
++      int pending;
++      dwc_spinlock_t *lock;
++      dwc_waitq_t *waitq;
++
++#ifdef DEBUG
++      struct work_container_queue entries;
++#endif
++};
++
++static void do_work(struct work_struct *work)
++{
++      int64_t flags;
++      struct delayed_work *dw = container_of(work, struct delayed_work, work);
++      work_container_t *container = container_of(dw, struct work_container, work);
++      dwc_workq_t *wq = container->wq;
++
++      container->cb(container->data);
++
++#ifdef DEBUG
++      DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry);
++#endif
++
++      if (container->name) {
++              DWC_DEBUG("Work done: %s, container=%p",
++                          container->name, container); //GRAYG
++              DWC_FREE(container->name);
++      }
++      DWC_FREE(container);
++
++      DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
++      wq->pending --;
++      DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
++      DWC_WAITQ_TRIGGER(wq->waitq);
++}
++
++static int work_done(void *data)
++{
++      dwc_workq_t *workq = (dwc_workq_t *)data;
++      return workq->pending == 0;
++}
++
++int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
++{
++      return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
++}
++EXPORT_SYMBOL(DWC_WORKQ_WAIT_WORK_DONE);
++
++dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
++{
++      dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
++      wq->wq = create_singlethread_workqueue(name);
++      wq->pending = 0;
++      wq->lock = DWC_SPINLOCK_ALLOC();
++      wq->waitq = DWC_WAITQ_ALLOC();
++#ifdef DEBUG
++      DWC_CIRCLEQ_INIT(&wq->entries);
++#endif
++      return wq;
++}
++EXPORT_SYMBOL(DWC_WORKQ_ALLOC);
++
++void DWC_WORKQ_FREE(dwc_workq_t *wq)
++{
++#ifdef DEBUG
++      if (wq->pending != 0) {
++              struct work_container *wc;
++              DWC_ERROR("Destroying work queue with pending work");
++              DWC_CIRCLEQ_FOREACH(wc, &wq->entries, entry) {
++                      DWC_ERROR("Work %s still pending", wc->name);
++              }
++      }
++#endif
++      destroy_workqueue((struct workqueue_struct *)wq->wq);
++      DWC_SPINLOCK_FREE(wq->lock);
++      DWC_WAITQ_FREE(wq->waitq);
++      DWC_FREE(wq);
++}
++EXPORT_SYMBOL(DWC_WORKQ_FREE);
++
++void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t work_cb, void *data, char *format, ...)
++{
++      int64_t flags;
++      work_container_t *container;
++      static char name[128];
++
++      va_list args;
++      va_start(args, format);
++        if (format)
++              DWC_VSNPRINTF(name, 128, format, args);
++      va_end(args);
++
++      DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
++      wq->pending ++;
++      DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
++      DWC_WAITQ_TRIGGER(wq->waitq);
++
++      container = DWC_ALLOC_ATOMIC(sizeof(*container));
++
++      container->data = data;
++      container->cb = work_cb;
++      container->wq = wq;
++        if (format) {
++                container->name = DWC_STRDUP(name);
++                DWC_DEBUG("Queueing work: %s, contianer=%p",
++                          container->name, container);
++        } else
++                container->name = NULL;
++        
++      INIT_WORK(&container->work.work, do_work);
++
++#ifdef DEBUG
++      DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
++#endif
++
++      queue_work(wq->wq, &container->work.work);
++
++}
++EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE);
++
++void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t work_cb, void *data, uint32_t time, char *format, ...)
++{
++      int64_t flags;
++      work_container_t *container;
++      static char name[128];
++
++      va_list args;
++      va_start(args, format);
++        if (format)
++              DWC_VSNPRINTF(name, 128, format, args);
++      va_end(args);
++
++      DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
++      wq->pending ++;
++      DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
++      DWC_WAITQ_TRIGGER(wq->waitq);
++
++      container = DWC_ALLOC_ATOMIC(sizeof(*container));
++
++      container->data = data;
++      container->cb = work_cb;
++      container->wq = wq;
++        if (format) { //GRAYG
++              container->name = DWC_STRDUP(name);
++                DWC_DEBUG("Queueing work: %s, contianer=%p",
++                          container->name, container);
++        } else
++           container->name = NULL;
++      INIT_DELAYED_WORK(&container->work, do_work);
++
++#ifdef DEBUG
++      DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
++#endif
++
++      queue_delayed_work(wq->wq, &container->work, msecs_to_jiffies(time));
++
++}
++EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE_DELAYED);
++
++
++int DWC_WORKQ_PENDING(dwc_workq_t *wq)
++{
++      return wq->pending;
++}
++EXPORT_SYMBOL(DWC_WORKQ_PENDING);
++
++dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
++{
++      spinlock_t *sl = (spinlock_t *)1;
++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
++      sl = DWC_ALLOC(sizeof(*sl));
++      spin_lock_init(sl);
++#endif
++      return (dwc_spinlock_t *)sl;
++}
++EXPORT_SYMBOL(DWC_SPINLOCK_ALLOC);
++
++void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
++{
++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
++      DWC_FREE(lock);
++#endif
++}
++EXPORT_SYMBOL(DWC_SPINLOCK_FREE);
++
++void DWC_SPINLOCK(dwc_spinlock_t *lock)
++{
++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
++      spin_lock((spinlock_t *)lock);
++#endif
++}
++EXPORT_SYMBOL(DWC_SPINLOCK);
++
++void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
++{
++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
++      spin_unlock((spinlock_t *)lock);
++#endif
++}
++EXPORT_SYMBOL(DWC_SPINUNLOCK);
++
++void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, uint64_t *flags)
++{
++      unsigned long f;
++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
++        spin_lock_irqsave((spinlock_t *)lock, f);
++#else
++      local_irq_save(f);
++#endif
++        *flags = f;
++}
++EXPORT_SYMBOL(DWC_SPINLOCK_IRQSAVE);
++
++void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, uint64_t flags)
++{
++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
++        spin_unlock_irqrestore((spinlock_t *)lock, flags);
++#else
++        // in kernel 2.6.31, at least, we check for unsigned long
++        local_irq_restore((unsigned long)flags);
++#endif
++}
++EXPORT_SYMBOL(DWC_SPINUNLOCK_IRQRESTORE);
++
++dwc_mutex_t *DWC_MUTEX_ALLOC(void)
++{
++      dwc_mutex_t *mutex = (dwc_mutex_t*)DWC_ALLOC(sizeof(struct mutex));
++      struct mutex *m = (struct mutex *)mutex;
++      mutex_init(m);
++      return mutex;
++}
++EXPORT_SYMBOL(DWC_MUTEX_ALLOC);
++
++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
++#else
++void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
++{
++      mutex_destroy((struct mutex *)mutex);
++      DWC_FREE(mutex);
++}
++EXPORT_SYMBOL(DWC_MUTEX_FREE);
++#endif
++
++void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
++{
++      struct mutex *m = (struct mutex *)mutex;
++      mutex_lock(m);
++}
++EXPORT_SYMBOL(DWC_MUTEX_LOCK);
++
++int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
++{
++      struct mutex *m = (struct mutex *)mutex;
++      return mutex_trylock(m);
++}
++EXPORT_SYMBOL(DWC_MUTEX_TRYLOCK);
++
++void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
++{
++      struct mutex *m = (struct mutex *)mutex;
++      mutex_unlock(m);
++}
++EXPORT_SYMBOL(DWC_MUTEX_UNLOCK);
++
++dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t thread_function, char *name, void *data)
++{
++      struct task_struct *thread = kthread_run(thread_function, data, name);
++      if (thread == ERR_PTR(-ENOMEM)) {
++              return NULL;
++      }
++      return (dwc_thread_t *)thread;
++}
++EXPORT_SYMBOL(DWC_THREAD_RUN);
++
++int DWC_THREAD_STOP(dwc_thread_t *thread)
++{
++      return kthread_stop((struct task_struct *)thread);
++}
++EXPORT_SYMBOL(DWC_THREAD_STOP);
++
++dwc_bool_t DWC_THREAD_SHOULD_STOP()
++{
++      return kthread_should_stop();
++}
++EXPORT_SYMBOL(DWC_THREAD_SHOULD_STOP);
++
++/* Timers */
++
++struct dwc_timer
++{
++      struct timer_list *t;
++      char *name;
++      dwc_timer_callback_t cb;
++      void *data;
++      uint8_t scheduled;
++      dwc_spinlock_t *lock;
++};
++
++static void set_scheduled(dwc_timer_t *t, int s)
++{
++      uint64_t flags;
++      DWC_SPINLOCK_IRQSAVE(t->lock, &flags);
++      t->scheduled = s;
++      DWC_SPINUNLOCK_IRQRESTORE(t->lock, flags);
++}
++
++static int get_scheduled(dwc_timer_t *t)
++{
++      int s;
++      uint64_t flags;
++      DWC_SPINLOCK_IRQSAVE(t->lock, &flags);
++      s = t->scheduled;
++      DWC_SPINUNLOCK_IRQRESTORE(t->lock, flags);
++      return s;
++}
++
++static void timer_callback(unsigned long data)
++{
++      dwc_timer_t *timer = (dwc_timer_t *)data;
++      set_scheduled(timer, 0);
++      DWC_DEBUG("Timer %s callback", timer->name);
++      timer->cb(timer->data);
++}
++
++dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
++{
++      dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
++      if (!t) {
++              DWC_ERROR("Cannot allocate memory for timer");
++              return NULL;
++      }
++      t->t = DWC_ALLOC(sizeof(*t->t));
++      if (!t->t) {
++              DWC_ERROR("Cannot allocate memory for timer->t");
++              goto no_timer;
++      }
++
++      t->name = DWC_STRDUP(name);
++      if (!t->name) {
++              DWC_ERROR("Cannot allocate memory for timer->name");
++              goto no_name;
++      }
++
++      t->lock = DWC_SPINLOCK_ALLOC();
++      if (!t->lock) {
++              DWC_ERROR("Cannot allocate memory for lock");
++              goto no_lock;
++      }
++      t->scheduled = 0;
++      t->t->base = &boot_tvec_bases;
++      t->t->expires = jiffies;
++      setup_timer(t->t, timer_callback, (unsigned long)t);
++
++      t->cb = cb;
++      t->data = data;
++
++      return t;
++
++ no_lock:
++      DWC_FREE(t->name);
++ no_name:
++      DWC_FREE(t->t);
++ no_timer:
++      DWC_FREE(t);
++      return NULL;
++}
++EXPORT_SYMBOL(DWC_TIMER_ALLOC);
++
++void DWC_TIMER_FREE(dwc_timer_t *timer)
++{
++      if (get_scheduled(timer)) {
++              del_timer(timer->t);
++      }
++
++      DWC_SPINLOCK_FREE(timer->lock);
++      DWC_FREE(timer->t);
++      DWC_FREE(timer->name);
++      DWC_FREE(timer);
++}
++EXPORT_SYMBOL(DWC_TIMER_FREE);
++
++void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
++{
++      if (!get_scheduled(timer)) {
++              set_scheduled(timer, 1);
++              //cgg: DWC_DEBUG("Scheduling timer %s to expire in +%d msec", timer->name, time);
++              timer->t->expires = jiffies + msecs_to_jiffies(time);
++              add_timer(timer->t);
++      }
++      else {
++                //cgg: DWC_DEBUG("Modifying timer %s to expire in +%d msec", timer->name, time);
++              mod_timer(timer->t, jiffies + msecs_to_jiffies(time));
++      }
++}
++EXPORT_SYMBOL(DWC_TIMER_SCHEDULE);
++
++void DWC_TIMER_CANCEL(dwc_timer_t *timer)
++{
++      del_timer(timer->t);
++}
++EXPORT_SYMBOL(DWC_TIMER_CANCEL);
++
++struct dwc_tasklet
++{
++      struct tasklet_struct t;
++      dwc_tasklet_callback_t cb; 
++      void *data;
++};
++
++static void tasklet_callback(unsigned long data)
++{
++      dwc_tasklet_t *t = (dwc_tasklet_t *)data;
++      t->cb(t->data);
++}
++
++dwc_tasklet_t *DWC_TASK_ALLOC(dwc_tasklet_callback_t cb, void *data)
++{
++      dwc_tasklet_t *t = DWC_ALLOC(sizeof(*t));
++      
++      if(t) {
++              t->data = data;
++              t->cb = cb;
++              tasklet_init(&t->t, tasklet_callback, (unsigned long)t);
++      } else {
++              DWC_ERROR("Cannot allocate memory for tasklet\n");
++      }
++      
++      return t;
++}
++EXPORT_SYMBOL(DWC_TASK_ALLOC);
++
++void DWC_TASK_FREE(dwc_tasklet_t *t)
++{
++      DWC_FREE(t);
++}
++EXPORT_SYMBOL(DWC_TASK_FREE);
++
++void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
++{
++      tasklet_schedule(&task->t);
++}
++EXPORT_SYMBOL(DWC_TASK_SCHEDULE);
++
++/* Timing */
++
++void DWC_UDELAY(uint32_t usecs)
++{
++      udelay(usecs);
++}
++EXPORT_SYMBOL(DWC_UDELAY);
++
++void DWC_MDELAY(uint32_t msecs)
++{
++      mdelay(msecs);
++}
++EXPORT_SYMBOL(DWC_MDELAY);
++
++void DWC_MSLEEP(uint32_t msecs)
++{
++      msleep(msecs);
++}
++EXPORT_SYMBOL(DWC_MSLEEP);
++
++uint32_t DWC_TIME(void)
++{
++      return jiffies_to_msecs(jiffies);
++}
++EXPORT_SYMBOL(DWC_TIME);
++
++
++/* Wait Queues */
++
++struct dwc_waitq
++{
++      wait_queue_head_t queue;
++      int abort;
++};
++
++dwc_waitq_t *DWC_WAITQ_ALLOC(void)
++{
++      dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
++      init_waitqueue_head(&wq->queue);
++      wq->abort = 0;
++      return wq;
++}
++EXPORT_SYMBOL(DWC_WAITQ_ALLOC);
++
++void DWC_WAITQ_FREE(dwc_waitq_t *wq)
++{
++      DWC_FREE(wq);
++}
++EXPORT_SYMBOL(DWC_WAITQ_FREE);
++
++static int32_t check_result(dwc_waitq_t *wq, int result)
++{     int32_t msecs;
++      if (result > 0) {
++              msecs = jiffies_to_msecs(result);
++              if (!msecs) {
++                      return 1;
++              }
++              return msecs;
++      }
++
++      if (result == 0) {
++              return -DWC_E_TIMEOUT;
++      }
++
++      if ((result == -ERESTARTSYS) || (wq->abort == 1)) {
++              return -DWC_E_ABORT;
++      }
++
++      return -DWC_E_UNKNOWN;
++}
++
++int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t condition, void *data)
++{
++      int result = wait_event_interruptible(wq->queue,
++                                                condition(data) || wq->abort);
++      return check_result(wq, result);
++}
++EXPORT_SYMBOL(DWC_WAITQ_WAIT);
++
++int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t condition,
++                             void *data, int32_t msecs)
++{
++      int result = wait_event_interruptible_timeout(wq->queue,
++                                                        condition(data) || wq->abort,
++                                                        msecs_to_jiffies(msecs));
++      return check_result(wq, result);
++}
++EXPORT_SYMBOL(DWC_WAITQ_WAIT_TIMEOUT);
++
++void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
++{
++      wake_up_interruptible(&wq->queue);
++}
++EXPORT_SYMBOL(DWC_WAITQ_TRIGGER);
++
++void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
++{
++      wq->abort = 1;
++      DWC_WAITQ_TRIGGER(wq);
++}
++EXPORT_SYMBOL(DWC_WAITQ_ABORT);
+--- /dev/null
++++ b/drivers/usb/host/dwc_common_port/dwc_crypto.c
+@@ -0,0 +1,306 @@
++/* =========================================================================
++ * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_crypto.c $
++ * $Revision: #1 $
++ * $Date: 2008/12/21 $
++ * $Change: 1156609 $
++ *
++ * Synopsys Portability Library Software and documentation
++ * (hereinafter, "Software") is an Unsupported proprietary work of
++ * Synopsys, Inc. unless otherwise expressly agreed to in writing
++ * between Synopsys and you.
++ *
++ * The Software IS NOT an item of Licensed Software or Licensed Product
++ * under any End User Software License Agreement or Agreement for
++ * Licensed Product with Synopsys or any supplement thereto. You are
++ * permitted to use and redistribute this Software in source and binary
++ * forms, with or without modification, provided that redistributions
++ * of source code must retain this notice. You may not view, use,
++ * disclose, copy or distribute this file or any information contained
++ * herein except pursuant to this license grant from Synopsys. If you
++ * do not agree with this notice, including the disclaimer below, then
++ * you are not authorized to use the Software.
++ *
++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
++ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
++ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
++ * DAMAGE.
++ * ========================================================================= */
++
++/** @file
++ * This file contains the WUSB cryptographic routines.
++ */
++
++#include "dwc_crypto.h"
++#include "usb.h"
++
++#ifdef DEBUG
++static inline void dump_bytes(char *name, uint8_t *bytes, int len)
++{
++      int i;
++      DWC_PRINTF("%s: ", name);
++      for (i=0; i<len; i++) {
++              DWC_PRINTF("%02x ", bytes[i]);
++      }
++      DWC_PRINTF("\n");
++}
++#else
++#define dump_bytes(x...)
++#endif
++
++/* Display a block */
++void show_block(const u8 *blk, const char *prefix, const char *suffix, int a)
++{
++#ifdef DEBUG_CRYPTO
++      int i, blksize = 16;
++
++      DWC_DEBUG("%s", prefix);
++
++      if (suffix == NULL) {
++              suffix = "\n";
++              blksize = a;
++      }
++
++      for (i = 0; i < blksize; i++)
++              DWC_PRINT("%02x%s", *blk++, ((i & 3) == 3) ? "  " : " ");
++      DWC_PRINT(suffix);
++
++#endif
++}
++
++/**
++ * Encrypts an array of bytes using the AES encryption engine.
++ * If <code>dst</code> == <code>src</code>, then the bytes will be encrypted
++ * in-place.
++ *
++ * @return  0 on success, negative error code on error.
++ */
++int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst)
++{
++      u8 block_t[16];
++      DWC_MEMSET(block_t, 0, 16);
++
++      return DWC_AES_CBC(src, 16, key, 16, block_t, dst);
++}
++
++/**
++ * The CCM-MAC-FUNCTION described in section 6.5 of the WUSB spec.
++ * This function takes a data string and returns the encrypted CBC
++ * Counter-mode MIC.
++ *
++ * @param key     The 128-bit symmetric key.
++ * @param nonce   The CCM nonce.
++ * @param label   The unique 14-byte ASCII text label.
++ * @param bytes   The byte array to be encrypted.
++ * @param len     Length of the byte array.
++ * @param result  Byte array to receive the 8-byte encrypted MIC.
++ */
++void dwc_wusb_cmf(u8 *key, u8 *nonce,
++                char *label, u8 *bytes, int len, u8 *result)
++{
++      u8 block_m[16];
++      u8 block_x[16];
++      u8 block_t[8];
++      int idx, blkNum;
++      u16 la = (u16)(len + 14);
++
++      /* Set the AES-128 key */
++      //dwc_aes_setkey(tfm, key, 16);
++
++      /* Fill block B0 from flags = 0x59, N, and l(m) = 0 */
++      block_m[0] = 0x59;
++      for (idx = 0; idx < 13; idx++)
++              block_m[idx + 1] = nonce[idx];
++      block_m[14] = 0;
++      block_m[15] = 0;
++
++      /* Produce the CBC IV */
++      dwc_wusb_aes_encrypt(block_m, key, block_x);
++      show_block(block_m, "CBC IV in: ", "\n", 0);
++      show_block(block_x, "CBC IV out:", "\n", 0);
++
++      /* Fill block B1 from l(a) = Blen + 14, and A */
++      block_x[0] ^= (u8)(la >> 8);
++      block_x[1] ^= (u8)la;
++      for (idx = 0; idx < 14; idx++)
++              block_x[idx + 2] ^= label[idx];
++      show_block(block_x, "After xor: ", "b1\n", 16);
++
++      dwc_wusb_aes_encrypt(block_x, key, block_x);
++      show_block(block_x, "After AES: ", "b1\n", 16);
++
++      idx = 0;
++      blkNum = 0;
++
++      /* Fill remaining blocks with B */
++      while (len-- > 0) {
++              block_x[idx] ^= *bytes++;
++              if (++idx >= 16) {
++                      idx = 0;
++                      show_block(block_x, "After xor: ", "\n", blkNum);
++                      dwc_wusb_aes_encrypt(block_x, key, block_x);
++                      show_block(block_x, "After AES: ", "\n", blkNum);
++                      blkNum++;
++              }
++      }
++
++      /* Handle partial last block */
++      if (idx > 0) {
++              show_block(block_x, "After xor: ", "\n", blkNum);
++              dwc_wusb_aes_encrypt(block_x, key, block_x);
++              show_block(block_x, "After AES: ", "\n", blkNum);
++      }
++
++      /* Save the MIC tag */
++      DWC_MEMCPY(block_t, block_x, 8);
++      show_block(block_t, "MIC tag  : ", NULL, 8);
++
++      /* Fill block A0 from flags = 0x01, N, and counter = 0 */
++      block_m[0] = 0x01;
++      block_m[14] = 0;
++      block_m[15] = 0;
++
++      /* Encrypt the counter */
++      dwc_wusb_aes_encrypt(block_m, key, block_x);
++      show_block(block_x, "CTR[MIC] : ", NULL, 8);
++
++      /* XOR with MIC tag */
++      for (idx = 0; idx < 8; idx++) {
++              block_t[idx] ^= block_x[idx];
++      }
++
++      /* Return result to caller */
++      DWC_MEMCPY(result, block_t, 8);
++      show_block(result, "CCM-MIC  : ", NULL, 8);
++
++}
++
++/**
++ * The PRF function described in section 6.5 of the WUSB spec. This function
++ * concatenates MIC values returned from dwc_cmf() to create a value of
++ * the requested length.
++ *
++ * @param prf_len  Length of the PRF function in bits (64, 128, or 256).
++ * @param key, nonce, label, bytes, len  Same as for dwc_cmf().
++ * @param result   Byte array to receive the result.
++ */
++void dwc_wusb_prf(int prf_len, u8 *key,
++                u8 *nonce, char *label, u8 *bytes, int len, u8 *result)
++{
++      int i;
++
++      nonce[0] = 0;
++      for (i = 0; i < prf_len >> 6; i++, nonce[0]++) {
++              dwc_wusb_cmf(key, nonce, label, bytes, len, result);
++              result += 8;
++      }
++}
++
++/**
++ * Fills in CCM Nonce per the WUSB spec.
++ *
++ * @param[in] haddr Host address.
++ * @param[in] daddr Device address.
++ * @param[in] tkid Session Key(PTK) identifier.
++ * @param[out] nonce Pointer to where the CCM Nonce output is to be written.
++ */
++void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,
++                           uint8_t *nonce)
++{
++
++      DWC_DEBUG("%s %x %x\n", __func__, daddr, haddr);
++
++      DWC_MEMSET(&nonce[0], 0, 16);
++
++      DWC_MEMCPY(&nonce[6], tkid, 3);
++      nonce[9] = daddr & 0xFF;
++      nonce[10] = (daddr >> 8) & 0xFF;
++      nonce[11] = haddr & 0xFF;
++      nonce[12] = (haddr >> 8) & 0xFF;
++
++      dump_bytes("CCM nonce", nonce, 16);
++}
++
++/**
++ * Generates a 16-byte cryptographic-grade random number for the Host/Device
++ * Nonce.
++ */
++void dwc_wusb_gen_nonce(uint16_t addr, uint8_t *nonce)
++{
++      uint8_t inonce[16];
++      uint32_t temp[4];
++
++      /* Fill in the Nonce */
++      DWC_MEMSET(&inonce[0], 0, sizeof(inonce));
++      inonce[9] = addr & 0xFF;
++      inonce[10] = (addr >> 8) & 0xFF;
++      inonce[11] = inonce[9];
++      inonce[12] = inonce[10];
++
++      /* Collect "randomness samples" */
++      DWC_RANDOM_BYTES((uint8_t *)temp, 16);
++
++      dwc_wusb_prf_128((uint8_t *)temp, nonce,
++                       "Random Numbers", (uint8_t *)temp, sizeof(temp),
++                       nonce);
++}
++
++/**
++ * Generates the Session Key (PTK) and Key Confirmation Key (KCK) per the
++ * WUSB spec.
++ *
++ * @param[in] ccm_nonce Pointer to CCM Nonce.
++ * @param[in] mk Master Key to derive the session from
++ * @param[in] hnonce Pointer to Host Nonce.
++ * @param[in] dnonce Pointer to Device Nonce.
++ * @param[out] kck Pointer to where the KCK output is to be written.
++ * @param[out] ptk Pointer to where the PTK output is to be written.
++ */
++void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, uint8_t *hnonce,
++                    uint8_t *dnonce, uint8_t *kck, uint8_t *ptk)
++{
++      uint8_t idata[32];
++      uint8_t odata[32];
++
++      dump_bytes("ck", mk, 16);
++      dump_bytes("hnonce", hnonce, 16);
++      dump_bytes("dnonce", dnonce, 16);
++
++      /* The data is the HNonce and DNonce concatenated */
++      DWC_MEMCPY(&idata[0], hnonce, 16);
++      DWC_MEMCPY(&idata[16], dnonce, 16);
++
++      dwc_wusb_prf_256(mk, ccm_nonce, "Pair-wise keys", idata, 32, odata);
++
++      /* Low 16 bytes of the result is the KCK, high 16 is the PTK */
++      DWC_MEMCPY(kck, &odata[0], 16);
++      DWC_MEMCPY(ptk, &odata[16], 16);
++
++      dump_bytes("kck", kck, 16);
++      dump_bytes("ptk", ptk, 16);
++}
++
++/**
++ * Generates the Message Integrity Code over the Handshake data per the
++ * WUSB spec.
++ *
++ * @param ccm_nonce Pointer to CCM Nonce.
++ * @param kck   Pointer to Key Confirmation Key.
++ * @param data  Pointer to Handshake data to be checked.
++ * @param mic   Pointer to where the MIC output is to be written.
++ */
++void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t *kck,
++                    uint8_t *data, uint8_t *mic)
++{
++
++      dwc_wusb_prf_64(kck, ccm_nonce, "out-of-bandMIC",
++                      data, WUSB_HANDSHAKE_LEN_FOR_MIC, mic);
++}
++
+--- /dev/null
++++ b/drivers/usb/host/dwc_common_port/dwc_crypto.h
+@@ -0,0 +1,103 @@
++/* =========================================================================
++ * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_crypto.h $
++ * $Revision: #1 $
++ * $Date: 2008/12/21 $
++ * $Change: 1156609 $
++ *
++ * Synopsys Portability Library Software and documentation
++ * (hereinafter, "Software") is an Unsupported proprietary work of
++ * Synopsys, Inc. unless otherwise expressly agreed to in writing
++ * between Synopsys and you.
++ *
++ * The Software IS NOT an item of Licensed Software or Licensed Product
++ * under any End User Software License Agreement or Agreement for
++ * Licensed Product with Synopsys or any supplement thereto. You are
++ * permitted to use and redistribute this Software in source and binary
++ * forms, with or without modification, provided that redistributions
++ * of source code must retain this notice. You may not view, use,
++ * disclose, copy or distribute this file or any information contained
++ * herein except pursuant to this license grant from Synopsys. If you
++ * do not agree with this notice, including the disclaimer below, then
++ * you are not authorized to use the Software.
++ *
++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
++ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
++ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
++ * DAMAGE.
++ * ========================================================================= */
++
++#ifndef _DWC_CRYPTO_H_
++#define _DWC_CRYPTO_H_
++
++/** @file
++ *
++ * This file contains declarations for the WUSB Cryptographic routines as
++ * defined in the WUSB spec.  They are only to be used internally by the DWC UWB
++ * modules.
++ */
++
++#include "dwc_os.h"
++
++int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst);
++
++void dwc_wusb_cmf(u8 *key, u8 *nonce,
++                char *label, u8 *bytes, int len, u8 *result);
++void dwc_wusb_prf(int prf_len, u8 *key,
++                u8 *nonce, char *label, u8 *bytes, int len, u8 *result);
++
++/**
++ * The PRF-64 function described in section 6.5 of the WUSB spec.
++ *
++ * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().
++ */
++static inline void dwc_wusb_prf_64(u8 *key, u8 *nonce,
++                                 char *label, u8 *bytes, int len, u8 *result)
++{
++      dwc_wusb_prf(64, key, nonce, label, bytes, len, result);
++}
++
++/**
++ * The PRF-128 function described in section 6.5 of the WUSB spec.
++ *
++ * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().
++ */
++static inline void dwc_wusb_prf_128(u8 *key, u8 *nonce,
++                                  char *label, u8 *bytes, int len, u8 *result)
++{
++      dwc_wusb_prf(128, key, nonce, label, bytes, len, result);
++}
++
++/**
++ * The PRF-256 function described in section 6.5 of the WUSB spec.
++ *
++ * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().
++ */
++static inline void dwc_wusb_prf_256(u8 *key, u8 *nonce,
++                                  char *label, u8 *bytes, int len, u8 *result)
++{
++      dwc_wusb_prf(256, key, nonce, label, bytes, len, result);
++}
++
++
++void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,
++                             uint8_t *nonce);
++void dwc_wusb_gen_nonce(uint16_t addr,
++                        uint8_t *nonce);
++
++void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk,
++                      uint8_t *hnonce, uint8_t *dnonce,
++                      uint8_t *kck, uint8_t *ptk);
++
++
++void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t
++                      *kck, uint8_t *data, uint8_t *mic);
++
++#endif /* _DWC_CRYPTO_H_ */
+--- /dev/null
++++ b/drivers/usb/host/dwc_common_port/dwc_dh.c
+@@ -0,0 +1,286 @@
++/* =========================================================================
++ * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_dh.c $
++ * $Revision: #1 $
++ * $Date: 2008/12/21 $
++ * $Change: 1156609 $
++ *
++ * Synopsys Portability Library Software and documentation
++ * (hereinafter, "Software") is an Unsupported proprietary work of
++ * Synopsys, Inc. unless otherwise expressly agreed to in writing
++ * between Synopsys and you.
++ *
++ * The Software IS NOT an item of Licensed Software or Licensed Product
++ * under any End User Software License Agreement or Agreement for
++ * Licensed Product with Synopsys or any supplement thereto. You are
++ * permitted to use and redistribute this Software in source and binary
++ * forms, with or without modification, provided that redistributions
++ * of source code must retain this notice. You may not view, use,
++ * disclose, copy or distribute this file or any information contained
++ * herein except pursuant to this license grant from Synopsys. If you
++ * do not agree with this notice, including the disclaimer below, then
++ * you are not authorized to use the Software.
++ *
++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
++ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
++ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
++ * DAMAGE.
++ * ========================================================================= */
++#ifndef CONFIG_MACH_IPMATE
++#include "dwc_dh.h"
++#include "dwc_modpow.h"
++
++#ifdef DEBUG
++/* This function prints out a buffer in the format described in the Association
++ * Model specification. */
++static void dh_dump(char *str, void *_num, int len)
++{
++      uint8_t *num = _num;
++      int i;
++      DWC_PRINTF("%s\n", str);
++      for (i = 0; i < len; i ++) {
++              DWC_PRINTF("%02x", num[i]);
++              if (((i + 1) % 2) == 0) DWC_PRINTF(" ");
++              if (((i + 1) % 26) == 0) DWC_PRINTF("\n");
++      }
++
++      DWC_PRINTF("\n");
++}
++#else
++#define dh_dump(_x...) do {; } while(0)
++#endif
++
++/* Constant g value */
++static __u32 dh_g[] = {
++      0x02000000,
++};
++
++/* Constant p value */
++static __u32 dh_p[] = {
++      0xFFFFFFFF, 0xFFFFFFFF, 0xA2DA0FC9, 0x34C26821, 0x8B62C6C4, 0xD11CDC80, 0x084E0229, 0x74CC678A,
++      0xA6BE0B02, 0x229B133B, 0x79084A51, 0xDD04348E, 0xB31995EF, 0x1B433ACD, 0x6D0A2B30, 0x37145FF2,
++      0x6D35E14F, 0x45C2516D, 0x76B585E4, 0xC67E5E62, 0xE9424CF4, 0x6BED37A6, 0xB65CFF0B, 0xEDB706F4,
++      0xFB6B38EE, 0xA59F895A, 0x11249FAE, 0xE61F4B7C, 0x51662849, 0x3D5BE4EC, 0xB87C00C2, 0x05BF63A1,
++      0x3648DA98, 0x9AD3551C, 0xA83F1669, 0x5FCF24FD, 0x235D6583, 0x96ADA3DC, 0x56F3621C, 0xBB528520,
++      0x0729D59E, 0x6D969670, 0x4E350C67, 0x0498BC4A, 0x086C74F1, 0x7C2118CA, 0x465E9032, 0x3BCE362E,
++      0x2C779EE3, 0x03860E18, 0xA283279B, 0x8FA207EC, 0xF05DC5B5, 0xC9524C6F, 0xF6CB2BDE, 0x18175895,
++      0x7C499539, 0xE56A95EA, 0x1826D215, 0x1005FA98, 0x5A8E7215, 0x2DC4AA8A, 0x0D1733AD, 0x337A5004,
++      0xAB2155A8, 0x64BA1CDF, 0x0485FBEC, 0x0AEFDB58, 0x5771EA8A, 0x7D0C065D, 0x850F97B3, 0xC7E4E1A6,
++      0x8CAEF5AB, 0xD73309DB, 0xE0948C1E, 0x9D61254A, 0x26D2E3CE, 0x6BEED21A, 0x06FA2FF1, 0x64088AD9,
++      0x730276D8, 0x646AC83E, 0x182B1F52, 0x0C207B17, 0x5717E1BB, 0x6C5D617A, 0xC0880977, 0xE246D9BA,
++      0xA04FE208, 0x31ABE574, 0xFC5BDB43, 0x8E10FDE0, 0x20D1824B, 0xCAD23AA9, 0xFFFFFFFF, 0xFFFFFFFF,
++};
++
++static void dh_swap_bytes(void *_in, void *_out, uint32_t len)
++{
++      uint8_t *in = _in;
++      uint8_t *out = _out;
++      int i;
++      for (i=0; i<len; i++) {
++              out[i] = in[len-1-i];
++      }
++}
++
++/* Computes the modular exponentiation (num^exp % mod).  num, exp, and mod are
++ * big endian numbers of size len, in bytes.  Each len value must be a multiple
++ * of 4. */
++int dwc_dh_modpow(void *num, uint32_t num_len,
++                       void *exp, uint32_t exp_len,
++                       void *mod, uint32_t mod_len,
++                       void *out)
++{
++      /* modpow() takes little endian numbers.  AM uses big-endian.  This
++       * function swaps bytes of numbers before passing onto modpow. */
++
++      int retval = 0;
++      uint32_t *result;
++
++      uint32_t *bignum_num = DWC_ALLOC(num_len + 4);
++      uint32_t *bignum_exp = DWC_ALLOC(exp_len + 4);
++      uint32_t *bignum_mod = DWC_ALLOC(mod_len + 4);
++
++      dh_swap_bytes(num, &bignum_num[1], num_len);
++      bignum_num[0] = num_len / 4;
++
++      dh_swap_bytes(exp, &bignum_exp[1], exp_len);
++      bignum_exp[0] = exp_len / 4;
++
++      dh_swap_bytes(mod, &bignum_mod[1], mod_len);
++      bignum_mod[0] = mod_len / 4;
++
++      result = dwc_modpow(bignum_num, bignum_exp, bignum_mod);
++      if (!result) {
++              retval = -1;
++              goto dh_modpow_nomem;
++      }
++
++      dh_swap_bytes(&result[1], out, result[0] * 4);
++      DWC_FREE(result);
++
++ dh_modpow_nomem:
++      DWC_FREE(bignum_num);
++      DWC_FREE(bignum_exp);
++      DWC_FREE(bignum_mod);
++      return retval;
++}
++
++
++int dwc_dh_pk(uint8_t nd, uint8_t *exp, uint8_t *pk, uint8_t *hash)
++{
++      int retval;
++      uint8_t m3[385];
++
++#ifndef DH_TEST_VECTORS
++      DWC_RANDOM_BYTES(exp, 32);
++#endif
++
++      /* Compute the pkd */
++      if ((retval = dwc_dh_modpow(dh_g, 4,
++                                        exp, 32,
++                                        dh_p, 384, pk))) {
++              return retval;
++      }
++
++      m3[384] = nd;
++      DWC_MEMCPY(&m3[0], pk, 384);
++      DWC_SHA256(m3, 385, hash);
++
++      dh_dump("PK", pk, 384);
++      dh_dump("SHA-256(M3)", hash, 32);
++      return 0;
++}
++
++int dwc_dh_derive_keys(uint8_t nd, uint8_t *pkh, uint8_t *pkd,
++                           uint8_t *exp, int is_host,
++                           char *dd, uint8_t *ck, uint8_t *kdk)
++{
++      int retval;
++      uint8_t mv[784];
++      uint8_t sha_result[32];
++      uint8_t dhkey[384];
++      uint8_t shared_secret[384];
++      char *message;
++      uint32_t vd;
++
++      uint8_t *pk;
++
++      if (is_host) {
++              pk = pkd;
++      }
++      else {
++              pk = pkh;
++      }
++
++      if ((retval = dwc_dh_modpow(pk, 384,
++                                        exp, 32,
++                                        dh_p, 384, shared_secret))) {
++              return retval;
++      }
++      dh_dump("Shared Secret", shared_secret, 384);
++
++      DWC_SHA256(shared_secret, 384, dhkey);
++      dh_dump("DHKEY", dhkey, 384);
++
++      DWC_MEMCPY(&mv[0], pkd, 384);
++      DWC_MEMCPY(&mv[384], pkh, 384);
++      DWC_MEMCPY(&mv[768], "displayed digest", 16);
++      dh_dump("MV", mv, 784);
++
++      DWC_SHA256(mv, 784, sha_result);
++      dh_dump("SHA-256(MV)", sha_result, 32);
++      dh_dump("First 32-bits of SHA-256(MV)", sha_result, 4);
++
++      dh_swap_bytes(sha_result, &vd, 4);
++#ifdef DEBUG
++      DWC_PRINTF("Vd (decimal) = %d\n", vd);
++#endif
++
++      switch (nd) {
++      case 2:
++              vd = vd % 100;
++              DWC_SPRINTF(dd, "%02d", vd);
++              break;
++      case 3:
++              vd = vd % 1000;
++              DWC_SPRINTF(dd, "%03d", vd);
++              break;
++      case 4:
++              vd = vd % 10000;
++              DWC_SPRINTF(dd, "%04d", vd);
++              break;
++      }
++#ifdef DEBUG
++      DWC_PRINTF("Display Digits: %s\n", dd);
++#endif
++
++      message = "connection key";
++      DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
++      dh_dump("HMAC(SHA-256, DHKey, connection key)", sha_result, 32);
++      DWC_MEMCPY(ck, sha_result, 16);
++
++      message = "key derivation key";
++      DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
++      dh_dump("HMAC(SHA-256, DHKey, key derivation key)", sha_result, 32);
++      DWC_MEMCPY(kdk, sha_result, 32);
++
++      return 0;
++}
++
++
++#ifdef DH_TEST_VECTORS
++
++static __u8 dh_a[] = {
++      0x44, 0x00, 0x51, 0xd6,
++      0xf0, 0xb5, 0x5e, 0xa9,
++      0x67, 0xab, 0x31, 0xc6,
++      0x8a, 0x8b, 0x5e, 0x37,
++      0xd9, 0x10, 0xda, 0xe0,
++      0xe2, 0xd4, 0x59, 0xa4,
++      0x86, 0x45, 0x9c, 0xaa,
++      0xdf, 0x36, 0x75, 0x16,
++};
++
++static __u8 dh_b[] = {
++      0x5d, 0xae, 0xc7, 0x86,
++      0x79, 0x80, 0xa3, 0x24,
++      0x8c, 0xe3, 0x57, 0x8f,
++      0xc7, 0x5f, 0x1b, 0x0f,
++      0x2d, 0xf8, 0x9d, 0x30,
++      0x6f, 0xa4, 0x52, 0xcd,
++      0xe0, 0x7a, 0x04, 0x8a,
++      0xde, 0xd9, 0x26, 0x56,
++};
++
++void dwc_run_dh_test_vectors(void)
++{
++      uint8_t pkd[384];
++      uint8_t pkh[384];
++      uint8_t hashd[32];
++      uint8_t hashh[32];
++      uint8_t ck[16];
++      uint8_t kdk[32];
++      char dd[5];
++
++      DWC_PRINTF("\n\n\nDH_TEST_VECTORS\n\n");
++
++      /* compute the PKd and SHA-256(PKd || Nd) */
++      DWC_PRINTF("Computing PKd\n");
++      dwc_dh_pk(2, dh_a, pkd, hashd);
++
++      /* compute the PKd and SHA-256(PKh || Nd) */
++      DWC_PRINTF("Computing PKh\n");
++      dwc_dh_pk(2, dh_b, pkh, hashh);
++
++      /* compute the dhkey */
++      dwc_dh_derive_keys(2, pkh, pkd, dh_a, 0, dd, ck, kdk);
++}
++#endif /* DH_TEST_VECTORS */
++
++#endif /* CONFIG_IPMATE_MACH */
+--- /dev/null
++++ b/drivers/usb/host/dwc_common_port/dwc_dh.h
+@@ -0,0 +1,98 @@
++/* =========================================================================
++ * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_dh.h $
++ * $Revision: #1 $
++ * $Date: 2008/12/21 $
++ * $Change: 1156609 $
++ *
++ * Synopsys Portability Library Software and documentation
++ * (hereinafter, "Software") is an Unsupported proprietary work of
++ * Synopsys, Inc. unless otherwise expressly agreed to in writing
++ * between Synopsys and you.
++ *
++ * The Software IS NOT an item of Licensed Software or Licensed Product
++ * under any End User Software License Agreement or Agreement for
++ * Licensed Product with Synopsys or any supplement thereto. You are
++ * permitted to use and redistribute this Software in source and binary
++ * forms, with or without modification, provided that redistributions
++ * of source code must retain this notice. You may not view, use,
++ * disclose, copy or distribute this file or any information contained
++ * herein except pursuant to this license grant from Synopsys. If you
++ * do not agree with this notice, including the disclaimer below, then
++ * you are not authorized to use the Software.
++ *
++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
++ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
++ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
++ * DAMAGE.
++ * ========================================================================= */
++#ifndef _DWC_DH_H_
++#define _DWC_DH_H_
++
++#include "dwc_os.h"
++
++/** @file
++ *
++ * This file defines the common functions on device and host for performing
++ * numeric association as defined in the WUSB spec.  They are only to be
++ * used internally by the DWC UWB modules. */
++
++extern int dwc_dh_sha256(uint8_t *message, uint32_t len, uint8_t *out);
++extern int dwc_dh_hmac_sha256(uint8_t *message, uint32_t messagelen,
++                                   uint8_t *key, uint32_t keylen,
++                                   uint8_t *out);
++extern int dwc_dh_modpow(void *num, uint32_t num_len,
++                             void *exp, uint32_t exp_len,
++                             void *mod, uint32_t mod_len,
++                             void *out);
++
++/** Computes PKD or PKH, and SHA-256(PKd || Nd)
++ *
++ * PK = g^exp mod p.
++ *
++ * Input:
++ * Nd = Number of digits on the device.
++ *
++ * Output:
++ * exp = A 32-byte buffer to be filled with a randomly generated number.
++ *       used as either A or B.
++ * pk = A 384-byte buffer to be filled with the PKH or PKD.
++ * hash = A 32-byte buffer to be filled with SHA-256(PK || ND).
++ */
++extern int dwc_dh_pk(uint8_t nd, uint8_t *exp, uint8_t *pkd, uint8_t *hash);
++
++/** Computes the DHKEY, and VD.
++ *
++ * If called from host, then it will comput DHKEY=PKD^exp % p.
++ * If called from device, then it will comput DHKEY=PKH^exp % p.
++ *
++ * Input:
++ * pkd = The PKD value.
++ * pkh = The PKH value.
++ * exp = The A value (if device) or B value (if host) generated in dwc_wudev_dh_pk.
++ * is_host = Set to non zero if a WUSB host is calling this function.
++ *
++ * Output:
++
++ * dd = A pointer to an buffer to be set to the displayed digits string to be shown
++ *      to the user.  This buffer should be at 5 bytes long to hold 4 digits plus a
++ *      null termination character.  This buffer can be used directly for display.
++ * ck = A 16-byte buffer to be filled with the CK.
++ * kdk = A 32-byte buffer to be filled with the KDK.
++ */
++extern int dwc_dh_derive_keys(uint8_t nd, uint8_t *pkh, uint8_t *pkd,
++                            uint8_t *exp, int is_host,
++                            char *dd, uint8_t *ck, uint8_t *kdk);
++
++#ifdef DH_TEST_VECTORS
++extern void dwc_run_dh_test_vectors(void);
++#endif
++
++#endif /* _DWC_DH_H_ */
+--- /dev/null
++++ b/drivers/usb/host/dwc_common_port/dwc_list.h
+@@ -0,0 +1,616 @@
++/*    $OpenBSD: queue.h,v 1.26 2004/05/04 16:59:32 grange Exp $       */
++/*    $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $       */
++
++/*
++ * Copyright (c) 1991, 1993
++ *    The Regents of the University of California.  All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. Neither the name of the University nor the names of its contributors
++ *    may be used to endorse or promote products derived from this software
++ *    without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++ *    @(#)queue.h     8.5 (Berkeley) 8/20/94
++ */
++
++#ifndef       _SYS_QUEUE_H_
++#define       _SYS_QUEUE_H_
++
++
++/** @file
++ *
++ * This file defines linked list operations.  It is derived from BSD with
++ * only the MACRO names being prefixed with DWC_.  This is because a few of
++ * these names conflict with those on Linux.  For documentation on use, see the
++ * inline comments in the source code.  The original license for this source
++ * code applies and is preserved in the dwc_list.h source file.
++ */
++
++/*
++ * This file defines five types of data structures: singly-linked lists, 
++ * lists, simple queues, tail queues, and circular queues.
++ *
++ *
++ * A singly-linked list is headed by a single forward pointer. The elements
++ * are singly linked for minimum space and pointer manipulation overhead at
++ * the expense of O(n) removal for arbitrary elements. New elements can be
++ * added to the list after an existing element or at the head of the list.
++ * Elements being removed from the head of the list should use the explicit
++ * macro for this purpose for optimum efficiency. A singly-linked list may
++ * only be traversed in the forward direction.  Singly-linked lists are ideal
++ * for applications with large datasets and few or no removals or for
++ * implementing a LIFO queue.
++ *
++ * A list is headed by a single forward pointer (or an array of forward
++ * pointers for a hash table header). The elements are doubly linked
++ * so that an arbitrary element can be removed without a need to
++ * traverse the list. New elements can be added to the list before
++ * or after an existing element or at the head of the list. A list
++ * may only be traversed in the forward direction.
++ *
++ * A simple queue is headed by a pair of pointers, one the head of the
++ * list and the other to the tail of the list. The elements are singly
++ * linked to save space, so elements can only be removed from the
++ * head of the list. New elements can be added to the list before or after
++ * an existing element, at the head of the list, or at the end of the
++ * list. A simple queue may only be traversed in the forward direction.
++ * 
++ * A tail queue is headed by a pair of pointers, one to the head of the
++ * list and the other to the tail of the list. The elements are doubly
++ * linked so that an arbitrary element can be removed without a need to
++ * traverse the list. New elements can be added to the list before or
++ * after an existing element, at the head of the list, or at the end of
++ * the list. A tail queue may be traversed in either direction.
++ *
++ * A circle queue is headed by a pair of pointers, one to the head of the
++ * list and the other to the tail of the list. The elements are doubly
++ * linked so that an arbitrary element can be removed without a need to
++ * traverse the list. New elements can be added to the list before or after
++ * an existing element, at the head of the list, or at the end of the list.
++ * A circle queue may be traversed in either direction, but has a more
++ * complex end of list detection.
++ *
++ * For details on the use of these macros, see the queue(3) manual page.
++ */
++
++/*
++ * Double-linked List.
++ */
++
++typedef struct dwc_list_link {
++      struct dwc_list_link *next;
++      struct dwc_list_link *prev;
++} dwc_list_link_t;
++
++#define DWC_LIST_INIT(link) do{               \
++      (link)->next = (link);          \
++      (link)->prev = (link);          \
++} while(0)
++
++#define DWC_LIST_FIRST(link)  ((link)->next)
++#define DWC_LIST_LAST(link)   ((link)->prev)
++#define DWC_LIST_END(link)    (link)
++#define DWC_LIST_NEXT(link)   ((link)->next)
++#define DWC_LIST_PREV(link)   ((link)->prev)
++#define DWC_LIST_EMPTY(link)  \
++      (DWC_LIST_FIRST(link) == DWC_LIST_END(link))
++#define DWC_LIST_ENTRY(link, type, field) (type *)            \
++      ((uint8_t *)(link) - (size_t)(&((type *)0)->field))
++
++#define DWC_LIST_INSERT_HEAD(list, link) do {                 \
++      (link)->next = (list)->next;                            \
++      (link)->prev = (list);                                  \
++      (list)->next->prev = link;                              \
++      (list)->next = link;                                    \
++} while(0)
++
++#define DWC_LIST_INSERT_TAIL(list, link) do {                 \
++      (link)->next = list;                                    \
++      (link)->prev = (list)->prev;                            \
++      (list)->prev->next = link;                              \
++      (list)->prev = link;                                    \
++} while(0)
++
++#define DWC_LIST_REMOVE(link) do {                            \
++      (link)->next->prev = (link)->prev;                      \
++      (link)->prev->next = (link)->next;                      \
++} while(0)
++
++#define DWC_LIST_REMOVE_INIT(link) do {                               \
++      DWC_LIST_REMOVE(link);                                  \
++      DWC_LIST_INIT(link);                                    \
++} while(0)
++
++#define DWC_LIST_MOVE_HEAD(list, link) do {                   \
++      DWC_LIST_REMOVE(link);                                  \
++      DWC_LIST_INSERT_HEAD(list, link);                       \
++} while(0)
++
++#define DWC_LIST_MOVE_TAIL(list, link) do {                   \
++      DWC_LIST_REMOVE(link);                                  \
++      DWC_LIST_INSERT_TAIL(list, link);                       \
++} while(0)
++
++#define DWC_LIST_FOREACH(var, list)                           \
++      for((var) = DWC_LIST_FIRST(list);                       \
++          (var) != DWC_LIST_END(list);                        \
++          (var) = DWC_LIST_NEXT(var))
++
++#define DWC_LIST_FOREACH_SAFE(var, var2, list)                        \
++      for((var) = DWC_LIST_FIRST(list), var2 = DWC_LIST_NEXT(var);    \
++          (var) != DWC_LIST_END(list);                        \
++          (var) = (var2), var2 = DWC_LIST_NEXT(var2))
++
++#define DWC_LIST_FOREACH_REVERSE(var, list)                   \
++      for((var) = DWC_LIST_LAST(list);                        \
++          (var) != DWC_LIST_END(list);                        \
++          (var) = DWC_LIST_PREV(var))
++
++/*
++ * Singly-linked List definitions.
++ */
++#define DWC_SLIST_HEAD(name, type)                                    \
++struct name {                                                         \
++      struct type *slh_first; /* first element */                     \
++}
++ 
++#define       DWC_SLIST_HEAD_INITIALIZER(head)                                        \
++      { NULL }
++ 
++#define DWC_SLIST_ENTRY(type)                                         \
++struct {                                                              \
++      struct type *sle_next;  /* next element */                      \
++}
++ 
++/*
++ * Singly-linked List access methods.
++ */
++#define DWC_SLIST_FIRST(head) ((head)->slh_first)
++#define DWC_SLIST_END(head)           NULL
++#define DWC_SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
++#define DWC_SLIST_NEXT(elm, field)    ((elm)->field.sle_next)
++
++#define DWC_SLIST_FOREACH(var, head, field)                                   \
++      for((var) = SLIST_FIRST(head);                                  \
++          (var) != SLIST_END(head);                                   \
++          (var) = SLIST_NEXT(var, field))
++
++#define DWC_SLIST_FOREACH_PREVPTR(var, varp, head, field)                     \
++      for ((varp) = &SLIST_FIRST((head));                             \
++          ((var) = *(varp)) != SLIST_END(head);                       \
++          (varp) = &SLIST_NEXT((var), field))
++
++/*
++ * Singly-linked List functions.
++ */
++#define DWC_SLIST_INIT(head) {                                                \
++      SLIST_FIRST(head) = SLIST_END(head);                            \
++}
++
++#define DWC_SLIST_INSERT_AFTER(slistelm, elm, field) do {                     \
++      (elm)->field.sle_next = (slistelm)->field.sle_next;             \
++      (slistelm)->field.sle_next = (elm);                             \
++} while (0)
++
++#define DWC_SLIST_INSERT_HEAD(head, elm, field) do {                  \
++      (elm)->field.sle_next = (head)->slh_first;                      \
++      (head)->slh_first = (elm);                                      \
++} while (0)
++
++#define DWC_SLIST_REMOVE_NEXT(head, elm, field) do {                  \
++      (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next;  \
++} while (0)
++
++#define DWC_SLIST_REMOVE_HEAD(head, field) do {                               \
++      (head)->slh_first = (head)->slh_first->field.sle_next;          \
++} while (0)
++
++#define DWC_SLIST_REMOVE(head, elm, type, field) do {                 \
++      if ((head)->slh_first == (elm)) {                               \
++              SLIST_REMOVE_HEAD((head), field);                       \
++      }                                                               \
++      else {                                                          \
++              struct type *curelm = (head)->slh_first;                \
++              while( curelm->field.sle_next != (elm) )                \
++                      curelm = curelm->field.sle_next;                \
++              curelm->field.sle_next =                                \
++                  curelm->field.sle_next->field.sle_next;             \
++      }                                                               \
++} while (0)
++
++#if 0
++
++/*
++ * List definitions.
++ */
++#define DWC_LIST_HEAD(name, type)                                             \
++struct name {                                                         \
++      struct type *lh_first;  /* first element */                     \
++}
++
++#define DWC_LIST_HEAD_INITIALIZER(head)                                       \
++      { NULL }
++
++#define DWC_LIST_ENTRY(type)                                          \
++struct {                                                              \
++      struct type *le_next;   /* next element */                      \
++      struct type **le_prev;  /* address of previous next element */  \
++}
++
++/*
++ * List access methods
++ */
++#define DWC_LIST_FIRST(head)          ((head)->lh_first)
++#define DWC_LIST_END(head)                    NULL
++#define DWC_LIST_EMPTY(head)          (DWC_LIST_FIRST(head) == DWC_LIST_END(head))
++#define DWC_LIST_NEXT(elm, field)             ((elm)->field.le_next)
++
++#define DWC_LIST_FOREACH(var, head, field)                                    \
++      for((var) = DWC_LIST_FIRST(head);                                       \
++          (var)!= DWC_LIST_END(head);                                 \
++          (var) = DWC_LIST_NEXT(var, field))
++#define DWC_LIST_FOREACH_SAFE(var, var2, head, field)                         \
++      for((var) = DWC_LIST_FIRST(head), var2 = DWC_LIST_NEXT(var, field);                             \
++          (var) != DWC_LIST_END(head);                                        \
++          (var) = var2, var2 = DWC_LIST_NEXT(var, field))
++
++/*
++ * List functions.
++ */
++#define DWC_LIST_INIT(head) do {                                              \
++      DWC_LIST_FIRST(head) = DWC_LIST_END(head);                              \
++} while (0)
++
++#define DWC_LIST_INSERT_AFTER(listelm, elm, field) do {                       \
++      if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)  \
++              (listelm)->field.le_next->field.le_prev =               \
++                  &(elm)->field.le_next;                              \
++      (listelm)->field.le_next = (elm);                               \
++      (elm)->field.le_prev = &(listelm)->field.le_next;               \
++} while (0)
++
++#define DWC_LIST_INSERT_BEFORE(listelm, elm, field) do {                      \
++      (elm)->field.le_prev = (listelm)->field.le_prev;                \
++      (elm)->field.le_next = (listelm);                               \
++      *(listelm)->field.le_prev = (elm);                              \
++      (listelm)->field.le_prev = &(elm)->field.le_next;               \
++} while (0)
++
++#define DWC_LIST_INSERT_HEAD(head, elm, field) do {                           \
++      if (((elm)->field.le_next = (head)->lh_first) != NULL)          \
++              (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
++      (head)->lh_first = (elm);                                       \
++      (elm)->field.le_prev = &(head)->lh_first;                       \
++} while (0)
++
++#define DWC_LIST_REMOVE(elm, field) do {                                      \
++      if ((elm)->field.le_next != NULL)                               \
++              (elm)->field.le_next->field.le_prev =                   \
++                  (elm)->field.le_prev;                               \
++      *(elm)->field.le_prev = (elm)->field.le_next;                   \
++} while (0)
++
++#define DWC_LIST_REPLACE(elm, elm2, field) do {                               \
++      if (((elm2)->field.le_next = (elm)->field.le_next) != NULL)     \
++              (elm2)->field.le_next->field.le_prev =                  \
++                  &(elm2)->field.le_next;                             \
++      (elm2)->field.le_prev = (elm)->field.le_prev;                   \
++      *(elm2)->field.le_prev = (elm2);                                \
++} while (0)
++
++#endif
++
++/*
++ * Simple queue definitions.
++ */
++#define DWC_SIMPLEQ_HEAD(name, type)                                  \
++struct name {                                                         \
++      struct type *sqh_first; /* first element */                     \
++      struct type **sqh_last; /* addr of last next element */         \
++}
++
++#define DWC_SIMPLEQ_HEAD_INITIALIZER(head)                                    \
++      { NULL, &(head).sqh_first }
++
++#define DWC_SIMPLEQ_ENTRY(type)                                               \
++struct {                                                              \
++      struct type *sqe_next;  /* next element */                      \
++}
++
++/*
++ * Simple queue access methods.
++ */
++#define DWC_SIMPLEQ_FIRST(head)           ((head)->sqh_first)
++#define DWC_SIMPLEQ_END(head)     NULL
++#define DWC_SIMPLEQ_EMPTY(head)           (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
++#define DWC_SIMPLEQ_NEXT(elm, field)    ((elm)->field.sqe_next)
++
++#define DWC_SIMPLEQ_FOREACH(var, head, field)                         \
++      for((var) = SIMPLEQ_FIRST(head);                                \
++          (var) != SIMPLEQ_END(head);                                 \
++          (var) = SIMPLEQ_NEXT(var, field))
++
++/*
++ * Simple queue functions.
++ */
++#define DWC_SIMPLEQ_INIT(head) do {                                           \
++      (head)->sqh_first = NULL;                                       \
++      (head)->sqh_last = &(head)->sqh_first;                          \
++} while (0)
++
++#define DWC_SIMPLEQ_INSERT_HEAD(head, elm, field) do {                        \
++      if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)        \
++              (head)->sqh_last = &(elm)->field.sqe_next;              \
++      (head)->sqh_first = (elm);                                      \
++} while (0)
++
++#define DWC_SIMPLEQ_INSERT_TAIL(head, elm, field) do {                        \
++      (elm)->field.sqe_next = NULL;                                   \
++      *(head)->sqh_last = (elm);                                      \
++      (head)->sqh_last = &(elm)->field.sqe_next;                      \
++} while (0)
++
++#define DWC_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {              \
++      if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
++              (head)->sqh_last = &(elm)->field.sqe_next;              \
++      (listelm)->field.sqe_next = (elm);                              \
++} while (0)
++
++#define DWC_SIMPLEQ_REMOVE_HEAD(head, field) do {                     \
++      if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
++              (head)->sqh_last = &(head)->sqh_first;                  \
++} while (0)
++
++/*
++ * Tail queue definitions.
++ */
++#define DWC_TAILQ_HEAD(name, type)                                            \
++struct name {                                                         \
++      struct type *tqh_first; /* first element */                     \
++      struct type **tqh_last; /* addr of last next element */         \
++}
++
++#define DWC_TAILQ_HEAD_INITIALIZER(head)                                      \
++      { NULL, &(head).tqh_first }
++
++#define DWC_TAILQ_ENTRY(type)                                         \
++struct {                                                              \
++      struct type *tqe_next;  /* next element */                      \
++      struct type **tqe_prev; /* address of previous next element */  \
++}
++
++/* 
++ * tail queue access methods 
++ */
++#define DWC_TAILQ_FIRST(head)         ((head)->tqh_first)
++#define DWC_TAILQ_END(head)                   NULL
++#define DWC_TAILQ_NEXT(elm, field)            ((elm)->field.tqe_next)
++#define DWC_TAILQ_LAST(head, headname)                                        \
++      (*(((struct headname *)((head)->tqh_last))->tqh_last))
++/* XXX */
++#define DWC_TAILQ_PREV(elm, headname, field)                          \
++      (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
++#define DWC_TAILQ_EMPTY(head)                                         \
++      (TAILQ_FIRST(head) == TAILQ_END(head))
++
++#define DWC_TAILQ_FOREACH(var, head, field)                                   \
++      for((var) = TAILQ_FIRST(head);                                  \
++          (var) != TAILQ_END(head);                                   \
++          (var) = TAILQ_NEXT(var, field))
++
++#define DWC_TAILQ_FOREACH_REVERSE(var, head, headname, field)         \
++      for((var) = TAILQ_LAST(head, headname);                         \
++          (var) != TAILQ_END(head);                                   \
++          (var) = TAILQ_PREV(var, headname, field))
++
++/*
++ * Tail queue functions.
++ */
++#define DWC_TAILQ_INIT(head) do {                                             \
++      (head)->tqh_first = NULL;                                       \
++      (head)->tqh_last = &(head)->tqh_first;                          \
++} while (0)
++
++#define DWC_TAILQ_INSERT_HEAD(head, elm, field) do {                  \
++      if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)        \
++              (head)->tqh_first->field.tqe_prev =                     \
++                  &(elm)->field.tqe_next;                             \
++      else                                                            \
++              (head)->tqh_last = &(elm)->field.tqe_next;              \
++      (head)->tqh_first = (elm);                                      \
++      (elm)->field.tqe_prev = &(head)->tqh_first;                     \
++} while (0)
++
++#define DWC_TAILQ_INSERT_TAIL(head, elm, field) do {                  \
++      (elm)->field.tqe_next = NULL;                                   \
++      (elm)->field.tqe_prev = (head)->tqh_last;                       \
++      *(head)->tqh_last = (elm);                                      \
++      (head)->tqh_last = &(elm)->field.tqe_next;                      \
++} while (0)
++
++#define DWC_TAILQ_INSERT_AFTER(head, listelm, elm, field) do {                \
++      if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
++              (elm)->field.tqe_next->field.tqe_prev =                 \
++                  &(elm)->field.tqe_next;                             \
++      else                                                            \
++              (head)->tqh_last = &(elm)->field.tqe_next;              \
++      (listelm)->field.tqe_next = (elm);                              \
++      (elm)->field.tqe_prev = &(listelm)->field.tqe_next;             \
++} while (0)
++
++#define DWC_TAILQ_INSERT_BEFORE(listelm, elm, field) do {                     \
++      (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
++      (elm)->field.tqe_next = (listelm);                              \
++      *(listelm)->field.tqe_prev = (elm);                             \
++      (listelm)->field.tqe_prev = &(elm)->field.tqe_next;             \
++} while (0)
++
++#define DWC_TAILQ_REMOVE(head, elm, field) do {                               \
++      if (((elm)->field.tqe_next) != NULL)                            \
++              (elm)->field.tqe_next->field.tqe_prev =                 \
++                  (elm)->field.tqe_prev;                              \
++      else                                                            \
++              (head)->tqh_last = (elm)->field.tqe_prev;               \
++      *(elm)->field.tqe_prev = (elm)->field.tqe_next;                 \
++} while (0)
++
++#define DWC_TAILQ_REPLACE(head, elm, elm2, field) do {                        \
++      if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL)   \
++              (elm2)->field.tqe_next->field.tqe_prev =                \
++                  &(elm2)->field.tqe_next;                            \
++      else                                                            \
++              (head)->tqh_last = &(elm2)->field.tqe_next;             \
++      (elm2)->field.tqe_prev = (elm)->field.tqe_prev;                 \
++      *(elm2)->field.tqe_prev = (elm2);                               \
++} while (0)
++
++/*
++ * Circular queue definitions.
++ */
++#define DWC_CIRCLEQ_HEAD(name, type)                                  \
++struct name {                                                         \
++      struct type *cqh_first;         /* first element */             \
++      struct type *cqh_last;          /* last element */              \
++}
++
++#define DWC_CIRCLEQ_HEAD_INITIALIZER(head)                                    \
++      { DWC_CIRCLEQ_END(&head), DWC_CIRCLEQ_END(&head) }
++
++#define DWC_CIRCLEQ_ENTRY(type)                                               \
++struct {                                                              \
++      struct type *cqe_next;          /* next element */              \
++      struct type *cqe_prev;          /* previous element */          \
++}
++
++/*
++ * Circular queue access methods 
++ */
++#define DWC_CIRCLEQ_FIRST(head)               ((head)->cqh_first)
++#define DWC_CIRCLEQ_LAST(head)                ((head)->cqh_last)
++#define DWC_CIRCLEQ_END(head)         ((void *)(head))
++#define DWC_CIRCLEQ_NEXT(elm, field)  ((elm)->field.cqe_next)
++#define DWC_CIRCLEQ_PREV(elm, field)  ((elm)->field.cqe_prev)
++#define DWC_CIRCLEQ_EMPTY(head)                                               \
++      (DWC_CIRCLEQ_FIRST(head) == DWC_CIRCLEQ_END(head))
++
++#define DWC_CIRCLEQ_EMPTY_ENTRY(elm, field) (((elm)->field.cqe_next == NULL) && ((elm)->field.cqe_prev == NULL))
++
++#define DWC_CIRCLEQ_FOREACH(var, head, field)                         \
++      for((var) = DWC_CIRCLEQ_FIRST(head);                            \
++          (var) != DWC_CIRCLEQ_END(head);                                     \
++          (var) = DWC_CIRCLEQ_NEXT(var, field))
++
++#define DWC_CIRCLEQ_FOREACH_SAFE(var, var2, head, field)                              \
++      for((var) = DWC_CIRCLEQ_FIRST(head), var2 = DWC_CIRCLEQ_NEXT(var, field);                               \
++          (var) != DWC_CIRCLEQ_END(head);                                     \
++          (var) = var2, var2 = DWC_CIRCLEQ_NEXT(var, field))
++
++#define DWC_CIRCLEQ_FOREACH_REVERSE(var, head, field)                 \
++      for((var) = DWC_CIRCLEQ_LAST(head);                                     \
++          (var) != DWC_CIRCLEQ_END(head);                                     \
++          (var) = DWC_CIRCLEQ_PREV(var, field))
++
++/*
++ * Circular queue functions.
++ */
++#define DWC_CIRCLEQ_INIT(head) do {                                           \
++      (head)->cqh_first = DWC_CIRCLEQ_END(head);                              \
++      (head)->cqh_last = DWC_CIRCLEQ_END(head);                               \
++} while (0)
++
++#define DWC_CIRCLEQ_INIT_ENTRY(elm, field) do { \
++      (elm)->field.cqe_next = NULL; \
++      (elm)->field.cqe_prev = NULL; \
++} while (0)
++
++#define DWC_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {              \
++      (elm)->field.cqe_next = (listelm)->field.cqe_next;              \
++      (elm)->field.cqe_prev = (listelm);                              \
++      if ((listelm)->field.cqe_next == DWC_CIRCLEQ_END(head))         \
++              (head)->cqh_last = (elm);                               \
++      else                                                            \
++              (listelm)->field.cqe_next->field.cqe_prev = (elm);      \
++      (listelm)->field.cqe_next = (elm);                              \
++} while (0)
++
++#define DWC_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {             \
++      (elm)->field.cqe_next = (listelm);                              \
++      (elm)->field.cqe_prev = (listelm)->field.cqe_prev;              \
++      if ((listelm)->field.cqe_prev == DWC_CIRCLEQ_END(head))         \
++              (head)->cqh_first = (elm);                              \
++      else                                                            \
++              (listelm)->field.cqe_prev->field.cqe_next = (elm);      \
++      (listelm)->field.cqe_prev = (elm);                              \
++} while (0)
++
++#define DWC_CIRCLEQ_INSERT_HEAD(head, elm, field) do {                        \
++      (elm)->field.cqe_next = (head)->cqh_first;                      \
++      (elm)->field.cqe_prev = DWC_CIRCLEQ_END(head);                  \
++      if ((head)->cqh_last == DWC_CIRCLEQ_END(head))                  \
++              (head)->cqh_last = (elm);                               \
++      else                                                            \
++              (head)->cqh_first->field.cqe_prev = (elm);              \
++      (head)->cqh_first = (elm);                                      \
++} while (0)
++
++#define DWC_CIRCLEQ_INSERT_TAIL(head, elm, field) do {                        \
++      (elm)->field.cqe_next = DWC_CIRCLEQ_END(head);                  \
++      (elm)->field.cqe_prev = (head)->cqh_last;                       \
++      if ((head)->cqh_first == DWC_CIRCLEQ_END(head))                 \
++              (head)->cqh_first = (elm);                              \
++      else                                                            \
++              (head)->cqh_last->field.cqe_next = (elm);               \
++      (head)->cqh_last = (elm);                                       \
++} while (0)
++
++#define DWC_CIRCLEQ_REMOVE(head, elm, field) do {                             \
++      if ((elm)->field.cqe_next == DWC_CIRCLEQ_END(head))                     \
++              (head)->cqh_last = (elm)->field.cqe_prev;               \
++      else                                                            \
++              (elm)->field.cqe_next->field.cqe_prev =                 \
++                  (elm)->field.cqe_prev;                              \
++      if ((elm)->field.cqe_prev == DWC_CIRCLEQ_END(head))                     \
++              (head)->cqh_first = (elm)->field.cqe_next;              \
++      else                                                            \
++              (elm)->field.cqe_prev->field.cqe_next =                 \
++                  (elm)->field.cqe_next;                              \
++} while (0)
++
++#define DWC_CIRCLEQ_REMOVE_INIT(head, elm, field) do { \
++      DWC_CIRCLEQ_REMOVE(head, elm, field); \
++      DWC_CIRCLEQ_INIT_ENTRY(elm, field); \
++} while (0)
++
++#define DWC_CIRCLEQ_REPLACE(head, elm, elm2, field) do {                      \
++      if (((elm2)->field.cqe_next = (elm)->field.cqe_next) ==         \
++          DWC_CIRCLEQ_END(head))                                              \
++              (head).cqh_last = (elm2);                               \
++      else                                                            \
++              (elm2)->field.cqe_next->field.cqe_prev = (elm2);        \
++      if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) ==         \
++          DWC_CIRCLEQ_END(head))                                              \
++              (head).cqh_first = (elm2);                              \
++      else                                                            \
++              (elm2)->field.cqe_prev->field.cqe_next = (elm2);        \
++} while (0)
++
++#endif        /* !_SYS_QUEUE_H_ */
+--- /dev/null
++++ b/drivers/usb/host/dwc_common_port/dwc_mem.c
+@@ -0,0 +1,172 @@
++#include "dwc_os.h"
++#include "dwc_list.h"
++
++/* Memory Debugging */
++#ifdef DEBUG_MEMORY
++
++struct allocation
++{
++      void *addr;
++      char *func;
++      int line;
++      uint32_t size;
++      int dma;
++      DWC_CIRCLEQ_ENTRY(allocation) entry;
++};
++
++DWC_CIRCLEQ_HEAD(allocation_queue, allocation);
++
++struct allocation_manager
++{
++      struct allocation_queue allocations;
++
++      /* statistics */
++      int num;
++      int num_freed;
++      int num_active;
++      uint32_t total;
++      uint32_t current;
++      uint32_t max;
++};
++
++
++static struct allocation_manager *manager = NULL;
++
++static void add_allocation(uint32_t size, char const* func, int line, void *addr, int dma)
++{
++      struct allocation *a = __DWC_ALLOC_ATOMIC(sizeof(*a));
++      a->func = __DWC_ALLOC_ATOMIC(DWC_STRLEN(func)+1);
++      DWC_MEMCPY(a->func, func, DWC_STRLEN(func)+1);
++      a->line = line;
++      a->size = size;
++      a->addr = addr;
++      a->dma = dma;
++      DWC_CIRCLEQ_INSERT_TAIL(&manager->allocations, a, entry);
++
++      /* Update stats */
++      manager->num ++;
++      manager->num_active ++;
++      manager->total += size;
++      manager->current += size;
++      if (manager->max < manager->current) {
++              manager->max = manager->current;
++      }
++}
++
++static struct allocation *find_allocation(void *addr)
++{
++      struct allocation *a;
++      DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
++              if (a->addr == addr) {
++                      return a;
++              }
++      }
++      return NULL;
++}
++
++static void free_allocation(void *addr, char const* func, int line)
++{
++      struct allocation *a = find_allocation(addr);
++      if (!a && func && (line >= 0)) {
++              DWC_ASSERT(0, "Free of address %p that was never allocated or already freed %s:%d", addr, func, line);
++              return;
++      }
++      DWC_CIRCLEQ_REMOVE(&manager->allocations, a, entry);
++
++      manager->num_active --;
++      manager->num_freed ++;
++      manager->current -= a->size;
++      __DWC_FREE(a->func);
++      __DWC_FREE(a);
++}
++
++void dwc_memory_debug_start(void)
++{
++      DWC_ASSERT(manager == NULL, "Memory debugging has already started\n");
++      if (manager == NULL) {
++              manager = __DWC_ALLOC(sizeof(*manager));
++      }
++
++      DWC_CIRCLEQ_INIT(&manager->allocations);
++      manager->num = 0;
++      manager->num_freed = 0;
++      manager->num_active = 0;
++      manager->total = 0;
++      manager->current = 0;
++      manager->max = 0;
++}
++
++void dwc_memory_debug_stop(void)
++{
++      struct allocation *a;
++      dwc_memory_debug_report();
++
++      DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
++              DWC_ERROR("Memory leaked from %s:%d\n", a->func, a->line);
++              free_allocation(a->addr, NULL, -1);
++      }
++
++      __DWC_FREE(manager);
++}
++
++void dwc_memory_debug_report(void)
++{
++      struct allocation *a;
++      DWC_PRINTF("\n\n\n----------------- Memory Debugging Report -----------------\n\n");
++      DWC_PRINTF("Num Allocations = %d\n", manager->num);
++      DWC_PRINTF("Freed = %d\n", manager->num_freed);
++      DWC_PRINTF("Active = %d\n", manager->num_active);
++      DWC_PRINTF("Current Memory Used = %d\n", manager->current);
++      DWC_PRINTF("Total Memory Used = %d\n", manager->total);
++      DWC_PRINTF("Maximum Memory Used at Once = %d\n", manager->max);
++      DWC_PRINTF("Unfreed allocations:\n");
++
++      DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
++              DWC_PRINTF("    addr=%p, size=%d from %s:%d, DMA=%d\n", a->addr, a->size, a->func, a->line, a->dma);
++      }
++}
++
++
++
++/* The replacement functions */
++void *dwc_alloc_debug(uint32_t size, char const* func, int line)
++{
++      void *addr = __DWC_ALLOC(size);
++      add_allocation(size, func, line, addr, 0);
++      return addr;
++}
++
++void *dwc_alloc_atomic_debug(uint32_t size, char const* func, int line)
++{
++      void *addr = __DWC_ALLOC_ATOMIC(size);
++      add_allocation(size, func, line, addr, 0);
++      return addr;
++}
++
++void dwc_free_debug(void *addr, char const* func, int line)
++{
++      free_allocation(addr, func, line);
++      __DWC_FREE(addr);
++}
++
++void *dwc_dma_alloc_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line)
++{
++      void *addr = __DWC_DMA_ALLOC(size, dma_addr);
++      add_allocation(size, func, line, addr, 1);
++      return addr;
++}
++
++void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line)
++{
++      void *addr = __DWC_DMA_ALLOC_ATOMIC(size, dma_addr);
++      add_allocation(size, func, line, addr, 1);
++      return addr;
++}
++
++void dwc_dma_free_debug(uint32_t size, void *virt_addr, dwc_dma_t dma_addr, char const *func, int line)
++{
++      free_allocation(virt_addr, func, line);
++      __DWC_DMA_FREE(size, virt_addr, dma_addr);
++}
++
++#endif /* DEBUG_MEMORY */
+--- /dev/null
++++ b/drivers/usb/host/dwc_common_port/dwc_modpow.c
+@@ -0,0 +1,622 @@
++/* Bignum routines adapted from PUTTY sources.  PuTTY copyright notice follows.
++ *
++ * PuTTY is copyright 1997-2007 Simon Tatham.
++ *
++ * Portions copyright Robert de Bath, Joris van Rantwijk, Delian
++ * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
++ * Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus
++ * Kuhn, and CORE SDI S.A.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be
++ * included in all copies or substantial portions of the Software.
++
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
++ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
++ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++ *
++ */
++
++#ifndef CONFIG_MACH_IPMATE
++
++
++#include "dwc_modpow.h"
++
++#define BIGNUM_INT_MASK  0xFFFFFFFFUL
++#define BIGNUM_TOP_BIT   0x80000000UL
++#define BIGNUM_INT_BITS  32
++
++
++static void *snmalloc(size_t n, size_t size)
++{
++    void *p;
++    size *= n;
++    if (size == 0) size = 1;
++    p = DWC_ALLOC(size);
++    return p;
++}
++
++#define snewn(n, type) ((type *)snmalloc((n), sizeof(type)))
++#define sfree DWC_FREE
++
++/*
++ * Usage notes:
++ *  * Do not call the DIVMOD_WORD macro with expressions such as array
++ *    subscripts, as some implementations object to this (see below).
++ *  * Note that none of the division methods below will cope if the
++ *    quotient won't fit into BIGNUM_INT_BITS. Callers should be careful
++ *    to avoid this case.
++ *    If this condition occurs, in the case of the x86 DIV instruction,
++ *    an overflow exception will occur, which (according to a correspondent)
++ *    will manifest on Windows as something like
++ *      0xC0000095: Integer overflow
++ *    The C variant won't give the right answer, either.
++ */
++
++#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
++
++#if defined __GNUC__ && defined __i386__
++#define DIVMOD_WORD(q, r, hi, lo, w) \
++    __asm__("div %2" : \
++          "=d" (r), "=a" (q) : \
++          "r" (w), "d" (hi), "a" (lo))
++#else
++#define DIVMOD_WORD(q, r, hi, lo, w) do { \
++    BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
++    q = n / w; \
++    r = n % w; \
++} while (0)
++#endif
++
++//    q = n / w;                                
++//    r = n % w;                                
++
++#define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8)
++
++#define BIGNUM_INTERNAL
++
++static Bignum newbn(int length)
++{
++    Bignum b = snewn(length + 1, BignumInt);
++    //if (!b)
++    //abort();                       /* FIXME */
++    DWC_MEMSET(b, 0, (length + 1) * sizeof(*b));
++    b[0] = length;
++    return b;
++}
++
++void freebn(Bignum b)
++{
++    /*
++     * Burn the evidence, just in case.
++     */
++    DWC_MEMSET(b, 0, sizeof(b[0]) * (b[0] + 1));
++    sfree(b);
++}
++
++/*
++ * Compute c = a * b.
++ * Input is in the first len words of a and b.
++ * Result is returned in the first 2*len words of c.
++ */
++static void internal_mul(BignumInt *a, BignumInt *b,
++                       BignumInt *c, int len)
++{
++    int i, j;
++    BignumDblInt t;
++
++    for (j = 0; j < 2 * len; j++)
++      c[j] = 0;
++
++    for (i = len - 1; i >= 0; i--) {
++      t = 0;
++      for (j = len - 1; j >= 0; j--) {
++          t += MUL_WORD(a[i], (BignumDblInt) b[j]);
++          t += (BignumDblInt) c[i + j + 1];
++          c[i + j + 1] = (BignumInt) t;
++          t = t >> BIGNUM_INT_BITS;
++      }
++      c[i] = (BignumInt) t;
++    }
++}
++
++static void internal_add_shifted(BignumInt *number,
++                               unsigned n, int shift)
++{
++    int word = 1 + (shift / BIGNUM_INT_BITS);
++    int bshift = shift % BIGNUM_INT_BITS;
++    BignumDblInt addend;
++
++    addend = (BignumDblInt)n << bshift;
++
++    while (addend) {
++      addend += number[word];
++      number[word] = (BignumInt) addend & BIGNUM_INT_MASK;
++      addend >>= BIGNUM_INT_BITS;
++      word++;
++    }
++}
++
++/*
++ * Compute a = a % m.
++ * Input in first alen words of a and first mlen words of m.
++ * Output in first alen words of a
++ * (of which first alen-mlen words will be zero).
++ * The MSW of m MUST have its high bit set.
++ * Quotient is accumulated in the `quotient' array, which is a Bignum
++ * rather than the internal bigendian format. Quotient parts are shifted
++ * left by `qshift' before adding into quot.
++ */
++static void internal_mod(BignumInt *a, int alen,
++                       BignumInt *m, int mlen,
++                       BignumInt *quot, int qshift)
++{
++    BignumInt m0, m1;
++    unsigned int h;
++    int i, k;
++
++    m0 = m[0];
++    if (mlen > 1)
++      m1 = m[1];
++    else
++      m1 = 0;
++
++    for (i = 0; i <= alen - mlen; i++) {
++      BignumDblInt t;
++      unsigned int q, r, c, ai1;
++
++      if (i == 0) {
++          h = 0;
++      } else {
++          h = a[i - 1];
++          a[i - 1] = 0;
++      }
++
++      if (i == alen - 1)
++          ai1 = 0;
++      else
++          ai1 = a[i + 1];
++
++      /* Find q = h:a[i] / m0 */
++      if (h >= m0) {
++          /*
++           * Special case.
++           * 
++           * To illustrate it, suppose a BignumInt is 8 bits, and
++           * we are dividing (say) A1:23:45:67 by A1:B2:C3. Then
++           * our initial division will be 0xA123 / 0xA1, which
++           * will give a quotient of 0x100 and a divide overflow.
++           * However, the invariants in this division algorithm
++           * are not violated, since the full number A1:23:... is
++           * _less_ than the quotient prefix A1:B2:... and so the
++           * following correction loop would have sorted it out.
++           * 
++           * In this situation we set q to be the largest
++           * quotient we _can_ stomach (0xFF, of course).
++           */
++          q = BIGNUM_INT_MASK;
++      } else {
++          /* Macro doesn't want an array subscript expression passed
++           * into it (see definition), so use a temporary. */
++          BignumInt tmplo = a[i];
++          DIVMOD_WORD(q, r, h, tmplo, m0);
++
++          /* Refine our estimate of q by looking at
++           h:a[i]:a[i+1] / m0:m1 */
++          t = MUL_WORD(m1, q);
++          if (t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) {
++              q--;
++              t -= m1;
++              r = (r + m0) & BIGNUM_INT_MASK;     /* overflow? */
++              if (r >= (BignumDblInt) m0 &&
++                  t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) q--;
++          }
++      }
++
++      /* Subtract q * m from a[i...] */
++      c = 0;
++      for (k = mlen - 1; k >= 0; k--) {
++          t = MUL_WORD(q, m[k]);
++          t += c;
++          c = (unsigned)(t >> BIGNUM_INT_BITS);
++          if ((BignumInt) t > a[i + k])
++              c++;
++          a[i + k] -= (BignumInt) t;
++      }
++
++      /* Add back m in case of borrow */
++      if (c != h) {
++          t = 0;
++          for (k = mlen - 1; k >= 0; k--) {
++              t += m[k];
++              t += a[i + k];
++              a[i + k] = (BignumInt) t;
++              t = t >> BIGNUM_INT_BITS;
++          }
++          q--;
++      }
++      if (quot)
++          internal_add_shifted(quot, q, qshift + BIGNUM_INT_BITS * (alen - mlen - i));
++    }
++}
++
++/*
++ * Compute p % mod.
++ * The most significant word of mod MUST be non-zero.
++ * We assume that the result array is the same size as the mod array.
++ * We optionally write out a quotient if `quotient' is non-NULL.
++ * We can avoid writing out the result if `result' is NULL.
++ */
++void bigdivmod(Bignum p, Bignum mod, Bignum result, Bignum quotient)
++{
++    BignumInt *n, *m;
++    int mshift;
++    int plen, mlen, i, j;
++
++    /* Allocate m of size mlen, copy mod to m */
++    /* We use big endian internally */
++    mlen = mod[0];
++    m = snewn(mlen, BignumInt);
++    for (j = 0; j < mlen; j++)
++      m[j] = mod[mod[0] - j];
++
++    /* Shift m left to make msb bit set */
++    for (mshift = 0; mshift < BIGNUM_INT_BITS-1; mshift++)
++      if ((m[0] << mshift) & BIGNUM_TOP_BIT)
++          break;
++    if (mshift) {
++      for (i = 0; i < mlen - 1; i++)
++          m[i] = (m[i] << mshift) | (m[i + 1] >> (BIGNUM_INT_BITS - mshift));
++      m[mlen - 1] = m[mlen - 1] << mshift;
++    }
++
++    plen = p[0];
++    /* Ensure plen > mlen */
++    if (plen <= mlen)
++      plen = mlen + 1;
++
++    /* Allocate n of size plen, copy p to n */
++    n = snewn(plen, BignumInt);
++    for (j = 0; j < plen; j++)
++      n[j] = 0;
++    for (j = 1; j <= (int)p[0]; j++)
++      n[plen - j] = p[j];
++
++    /* Main computation */
++    internal_mod(n, plen, m, mlen, quotient, mshift);
++
++    /* Fixup result in case the modulus was shifted */
++    if (mshift) {
++      for (i = plen - mlen - 1; i < plen - 1; i++)
++          n[i] = (n[i] << mshift) | (n[i + 1] >> (BIGNUM_INT_BITS - mshift));
++      n[plen - 1] = n[plen - 1] << mshift;
++      internal_mod(n, plen, m, mlen, quotient, 0);
++      for (i = plen - 1; i >= plen - mlen; i--)
++          n[i] = (n[i] >> mshift) | (n[i - 1] << (BIGNUM_INT_BITS - mshift));
++    }
++
++    /* Copy result to buffer */
++    if (result) {
++      for (i = 1; i <= (int)result[0]; i++) {
++          int j = plen - i;
++          result[i] = j >= 0 ? n[j] : 0;
++      }
++    }
++
++    /* Free temporary arrays */
++    for (i = 0; i < mlen; i++)
++      m[i] = 0;
++    sfree(m);
++    for (i = 0; i < plen; i++)
++      n[i] = 0;
++    sfree(n);
++}
++
++/*
++ * Simple remainder.
++ */
++Bignum bigmod(Bignum a, Bignum b)
++{
++    Bignum r = newbn(b[0]);
++    bigdivmod(a, b, r, NULL);
++    return r;
++}
++
++/*
++ * Compute (base ^ exp) % mod.
++ */
++Bignum dwc_modpow(Bignum base_in, Bignum exp, Bignum mod)
++{
++    BignumInt *a, *b, *n, *m;
++    int mshift;
++    int mlen, i, j;
++    Bignum base, result;
++
++    /*
++     * The most significant word of mod needs to be non-zero. It
++     * should already be, but let's make sure.
++     */
++    //assert(mod[mod[0]] != 0);
++
++    /*
++     * Make sure the base is smaller than the modulus, by reducing
++     * it modulo the modulus if not.
++     */
++    base = bigmod(base_in, mod);
++
++    /* Allocate m of size mlen, copy mod to m */
++    /* We use big endian internally */
++    mlen = mod[0];
++    m = snewn(mlen, BignumInt);
++    for (j = 0; j < mlen; j++)
++      m[j] = mod[mod[0] - j];
++
++    /* Shift m left to make msb bit set */
++    for (mshift = 0; mshift < BIGNUM_INT_BITS - 1; mshift++)
++      if ((m[0] << mshift) & BIGNUM_TOP_BIT)
++          break;
++    if (mshift) {
++      for (i = 0; i < mlen - 1; i++)
++          m[i] =
++              (m[i] << mshift) | (m[i + 1] >>
++                                  (BIGNUM_INT_BITS - mshift));
++      m[mlen - 1] = m[mlen - 1] << mshift;
++    }
++
++    /* Allocate n of size mlen, copy base to n */
++    n = snewn(mlen, BignumInt);
++    i = mlen - base[0];
++    for (j = 0; j < i; j++)
++      n[j] = 0;
++    for (j = 0; j < base[0]; j++)
++      n[i + j] = base[base[0] - j];
++
++    /* Allocate a and b of size 2*mlen. Set a = 1 */
++    a = snewn(2 * mlen, BignumInt);
++    b = snewn(2 * mlen, BignumInt);
++    for (i = 0; i < 2 * mlen; i++)
++      a[i] = 0;
++    a[2 * mlen - 1] = 1;
++
++    /* Skip leading zero bits of exp. */
++    i = 0;
++    j = BIGNUM_INT_BITS - 1;
++    while (i < exp[0] && (exp[exp[0] - i] & (1 << j)) == 0) {
++      j--;
++      if (j < 0) {
++          i++;
++          j = BIGNUM_INT_BITS - 1;
++      }
++    }
++
++    /* Main computation */
++    while (i < exp[0]) {
++      while (j >= 0) {
++          internal_mul(a + mlen, a + mlen, b, mlen);
++          internal_mod(b, mlen * 2, m, mlen, NULL, 0);
++          if ((exp[exp[0] - i] & (1 << j)) != 0) {
++              internal_mul(b + mlen, n, a, mlen);
++              internal_mod(a, mlen * 2, m, mlen, NULL, 0);
++          } else {
++              BignumInt *t;
++              t = a;
++              a = b;
++              b = t;
++          }
++          j--;
++      }
++      i++;
++      j = BIGNUM_INT_BITS - 1;
++    }
++
++    /* Fixup result in case the modulus was shifted */
++    if (mshift) {
++      for (i = mlen - 1; i < 2 * mlen - 1; i++)
++          a[i] =
++              (a[i] << mshift) | (a[i + 1] >>
++                                  (BIGNUM_INT_BITS - mshift));
++      a[2 * mlen - 1] = a[2 * mlen - 1] << mshift;
++      internal_mod(a, mlen * 2, m, mlen, NULL, 0);
++      for (i = 2 * mlen - 1; i >= mlen; i--)
++          a[i] =
++              (a[i] >> mshift) | (a[i - 1] <<
++                                  (BIGNUM_INT_BITS - mshift));
++    }
++
++    /* Copy result to buffer */
++    result = newbn(mod[0]);
++    for (i = 0; i < mlen; i++)
++      result[result[0] - i] = a[i + mlen];
++    while (result[0] > 1 && result[result[0]] == 0)
++      result[0]--;
++
++    /* Free temporary arrays */
++    for (i = 0; i < 2 * mlen; i++)
++      a[i] = 0;
++    sfree(a);
++    for (i = 0; i < 2 * mlen; i++)
++      b[i] = 0;
++    sfree(b);
++    for (i = 0; i < mlen; i++)
++      m[i] = 0;
++    sfree(m);
++    for (i = 0; i < mlen; i++)
++      n[i] = 0;
++    sfree(n);
++
++    freebn(base);
++
++    return result;
++}
++
++
++#ifdef UNITTEST
++
++static __u32 dh_p[] = {
++      96,
++      0xFFFFFFFF,
++      0xFFFFFFFF,
++      0xA93AD2CA,
++      0x4B82D120,
++      0xE0FD108E,
++      0x43DB5BFC,
++      0x74E5AB31,
++      0x08E24FA0,
++      0xBAD946E2,
++      0x770988C0,
++      0x7A615D6C,
++      0xBBE11757,
++      0x177B200C,
++      0x521F2B18,
++      0x3EC86A64,
++      0xD8760273,
++      0xD98A0864,
++      0xF12FFA06,
++      0x1AD2EE6B,
++      0xCEE3D226,
++      0x4A25619D,
++      0x1E8C94E0,
++      0xDB0933D7,
++      0xABF5AE8C,
++      0xA6E1E4C7,
++      0xB3970F85,
++      0x5D060C7D,
++      0x8AEA7157,
++      0x58DBEF0A,
++      0xECFB8504,
++      0xDF1CBA64,
++      0xA85521AB,
++      0x04507A33,
++      0xAD33170D,
++      0x8AAAC42D,
++      0x15728E5A,
++      0x98FA0510,
++      0x15D22618,
++      0xEA956AE5,
++      0x3995497C,
++      0x95581718,
++      0xDE2BCBF6,
++      0x6F4C52C9,
++      0xB5C55DF0,
++      0xEC07A28F,
++      0x9B2783A2,
++      0x180E8603,
++      0xE39E772C,
++      0x2E36CE3B,
++      0x32905E46,
++      0xCA18217C,
++      0xF1746C08,
++      0x4ABC9804,
++      0x670C354E,
++      0x7096966D,
++      0x9ED52907,
++      0x208552BB,
++      0x1C62F356,
++      0xDCA3AD96,
++      0x83655D23,
++      0xFD24CF5F,
++      0x69163FA8,
++      0x1C55D39A,
++      0x98DA4836,
++      0xA163BF05,
++      0xC2007CB8,
++      0xECE45B3D,
++      0x49286651,
++      0x7C4B1FE6,
++      0xAE9F2411,
++      0x5A899FA5,
++      0xEE386BFB,
++      0xF406B7ED,
++      0x0BFF5CB6,
++      0xA637ED6B,
++      0xF44C42E9,
++      0x625E7EC6,
++      0xE485B576,
++      0x6D51C245,
++      0x4FE1356D,
++      0xF25F1437,
++      0x302B0A6D,
++      0xCD3A431B,
++      0xEF9519B3,
++      0x8E3404DD,
++      0x514A0879,
++      0x3B139B22,
++      0x020BBEA6,
++      0x8A67CC74,
++      0x29024E08,
++      0x80DC1CD1,
++      0xC4C6628B,
++      0x2168C234,
++      0xC90FDAA2,
++      0xFFFFFFFF,
++      0xFFFFFFFF,
++};
++
++static __u32 dh_a[] = {
++      8,
++      0xdf367516,
++      0x86459caa,
++      0xe2d459a4,
++      0xd910dae0,
++      0x8a8b5e37,
++      0x67ab31c6,
++      0xf0b55ea9,
++      0x440051d6,
++};
++
++static __u32 dh_b[] = {
++      8,
++      0xded92656,
++      0xe07a048a,
++      0x6fa452cd,
++      0x2df89d30,
++      0xc75f1b0f,
++      0x8ce3578f, 
++      0x7980a324,
++      0x5daec786,
++};
++
++static __u32 dh_g[] = {
++      1,
++      2,
++};
++
++int main(void)
++{
++      int i;
++      __u32 *k;
++      k = modpow(dh_g, dh_a, dh_p);
++
++      printf("\n\n");
++      for (i=0; i<k[0]; i++) {
++              __u32 word32 = k[k[0] - i];
++              __u16 l = word32 & 0xffff;
++              __u16 m = (word32 & 0xffff0000) >> 16;
++              printf("%04x %04x ", m, l);
++              if (!((i + 1)%13)) printf("\n");
++      }
++      printf("\n\n");
++
++      if ((k[0] == 0x60) && (k[1] == 0x28e490e5) && (k[0x60] == 0x5a0d3d4e)) {
++              printf("PASS\n\n");
++      }
++      else {
++              printf("FAIL\n\n");
++      }
++
++}
++
++#endif /* UNITTEST */
++
++#endif /* CONFIG_MACH_IPMATE */
+--- /dev/null
++++ b/drivers/usb/host/dwc_common_port/dwc_modpow.h
+@@ -0,0 +1,26 @@
++/*
++ * dwc_modpow.h
++ * See dwc_modpow.c for license and changes
++ */
++#ifndef _DWC_MODPOW_H
++#define _DWC_MODPOW_H
++
++#include "dwc_os.h"
++
++/** @file
++ *
++ * This file defines the module exponentiation function which is only used
++ * internally by the DWC UWB modules for calculation of PKs during numeric
++ * association.  The routine is taken from the PUTTY, an open source terminal
++ * emulator.  The PUTTY License is preserved in the dwc_modpow.c file.
++ *
++ */
++
++typedef uint32_t BignumInt;
++typedef uint64_t BignumDblInt;
++typedef BignumInt *Bignum;
++
++/* Compute modular exponentiaion */
++extern Bignum dwc_modpow(Bignum base_in, Bignum exp, Bignum mod);
++
++#endif /* _LINUX_BIGNUM_H */
+--- /dev/null
++++ b/drivers/usb/host/dwc_common_port/dwc_notifier.c
+@@ -0,0 +1,256 @@
++#include "dwc_notifier.h"
++#include "dwc_list.h"
++
++typedef struct dwc_observer
++{
++      void *observer;
++      dwc_notifier_callback_t callback;
++      void *data;
++      char *notification;
++      DWC_CIRCLEQ_ENTRY(dwc_observer) list_entry;
++} observer_t;
++
++DWC_CIRCLEQ_HEAD(observer_queue, dwc_observer);
++
++typedef struct dwc_notifier
++{
++      void *object;
++      struct observer_queue observers;
++      DWC_CIRCLEQ_ENTRY(dwc_notifier) list_entry;
++} notifier_t;
++
++DWC_CIRCLEQ_HEAD(notifier_queue, dwc_notifier);
++
++typedef struct manager
++{
++      dwc_workq_t *wq;
++      dwc_mutex_t *mutex;
++      struct notifier_queue notifiers;
++} manager_t;
++
++static manager_t *manager = NULL;
++
++static void create_manager(void)
++{
++      manager = DWC_ALLOC(sizeof(manager_t));
++      DWC_CIRCLEQ_INIT(&manager->notifiers);
++      manager->wq = DWC_WORKQ_ALLOC("DWC Notification WorkQ");
++}
++
++static void free_manager(void)
++{
++      DWC_WORKQ_FREE(manager->wq);
++      /* All notifiers must have unregistered themselves before this module
++       * can be removed.  Hitting this assertion indicates a programmer
++       * error. */
++      DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&manager->notifiers), "Notification manager being freed before all notifiers have been removed");
++      DWC_FREE(manager);
++}
++
++#ifdef DEBUG
++static void dump_manager(void)
++{
++      notifier_t *n;
++      observer_t *o;
++      DWC_ASSERT(manager, "Notification manager not found");
++      DWC_DEBUG("List of all notifiers and observers:");
++      DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) {
++              DWC_DEBUG("Notifier %p has observers:", n->object);
++              DWC_CIRCLEQ_FOREACH(o, &n->observers, list_entry) {
++                      DWC_DEBUG("    %p watching %s", o->observer, o->notification);
++              }
++      }
++}
++#else
++#define dump_manager(...)
++#endif
++
++static observer_t *alloc_observer(void *observer, char *notification, dwc_notifier_callback_t callback, void *data)
++{
++      observer_t *new_observer = DWC_ALLOC(sizeof(observer_t));
++      DWC_CIRCLEQ_INIT_ENTRY(new_observer, list_entry);
++      new_observer->observer = observer;
++      new_observer->notification = notification;
++      new_observer->callback = callback;
++      new_observer->data = data;
++      return new_observer;
++}
++
++static void free_observer(observer_t *observer)
++{
++      DWC_FREE(observer);
++}
++
++static notifier_t *alloc_notifier(void *object)
++{
++      notifier_t *notifier;
++
++      if (!object) {
++              return NULL;
++      }
++
++      notifier = DWC_ALLOC(sizeof(notifier_t));
++      DWC_CIRCLEQ_INIT(&notifier->observers);
++      DWC_CIRCLEQ_INIT_ENTRY(notifier, list_entry);
++
++      notifier->object = object;
++      return notifier;
++}
++
++static void free_notifier(notifier_t *notifier)
++{
++      observer_t *observer;
++      DWC_CIRCLEQ_FOREACH(observer, &notifier->observers, list_entry) {
++              free_observer(observer);
++      }
++      DWC_FREE(notifier);
++}
++
++static notifier_t *find_notifier(void *object)
++{
++      notifier_t *notifier;
++      if (!object) {
++              return NULL;
++      }
++      DWC_ASSERT(manager, "Notification manager not found");
++      DWC_CIRCLEQ_FOREACH(notifier, &manager->notifiers, list_entry) {
++              if (notifier->object == object) {
++                      return notifier;
++              }
++      }
++      return NULL;
++}
++
++void dwc_alloc_notification_manager(void)
++{
++      create_manager();
++}
++
++void dwc_free_notification_manager(void)
++{
++      free_manager();
++}
++
++dwc_notifier_t *dwc_register_notifier(void *object)
++{
++      notifier_t *notifier = find_notifier(object);
++      DWC_ASSERT(manager, "Notification manager not found");
++      if (notifier) {
++              DWC_ERROR("Notifier %p is already registered", object);
++              return NULL;
++      }
++
++      notifier = alloc_notifier(object);
++      DWC_CIRCLEQ_INSERT_TAIL(&manager->notifiers, notifier, list_entry);
++
++
++      DWC_INFO("Notifier %p registered", object);
++      dump_manager();
++
++      return notifier;
++}
++
++void dwc_unregister_notifier(dwc_notifier_t *notifier)
++{
++      DWC_ASSERT(manager, "Notification manager not found");
++      if (!DWC_CIRCLEQ_EMPTY(&notifier->observers)) {
++              observer_t *o;
++              DWC_ERROR("Notifier %p has active observers when removing", notifier->object);
++              DWC_CIRCLEQ_FOREACH(o, &notifier->observers, list_entry) {
++                      DWC_DEBUG("    %p watching %s", o->observer, o->notification);
++              }
++              DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&notifier->observers), "Notifier %p has active observers when removing", notifier);
++      }
++
++      DWC_CIRCLEQ_REMOVE_INIT(&manager->notifiers, notifier, list_entry);
++      free_notifier(notifier);
++
++      DWC_INFO("Notifier unregistered");
++      dump_manager();
++}
++
++/* Add an observer to observe the notifier for a particular state, event, or notification. */
++int dwc_add_observer(void *observer, void *object, char *notification, dwc_notifier_callback_t callback, void *data)
++{
++      notifier_t *notifier = find_notifier(object);
++      observer_t *new_observer;
++      if (!notifier) {
++              DWC_ERROR("Notifier %p is not found when adding observer", object);
++              return -1;
++      }
++
++      new_observer = alloc_observer(observer, notification, callback, data);
++
++      DWC_CIRCLEQ_INSERT_TAIL(&notifier->observers, new_observer, list_entry);
++
++      DWC_INFO("Added observer %p to notifier %p observing notification %s, callback=%p, data=%p",
++               observer, object, notification, callback, data);
++
++      dump_manager();
++      return 0;
++}
++
++int dwc_remove_observer(void *observer)
++{
++      notifier_t *n;
++      DWC_ASSERT(manager, "Notification manager not found");
++      DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) {
++              observer_t *o;
++              observer_t *o2;
++              DWC_CIRCLEQ_FOREACH_SAFE(o, o2, &n->observers, list_entry) {
++                      if (o->observer == observer) {
++                              DWC_CIRCLEQ_REMOVE_INIT(&n->observers, o, list_entry);
++                              DWC_INFO("Removing observer %p from notifier %p watching notification %s:",
++                                       o->observer, n->object, o->notification);
++                              free_observer(o);
++                      }
++              }
++      }
++
++      dump_manager();
++      return 0;
++}
++
++typedef struct callback_data
++{
++      dwc_notifier_callback_t cb;
++      void *observer;
++      void *data;
++      void *object;
++      void *notification;
++      void *notification_data;
++} cb_data_t;
++
++static void cb_task(void *data)
++{
++      cb_data_t *cb = (cb_data_t *)data;
++      cb->cb(cb->object, cb->notification, cb->observer, cb->notification_data, cb->data);
++      DWC_FREE(cb);
++}
++
++void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data)
++{
++      observer_t *o;
++      DWC_ASSERT(manager, "Notification manager not found");
++      DWC_CIRCLEQ_FOREACH(o, &notifier->observers, list_entry) {
++              int len = DWC_STRLEN(notification);
++              if (DWC_STRLEN(o->notification) != len) {
++                      continue;
++              }
++
++              if (DWC_STRNCMP(o->notification, notification, len) == 0) {
++                      cb_data_t *cb_data = DWC_ALLOC(sizeof(cb_data_t));
++                      cb_data->cb = o->callback;
++                      cb_data->observer = o->observer;
++                      cb_data->data = o->data;
++                      cb_data->object = notifier->object;
++                      cb_data->notification = notification;
++                      cb_data->notification_data = notification_data;
++                      DWC_DEBUG("Observer found %p for notification %s", o->observer, notification);
++                      DWC_WORKQ_SCHEDULE(manager->wq, cb_task, cb_data,
++                                         "Notify callback from %p for Notification %s, to observer %p",
++                                         cb_data->object, notification, cb_data->observer);
++              }
++      }
++}
++
+--- /dev/null
++++ b/drivers/usb/host/dwc_common_port/dwc_notifier.h
+@@ -0,0 +1,112 @@
++
++#ifndef __DWC_NOTIFIER_H__
++#define __DWC_NOTIFIER_H__
++
++#include "dwc_os.h"
++
++/** @file
++ *
++ * A simple implementation of the Observer pattern.  Any "module" can
++ * register as an observer or notifier.  The notion of "module" is abstract and
++ * can mean anything used to identify either an observer or notifier.  Usually
++ * it will be a pointer to a data structure which contains some state, ie an
++ * object.
++ *
++ * Before any notifiers can be added, the global notification manager must be
++ * brought up with dwc_alloc_notification_manager().
++ * dwc_free_notification_manager() will bring it down and free all resources.
++ * These would typically be called upon module load and unload.  The
++ * notification manager is a single global instance that handles all registered
++ * observable modules and observers so this should be done only once.
++ *
++ * A module can be observable by using Notifications to publicize some general
++ * information about it's state or operation.  It does not care who listens, or
++ * even if anyone listens, or what they do with the information.  The observable
++ * modules do not need to know any information about it's observers or their
++ * interface, or their state or data.
++ *
++ * Any module can register to emit Notifications.  It should publish a list of
++ * notifications that it can emit and their behavior, such as when they will get
++ * triggered, and what information will be provided to the observer.  Then it
++ * should register itself as an observable module. See dwc_register_notifier().
++ *
++ * Any module can observe any observable, registered module, provided it has a
++ * handle to the other module and knows what notifications to observe.  See
++ * dwc_add_observer().
++ *
++ * A function of type dwc_notifier_callback_t is called whenever a notification
++ * is triggered with one or more observers observing it.  This function is
++ * called in it's own process so it may sleep or block if needed.  It is
++ * guaranteed to be called sometime after the notification has occurred and will
++ * be called once per each time the notification is triggered.  It will NOT be
++ * called in the same process context used to trigger the notification.
++ *
++ * @section Limitiations
++ *
++ * Keep in mind that Notifications that can be triggered in rapid sucession may
++ * schedule too many processes too handle.  Be aware of this limitation when
++ * designing to use notifications, and only add notifications for appropriate
++ * observable information.
++ *
++ * Also Notification callbacks are not synchronous.  If you need to synchronize
++ * the behavior between module/observer you must use other means.  And perhaps
++ * that will mean Notifications are not the proper solution.
++ */
++
++struct dwc_notifier;
++typedef struct dwc_notifier dwc_notifier_t;
++
++/** The callback function must be of this type.
++ *
++ * @param object This is the object that is being observed.
++ * @param notification This is the notification that was triggered.
++ * @param observer This is the observer
++ * @param notification_data This is notification-specific data that the notifier
++ * has included in this notification.  The value of this should be published in
++ * the documentation of the observable module with the notifications.
++ * @param user_data This is any custom data that the observer provided when
++ * adding itself as an observer to the notification. */
++typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer, void *notification_data, void *user_data);
++
++/** Brings up the notification manager. */
++extern void dwc_alloc_notification_manager(void);
++/** Brings down the notification manager. */
++extern void dwc_free_notification_manager(void);
++
++/** This function register an observable module.  A dwc_notifier_t object is
++ * returned to the observable module.  This is an opaque object that is used by
++ * the observable module to trigger notifications.  This object should only be
++ * accessible to functions that are authorized to trigger notifications for this
++ * module.  Observers do not need this object. */
++extern dwc_notifier_t *dwc_register_notifier(void *object);
++
++/** This function unregister an observable module.  All observers have to be
++ * removed prior to unregistration. */
++extern void dwc_unregister_notifier(dwc_notifier_t *notifier);
++
++/** Add a module as an observer to the observable module.  The observable module
++ * needs to have previously registered with the notification manager.
++ *
++ * @param observer The observer module
++ * @param object The module to observe
++ * @param notification The notification to observe
++ * @param callback The callback function to call
++ * @param user_data Any additional user data to pass into the callback function */
++extern int dwc_add_observer(void *observer, void *object, char *notification, dwc_notifier_callback_t callback, void *user_data);
++
++/** Removes the specified observer from all notifications that it is currently
++ * observing. */
++extern int dwc_remove_observer(void *observer);
++
++/** This function triggers a Notification.  It should be called by the
++ * observable module, or any module or library which the observable module
++ * allows to trigger notification on it's behalf.  Such as the dwc_cc_t.
++ *
++ * dwc_notify is a non-blocking function.  Callbacks are scheduled called in
++ * their own process context for each trigger.  Callbacks can be blocking.
++ * dwc_notify can be called from interrupt context if needed.
++ *
++ */
++void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data);
++
++#endif /* __DWC_NOTIFIER_H__ */
+--- /dev/null
++++ b/drivers/usb/host/dwc_common_port/dwc_os.h
+@@ -0,0 +1,924 @@
++/* =========================================================================
++ * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_os.h $
++ * $Revision: #2 $
++ * $Date: 2009/04/02 $
++ * $Change: 1224130 $
++ *
++ * Synopsys Portability Library Software and documentation
++ * (hereinafter, "Software") is an Unsupported proprietary work of
++ * Synopsys, Inc. unless otherwise expressly agreed to in writing
++ * between Synopsys and you.
++ *
++ * The Software IS NOT an item of Licensed Software or Licensed Product
++ * under any End User Software License Agreement or Agreement for
++ * Licensed Product with Synopsys or any supplement thereto. You are
++ * permitted to use and redistribute this Software in source and binary
++ * forms, with or without modification, provided that redistributions
++ * of source code must retain this notice. You may not view, use,
++ * disclose, copy or distribute this file or any information contained
++ * herein except pursuant to this license grant from Synopsys. If you
++ * do not agree with this notice, including the disclaimer below, then
++ * you are not authorized to use the Software.
++ *
++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
++ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
++ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
++ * DAMAGE.
++ * ========================================================================= */
++#ifndef _DWC_OS_H_
++#define _DWC_OS_H_
++
++/** @file
++ *
++ * DWC portability library, low level os-wrapper functions
++ *
++ */
++
++/* These basic types need to be defined by some OS header file or custom header
++ * file for your specific target architecture.
++ *
++ * uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t
++ *
++ * Any custom or alternate header file must be added and enabled here.
++ */
++
++#ifdef DWC_LINUX
++#  include <linux/types.h>
++#  ifdef CONFIG_DEBUG_MUTEXES
++#    include <linux/mutex.h>
++#  endif
++#else
++#  include <stdint.h>
++#endif
++
++
++/** @name Primitive Types and Values */
++
++/** We define a boolean type for consistency.  Can be either YES or NO */
++typedef uint8_t dwc_bool_t;
++#define YES  1
++#define NO   0
++
++/** @todo make them positive and return the negative error code */
++/** @name Error Codes */
++#define DWC_E_INVALID         1001
++#define DWC_E_NO_MEMORY       1002
++#define DWC_E_NO_DEVICE       1003
++#define DWC_E_NOT_SUPPORTED   1004
++#define DWC_E_TIMEOUT         1005
++#define DWC_E_BUSY            1006
++#define DWC_E_AGAIN           1007
++#define DWC_E_RESTART         1008
++#define DWC_E_ABORT           1009
++#define DWC_E_SHUTDOWN        1010
++#define DWC_E_NO_DATA         1011
++#define DWC_E_DISCONNECT      2000
++#define DWC_E_UNKNOWN         3000
++#define DWC_E_NO_STREAM_RES   4001
++#define DWC_E_COMMUNICATION   4002
++#define DWC_E_OVERFLOW        4003
++#define DWC_E_PROTOCOL        4004
++#define DWC_E_IN_PROGRESS     4005
++#define DWC_E_PIPE            4006
++#define DWC_E_IO              4007
++#define DWC_E_NO_SPACE        4008
++
++/** @name Tracing/Logging Functions
++ *
++ * These function provide the capability to add tracing, debugging, and error
++ * messages, as well exceptions as assertions.  The WUDEV uses these
++ * extensively.  These could be logged to the main console, the serial port, an
++ * internal buffer, etc.  These functions could also be no-op if they are too
++ * expensive on your system.  By default undefining the DEBUG macro already
++ * no-ops some of these functions. */
++
++#include <stdarg.h>
++
++/** Returns non-zero if in interrupt context. */
++extern dwc_bool_t DWC_IN_IRQ(void);
++#define dwc_in_irq DWC_IN_IRQ
++
++/** Returns "IRQ" if DWC_IN_IRQ is true. */
++static inline char *dwc_irq(void) {
++      return DWC_IN_IRQ() ? "IRQ" : "";
++}
++
++/**
++ * A vprintf() clone.  Just call vprintf if you've got it.
++ */
++extern void DWC_VPRINTF(char *format, va_list args);
++#define dwc_vprintf DWC_VPRINTF
++
++/**
++ * A vsnprintf() clone.  Just call vprintf if you've got it.
++ */
++extern int DWC_VSNPRINTF(char *str, int size, char *format, va_list args);
++#define dwc_vsnprintf DWC_VSNPRINTF
++
++/**
++ * printf() clone.  Just call printf if you've go it.
++ */
++extern void DWC_PRINTF(char *format, ...)
++/* This provides compiler level static checking of the parameters if you're
++ * using GCC. */
++#ifdef __GNUC__
++      __attribute__ ((format(printf, 1, 2)));
++#else
++  ;
++#endif
++#define dwc_printf DWC_PRINTF
++
++/**
++ * sprintf() clone.  Just call sprintf if you've got it.
++ */
++extern int DWC_SPRINTF(char *string, char *format, ...)
++#ifdef __GNUC__
++     __attribute__ ((format(printf, 2, 3)));
++#else
++     ;
++#endif
++#define dwc_sprintf DWC_SPRINTF
++
++/**
++ * snprintf() clone.  Just call snprintf if you've got it.
++ */
++extern int DWC_SNPRINTF(char *string, int size, char *format, ...)
++#ifdef __GNUC__
++     __attribute__ ((format(printf, 3, 4)));
++#else
++     ;
++#endif
++#define dwc_snprintf DWC_SNPRINTF
++
++/**
++ * Prints a WARNING message.  On systems that don't differentiate between
++ * warnings and regular log messages, just print it.  Indicates that something
++ * may be wrong with the driver.  Works like printf().
++ *
++ * Use the DWC_WARN macro to call this function.
++ */
++extern void __DWC_WARN(char *format, ...)
++#ifdef __GNUC__
++     __attribute__ ((format(printf, 1, 2)));
++#else
++     ;
++#endif
++
++/**
++ * Prints an error message.  On systems that don't differentiate between errors
++ * and regular log messages, just print it.  Indicates that something went wrong
++ * with the driver, but it can be recovered from.  Works like printf().
++ *
++ * Use the DWC_ERROR macro to call this function.
++ */
++extern void __DWC_ERROR(char *format, ...)
++#ifdef __GNUC__
++     __attribute__ ((format(printf, 1, 2)));
++#else
++     ;
++#endif
++
++/**
++ * Prints an exception error message and takes some user-defined action such as
++ * print out a backtrace or trigger a breakpoint.  Indicates that something went
++ * abnormally wrong with the driver such as programmer error, or other
++ * exceptional condition.  It should not be ignored so even on systems without
++ * printing capability, some action should be taken to notify the developer of
++ * it.  Works like printf().
++ */
++extern void DWC_EXCEPTION(char *format, ...)
++#ifdef __GNUC__
++     __attribute__ ((format(printf, 1, 2)));
++#else
++     ;
++#endif
++#define dwc_exception DWC_EXCEPTION
++
++#ifdef DEBUG
++/**
++ * Prints out a debug message.  Used for logging/trace messages.
++ *
++ * Use the DWC_DEBUG macro to call this function
++ */
++extern void __DWC_DEBUG(char *format, ...)
++#ifdef __GNUC__
++     __attribute__ ((format(printf, 1, 2)));
++#else
++     ;
++#endif
++#else
++#define __DWC_DEBUG printk
++#endif
++
++/**
++ * Prints out a Debug message.
++ */
++#define DWC_DEBUG(_format, _args...) __DWC_DEBUG("DEBUG:%s:%s: " _format "\n", __func__, dwc_irq(), ## _args)
++#define dwc_debug DWC_DEBUG
++/**
++ * Prints out an informative message.
++ */
++#define DWC_INFO(_format, _args...) DWC_PRINTF("INFO:%s: " _format "\n", dwc_irq(), ## _args)
++#define dwc_info DWC_INFO
++/**
++ * Prints out a warning message.
++ */
++#define DWC_WARN(_format, _args...) __DWC_WARN("WARN:%s:%s:%d: " _format "\n", dwc_irq(), __func__, __LINE__, ## _args)
++#define dwc_warn DWC_WARN
++/**
++ * Prints out an error message.
++ */
++#define DWC_ERROR(_format, _args...) __DWC_ERROR("ERROR:%s:%s:%d: " _format "\n", dwc_irq(), __func__, __LINE__, ## _args)
++#define dwc_error DWC_ERROR
++
++#define DWC_PROTO_ERROR(_format, _args...) __DWC_WARN("ERROR:%s:%s:%d: " _format "\n", dwc_irq(), __func__, __LINE__, ## _args)
++#define dwc_proto_error DWC_PROTO_ERROR
++
++#ifdef DEBUG
++/** Prints out a exception error message if the _expr expression fails.  Disabled
++ * if DEBUG is not enabled. */
++#define DWC_ASSERT(_expr, _format, _args...) if (!(_expr)) { DWC_EXCEPTION("%s:%s:%d: " _format "\n", dwc_irq(), __FILE__, __LINE__, ## _args); }
++#else
++#define DWC_ASSERT(_x...)
++#endif
++#define dwc_assert DWC_ASSERT
++
++/** @name Byter Ordering
++ * The following functions are for conversions between processor's byte ordering
++ * and specific ordering you want.
++ */
++
++/** Converts 32 bit data in CPU byte ordering to little endian. */
++extern uint32_t DWC_CPU_TO_LE32(void *p);
++#define dwc_cpu_to_le32 DWC_CPU_TO_LE32
++/** Converts 32 bit data in CPU byte orderint to big endian. */
++extern uint32_t DWC_CPU_TO_BE32(void *p);
++#define dwc_cpu_to_be32 DWC_CPU_TO_BE32
++
++/** Converts 32 bit little endian data to CPU byte ordering. */
++extern uint32_t DWC_LE32_TO_CPU(void *p);
++#define dwc_le32_to_cpu DWC_LE32_TO_CPU
++/** Converts 32 bit big endian data to CPU byte ordering. */
++extern uint32_t DWC_BE32_TO_CPU(void *p);
++#define dwc_be32_to_cpu DWC_BE32_TO_CPU
++
++/** Converts 16 bit data in CPU byte ordering to little endian. */
++extern uint16_t DWC_CPU_TO_LE16(void *p);
++#define dwc_cpu_to_le16 DWC_CPU_TO_LE16
++/** Converts 16 bit data in CPU byte orderint to big endian. */
++extern uint16_t DWC_CPU_TO_BE16(void *p);
++#define dwc_cpu_to_be16 DWC_CPU_TO_BE16
++
++/** Converts 16 bit little endian data to CPU byte ordering. */
++extern uint16_t DWC_LE16_TO_CPU(void *p);
++#define dwc_le16_to_cpu DWC_LE16_TO_CPU
++/** Converts 16 bit bi endian data to CPU byte ordering. */
++extern uint16_t DWC_BE16_TO_CPU(void *p);
++#define dwc_be16_to_cpu DWC_BE16_TO_CPU
++
++/** @name Register Read/Write
++ *
++ * The following five functions should be implemented to read/write registers of
++ * 32-bit and 64-bit sizes.  All modules use this to read/write register values.
++ * The reg value is a pointer to the register calculated from the void *base
++ * variable passed into the driver when it is started.  */
++
++/** Reads the content of a 32-bit register. */
++extern uint32_t DWC_READ_REG32(uint32_t volatile *reg);
++#define dwc_read_reg32 DWC_READ_REG32
++/** Reads the content of a 64-bit register. */
++extern uint64_t DWC_READ_REG64(uint64_t volatile *reg);
++#define dwc_read_reg64 DWC_READ_REG64
++/** Writes to a 32-bit register. */
++extern void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value);
++#define dwc_write_reg32 DWC_WRITE_REG32
++/** Writes to a 64-bit register. */
++extern void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value);
++#define dwc_write_reg64 DWC_WRITE_REG64
++/**  
++ * Modify bit values in a register.  Using the
++ * algorithm: (reg_contents & ~clear_mask) | set_mask.
++ */
++extern void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);
++#define dwc_modify_reg32 DWC_MODIFY_REG32
++
++/** @cond */
++
++/** @name Some convenience MACROS used internally.  Define DEBUG_REGS to log the
++ * register writes. */
++
++#ifdef DEBUG_REGS
++
++#define dwc_define_read_write_reg_n(_reg,_container_type) \
++static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \
++      return DWC_READ_REG32(&container->regs->_reg[num]); \
++} \
++static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \
++        DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, &(((uint32_t*)container->regs->_reg)[num]), data); \
++      DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \
++}
++
++#define dwc_define_read_write_reg(_reg,_container_type) \
++static inline uint32_t dwc_read_##_reg(_container_type *container) { \
++      return DWC_READ_REG32(&container->regs->_reg); \
++} \
++static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \
++        DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \
++      DWC_WRITE_REG32(&container->regs->_reg, data); \
++}
++
++#else
++
++#define dwc_define_read_write_reg_n(_reg,_container_type) \
++static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \
++      return DWC_READ_REG32(&container->regs->_reg[num]); \
++} \
++static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \
++      DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \
++}
++
++#define dwc_define_read_write_reg(_reg,_container_type) \
++static inline uint32_t dwc_read_##_reg(_container_type *container) { \
++      return DWC_READ_REG32(&container->regs->_reg); \
++} \
++static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \
++      DWC_WRITE_REG32(&container->regs->_reg, data); \
++}
++
++#endif
++
++/** @endcond */
++
++
++/** @name Crypto Functions
++ *
++ * These are the low-level cryptographic functions used by the driver. */
++
++/** Perform AES CBC */
++extern int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out);
++#define dwc_aes_cbc DWC_AES_CBC
++/** Fill the provided buffer with random bytes.  These should be cryptographic grade random numbers. */
++extern void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length);
++#define dwc_random_bytes DWC_RANDOM_BYTES
++/** Perform the SHA-256 hash function */
++extern int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out);
++#define dwc_sha256 DWC_SHA256
++/** Calculated the HMAC-SHA256 */
++extern int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t *out);
++#define dwc_hmac_sha256 DWC_HMAC_SHA256
++
++
++/** @name Memory Allocation
++ *
++ * These function provide access to memory allocation.  There are only 2 DMA
++ * functions and 3 Regular memory functions that need to be implemented.  None
++ * of the memory debugging routines need to be implemented.  The allocation
++ * routines all ZERO the contents of the memory.
++ *
++ * Defining DEBUG_MEMORY turns on memory debugging and statistic gathering.
++ * This checks for memory leaks, keeping track of alloc/free pairs.  It also
++ * keeps track of how much memory the driver is using at any given time. */
++
++#define DWC_PAGE_SIZE 4096
++#define DWC_PAGE_OFFSET(addr) (((uint32_t)addr) & 0xfff)
++#define DWC_PAGE_ALIGNED(addr) ((((uint32_t)addr) & 0xfff) == 0)
++
++#define DWC_INVALID_DMA_ADDR 0x0
++
++typedef uint32_t dwc_dma_t;
++
++/** @todo these functions will be added in the future */
++#if 0
++/**
++ * Creates a DMA pool from which you can allocate DMA buffers.  Buffers
++ * allocated from this pool will be guaranteed to meet the size, alignment, and
++ * boundary requirements specified.
++ *
++ * @param[in] size Specifies the size of the buffers that will be allocated from
++ * this pool.
++ * @param[in] align Specifies the byte alignment requirements of the buffers
++ * allocated from this pool.  Must be a power of 2.
++ * @param[in] boundary Specifies the N-byte boundary that buffers allocated from
++ * this pool must not cross.
++ *
++ * @returns A pointer to an internal opaque structure which is not to be
++ * accessed outside of these library functions.  Use this handle to specify
++ * which pools to allocate/free DMA buffers from and also to destroy the pool,
++ * when you are done with it.
++ */
++extern dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, uint32_t align, uint32_t boundary);
++/**
++ * Destroy a DMA pool.  All buffers allocated from that pool must be freed first.
++ */
++extern void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool);
++/**
++ * Allocate a buffer from the specified DMA pool and zeros its contents.
++ */
++extern void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr);
++/**
++ * Free a previously allocated buffer from the DMA pool.
++ */
++extern void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr);
++#endif
++
++
++/** Allocates a DMA capable buffer and zeroes its contents. */
++extern void *__DWC_DMA_ALLOC(uint32_t size, dwc_dma_t *dma_addr);
++
++/** Allocates a DMA capable buffer and zeroes its contents in atomic contest */
++extern void *__DWC_DMA_ALLOC_ATOMIC(uint32_t size, dwc_dma_t *dma_addr);
++
++/** Frees a previosly allocated buffer. */
++extern void __DWC_DMA_FREE(uint32_t size, void *virt_addr, dwc_dma_t dma_addr);
++
++/** Allocates a block of memory and zeroes its contents. */
++extern void *__DWC_ALLOC(uint32_t size);
++
++/** Allocates a block of memory and zeroes its contents, in an atomic manner
++ * which can be used inside interrupt context.  The size should be sufficiently
++ * small, a few KB at most, such that failures are not likely to occur.  Can just call
++ * __DWC_ALLOC if it is atomic. */
++extern void *__DWC_ALLOC_ATOMIC(uint32_t size);
++
++/** Frees a previously allocated buffer. */
++extern void __DWC_FREE(void *addr);
++
++#ifndef DEBUG_MEMORY
++
++#define DWC_ALLOC(_size_) __DWC_ALLOC(_size_)
++#define DWC_ALLOC_ATOMIC(_size_) __DWC_ALLOC_ATOMIC(_size_)
++#define DWC_FREE(_addr_) __DWC_FREE(_addr_)
++#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(_size_,_dma_)
++#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(_size_,_dma_)
++#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(_size_,_virt_,_dma_)
++
++#else
++
++extern void *dwc_alloc_debug(uint32_t size, char const *func, int line);
++extern void *dwc_alloc_atomic_debug(uint32_t size, char const *func, int line);
++extern void dwc_free_debug(void *addr, char const *func, int line);
++extern void *dwc_dma_alloc_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line);
++extern void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line);
++extern void dwc_dma_free_debug(uint32_t size, void *virt_addr, dwc_dma_t dma_addr, char const *func, int line);
++
++extern void dwc_memory_debug_start(void);
++extern void dwc_memory_debug_stop(void);
++extern void dwc_memory_debug_report(void);
++
++#define DWC_ALLOC(_size_) (dwc_alloc_debug(_size_, __func__, __LINE__))
++#define DWC_ALLOC_ATOMIC(_size_) (dwc_alloc_atomic_debug(_size_, __func__, __LINE__))
++#define DWC_FREE(_addr_) (dwc_free_debug(_addr_, __func__, __LINE__))
++#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(_size_, _dma_, __func__, __LINE__)
++#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(_size_, _dma_, __func__, __LINE__)
++#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(_size_, _virt_, _dma_, __func__, __LINE__)
++
++#endif /* DEBUG_MEMORY */
++
++#define dwc_alloc DWC_ALLOC
++#define dwc_alloc_atomic DWC_ALLOC_ATOMIC
++#define dwc_free DWC_FREE
++#define dwc_dma_alloc DWC_DMA_ALLOC
++#define dwc_dma_alloc_atomic DWC_DMA_ALLOC_ATOMIC
++#define dwc_dma_free DWC_DMA_FREE
++
++
++/** @name Memory and String Processing */
++
++/** memset() clone */
++extern void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size);
++#define dwc_memset DWC_MEMSET
++/** memcpy() clone */
++extern void *DWC_MEMCPY(void *dest, void const *src, uint32_t size);
++#define dwc_memcpy DWC_MEMCPY
++/** memmove() clone */
++extern void *DWC_MEMMOVE(void *dest, void *src, uint32_t size);
++#define dwc_memmove DWC_MEMMOVE
++/** memcmp() clone */
++extern int DWC_MEMCMP(void *m1, void *m2, uint32_t size);
++#define dwc_memcmp DWC_MEMCMP
++/** strcmp() clone */
++extern int DWC_STRCMP(void *s1, void *s2);
++#define dwc_strcmp DWC_STRCMP
++/** strncmp() clone */
++extern int DWC_STRNCMP(void *s1, void *s2, uint32_t size);
++#define dwc_strncmp DWC_STRNCMP
++/** strlen() clone, for NULL terminated ASCII strings */
++extern int DWC_STRLEN(char const *str);
++#define dwc_strlen DWC_STRLEN
++/** strcpy() clone, for NULL terminated ASCII strings */
++extern char *DWC_STRCPY(char *to, const char *from);
++#define dwc_strcpy DWC_STRCPY
++
++/** strdup() clone.  If you wish to use memory allocation debugging, this
++ * implementation of strdup should use the DWC_* memory routines instead of
++ * calling a predefined strdup.  Otherwise the memory allocated by this routine
++ * will not be seen by the debugging routines. */
++extern char *DWC_STRDUP(char const *str);
++#define dwc_strdup DWC_STRDUP
++
++/** NOT an atoi() clone.  Read the description carefully.  Returns an integer
++ * converted from the string str in base 10 unless the string begins with a "0x"
++ * in which case it is base 16.  String must be a NULL terminated sequence of
++ * ASCII characters and may optionally begin with whitespace, a + or -, and a
++ * "0x" prefix if base 16.  The remaining characters must be valid digits for
++ * the number and end with a NULL character.  If any invalid characters are
++ * encountered or it returns with a negative error code and the results of the
++ * conversion are undefined.  On sucess it returns 0.  Overflow conditions are
++ * undefined.  An example implementation using atoi() can be referenced from the
++ * Linux implementation. */
++extern int DWC_ATOI(char *str, int32_t *value);
++#define dwc_atoi DWC_ATOI
++/** Same as above but for unsigned. */
++extern int DWC_ATOUI(char *str, uint32_t *value);
++#define dwc_atoui DWC_ATOUI
++/** This routine returns a UTF16LE unicode encoded string from a UTF8 string. */
++extern int DWC_UTF8_TO_UTF16LE(uint8_t const *utf8string, uint16_t *utf16string, unsigned len);
++#define dwc_utf8_to_utf16le DWC_UTF8_TO_UTF16LE
++
++/** @name Wait queues
++ *
++ * Wait queues provide a means of synchronizing between threads or processes.  A
++ * process can block on a waitq if some condition is not true, waiting for it to
++ * become true.  When the waitq is triggered all waiting process will get
++ * unblocked and the condition will be check again.  Waitqs should be triggered
++ * every time a condition can potentially change.*/
++struct dwc_waitq;
++typedef struct dwc_waitq dwc_waitq_t;
++
++/** The type of waitq condition callback function.  This is called every time
++ * condition is evaluated. */
++typedef int (*dwc_waitq_condition_t)(void *data);
++
++/** Allocate a waitq */
++extern dwc_waitq_t *DWC_WAITQ_ALLOC(void);
++#define dwc_waitq_alloc DWC_WAITQ_ALLOC
++/** Free a waitq */
++extern void DWC_WAITQ_FREE(dwc_waitq_t *wq);
++#define dwc_waitq_free DWC_WAITQ_FREE
++
++/** Check the condition and if it is false, block on the waitq.  When unblocked, check the
++ * condition again.  The function returns when the condition becomes true.  The return value
++ * is 0 on condition true, DWC_WAITQ_ABORTED on abort or killed, or DWC_WAITQ_UNKNOWN on error. */
++extern int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t condition, void *data);
++#define dwc_waitq_wait DWC_WAITQ_WAIT;
++/** Check the condition and if it is false, block on the waitq.  When unblocked,
++ * check the condition again.  The function returns when the condition become
++ * true or the timeout has passed.  The return value is 0 on condition true or
++ * DWC_TIMED_OUT on timeout, or DWC_WAITQ_ABORTED, or DWC_WAITQ_UNKNOWN on
++ * error. */
++extern int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t condition, void *data, int32_t msecs);
++#define dwc_waitq_wait_timeout DWC_WAITQ_WAIT_TIMEOUT
++/** Trigger a waitq, unblocking all processes.  This should be called whenever a condition
++ * has potentially changed. */
++extern void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq);
++#define dwc_waitq_trigger DWC_WAITQ_TRIGGER
++/** Unblock all processes waiting on the waitq with an ABORTED result. */
++extern void DWC_WAITQ_ABORT(dwc_waitq_t *wq);
++#define dwc_waitq_abort DWC_WAITQ_ABORT
++
++/** @name Threads
++ *
++ * A thread must be explicitly stopped.  It must check DWC_THREAD_SHOULD_STOP
++ * whenever it is woken up, and then return.  The DWC_THREAD_STOP function
++ * returns the value from the thread.
++ */
++
++struct dwc_thread;
++typedef struct dwc_thread dwc_thread_t;
++
++/** The thread function */
++typedef int (*dwc_thread_function_t)(void *data);
++
++/** Create a thread and start it running the thread_function.  Returns a handle
++ * to the thread */
++extern dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t thread_function, char *name, void *data);
++#define dwc_thread_run DWC_THREAD_RUN
++/** Stops a thread.  Return the value returned by the thread.  Or will return
++ * DWC_ABORT if the thread never started. */
++extern int DWC_THREAD_STOP(dwc_thread_t *thread);
++#define dwc_thread_stop DWC_THREAD_STOP
++/** Signifies to the thread that it must stop. */
++extern dwc_bool_t DWC_THREAD_SHOULD_STOP(void);
++#define dwc_thread_should_stop DWC_THREAD_SHOULD_STOP
++
++/** @name Work queues
++ *
++ * Workqs are used to queue a callback function to be called at some later time,
++ * in another thread. */
++struct dwc_workq;
++typedef struct dwc_workq dwc_workq_t;
++
++/** The type of the callback function to be called. */
++typedef void (*dwc_work_callback_t)(void *data);
++
++/** Allocate a workq */
++extern dwc_workq_t *DWC_WORKQ_ALLOC(char *name);
++#define dwc_workq_alloc DWC_WORKQ_ALLOC
++/** Free a workq.  All work must be completed before being freed. */
++extern void DWC_WORKQ_FREE(dwc_workq_t *workq);
++#define dwc_workq_free DWC_WORKQ_FREE
++/** Schedule a callback on the workq, passing in data.  The function will be
++ * scheduled at some later time. */
++extern void DWC_WORKQ_SCHEDULE(dwc_workq_t *workq, dwc_work_callback_t work_cb, void *data, char *format, ...)
++#ifdef __GNUC__
++      __attribute__ ((format(printf, 4, 5)));
++#else
++  ;
++#endif
++#define dwc_workq_schedule DWC_WORKQ_SCHEDULE
++
++/** Schedule a callback on the workq, that will be called until at least 
++ * given number miliseconds have passed. */
++extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t work_cb, void *data, uint32_t time, char *format, ...)
++#ifdef __GNUC__
++      __attribute__ ((format(printf, 5, 6)));
++#else
++  ;
++#endif
++#define dwc_workq_schedule_delayed DWC_WORKQ_SCHEDULE_DELAYED
++
++/** The number of processes in the workq */
++extern int DWC_WORKQ_PENDING(dwc_workq_t *workq);
++#define dwc_workq_pending DWC_WORKQ_PENDING
++/** Blocks until all the work in the workq is complete or timed out.  Returns <
++ * 0 on timeout. */
++extern int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout);
++#define dwc_workq_wait_work_done DWC_WORKQ_WAIT_WORK_DONE
++
++
++/** @name Tasklets
++ *
++ */
++struct dwc_tasklet;
++typedef struct dwc_tasklet dwc_tasklet_t;
++
++typedef void (*dwc_tasklet_callback_t)(void *data);
++
++extern dwc_tasklet_t *DWC_TASK_ALLOC(dwc_tasklet_callback_t cb, void *data);
++#define dwc_task_alloc DWC_TASK_ALLOC
++extern void DWC_TASK_FREE(dwc_tasklet_t *t);
++#define dwc_task_free DWC_TASK_FREE
++extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task);
++#define dwc_task_schedule DWC_TASK_SCHEDULE
++
++
++/** @name Timer
++ *
++ * Callbacks must be small and atomic.
++ */
++struct dwc_timer;
++typedef struct dwc_timer dwc_timer_t;
++
++typedef void (*dwc_timer_callback_t)(void *data);
++
++extern dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data);
++#define dwc_timer_alloc DWC_TIMER_ALLOC
++extern void DWC_TIMER_FREE(dwc_timer_t *timer);
++#define dwc_timer_free DWC_TIMER_FREE
++
++/** Schedules the timer to run at time ms from now.  And will repeat at every
++ * repeat_interval msec therafter
++ *
++ * Modifies a timer that is still awaiting execution to a new expiration time.
++ * The mod_time is added to the old time.  */
++extern void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time);
++#define dwc_timer_schedule DWC_TIMER_SCHEDULE
++
++/** Disables the timer from execution. */
++extern void DWC_TIMER_CANCEL(dwc_timer_t *timer);
++#define dwc_timer_cancel DWC_TIMER_CANCEL
++
++
++
++/** @name Spinlocks
++ *
++ * These locks are used when the work between the lock/unlock is atomic and
++ * short.  Interrupts are also disabled during the lock/unlock and thus they are
++ * suitable to lock between interrupt/non-interrupt context.  They also lock
++ * between processes if you have multiple CPUs or Preemption.  If you don't have
++ * multiple CPUS or Preemption, then the you can simply implement the
++ * DWC_SPINLOCK and DWC_SPINUNLOCK to disable and enable interrupts.  Because
++ * the work between the lock/unlock is atomic, the process context will never
++ * change, and so you never have to lock between processes.  */
++
++struct dwc_spinlock;
++typedef struct dwc_spinlock dwc_spinlock_t;
++
++/** Returns an initialized lock variable.  This function should allocate and
++ * initialize the OS-specific data structure used for locking.  This data
++ * structure is to be used for the DWC_LOCK and DWC_UNLOCK functions and should
++ * be freed by the DWC_FREE_LOCK when it is no longer used. */
++extern dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void);
++#define dwc_spinlock_alloc DWC_SPINLOCK_ALLOC
++
++/** Frees an initialized lock variable. */
++extern void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock);
++#define dwc_spinlock_free DWC_SPINLOCK_FREE
++
++/** Disables interrupts and blocks until it acquires the lock.
++ *
++ * @param lock Pointer to the spinlock.
++ * @param flags Unsigned long for irq flags storage.
++ */
++extern void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, uint64_t *flags);
++#define dwc_spinlock_irqsave DWC_SPINLOCK_IRQSAVE
++
++/** Re-enables the interrupt and releases the lock.
++ *
++ * @param lock Pointer to the spinlock.
++ * @param flags Unsigned long for irq flags storage.  Must be the same as was
++ * passed into DWC_LOCK.
++ */
++extern void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, uint64_t flags);
++#define dwc_spinunlock_irqrestore DWC_SPINUNLOCK_IRQRESTORE
++
++/** Blocks until it acquires the lock.
++ *
++ * @param lock Pointer to the spinlock.
++ */
++extern void DWC_SPINLOCK(dwc_spinlock_t *lock);
++#define dwc_spinlock DWC_SPINLOCK
++
++/** Releases the lock.
++ *
++ * @param lock Pointer to the spinlock.
++ */
++extern void DWC_SPINUNLOCK(dwc_spinlock_t *lock);
++#define dwc_spinunlock DWC_SPINUNLOCK
++
++/** @name Mutexes
++ *
++ * Unlike spinlocks Mutexes lock only between processes and the work between the
++ * lock/unlock CAN block, therefore it CANNOT be called from interrupt context.
++ */
++
++struct dwc_mutex;
++typedef struct dwc_mutex dwc_mutex_t;
++
++
++/* For Linux Mutex Debugging make it inline because the debugging routines use
++ * the symbol to determine recursive locking.  This makes it falsely think
++ * recursive locking occurs. */
++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
++#define DWC_MUTEX_ALLOC_LINUX_DEBUG(__mutexp) ({ \
++      __mutexp = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); \
++      mutex_init((struct mutex *)__mutexp); \
++})
++#endif
++extern dwc_mutex_t *DWC_MUTEX_ALLOC(void);
++#define dwc_mutex_alloc DWC_MUTEX_ALLOC
++
++/* For memory leak debugging when using Linux Mutex Debugging */
++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
++#define DWC_MUTEX_FREE(__mutexp) do { \
++      mutex_destroy((struct mutex *)__mutexp); \
++      DWC_FREE(__mutexp); \
++} while(0)
++#else
++extern void DWC_MUTEX_FREE(dwc_mutex_t *mutex);
++#define dwc_mutex_free DWC_MUTEX_FREE
++#endif
++
++extern void DWC_MUTEX_LOCK(dwc_mutex_t *mutex);
++#define dwc_mutex_lock DWC_MUTEX_LOCK
++/** Non-blocking lock returns 1 on successful lock. */
++extern int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex);
++#define dwc_mutex_trylock DWC_MUTEX_TRYLOCK
++extern void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex);
++#define dwc_mutex_unlock DWC_MUTEX_UNLOCK
++
++
++
++
++/** @name Time */
++
++/** Microsecond delay.
++ *
++ * @param usecs  Microseconds to delay.
++ */
++extern void DWC_UDELAY(uint32_t usecs);
++#define dwc_udelay DWC_UDELAY
++
++/** Millisecond delay.
++ *
++ * @param msecs  Milliseconds to delay.
++ */
++extern void DWC_MDELAY(uint32_t msecs);
++#define dwc_mdelay DWC_MDELAY
++
++/** Non-busy waiting.
++ * Sleeps for specified number of milliseconds.
++ *
++ * @param msecs Milliseconds to sleep.
++ */
++extern void DWC_MSLEEP(uint32_t msecs);
++#define dwc_msleep DWC_MSLEEP
++
++extern uint32_t DWC_TIME(void);
++#define dwc_time DWC_TIME
++
++#endif // _DWC_OS_H_
++
++
++
++
++/** @mainpage DWC Portability and Common Library
++ *
++ * This is the documentation for the DWC Portability and Common Library.
++ *
++ * @section intro Introduction
++ *
++ * The DWC Portability library consists of wrapper calls and data structures to
++ * all low-level functions which are typically provided by the OS.  The WUDEV
++ * driver uses only these functions.  In order to port the WUDEV driver, only
++ * the functions in this library need to be re-implemented, with the same
++ * behavior as documented here.
++ *
++ * The Common library consists of higher level functions, which rely only on
++ * calling the functions from the DWC Portability library.  These common
++ * routines are shared across modules.  Some of the common libraries need to be
++ * used directly by the driver programmer when porting WUDEV.  Such as the
++ * parameter and notification libraries.
++ *
++ * @section low Portability Library OS Wrapper Functions
++ *
++ * Any function starting with DWC and in all CAPS is a low-level OS-wrapper that
++ * needs to be implemented when porting, for example DWC_MUTEX_ALLOC().  All of
++ * these functions are included in the dwc_os.h file.
++ *
++ * There are many functions here covering a wide array of OS services.  Please
++ * see dwc_os.h for details, and implementation notes for each function.
++ *
++ * @section common Common Library Functions
++ *
++ * Any function starting with dwc and in all lowercase is a common library
++ * routine.  These functions have a portable implementation and do not need to
++ * be reimplemented when porting.  The common routines can be used by any
++ * driver, and some must be used by the end user to control the drivers.  For
++ * example, you must use the Parameter common library in order to set the
++ * parameters in the WUDEV module.
++ *
++ * The common libraries consist of the following:
++ *
++ * - Connection Contexts - Used internally and can be used by end-user.  See dwc_cc.h
++ * - Parameters - Used internally and can be used by end-user.  See dwc_params.h
++ * - Notifications - Used internally and can be used by end-user.  See dwc_notifier.h
++ * - Lists - Used internally and can be used by end-user.  See dwc_list.h
++ * - Memory Debugging - Used internally and can be used by end-user.  See dwc_os.h
++ * - Modpow - Used internally only.  See dwc_modpow.h
++ * - DH - Used internally only.  See dwc_dh.h
++ * - Crypto - Used internally only.  See dwc_crypto.h
++ *
++ *
++ * @section prereq Prerequistes For dwc_os.h
++ * @subsection types Data Types
++ *
++ * The dwc_os.h file assumes that several low-level data types are pre defined for the
++ * compilation environment.  These data types are:
++ *
++ * - uint8_t - unsigned 8-bit data type
++ * - int8_t - signed 8-bit data type
++ * - uint16_t - unsigned 16-bit data type
++ * - int16_t - signed 16-bit data type
++ * - uint32_t - unsigned 32-bit data type
++ * - int32_t - signed 32-bit data type
++ * - uint64_t - unsigned 64-bit data type
++ * - int64_t - signed 64-bit data type
++ *
++ * Ensure that these are defined before using dwc_os.h.  The easiest way to do
++ * that is to modify the top of the file to include the appropriate header.
++ * This is already done for the Linux environment.  If the DWC_LINUX macro is
++ * defined, the correct header will be added.  A standard header <stdint.h> is
++ * also used for environments where standard C headers are available.
++ *
++ * @subsection stdarg Variable Arguments
++ *
++ * Variable arguments are provided by a standard C header <stdarg.h>.  it is
++ * available in Both the Linux and ANSI C enviornment.  An equivalent must be
++ * provided in your enviornment in order to use dwc_os.h with the debug and
++ * tracing message functionality.
++ *
++ * @subsection thread Threading
++ *
++ * WUDEV Core must be run on an operating system that provides for multiple
++ * threads/processes.  Threading can be implemented in many ways, even in
++ * embedded systems without an operating system.  At the bare minimum, the
++ * system should be able to start any number of processes at any time to handle
++ * special work.  It need not be a pre-emptive system.  Process context can
++ * change upon a call to a blocking function.  The hardware interrupt context
++ * that calls the module's ISR() function must be differentiable from process
++ * context, even if your processes are impemented via a hardware interrupt.
++ * Further locking mechanism between process must exist (or be implemented), and
++ * process context must have a way to disable interrupts for a period of time to
++ * lock them out.  If all of this exists, the functions in dwc_os.h related to
++ * threading should be able to be implemented with the defined behavior.
++ *
++ */
+--- /dev/null
++++ b/drivers/usb/host/dwc_common_port/usb.h
+@@ -0,0 +1,850 @@
++/*
++ * Copyright (c) 1998 The NetBSD Foundation, Inc.
++ * All rights reserved.
++ *
++ * This code is derived from software contributed to The NetBSD Foundation
++ * by Lennart Augustsson (lennart@augustsson.net) at
++ * Carlstedt Research & Technology.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ *    must display the following acknowledgement:
++ *        This product includes software developed by the NetBSD
++ *        Foundation, Inc. and its contributors.
++ * 4. Neither the name of The NetBSD Foundation nor the names of its
++ *    contributors may be used to endorse or promote products derived
++ *    from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
++ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
++ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
++ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++
++/* Modified by Synopsys, Inc, 12/12/2007 */
++
++
++#ifndef _USB_H_
++#define _USB_H_
++
++#include "dwc_os.h"
++
++/*
++ * The USB records contain some unaligned little-endian word
++ * components.  The U[SG]ETW macros take care of both the alignment
++ * and endian problem and should always be used to access non-byte
++ * values.
++ */
++typedef u_int8_t uByte;
++typedef u_int8_t uWord[2];
++typedef u_int8_t uDWord[4];
++
++#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h))
++
++#if 1
++#define UGETW(w) ((w)[0] | ((w)[1] << 8))
++#define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8))
++#define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24))
++#define USETDW(w,v) ((w)[0] = (u_int8_t)(v), \
++                   (w)[1] = (u_int8_t)((v) >> 8), \
++                   (w)[2] = (u_int8_t)((v) >> 16), \
++                   (w)[3] = (u_int8_t)((v) >> 24))
++#else
++/*
++ * On little-endian machines that can handle unanliged accesses
++ * (e.g. i386) these macros can be replaced by the following.
++ */
++#define UGETW(w) (*(u_int16_t *)(w))
++#define USETW(w,v) (*(u_int16_t *)(w) = (v))
++#define UGETDW(w) (*(u_int32_t *)(w))
++#define USETDW(w,v) (*(u_int32_t *)(w) = (v))
++#endif
++
++#define UPACKED __attribute__((__packed__))
++
++typedef struct {
++      uByte           bmRequestType;
++      uByte           bRequest;
++      uWord           wValue;
++      uWord           wIndex;
++      uWord           wLength;
++} UPACKED usb_device_request_t;
++
++#define UT_GET_DIR(a) ((a) & 0x80)
++#define UT_WRITE              0x00
++#define UT_READ                       0x80
++
++#define UT_GET_TYPE(a) ((a) & 0x60)
++#define UT_STANDARD           0x00
++#define UT_CLASS              0x20
++#define UT_VENDOR             0x40
++
++#define UT_GET_RECIPIENT(a) ((a) & 0x1f)
++#define UT_DEVICE             0x00
++#define UT_INTERFACE          0x01
++#define UT_ENDPOINT           0x02
++#define UT_OTHER              0x03
++
++#define UT_READ_DEVICE                (UT_READ  | UT_STANDARD | UT_DEVICE)
++#define UT_READ_INTERFACE     (UT_READ  | UT_STANDARD | UT_INTERFACE)
++#define UT_READ_ENDPOINT      (UT_READ  | UT_STANDARD | UT_ENDPOINT)
++#define UT_WRITE_DEVICE               (UT_WRITE | UT_STANDARD | UT_DEVICE)
++#define UT_WRITE_INTERFACE    (UT_WRITE | UT_STANDARD | UT_INTERFACE)
++#define UT_WRITE_ENDPOINT     (UT_WRITE | UT_STANDARD | UT_ENDPOINT)
++#define UT_READ_CLASS_DEVICE  (UT_READ  | UT_CLASS | UT_DEVICE)
++#define UT_READ_CLASS_INTERFACE       (UT_READ  | UT_CLASS | UT_INTERFACE)
++#define UT_READ_CLASS_OTHER   (UT_READ  | UT_CLASS | UT_OTHER)
++#define UT_READ_CLASS_ENDPOINT        (UT_READ  | UT_CLASS | UT_ENDPOINT)
++#define UT_WRITE_CLASS_DEVICE (UT_WRITE | UT_CLASS | UT_DEVICE)
++#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE)
++#define UT_WRITE_CLASS_OTHER  (UT_WRITE | UT_CLASS | UT_OTHER)
++#define UT_WRITE_CLASS_ENDPOINT       (UT_WRITE | UT_CLASS | UT_ENDPOINT)
++#define UT_READ_VENDOR_DEVICE (UT_READ  | UT_VENDOR | UT_DEVICE)
++#define UT_READ_VENDOR_INTERFACE (UT_READ  | UT_VENDOR | UT_INTERFACE)
++#define UT_READ_VENDOR_OTHER  (UT_READ  | UT_VENDOR | UT_OTHER)
++#define UT_READ_VENDOR_ENDPOINT       (UT_READ  | UT_VENDOR | UT_ENDPOINT)
++#define UT_WRITE_VENDOR_DEVICE        (UT_WRITE | UT_VENDOR | UT_DEVICE)
++#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE)
++#define UT_WRITE_VENDOR_OTHER (UT_WRITE | UT_VENDOR | UT_OTHER)
++#define UT_WRITE_VENDOR_ENDPOINT (UT_WRITE | UT_VENDOR | UT_ENDPOINT)
++
++/* Requests */
++#define UR_GET_STATUS         0x00
++#define  USTAT_STANDARD_STATUS  0x00
++#define  WUSTAT_WUSB_FEATURE    0x01
++#define  WUSTAT_CHANNEL_INFO    0x02
++#define  WUSTAT_RECEIVED_DATA   0x03
++#define  WUSTAT_MAS_AVAILABILITY 0x04
++#define  WUSTAT_CURRENT_TRANSMIT_POWER 0x05
++#define UR_CLEAR_FEATURE      0x01
++#define UR_SET_FEATURE                0x03
++#define UR_SET_AND_TEST_FEATURE 0x0c
++#define UR_SET_ADDRESS                0x05
++#define UR_GET_DESCRIPTOR     0x06
++#define  UDESC_DEVICE         0x01
++#define  UDESC_CONFIG         0x02
++#define  UDESC_STRING         0x03
++#define  UDESC_INTERFACE      0x04
++#define  UDESC_ENDPOINT               0x05
++#define  UDESC_DEVICE_QUALIFIER       0x06
++#define  UDESC_OTHER_SPEED_CONFIGURATION 0x07
++#define  UDESC_INTERFACE_POWER        0x08
++#define  UDESC_OTG            0x09
++#define  WUDESC_SECURITY      0x0c
++#define  WUDESC_KEY           0x0d
++#define   WUD_GET_KEY_INDEX(_wValue_) ((_wValue_) & 0xf)
++#define   WUD_GET_KEY_TYPE(_wValue_) (((_wValue_) & 0x30) >> 4)
++#define    WUD_KEY_TYPE_ASSOC    0x01
++#define    WUD_KEY_TYPE_GTK      0x02
++#define   WUD_GET_KEY_ORIGIN(_wValue_) (((_wValue_) & 0x40) >> 6)
++#define    WUD_KEY_ORIGIN_HOST   0x00
++#define    WUD_KEY_ORIGIN_DEVICE 0x01
++#define  WUDESC_ENCRYPTION_TYPE       0x0e
++#define  WUDESC_BOS           0x0f
++#define  WUDESC_DEVICE_CAPABILITY 0x10
++#define  WUDESC_WIRELESS_ENDPOINT_COMPANION 0x11
++#define  UDESC_CS_DEVICE      0x21    /* class specific */
++#define  UDESC_CS_CONFIG      0x22
++#define  UDESC_CS_STRING      0x23
++#define  UDESC_CS_INTERFACE   0x24
++#define  UDESC_CS_ENDPOINT    0x25
++#define  UDESC_HUB            0x29
++#define UR_SET_DESCRIPTOR     0x07
++#define UR_GET_CONFIG         0x08
++#define UR_SET_CONFIG         0x09
++#define UR_GET_INTERFACE      0x0a
++#define UR_SET_INTERFACE      0x0b
++#define UR_SYNCH_FRAME                0x0c
++#define WUR_SET_ENCRYPTION      0x0d
++#define WUR_GET_ENCRYPTION    0x0e
++#define WUR_SET_HANDSHAKE     0x0f
++#define WUR_GET_HANDSHAKE     0x10
++#define WUR_SET_CONNECTION    0x11
++#define WUR_SET_SECURITY_DATA 0x12
++#define WUR_GET_SECURITY_DATA 0x13
++#define WUR_SET_WUSB_DATA     0x14
++#define  WUDATA_DRPIE_INFO  0x01
++#define  WUDATA_TRANSMIT_DATA 0x02
++#define  WUDATA_TRANSMIT_PARAMS 0x03
++#define  WUDATA_RECEIVE_PARAMS 0x04
++#define  WUDATA_TRANSMIT_POWER 0x05
++#define WUR_LOOPBACK_DATA_WRITE       0x15
++#define WUR_LOOPBACK_DATA_READ        0x16
++#define WUR_SET_INTERFACE_DS  0x17
++
++/* Feature numbers */
++#define UF_ENDPOINT_HALT      0
++#define UF_DEVICE_REMOTE_WAKEUP       1
++#define UF_TEST_MODE          2
++#define UF_DEVICE_B_HNP_ENABLE        3
++#define UF_DEVICE_A_HNP_SUPPORT       4
++#define UF_DEVICE_A_ALT_HNP_SUPPORT 5
++#define WUF_WUSB                3
++#define  WUF_TX_DRPIE           0x0
++#define  WUF_DEV_XMIT_PACKET    0x1
++#define  WUF_COUNT_PACKETS      0x2
++#define  WUF_CAPTURE_PACKETS    0x3
++
++/* Class requests from the USB 2.0 hub spec, table 11-15 */
++#define UCR_CLEAR_HUB_FEATURE         (0x2000 | UR_CLEAR_FEATURE)
++#define UCR_CLEAR_PORT_FEATURE                (0x2300 | UR_CLEAR_FEATURE)
++#define UCR_GET_HUB_DESCRIPTOR                (0xa000 | UR_GET_DESCRIPTOR)
++#define UCR_GET_HUB_STATUS            (0xa000 | UR_GET_STATUS)
++#define UCR_GET_PORT_STATUS           (0xa300 | UR_GET_STATUS)
++#define UCR_SET_HUB_FEATURE           (0x2000 | UR_SET_FEATURE)
++#define UCR_SET_PORT_FEATURE          (0x2300 | UR_SET_FEATURE)
++#define UCR_SET_AND_TEST_PORT_FEATURE (0xa300 | UR_SET_AND_TEST_FEATURE)
++
++typedef struct {
++      uByte           bLength;
++      uByte           bDescriptorType;
++      uByte           bDescriptorSubtype;
++} UPACKED usb_descriptor_t;
++
++typedef struct {
++      uByte           bLength;
++      uByte           bDescriptorType;
++      uWord           bcdUSB;
++#define UD_USB_2_0            0x0200
++#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0)
++      uByte           bDeviceClass;
++      uByte           bDeviceSubClass;
++      uByte           bDeviceProtocol;
++      uByte           bMaxPacketSize;
++      /* The fields below are not part of the initial descriptor. */
++      uWord           idVendor;
++      uWord           idProduct;
++      uWord           bcdDevice;
++      uByte           iManufacturer;
++      uByte           iProduct;
++      uByte           iSerialNumber;
++      uByte           bNumConfigurations;
++} UPACKED usb_device_descriptor_t;
++#define USB_DEVICE_DESCRIPTOR_SIZE 18
++
++typedef struct {
++      uByte           bLength;
++      uByte           bDescriptorType;
++      uWord           wTotalLength;
++      uByte           bNumInterface;
++      uByte           bConfigurationValue;
++      uByte           iConfiguration;
++      uByte           bmAttributes;
++#define UC_BUS_POWERED                0x80
++#define UC_SELF_POWERED               0x40
++#define UC_REMOTE_WAKEUP      0x20
++      uByte           bMaxPower; /* max current in 2 mA units */
++#define UC_POWER_FACTOR 2
++} UPACKED usb_config_descriptor_t;
++#define USB_CONFIG_DESCRIPTOR_SIZE 9
++
++typedef struct {
++      uByte           bLength;
++      uByte           bDescriptorType;
++      uByte           bInterfaceNumber;
++      uByte           bAlternateSetting;
++      uByte           bNumEndpoints;
++      uByte           bInterfaceClass;
++      uByte           bInterfaceSubClass;
++      uByte           bInterfaceProtocol;
++      uByte           iInterface;
++} UPACKED usb_interface_descriptor_t;
++#define USB_INTERFACE_DESCRIPTOR_SIZE 9
++
++typedef struct {
++      uByte           bLength;
++      uByte           bDescriptorType;
++      uByte           bEndpointAddress;
++#define UE_GET_DIR(a) ((a) & 0x80)
++#define UE_SET_DIR(a,d)       ((a) | (((d)&1) << 7))
++#define UE_DIR_IN     0x80
++#define UE_DIR_OUT    0x00
++#define UE_ADDR               0x0f
++#define UE_GET_ADDR(a)        ((a) & UE_ADDR)
++      uByte           bmAttributes;
++#define UE_XFERTYPE   0x03
++#define  UE_CONTROL   0x00
++#define  UE_ISOCHRONOUS       0x01
++#define  UE_BULK      0x02
++#define  UE_INTERRUPT 0x03
++#define UE_GET_XFERTYPE(a)    ((a) & UE_XFERTYPE)
++#define UE_ISO_TYPE   0x0c
++#define  UE_ISO_ASYNC 0x04
++#define  UE_ISO_ADAPT 0x08
++#define  UE_ISO_SYNC  0x0c
++#define UE_GET_ISO_TYPE(a)    ((a) & UE_ISO_TYPE)
++      uWord           wMaxPacketSize;
++      uByte           bInterval;
++} UPACKED usb_endpoint_descriptor_t;
++#define USB_ENDPOINT_DESCRIPTOR_SIZE 7
++
++typedef struct {
++      uByte           bLength;
++      uByte           bDescriptorType;
++      uWord           bString[127];
++} UPACKED usb_string_descriptor_t;
++#define USB_MAX_STRING_LEN 128
++#define USB_LANGUAGE_TABLE 0  /* # of the string language id table */
++
++/* Hub specific request */
++#define UR_GET_BUS_STATE      0x02
++#define UR_CLEAR_TT_BUFFER    0x08
++#define UR_RESET_TT           0x09
++#define UR_GET_TT_STATE               0x0a
++#define UR_STOP_TT            0x0b
++
++/* Hub features */
++#define UHF_C_HUB_LOCAL_POWER 0
++#define UHF_C_HUB_OVER_CURRENT        1
++#define UHF_PORT_CONNECTION   0
++#define UHF_PORT_ENABLE               1
++#define UHF_PORT_SUSPEND      2
++#define UHF_PORT_OVER_CURRENT 3
++#define UHF_PORT_RESET                4
++#define UHF_PORT_L1           5
++#define UHF_PORT_POWER                8
++#define UHF_PORT_LOW_SPEED    9
++#define UHF_PORT_HIGH_SPEED   10
++#define UHF_C_PORT_CONNECTION 16
++#define UHF_C_PORT_ENABLE     17
++#define UHF_C_PORT_SUSPEND    18
++#define UHF_C_PORT_OVER_CURRENT       19
++#define UHF_C_PORT_RESET      20
++#define UHF_C_PORT_L1         23
++#define UHF_PORT_TEST         21
++#define UHF_PORT_INDICATOR    22
++
++typedef struct {
++      uByte           bDescLength;
++      uByte           bDescriptorType;
++      uByte           bNbrPorts;
++      uWord           wHubCharacteristics;
++#define UHD_PWR                       0x0003
++#define  UHD_PWR_GANGED               0x0000
++#define  UHD_PWR_INDIVIDUAL   0x0001
++#define  UHD_PWR_NO_SWITCH    0x0002
++#define UHD_COMPOUND          0x0004
++#define UHD_OC                        0x0018
++#define  UHD_OC_GLOBAL                0x0000
++#define  UHD_OC_INDIVIDUAL    0x0008
++#define  UHD_OC_NONE          0x0010
++#define UHD_TT_THINK          0x0060
++#define  UHD_TT_THINK_8               0x0000
++#define  UHD_TT_THINK_16      0x0020
++#define  UHD_TT_THINK_24      0x0040
++#define  UHD_TT_THINK_32      0x0060
++#define UHD_PORT_IND          0x0080
++      uByte           bPwrOn2PwrGood; /* delay in 2 ms units */
++#define UHD_PWRON_FACTOR 2
++      uByte           bHubContrCurrent;
++      uByte           DeviceRemovable[32]; /* max 255 ports */
++#define UHD_NOT_REMOV(desc, i) \
++    (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1)
++      /* deprecated */ uByte          PortPowerCtrlMask[1];
++} UPACKED usb_hub_descriptor_t;
++#define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */
++
++typedef struct {
++      uByte           bLength;
++      uByte           bDescriptorType;
++      uWord           bcdUSB;
++      uByte           bDeviceClass;
++      uByte           bDeviceSubClass;
++      uByte           bDeviceProtocol;
++      uByte           bMaxPacketSize0;
++      uByte           bNumConfigurations;
++      uByte           bReserved;
++} UPACKED usb_device_qualifier_t;
++#define USB_DEVICE_QUALIFIER_SIZE 10
++
++typedef struct {
++      uByte           bLength;
++      uByte           bDescriptorType;
++      uByte           bmAttributes;
++#define UOTG_SRP      0x01
++#define UOTG_HNP      0x02
++} UPACKED usb_otg_descriptor_t;
++
++/* OTG feature selectors */
++#define UOTG_B_HNP_ENABLE     3
++#define UOTG_A_HNP_SUPPORT    4
++#define UOTG_A_ALT_HNP_SUPPORT        5
++
++typedef struct {
++      uWord           wStatus;
++/* Device status flags */
++#define UDS_SELF_POWERED              0x0001
++#define UDS_REMOTE_WAKEUP             0x0002
++/* Endpoint status flags */
++#define UES_HALT                      0x0001
++} UPACKED usb_status_t;
++
++typedef struct {
++      uWord           wHubStatus;
++#define UHS_LOCAL_POWER                       0x0001
++#define UHS_OVER_CURRENT              0x0002
++      uWord           wHubChange;
++} UPACKED usb_hub_status_t;
++
++typedef struct {
++      uWord           wPortStatus;
++#define UPS_CURRENT_CONNECT_STATUS    0x0001
++#define UPS_PORT_ENABLED              0x0002
++#define UPS_SUSPEND                   0x0004
++#define UPS_OVERCURRENT_INDICATOR     0x0008
++#define UPS_RESET                     0x0010
++#define UPS_PORT_POWER                        0x0100
++#define UPS_LOW_SPEED                 0x0200
++#define UPS_HIGH_SPEED                        0x0400
++#define UPS_PORT_TEST                 0x0800
++#define UPS_PORT_INDICATOR            0x1000
++      uWord           wPortChange;
++#define UPS_C_CONNECT_STATUS          0x0001
++#define UPS_C_PORT_ENABLED            0x0002
++#define UPS_C_SUSPEND                 0x0004
++#define UPS_C_OVERCURRENT_INDICATOR   0x0008
++#define UPS_C_PORT_RESET              0x0010
++} UPACKED usb_port_status_t;
++
++/* Device class codes */
++#define UDCLASS_IN_INTERFACE  0x00
++#define UDCLASS_COMM          0x02
++#define UDCLASS_HUB           0x09
++#define  UDSUBCLASS_HUB               0x00
++#define  UDPROTO_FSHUB                0x00
++#define  UDPROTO_HSHUBSTT     0x01
++#define  UDPROTO_HSHUBMTT     0x02
++#define UDCLASS_DIAGNOSTIC    0xdc
++#define UDCLASS_WIRELESS      0xe0
++#define  UDSUBCLASS_RF                0x01
++#define   UDPROTO_BLUETOOTH   0x01
++#define UDCLASS_VENDOR                0xff
++
++/* Interface class codes */
++#define UICLASS_UNSPEC                0x00
++
++#define UICLASS_AUDIO         0x01
++#define  UISUBCLASS_AUDIOCONTROL      1
++#define  UISUBCLASS_AUDIOSTREAM               2
++#define  UISUBCLASS_MIDISTREAM                3
++
++#define UICLASS_CDC           0x02 /* communication */
++#define        UISUBCLASS_DIRECT_LINE_CONTROL_MODEL   1
++#define  UISUBCLASS_ABSTRACT_CONTROL_MODEL    2
++#define        UISUBCLASS_TELEPHONE_CONTROL_MODEL     3
++#define        UISUBCLASS_MULTICHANNEL_CONTROL_MODEL  4
++#define        UISUBCLASS_CAPI_CONTROLMODEL           5
++#define        UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6
++#define        UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7
++#define   UIPROTO_CDC_AT                      1
++
++#define UICLASS_HID           0x03
++#define  UISUBCLASS_BOOT      1
++#define  UIPROTO_BOOT_KEYBOARD        1
++
++#define UICLASS_PHYSICAL      0x05
++
++#define UICLASS_IMAGE         0x06
++
++#define UICLASS_PRINTER               0x07
++#define  UISUBCLASS_PRINTER   1
++#define  UIPROTO_PRINTER_UNI  1
++#define  UIPROTO_PRINTER_BI   2
++#define  UIPROTO_PRINTER_1284 3
++
++#define UICLASS_MASS          0x08
++#define  UISUBCLASS_RBC               1
++#define  UISUBCLASS_SFF8020I  2
++#define  UISUBCLASS_QIC157    3
++#define  UISUBCLASS_UFI               4
++#define  UISUBCLASS_SFF8070I  5
++#define  UISUBCLASS_SCSI      6
++#define  UIPROTO_MASS_CBI_I   0
++#define  UIPROTO_MASS_CBI     1
++#define  UIPROTO_MASS_BBB_OLD 2       /* Not in the spec anymore */
++#define  UIPROTO_MASS_BBB     80      /* 'P' for the Iomega Zip drive */
++
++#define UICLASS_HUB           0x09
++#define  UISUBCLASS_HUB               0
++#define  UIPROTO_FSHUB                0
++#define  UIPROTO_HSHUBSTT     0 /* Yes, same as previous */
++#define  UIPROTO_HSHUBMTT     1
++
++#define UICLASS_CDC_DATA      0x0a
++#define  UISUBCLASS_DATA              0
++#define   UIPROTO_DATA_ISDNBRI                0x30    /* Physical iface */
++#define   UIPROTO_DATA_HDLC           0x31    /* HDLC */
++#define   UIPROTO_DATA_TRANSPARENT    0x32    /* Transparent */
++#define   UIPROTO_DATA_Q921M          0x50    /* Management for Q921 */
++#define   UIPROTO_DATA_Q921           0x51    /* Data for Q921 */
++#define   UIPROTO_DATA_Q921TM         0x52    /* TEI multiplexer for Q921 */
++#define   UIPROTO_DATA_V42BIS         0x90    /* Data compression */
++#define   UIPROTO_DATA_Q931           0x91    /* Euro-ISDN */
++#define   UIPROTO_DATA_V120           0x92    /* V.24 rate adaption */
++#define   UIPROTO_DATA_CAPI           0x93    /* CAPI 2.0 commands */
++#define   UIPROTO_DATA_HOST_BASED     0xfd    /* Host based driver */
++#define   UIPROTO_DATA_PUF            0xfe    /* see Prot. Unit Func. Desc.*/
++#define   UIPROTO_DATA_VENDOR         0xff    /* Vendor specific */
++
++#define UICLASS_SMARTCARD     0x0b
++
++/*#define UICLASS_FIRM_UPD    0x0c*/
++
++#define UICLASS_SECURITY      0x0d
++
++#define UICLASS_DIAGNOSTIC    0xdc
++
++#define UICLASS_WIRELESS      0xe0
++#define  UISUBCLASS_RF                        0x01
++#define   UIPROTO_BLUETOOTH           0x01
++
++#define UICLASS_APPL_SPEC     0xfe
++#define  UISUBCLASS_FIRMWARE_DOWNLOAD 1
++#define  UISUBCLASS_IRDA              2
++#define  UIPROTO_IRDA                 0
++
++#define UICLASS_VENDOR                0xff
++
++
++#define USB_HUB_MAX_DEPTH 5
++
++/*
++ * Minimum time a device needs to be powered down to go through
++ * a power cycle.  XXX Are these time in the spec?
++ */
++#define USB_POWER_DOWN_TIME   200 /* ms */
++#define USB_PORT_POWER_DOWN_TIME      100 /* ms */
++
++#if 0
++/* These are the values from the spec. */
++#define USB_PORT_RESET_DELAY  10  /* ms */
++#define USB_PORT_ROOT_RESET_DELAY 50  /* ms */
++#define USB_PORT_RESET_RECOVERY       10  /* ms */
++#define USB_PORT_POWERUP_DELAY        100 /* ms */
++#define USB_SET_ADDRESS_SETTLE        2   /* ms */
++#define USB_RESUME_DELAY      (20*5)  /* ms */
++#define USB_RESUME_WAIT               10  /* ms */
++#define USB_RESUME_RECOVERY   10  /* ms */
++#define USB_EXTRA_POWER_UP_TIME       0   /* ms */
++#else
++/* Allow for marginal (i.e. non-conforming) devices. */
++#define USB_PORT_RESET_DELAY  50  /* ms */
++#define USB_PORT_ROOT_RESET_DELAY 250  /* ms */
++#define USB_PORT_RESET_RECOVERY       250  /* ms */
++#define USB_PORT_POWERUP_DELAY        300 /* ms */
++#define USB_SET_ADDRESS_SETTLE        10  /* ms */
++#define USB_RESUME_DELAY      (50*5)  /* ms */
++#define USB_RESUME_WAIT               50  /* ms */
++#define USB_RESUME_RECOVERY   50  /* ms */
++#define USB_EXTRA_POWER_UP_TIME       20  /* ms */
++#endif
++
++#define USB_MIN_POWER         100 /* mA */
++#define USB_MAX_POWER         500 /* mA */
++
++#define USB_BUS_RESET_DELAY   100 /* ms XXX?*/
++
++
++#define USB_UNCONFIG_NO 0
++#define USB_UNCONFIG_INDEX (-1)
++
++/*** ioctl() related stuff ***/
++
++struct usb_ctl_request {
++      int     ucr_addr;
++      usb_device_request_t ucr_request;
++      void    *ucr_data;
++      int     ucr_flags;
++#define USBD_SHORT_XFER_OK    0x04    /* allow short reads */
++      int     ucr_actlen;             /* actual length transferred */
++};
++
++struct usb_alt_interface {
++      int     uai_config_index;
++      int     uai_interface_index;
++      int     uai_alt_no;
++};
++
++#define USB_CURRENT_CONFIG_INDEX (-1)
++#define USB_CURRENT_ALT_INDEX (-1)
++
++struct usb_config_desc {
++      int     ucd_config_index;
++      usb_config_descriptor_t ucd_desc;
++};
++
++struct usb_interface_desc {
++      int     uid_config_index;
++      int     uid_interface_index;
++      int     uid_alt_index;
++      usb_interface_descriptor_t uid_desc;
++};
++
++struct usb_endpoint_desc {
++      int     ued_config_index;
++      int     ued_interface_index;
++      int     ued_alt_index;
++      int     ued_endpoint_index;
++      usb_endpoint_descriptor_t ued_desc;
++};
++
++struct usb_full_desc {
++      int     ufd_config_index;
++      u_int   ufd_size;
++      u_char  *ufd_data;
++};
++
++struct usb_string_desc {
++      int     usd_string_index;
++      int     usd_language_id;
++      usb_string_descriptor_t usd_desc;
++};
++
++struct usb_ctl_report_desc {
++      int     ucrd_size;
++      u_char  ucrd_data[1024];        /* filled data size will vary */
++};
++
++typedef struct { u_int32_t cookie; } usb_event_cookie_t;
++
++#define USB_MAX_DEVNAMES 4
++#define USB_MAX_DEVNAMELEN 16
++struct usb_device_info {
++      u_int8_t        udi_bus;
++      u_int8_t        udi_addr;       /* device address */
++      usb_event_cookie_t udi_cookie;
++      char            udi_product[USB_MAX_STRING_LEN];
++      char            udi_vendor[USB_MAX_STRING_LEN];
++      char            udi_release[8];
++      u_int16_t       udi_productNo;
++      u_int16_t       udi_vendorNo;
++      u_int16_t       udi_releaseNo;
++      u_int8_t        udi_class;
++      u_int8_t        udi_subclass;
++      u_int8_t        udi_protocol;
++      u_int8_t        udi_config;
++      u_int8_t        udi_speed;
++#define USB_SPEED_LOW  1
++#define USB_SPEED_FULL 2
++#define USB_SPEED_HIGH 3
++      int             udi_power;      /* power consumption in mA, 0 if selfpowered */
++      int             udi_nports;
++      char            udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN];
++      u_int8_t        udi_ports[16];/* hub only: addresses of devices on ports */
++#define USB_PORT_ENABLED 0xff
++#define USB_PORT_SUSPENDED 0xfe
++#define USB_PORT_POWERED 0xfd
++#define USB_PORT_DISABLED 0xfc
++};
++
++struct usb_ctl_report {
++      int     ucr_report;
++      u_char  ucr_data[1024]; /* filled data size will vary */
++};
++
++struct usb_device_stats {
++      u_long  uds_requests[4];        /* indexed by transfer type UE_* */
++};
++
++
++
++
++#define WUSB_MIN_IE                   0x80
++#define WUSB_WCTA_IE                  0x80
++#define WUSB_WCONNECTACK_IE           0x81
++#define WUSB_WHOSTINFO_IE             0x82
++#define  WUHI_GET_CA(_bmAttributes_) ((_bmAttributes_) & 0x3)
++#define   WUHI_CA_RECONN                      0x00
++#define   WUHI_CA_LIMITED             0x01
++#define   WUHI_CA_ALL                 0x03
++#define  WUHI_GET_MLSI(_bmAttributes_) (((_bmAttributes_) & 0x38) >> 3)
++#define WUSB_WCHCHANGEANNOUNCE_IE     0x83
++#define WUSB_WDEV_DISCONNECT_IE               0x84
++#define WUSB_WHOST_DISCONNECT_IE      0x85
++#define WUSB_WRELEASE_CHANNEL_IE      0x86
++#define WUSB_WWORK_IE                 0x87
++#define WUSB_WCHANNEL_STOP_IE         0x88
++#define WUSB_WDEV_KEEPALIVE_IE                0x89
++#define WUSB_WISOCH_DISCARD_IE                0x8A
++#define WUSB_WRESETDEVICE_IE          0x8B
++#define WUSB_WXMIT_PACKET_ADJUST_IE   0x8C
++#define WUSB_MAX_IE                   0x8C
++
++/* Device Notification Types */
++
++#define WUSB_DN_MIN                   0x01
++#define WUSB_DN_CONNECT                       0x01
++# define WUSB_DA_OLDCONN      0x00
++# define WUSB_DA_NEWCONN      0x01
++# define WUSB_DA_SELF_BEACON  0x02
++# define WUSB_DA_DIR_BEACON   0x04
++# define WUSB_DA_NO_BEACON    0x06
++#define WUSB_DN_DISCONNECT            0x02
++#define WUSB_DN_EPRDY                 0x03
++#define WUSB_DN_MASAVAILCHANGED               0x04
++#define WUSB_DN_REMOTEWAKEUP          0x05
++#define WUSB_DN_SLEEP                 0x06
++#define WUSB_DN_ALIVE                 0x07
++#define WUSB_DN_MAX                   0x07
++
++
++/* WUSB Handshake Data.  Used during the SET/GET HANDSHAKE requests */
++typedef struct wusb_hndshk_data {
++      uint8_t bMessageNumber;
++      uint8_t bStatus;
++      uint8_t tTKID[3];
++      uint8_t bReserved;
++      uint8_t CDID[16];
++      uint8_t Nonce[16];
++      uint8_t MIC[8];
++} UPACKED wusb_hndshk_data_t;
++#define WUSB_HANDSHAKE_LEN_FOR_MIC    38
++
++/* WUSB Connection Context */
++typedef struct wusb_conn_context {
++      uint8_t CHID [16];
++      uint8_t CDID [16];
++      uint8_t CK [16];
++} UPACKED wusb_conn_context_t;
++
++/* WUSB Security Descriptor */
++typedef struct wusb_security_desc {
++      uint8_t bLength;
++      uint8_t bDescriptorType;
++      uint16_t wTotalLength;
++      uint8_t bNumEncryptionTypes;
++} UPACKED wusb_security_desc_t;
++
++/* WUSB Encryption Type Descriptor */
++typedef struct wusb_encrypt_type_desc {
++      uint8_t bLength;
++      uint8_t bDescriptorType;
++
++      uint8_t bEncryptionType;
++#define WUETD_UNSECURE                0
++#define WUETD_WIRED           1
++#define WUETD_CCM_1           2
++#define WUETD_RSA_1           3
++
++      uint8_t bEncryptionValue;
++      uint8_t bAuthKeyIndex;
++} UPACKED wusb_encrypt_type_desc_t;
++
++/* WUSB Key Descriptor */
++typedef struct wusb_key_desc {
++      uint8_t bLength;
++      uint8_t bDescriptorType;
++      uint8_t tTKID[3];
++      uint8_t bReserved;
++      uint8_t KeyData[1];     /* variable length */
++} UPACKED wusb_key_desc_t;
++
++/* WUSB BOS Descriptor (Binary device Object Store) */
++typedef struct wusb_bos_desc {
++      uint8_t bLength;
++      uint8_t bDescriptorType;
++      uint16_t wTotalLength;
++      uint8_t bNumDeviceCaps;
++} UPACKED wusb_bos_desc_t;
++
++
++/* Device Capability Type Codes */
++#define WUSB_DEVICE_CAPABILITY_WIRELESS_USB 0x01
++
++/* Device Capability Descriptor */
++typedef struct wusb_dev_cap_desc {
++      uint8_t bLength;
++      uint8_t bDescriptorType;
++      uint8_t bDevCapabilityType;
++      uint8_t caps[1];              /* Variable length */
++} UPACKED wusb_dev_cap_desc_t;
++
++/* Device Capability Descriptor */
++typedef struct wusb_dev_cap_uwb_desc {
++      uint8_t bLength;
++      uint8_t bDescriptorType;
++      uint8_t bDevCapabilityType;
++      uint8_t bmAttributes;
++      uint16_t wPHYRates;      /* Bitmap */
++      uint8_t bmTFITXPowerInfo;
++      uint8_t bmFFITXPowerInfo;
++      uint16_t bmBandGroup;
++      uint8_t bReserved;
++} UPACKED wusb_dev_cap_uwb_desc_t;
++
++/* Wireless USB Endpoint Companion Descriptor */
++typedef struct wusb_endpoint_companion_desc {
++      uint8_t bLength;
++      uint8_t bDescriptorType;
++      uint8_t bMaxBurst;
++      uint8_t bMaxSequence;
++      uint16_t wMaxStreamDelay;
++      uint16_t wOverTheAirPacketSize;
++      uint8_t bOverTheAirInterval;
++      uint8_t bmCompAttributes;
++} UPACKED wusb_endpoint_companion_desc_t;
++
++
++/* Wireless USB Numeric Association M1 Data Structure */
++typedef struct wusb_m1_data {
++      uint8_t version;
++      uint16_t langId;
++      uint8_t deviceFriendlyNameLength;
++      uint8_t sha_256_m3[32];
++      uint8_t deviceFriendlyName[256];
++} UPACKED wusb_m1_data_t;
++
++typedef struct wusb_m2_data {
++      uint8_t version;
++      uint16_t langId;
++      uint8_t hostFriendlyNameLength;
++      uint8_t pkh[384];
++      uint8_t hostFriendlyName[256];
++} UPACKED wusb_m2_data_t;
++
++typedef struct wusb_m3_data {
++      uint8_t pkd[384];
++      uint8_t nd;
++} UPACKED wusb_m3_data_t;
++
++typedef struct wusb_m4_data {
++      uint32_t _attributeTypeIdAndLength_1;
++      uint16_t associationTypeId;
++
++      uint32_t _attributeTypeIdAndLength_2;
++      uint16_t associationSubTypeId;
++
++      uint32_t _attributeTypeIdAndLength_3;
++      uint32_t length;
++
++      uint32_t _attributeTypeIdAndLength_4;
++      uint32_t associationStatus;
++
++      uint32_t _attributeTypeIdAndLength_5;
++      uint8_t chid[16];
++
++      uint32_t _attributeTypeIdAndLength_6;
++      uint8_t cdid[16];
++
++      uint32_t _attributeTypeIdAndLength_7;
++      uint8_t bandGroups[2];
++} UPACKED wusb_m4_data_t;
++
++
++
++
++#endif /* _USB_H_ */
+--- /dev/null
++++ b/drivers/usb/host/dwc_otg/Makefile
+@@ -0,0 +1,78 @@
++#
++# Makefile for DWC_otg Highspeed USB controller driver
++#
++
++ifneq ($(KERNELRELEASE),)
++
++ifeq ($(BUS_INTERFACE),)
++      # BUS_INTERFACE = -DLM_INTERFACE
++      BUS_INTERFACE = -DPLATFORM_INTERFACE=1
++endif
++
++CPPFLAGS      += -DDEBUG 
++
++# Use one of the following flags to compile the software in host-only or
++# device-only mode.
++#CPPFLAGS        += -DDWC_HOST_ONLY
++#CPPFLAGS        += -DDWC_DEVICE_ONLY
++
++CPPFLAGS      += -Dlinux -DDWC_HS_ELECT_TST
++#CGG: CPPFLAGS        += -DDWC_EN_ISOC
++CPPFLAGS      += -I$(obj)/../dwc_common_port
++#CPPFLAGS     += -I$(PORTLIB)
++CPPFLAGS      += -DDWC_LINUX
++CPPFLAGS      += $(CFI)
++CPPFLAGS      += $(BUS_INTERFACE)
++
++obj-$(CONFIG_USB_DWCOTG) += dwc_otg.o
++
++dwc_otg-objs  := dwc_otg_driver.o dwc_otg_attr.o 
++dwc_otg-objs  += dwc_otg_cil.o dwc_otg_cil_intr.o 
++dwc_otg-objs  += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o 
++dwc_otg-objs  += dwc_otg_hcd.o dwc_otg_hcd_linux.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o dwc_otg_hcd_ddma.o
++ifneq ($(CFI),)
++dwc_otg-objs  += dwc_otg_cfi.o
++endif
++
++kernrelwd := $(subst ., ,$(KERNELRELEASE))
++kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))
++
++ifneq ($(kernrel3),2.6.20)
++EXTRA_CFLAGS += $(CPPFLAGS)
++endif
++
++else
++
++PWD           := $(shell pwd)
++PORTLIB               := $(PWD)/../dwc_common_port
++
++# Command paths
++CTAGS         := $(CTAGS)
++DOXYGEN               := $(DOXYGEN)
++
++default: portlib
++      $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
++
++install: default
++ifneq ($(INSTALL_MOD_PATH),)
++      $(MAKE) -C$(KDIR) M=$(PORTLIB) modules_install
++      $(MAKE) -C$(KDIR) M=$(PWD) modules_install      
++else
++      @echo "No install path defined"
++endif
++
++portlib:
++      $(MAKE) -C$(KDIR) M=$(PORTLIB) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
++      cp $(PORTLIB)/Module.symvers $(PWD)/
++
++docs: $(wildcard *.[hc]) doc/doxygen.cfg
++      $(DOXYGEN) doc/doxygen.cfg
++
++tags: $(wildcard *.[hc])
++      $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
++
++
++clean:
++      rm -rf   *.o *.ko .*cmd *.mod.c .tmp_versions
++
++endif
+--- /dev/null
++++ b/drivers/usb/host/dwc_otg/dummy_audio.c
+@@ -0,0 +1,1575 @@
++/*
++ * zero.c -- Gadget Zero, for USB development
++ *
++ * Copyright (C) 2003-2004 David Brownell
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions, and the following disclaimer,
++ *    without modification.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. The names of the above-listed copyright holders may not be used
++ *    to endorse or promote products derived from this software without
++ *    specific prior written permission.
++ *
++ * ALTERNATIVELY, this software may be distributed under the terms of the
++ * GNU General Public License ("GPL") as published by the Free Software
++ * Foundation, either version 2 of that License or (at your option) any
++ * later version.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
++ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
++ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++
++/*
++ * Gadget Zero only needs two bulk endpoints, and is an example of how you
++ * can write a hardware-agnostic gadget driver running inside a USB device.
++ *
++ * Hardware details are visible (see CONFIG_USB_ZERO_* below) but don't
++ * affect most of the driver.
++ *
++ * Use it with the Linux host/master side "usbtest" driver to get a basic
++ * functional test of your device-side usb stack, or with "usb-skeleton".
++ *
++ * It supports two similar configurations.  One sinks whatever the usb host
++ * writes, and in return sources zeroes.  The other loops whatever the host
++ * writes back, so the host can read it.  Module options include:
++ *
++ *   buflen=N         default N=4096, buffer size used
++ *   qlen=N           default N=32, how many buffers in the loopback queue
++ *   loopdefault      default false, list loopback config first
++ *
++ * Many drivers will only have one configuration, letting them be much
++ * simpler if they also don't support high speed operation (like this
++ * driver does).
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/ioport.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/smp_lock.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/timer.h>
++#include <linux/list.h>
++#include <linux/interrupt.h>
++#include <linux/uts.h>
++#include <linux/version.h>
++#include <linux/device.h>
++#include <linux/moduleparam.h>
++#include <linux/proc_fs.h>
++
++#include <asm/byteorder.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/system.h>
++#include <asm/unaligned.h>
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
++# include <linux/usb/ch9.h>
++#else
++# include <linux/usb_ch9.h>
++#endif
++
++#include <linux/usb_gadget.h>
++
++
++/*-------------------------------------------------------------------------*/
++/*-------------------------------------------------------------------------*/
++
++
++static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len)
++{
++      int     count = 0;
++      u8      c;
++      u16     uchar;
++
++      /* this insists on correct encodings, though not minimal ones.
++       * BUT it currently rejects legit 4-byte UTF-8 code points,
++       * which need surrogate pairs.  (Unicode 3.1 can use them.)
++       */
++      while (len != 0 && (c = (u8) *s++) != 0) {
++              if (unlikely(c & 0x80)) {
++                      // 2-byte sequence:
++                      // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
++                      if ((c & 0xe0) == 0xc0) {
++                              uchar = (c & 0x1f) << 6;
++
++                              c = (u8) *s++;
++                              if ((c & 0xc0) != 0xc0)
++                                      goto fail;
++                              c &= 0x3f;
++                              uchar |= c;
++
++                      // 3-byte sequence (most CJKV characters):
++                      // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
++                      } else if ((c & 0xf0) == 0xe0) {
++                              uchar = (c & 0x0f) << 12;
++
++                              c = (u8) *s++;
++                              if ((c & 0xc0) != 0xc0)
++                                      goto fail;
++                              c &= 0x3f;
++                              uchar |= c << 6;
++
++                              c = (u8) *s++;
++                              if ((c & 0xc0) != 0xc0)
++                                      goto fail;
++                              c &= 0x3f;
++                              uchar |= c;
++
++                              /* no bogus surrogates */
++                              if (0xd800 <= uchar && uchar <= 0xdfff)
++                                      goto fail;
++
++                      // 4-byte sequence (surrogate pairs, currently rare):
++                      // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
++                      //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
++                      // (uuuuu = wwww + 1)
++                      // FIXME accept the surrogate code points (only)
++
++                      } else
++                              goto fail;
++              } else
++                      uchar = c;
++              put_unaligned (cpu_to_le16 (uchar), cp++);
++              count++;
++              len--;
++      }
++      return count;
++fail:
++      return -1;
++}
++
++
++/**
++ * usb_gadget_get_string - fill out a string descriptor 
++ * @table: of c strings encoded using UTF-8
++ * @id: string id, from low byte of wValue in get string descriptor
++ * @buf: at least 256 bytes
++ *
++ * Finds the UTF-8 string matching the ID, and converts it into a
++ * string descriptor in utf16-le.
++ * Returns length of descriptor (always even) or negative errno
++ *
++ * If your driver needs stings in multiple languages, you'll probably
++ * "switch (wIndex) { ... }"  in your ep0 string descriptor logic,
++ * using this routine after choosing which set of UTF-8 strings to use.
++ * Note that US-ASCII is a strict subset of UTF-8; any string bytes with
++ * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1
++ * characters (which are also widely used in C strings).
++ */
++int
++usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
++{
++      struct usb_string       *s;
++      int                     len;
++
++      /* descriptor 0 has the language id */
++      if (id == 0) {
++              buf [0] = 4;
++              buf [1] = USB_DT_STRING;
++              buf [2] = (u8) table->language;
++              buf [3] = (u8) (table->language >> 8);
++              return 4;
++      }
++      for (s = table->strings; s && s->s; s++)
++              if (s->id == id)
++                      break;
++
++      /* unrecognized: stall. */
++      if (!s || !s->s)
++              return -EINVAL;
++
++      /* string descriptors have length, tag, then UTF16-LE text */
++      len = min ((size_t) 126, strlen (s->s));
++      memset (buf + 2, 0, 2 * len);   /* zero all the bytes */
++      len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len);
++      if (len < 0)
++              return -EINVAL;
++      buf [0] = (len + 1) * 2;
++      buf [1] = USB_DT_STRING;
++      return buf [0];
++}
++
++
++/*-------------------------------------------------------------------------*/
++/*-------------------------------------------------------------------------*/
++
++
++/**
++ * usb_descriptor_fillbuf - fill buffer with descriptors
++ * @buf: Buffer to be filled
++ * @buflen: Size of buf
++ * @src: Array of descriptor pointers, terminated by null pointer.
++ *
++ * Copies descriptors into the buffer, returning the length or a
++ * negative error code if they can't all be copied.  Useful when
++ * assembling descriptors for an associated set of interfaces used
++ * as part of configuring a composite device; or in other cases where
++ * sets of descriptors need to be marshaled.
++ */
++int
++usb_descriptor_fillbuf(void *buf, unsigned buflen,
++              const struct usb_descriptor_header **src)
++{
++      u8      *dest = buf;
++
++      if (!src)
++              return -EINVAL;
++
++      /* fill buffer from src[] until null descriptor ptr */
++      for (; 0 != *src; src++) {
++              unsigned                len = (*src)->bLength;
++
++              if (len > buflen)
++                      return -EINVAL;
++              memcpy(dest, *src, len);
++              buflen -= len;
++              dest += len;
++      }
++      return dest - (u8 *)buf;
++}
++
++
++/**
++ * usb_gadget_config_buf - builts a complete configuration descriptor
++ * @config: Header for the descriptor, including characteristics such
++ *    as power requirements and number of interfaces.
++ * @desc: Null-terminated vector of pointers to the descriptors (interface,
++ *    endpoint, etc) defining all functions in this device configuration.
++ * @buf: Buffer for the resulting configuration descriptor.
++ * @length: Length of buffer.  If this is not big enough to hold the
++ *    entire configuration descriptor, an error code will be returned.
++ *
++ * This copies descriptors into the response buffer, building a descriptor
++ * for that configuration.  It returns the buffer length or a negative
++ * status code.  The config.wTotalLength field is set to match the length
++ * of the result, but other descriptor fields (including power usage and
++ * interface count) must be set by the caller.
++ *
++ * Gadget drivers could use this when constructing a config descriptor
++ * in response to USB_REQ_GET_DESCRIPTOR.  They will need to patch the
++ * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.
++ */
++int usb_gadget_config_buf(
++      const struct usb_config_descriptor      *config,
++      void                                    *buf,
++      unsigned                                length,
++      const struct usb_descriptor_header      **desc
++)
++{
++      struct usb_config_descriptor            *cp = buf;
++      int                                     len;
++
++      /* config descriptor first */
++      if (length < USB_DT_CONFIG_SIZE || !desc)
++              return -EINVAL;
++      *cp = *config; 
++
++      /* then interface/endpoint/class/vendor/... */
++      len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
++                      length - USB_DT_CONFIG_SIZE, desc);
++      if (len < 0)
++              return len;
++      len += USB_DT_CONFIG_SIZE;
++      if (len > 0xffff)
++              return -EINVAL;
++
++      /* patch up the config descriptor */
++      cp->bLength = USB_DT_CONFIG_SIZE;
++      cp->bDescriptorType = USB_DT_CONFIG;
++      cp->wTotalLength = cpu_to_le16(len);
++      cp->bmAttributes |= USB_CONFIG_ATT_ONE;
++      return len;
++}
++
++/*-------------------------------------------------------------------------*/
++/*-------------------------------------------------------------------------*/
++
++
++#define RBUF_LEN (1024*1024)
++static int rbuf_start;
++static int rbuf_len;
++static __u8 rbuf[RBUF_LEN];
++
++/*-------------------------------------------------------------------------*/
++
++#define DRIVER_VERSION                "St Patrick's Day 2004"
++
++static const char shortname [] = "zero";
++static const char longname [] = "YAMAHA YST-MS35D USB Speaker  ";
++
++static const char source_sink [] = "source and sink data";
++static const char loopback [] = "loop input to output";
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * driver assumes self-powered hardware, and
++ * has no way for users to trigger remote wakeup.
++ *
++ * this version autoconfigures as much as possible,
++ * which is reasonable for most "bulk-only" drivers.
++ */
++static const char *EP_IN_NAME;                /* source */
++static const char *EP_OUT_NAME;               /* sink */
++
++/*-------------------------------------------------------------------------*/
++
++/* big enough to hold our biggest descriptor */
++#define USB_BUFSIZ    512
++
++struct zero_dev {
++      spinlock_t              lock;
++      struct usb_gadget       *gadget;
++      struct usb_request      *req;           /* for control responses */
++
++      /* when configured, we have one of two configs:
++       * - source data (in to host) and sink it (out from host)
++       * - or loop it back (out from host back in to host)
++       */
++      u8                      config;
++      struct usb_ep           *in_ep, *out_ep;
++
++      /* autoresume timer */
++      struct timer_list       resume;
++};
++
++#define xprintk(d,level,fmt,args...) \
++      dev_printk(level , &(d)->gadget->dev , fmt , ## args)
++
++#ifdef DEBUG
++#define DBG(dev,fmt,args...) \
++      xprintk(dev , KERN_DEBUG , fmt , ## args)
++#else
++#define DBG(dev,fmt,args...) \
++      do { } while (0)
++#endif /* DEBUG */
++
++#ifdef VERBOSE
++#define VDBG  DBG
++#else
++#define VDBG(dev,fmt,args...) \
++      do { } while (0)
++#endif /* VERBOSE */
++
++#define ERROR(dev,fmt,args...) \
++      xprintk(dev , KERN_ERR , fmt , ## args)
++#define WARN(dev,fmt,args...) \
++      xprintk(dev , KERN_WARNING , fmt , ## args)
++#define INFO(dev,fmt,args...) \
++      xprintk(dev , KERN_INFO , fmt , ## args)
++
++/*-------------------------------------------------------------------------*/
++
++static unsigned buflen = 4096;
++static unsigned qlen = 32;
++static unsigned pattern = 0;
++
++module_param (buflen, uint, S_IRUGO|S_IWUSR);
++module_param (qlen, uint, S_IRUGO|S_IWUSR);
++module_param (pattern, uint, S_IRUGO|S_IWUSR);
++
++/*
++ * if it's nonzero, autoresume says how many seconds to wait
++ * before trying to wake up the host after suspend.
++ */
++static unsigned autoresume = 0;
++module_param (autoresume, uint, 0);
++
++/*
++ * Normally the "loopback" configuration is second (index 1) so
++ * it's not the default.  Here's where to change that order, to
++ * work better with hosts where config changes are problematic.
++ * Or controllers (like superh) that only support one config.
++ */
++static int loopdefault = 0;
++
++module_param (loopdefault, bool, S_IRUGO|S_IWUSR);
++
++/*-------------------------------------------------------------------------*/
++
++/* Thanks to NetChip Technologies for donating this product ID.
++ *
++ * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
++ * Instead:  allocate your own, using normal USB-IF procedures.
++ */
++#ifndef       CONFIG_USB_ZERO_HNPTEST
++#define DRIVER_VENDOR_NUM     0x0525          /* NetChip */
++#define DRIVER_PRODUCT_NUM    0xa4a0          /* Linux-USB "Gadget Zero" */
++#else
++#define DRIVER_VENDOR_NUM     0x1a0a          /* OTG test device IDs */
++#define DRIVER_PRODUCT_NUM    0xbadd
++#endif
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * DESCRIPTORS ... most are static, but strings and (full)
++ * configuration descriptors are built on demand.
++ */
++
++/*
++#define STRING_MANUFACTURER           25
++#define STRING_PRODUCT                        42
++#define STRING_SERIAL                 101
++*/
++#define STRING_MANUFACTURER           1
++#define STRING_PRODUCT                        2
++#define STRING_SERIAL                 3
++
++#define STRING_SOURCE_SINK            250
++#define STRING_LOOPBACK                       251
++
++/*
++ * This device advertises two configurations; these numbers work
++ * on a pxa250 as well as more flexible hardware.
++ */
++#define       CONFIG_SOURCE_SINK      3
++#define       CONFIG_LOOPBACK         2
++
++/*
++static struct usb_device_descriptor
++device_desc = {
++      .bLength =              sizeof device_desc,
++      .bDescriptorType =      USB_DT_DEVICE,
++
++      .bcdUSB =               __constant_cpu_to_le16 (0x0200),
++      .bDeviceClass =         USB_CLASS_VENDOR_SPEC,
++
++      .idVendor =             __constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
++      .idProduct =            __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
++      .iManufacturer =        STRING_MANUFACTURER,
++      .iProduct =             STRING_PRODUCT,
++      .iSerialNumber =        STRING_SERIAL,
++      .bNumConfigurations =   2,
++};
++*/
++static struct usb_device_descriptor
++device_desc = {
++      .bLength =              sizeof device_desc,
++      .bDescriptorType =      USB_DT_DEVICE,
++      .bcdUSB =               __constant_cpu_to_le16 (0x0100),
++      .bDeviceClass =         USB_CLASS_PER_INTERFACE,
++      .bDeviceSubClass =      0,
++      .bDeviceProtocol =      0,
++      .bMaxPacketSize0 =      64,
++      .bcdDevice =            __constant_cpu_to_le16 (0x0100),
++      .idVendor =             __constant_cpu_to_le16 (0x0499),
++      .idProduct =            __constant_cpu_to_le16 (0x3002),
++      .iManufacturer =        STRING_MANUFACTURER,
++      .iProduct =             STRING_PRODUCT,
++      .iSerialNumber =        STRING_SERIAL,
++      .bNumConfigurations =   1,
++};
++
++static struct usb_config_descriptor
++z_config = {
++      .bLength =              sizeof z_config,
++      .bDescriptorType =      USB_DT_CONFIG,
++
++      /* compute wTotalLength on the fly */
++      .bNumInterfaces =       2,
++      .bConfigurationValue =  1,
++      .iConfiguration =       0,
++      .bmAttributes =         0x40,
++      .bMaxPower =            0,      /* self-powered */
++};
++
++
++static struct usb_otg_descriptor
++otg_descriptor = {
++      .bLength =              sizeof otg_descriptor,
++      .bDescriptorType =      USB_DT_OTG,
++
++      .bmAttributes =         USB_OTG_SRP,
++};
++
++/* one interface in each configuration */
++#ifdef        CONFIG_USB_GADGET_DUALSPEED
++
++/*
++ * usb 2.0 devices need to expose both high speed and full speed
++ * descriptors, unless they only run at full speed.
++ *
++ * that means alternate endpoint descriptors (bigger packets)
++ * and a "device qualifier" ... plus more construction options
++ * for the config descriptor.
++ */
++
++static struct usb_qualifier_descriptor
++dev_qualifier = {
++      .bLength =              sizeof dev_qualifier,
++      .bDescriptorType =      USB_DT_DEVICE_QUALIFIER,
++
++      .bcdUSB =               __constant_cpu_to_le16 (0x0200),
++      .bDeviceClass =         USB_CLASS_VENDOR_SPEC,
++
++      .bNumConfigurations =   2,
++};
++
++
++struct usb_cs_as_general_descriptor {
++      __u8  bLength;
++      __u8  bDescriptorType;
++
++      __u8  bDescriptorSubType;
++      __u8  bTerminalLink;
++      __u8  bDelay;
++      __u16  wFormatTag;
++} __attribute__ ((packed));
++
++struct usb_cs_as_format_descriptor {
++      __u8  bLength;
++      __u8  bDescriptorType;
++
++      __u8  bDescriptorSubType;
++      __u8  bFormatType;
++      __u8  bNrChannels;
++      __u8  bSubframeSize;
++      __u8  bBitResolution;
++      __u8  bSamfreqType;
++      __u8  tLowerSamFreq[3];
++      __u8  tUpperSamFreq[3];
++} __attribute__ ((packed));
++
++static const struct usb_interface_descriptor
++z_audio_control_if_desc = {
++      .bLength =              sizeof z_audio_control_if_desc,
++      .bDescriptorType =      USB_DT_INTERFACE,
++      .bInterfaceNumber = 0,
++      .bAlternateSetting = 0,
++      .bNumEndpoints = 0,
++      .bInterfaceClass = USB_CLASS_AUDIO,
++      .bInterfaceSubClass = 0x1,
++      .bInterfaceProtocol = 0,
++      .iInterface = 0,
++};
++
++static const struct usb_interface_descriptor
++z_audio_if_desc = {
++      .bLength =              sizeof z_audio_if_desc,
++      .bDescriptorType =      USB_DT_INTERFACE,
++      .bInterfaceNumber = 1,
++      .bAlternateSetting = 0,
++      .bNumEndpoints = 0,
++      .bInterfaceClass = USB_CLASS_AUDIO,
++      .bInterfaceSubClass = 0x2,
++      .bInterfaceProtocol = 0,
++      .iInterface = 0,
++};
++
++static const struct usb_interface_descriptor
++z_audio_if_desc2 = {
++      .bLength =              sizeof z_audio_if_desc,
++      .bDescriptorType =      USB_DT_INTERFACE,
++      .bInterfaceNumber = 1,
++      .bAlternateSetting = 1,
++      .bNumEndpoints = 1,
++      .bInterfaceClass = USB_CLASS_AUDIO,
++      .bInterfaceSubClass = 0x2,
++      .bInterfaceProtocol = 0,
++      .iInterface = 0,
++};
++
++static const struct usb_cs_as_general_descriptor
++z_audio_cs_as_if_desc = {
++      .bLength = 7,
++      .bDescriptorType = 0x24,
++      
++      .bDescriptorSubType = 0x01,
++      .bTerminalLink = 0x01,
++      .bDelay = 0x0,
++      .wFormatTag = __constant_cpu_to_le16 (0x0001)
++};
++
++
++static const struct usb_cs_as_format_descriptor 
++z_audio_cs_as_format_desc = {
++      .bLength = 0xe,
++      .bDescriptorType = 0x24,
++      
++      .bDescriptorSubType = 2,
++      .bFormatType = 1,
++      .bNrChannels = 1,
++      .bSubframeSize = 1,
++      .bBitResolution = 8,
++      .bSamfreqType = 0,
++      .tLowerSamFreq = {0x7e, 0x13, 0x00},
++      .tUpperSamFreq = {0xe2, 0xd6, 0x00},
++};
++
++static const struct usb_endpoint_descriptor 
++z_iso_ep = {
++      .bLength = 0x09,
++      .bDescriptorType = 0x05,
++      .bEndpointAddress = 0x04,
++      .bmAttributes = 0x09,
++      .wMaxPacketSize = 0x0038,
++      .bInterval = 0x01,
++      .bRefresh = 0x00,
++      .bSynchAddress = 0x00,  
++};
++
++static char z_iso_ep2[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
++
++// 9 bytes
++static char z_ac_interface_header_desc[] = 
++{ 0x09, 0x24, 0x01, 0x00, 0x01, 0x2b, 0x00, 0x01, 0x01 };
++
++// 12 bytes
++static char z_0[] = {0x0c, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02, 
++                   0x03, 0x00, 0x00, 0x00};
++// 13 bytes
++static char z_1[] = {0x0d, 0x24, 0x06, 0x02, 0x01, 0x02, 0x15, 0x00, 
++                   0x02, 0x00, 0x02, 0x00, 0x00};
++// 9 bytes
++static char z_2[] = {0x09, 0x24, 0x03, 0x03, 0x01, 0x03, 0x00, 0x02, 
++                   0x00};
++
++static char za_0[] = {0x09, 0x04, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, 
++                    0x00};
++
++static char za_1[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
++
++static char za_2[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x01, 0x08, 0x00, 
++                    0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
++
++static char za_3[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00,
++                    0x00};
++
++static char za_4[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
++
++static char za_5[] = {0x09, 0x04, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00,
++                    0x00};
++
++static char za_6[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
++
++static char za_7[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x02, 0x10, 0x00,
++                    0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
++
++static char za_8[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00,
++                    0x00};
++
++static char za_9[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
++
++static char za_10[] = {0x09, 0x04, 0x01, 0x04, 0x01, 0x01, 0x02, 0x00,
++                     0x00};
++
++static char za_11[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
++
++static char za_12[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x00,
++                     0x73, 0x13, 0x00, 0xe2, 0xd6, 0x00};
++
++static char za_13[] = {0x09, 0x05, 0x04, 0x09, 0xe0, 0x00, 0x01, 0x00,
++                     0x00};
++
++static char za_14[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
++
++static char za_15[] = {0x09, 0x04, 0x01, 0x05, 0x01, 0x01, 0x02, 0x00, 
++                     0x00};
++
++static char za_16[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
++
++static char za_17[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x03, 0x14, 0x00, 
++                     0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
++
++static char za_18[] = {0x09, 0x05, 0x04, 0x09, 0xa8, 0x00, 0x01, 0x00,
++                     0x00};
++
++static char za_19[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
++
++static char za_20[] = {0x09, 0x04, 0x01, 0x06, 0x01, 0x01, 0x02, 0x00,
++                     0x00};
++
++static char za_21[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
++
++static char za_22[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x03, 0x14, 0x00, 
++                     0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
++
++static char za_23[] = {0x09, 0x05, 0x04, 0x09, 0x50, 0x01, 0x01, 0x00,
++                     0x00};
++
++static char za_24[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
++
++
++
++static const struct usb_descriptor_header *z_function [] = {
++      (struct usb_descriptor_header *) &z_audio_control_if_desc,
++      (struct usb_descriptor_header *) &z_ac_interface_header_desc,
++      (struct usb_descriptor_header *) &z_0,
++      (struct usb_descriptor_header *) &z_1,
++      (struct usb_descriptor_header *) &z_2,
++      (struct usb_descriptor_header *) &z_audio_if_desc,
++      (struct usb_descriptor_header *) &z_audio_if_desc2,
++      (struct usb_descriptor_header *) &z_audio_cs_as_if_desc,
++      (struct usb_descriptor_header *) &z_audio_cs_as_format_desc,
++      (struct usb_descriptor_header *) &z_iso_ep,
++      (struct usb_descriptor_header *) &z_iso_ep2,
++      (struct usb_descriptor_header *) &za_0,
++      (struct usb_descriptor_header *) &za_1,
++      (struct usb_descriptor_header *) &za_2,
++      (struct usb_descriptor_header *) &za_3,
++      (struct usb_descriptor_header *) &za_4,
++      (struct usb_descriptor_header *) &za_5,
++      (struct usb_descriptor_header *) &za_6,
++      (struct usb_descriptor_header *) &za_7,
++      (struct usb_descriptor_header *) &za_8,
++      (struct usb_descriptor_header *) &za_9,
++      (struct usb_descriptor_header *) &za_10,
++      (struct usb_descriptor_header *) &za_11,
++      (struct usb_descriptor_header *) &za_12,
++      (struct usb_descriptor_header *) &za_13,
++      (struct usb_descriptor_header *) &za_14,
++      (struct usb_descriptor_header *) &za_15,
++      (struct usb_descriptor_header *) &za_16,
++      (struct usb_descriptor_header *) &za_17,
++      (struct usb_descriptor_header *) &za_18,
++      (struct usb_descriptor_header *) &za_19,
++      (struct usb_descriptor_header *) &za_20,
++      (struct usb_descriptor_header *) &za_21,
++      (struct usb_descriptor_header *) &za_22,
++      (struct usb_descriptor_header *) &za_23,
++      (struct usb_descriptor_header *) &za_24,
++      NULL,
++};
++
++/* maxpacket and other transfer characteristics vary by speed. */
++#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
++
++#else
++
++/* if there's no high speed support, maxpacket doesn't change. */
++#define ep_desc(g,hs,fs) fs
++
++#endif        /* !CONFIG_USB_GADGET_DUALSPEED */
++
++static char                           manufacturer [40];
++//static char                         serial [40];
++static char                           serial [] = "Ser 00 em";
++
++/* static strings, in UTF-8 */
++static struct usb_string              strings [] = {
++      { STRING_MANUFACTURER, manufacturer, },
++      { STRING_PRODUCT, longname, },
++      { STRING_SERIAL, serial, },
++      { STRING_LOOPBACK, loopback, },
++      { STRING_SOURCE_SINK, source_sink, },
++      {  }                    /* end of list */
++};
++
++static struct usb_gadget_strings      stringtab = {
++      .language       = 0x0409,       /* en-us */
++      .strings        = strings,
++};
++
++/*
++ * config descriptors are also handcrafted.  these must agree with code
++ * that sets configurations, and with code managing interfaces and their
++ * altsettings.  other complexity may come from:
++ *
++ *  - high speed support, including "other speed config" rules
++ *  - multiple configurations
++ *  - interfaces with alternate settings
++ *  - embedded class or vendor-specific descriptors
++ *
++ * this handles high speed, and has a second config that could as easily
++ * have been an alternate interface setting (on most hardware).
++ *
++ * NOTE:  to demonstrate (and test) more USB capabilities, this driver
++ * should include an altsetting to test interrupt transfers, including
++ * high bandwidth modes at high speed.  (Maybe work like Intel's test
++ * device?)
++ */
++static int
++config_buf (struct usb_gadget *gadget, u8 *buf, u8 type, unsigned index)
++{
++      int len;
++      const struct usb_descriptor_header **function;
++      
++      function = z_function;
++      len = usb_gadget_config_buf (&z_config, buf, USB_BUFSIZ, function);
++      if (len < 0)
++              return len;
++      ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
++      return len;
++}
++
++/*-------------------------------------------------------------------------*/
++
++static struct usb_request *
++alloc_ep_req (struct usb_ep *ep, unsigned length)
++{
++      struct usb_request      *req;
++
++      req = usb_ep_alloc_request (ep, GFP_ATOMIC);
++      if (req) {
++              req->length = length;
++              req->buf = usb_ep_alloc_buffer (ep, length,
++                              &req->dma, GFP_ATOMIC);
++              if (!req->buf) {
++                      usb_ep_free_request (ep, req);
++                      req = NULL;
++              }
++      }
++      return req;
++}
++
++static void free_ep_req (struct usb_ep *ep, struct usb_request *req)
++{
++      if (req->buf)
++              usb_ep_free_buffer (ep, req->buf, req->dma, req->length);
++      usb_ep_free_request (ep, req);
++}
++
++/*-------------------------------------------------------------------------*/
++
++/* optionally require specific source/sink data patterns  */
++
++static int
++check_read_data (
++      struct zero_dev         *dev,
++      struct usb_ep           *ep,
++      struct usb_request      *req
++)
++{
++      unsigned        i;
++      u8              *buf = req->buf;
++
++      for (i = 0; i < req->actual; i++, buf++) {
++              switch (pattern) {
++              /* all-zeroes has no synchronization issues */
++              case 0:
++                      if (*buf == 0)
++                              continue;
++                      break;
++              /* mod63 stays in sync with short-terminated transfers,
++               * or otherwise when host and gadget agree on how large
++               * each usb transfer request should be.  resync is done
++               * with set_interface or set_config.
++               */
++              case 1:
++                      if (*buf == (u8)(i % 63))
++                              continue;
++                      break;
++              }
++              ERROR (dev, "bad OUT byte, buf [%d] = %d\n", i, *buf);
++              usb_ep_set_halt (ep);
++              return -EINVAL;
++      }
++      return 0;
++}
++
++/*-------------------------------------------------------------------------*/
++
++static void zero_reset_config (struct zero_dev *dev)
++{
++      if (dev->config == 0)
++              return;
++
++      DBG (dev, "reset config\n");
++
++      /* just disable endpoints, forcing completion of pending i/o.
++       * all our completion handlers free their requests in this case.
++       */
++      if (dev->in_ep) {
++              usb_ep_disable (dev->in_ep);
++              dev->in_ep = NULL;
++      }
++      if (dev->out_ep) {
++              usb_ep_disable (dev->out_ep);
++              dev->out_ep = NULL;
++      }
++      dev->config = 0;
++      del_timer (&dev->resume);
++}
++
++#define _write(f, buf, sz) (f->f_op->write(f, buf, sz, &f->f_pos))
++
++static void 
++zero_isoc_complete (struct usb_ep *ep, struct usb_request *req)
++{
++      struct zero_dev *dev = ep->driver_data;
++      int             status = req->status;
++      int i, j;
++
++      switch (status) {
++
++      case 0:                         /* normal completion? */
++              //printk ("\nzero ---------------> isoc normal completion %d bytes\n", req->actual);
++              for (i=0, j=rbuf_start; i<req->actual; i++) {
++                      //printk ("%02x ", ((__u8*)req->buf)[i]);
++                      rbuf[j] = ((__u8*)req->buf)[i];
++                      j++;
++                      if (j >= RBUF_LEN) j=0;
++              }
++              rbuf_start = j;
++              //printk ("\n\n");
++
++              if (rbuf_len < RBUF_LEN) {
++                      rbuf_len += req->actual;
++                      if (rbuf_len > RBUF_LEN) {
++                              rbuf_len = RBUF_LEN;
++                      }
++              }
++
++              break;
++
++      /* this endpoint is normally active while we're configured */
++      case -ECONNABORTED:             /* hardware forced ep reset */
++      case -ECONNRESET:               /* request dequeued */
++      case -ESHUTDOWN:                /* disconnect from host */
++              VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status,
++                              req->actual, req->length);
++              if (ep == dev->out_ep)
++                      check_read_data (dev, ep, req);
++              free_ep_req (ep, req);
++              return;
++
++      case -EOVERFLOW:                /* buffer overrun on read means that
++                                       * we didn't provide a big enough
++                                       * buffer.
++                                       */
++      default:
++#if 1
++              DBG (dev, "%s complete --> %d, %d/%d\n", ep->name,
++                              status, req->actual, req->length);
++#endif
++      case -EREMOTEIO:                /* short read */
++              break;
++      }
++
++      status = usb_ep_queue (ep, req, GFP_ATOMIC);
++      if (status) {
++              ERROR (dev, "kill %s:  resubmit %d bytes --> %d\n",
++                              ep->name, req->length, status);
++              usb_ep_set_halt (ep);
++              /* FIXME recover later ... somehow */
++      }
++}
++
++static struct usb_request *
++zero_start_isoc_ep (struct usb_ep *ep, int gfp_flags)
++{
++      struct usb_request      *req;
++      int                     status;
++
++      req = alloc_ep_req (ep, 512);
++      if (!req)
++              return NULL;
++
++      req->complete = zero_isoc_complete;
++
++      status = usb_ep_queue (ep, req, gfp_flags);
++      if (status) {
++              struct zero_dev *dev = ep->driver_data;
++
++              ERROR (dev, "start %s --> %d\n", ep->name, status);
++              free_ep_req (ep, req);
++              req = NULL;
++      }
++
++      return req;
++}
++
++/* change our operational config.  this code must agree with the code
++ * that returns config descriptors, and altsetting code.
++ *
++ * it's also responsible for power management interactions. some
++ * configurations might not work with our current power sources.
++ *
++ * note that some device controller hardware will constrain what this
++ * code can do, perhaps by disallowing more than one configuration or
++ * by limiting configuration choices (like the pxa2xx).
++ */
++static int
++zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags)
++{
++      int                     result = 0;
++      struct usb_gadget       *gadget = dev->gadget;
++      const struct usb_endpoint_descriptor    *d;
++      struct usb_ep           *ep;
++
++      if (number == dev->config)
++              return 0;
++
++      zero_reset_config (dev);
++
++      gadget_for_each_ep (ep, gadget) {
++
++              if (strcmp (ep->name, "ep4") == 0) {
++
++                      d = (struct usb_endpoint_descripter *)&za_23; // isoc ep desc for audio i/f alt setting 6
++                      result = usb_ep_enable (ep, d);
++
++                      if (result == 0) {
++                              ep->driver_data = dev;
++                              dev->in_ep = ep;
++
++                              if (zero_start_isoc_ep (ep, gfp_flags) != 0) {
++
++                                      dev->in_ep = ep;
++                                      continue;
++                              }
++
++                              usb_ep_disable (ep);
++                              result = -EIO;
++                      }
++              }
++
++      }
++
++      dev->config = number;
++      return result;
++}
++
++/*-------------------------------------------------------------------------*/
++
++static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req)
++{
++      if (req->status || req->actual != req->length)
++              DBG ((struct zero_dev *) ep->driver_data,
++                              "setup complete --> %d, %d/%d\n",
++                              req->status, req->actual, req->length);
++}
++
++/*
++ * The setup() callback implements all the ep0 functionality that's
++ * not handled lower down, in hardware or the hardware driver (like
++ * device and endpoint feature flags, and their status).  It's all
++ * housekeeping for the gadget function we're implementing.  Most of
++ * the work is in config-specific setup.
++ */
++static int
++zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
++{
++      struct zero_dev         *dev = get_gadget_data (gadget);
++      struct usb_request      *req = dev->req;
++      int                     value = -EOPNOTSUPP;
++
++      /* usually this stores reply data in the pre-allocated ep0 buffer,
++       * but config change events will reconfigure hardware.
++       */
++      req->zero = 0;
++      switch (ctrl->bRequest) {
++
++      case USB_REQ_GET_DESCRIPTOR:
++
++              switch (ctrl->wValue >> 8) {
++
++              case USB_DT_DEVICE:
++                      value = min (ctrl->wLength, (u16) sizeof device_desc);
++                      memcpy (req->buf, &device_desc, value);
++                      break;
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++              case USB_DT_DEVICE_QUALIFIER:
++                      if (!gadget->is_dualspeed)
++                              break;
++                      value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
++                      memcpy (req->buf, &dev_qualifier, value);
++                      break;
++
++              case USB_DT_OTHER_SPEED_CONFIG:
++                      if (!gadget->is_dualspeed)
++                              break;
++                      // FALLTHROUGH
++#endif /* CONFIG_USB_GADGET_DUALSPEED */
++              case USB_DT_CONFIG:
++                      value = config_buf (gadget, req->buf,
++                                      ctrl->wValue >> 8,
++                                      ctrl->wValue & 0xff);
++                      if (value >= 0)
++                              value = min (ctrl->wLength, (u16) value);
++                      break;
++
++              case USB_DT_STRING:
++                      /* wIndex == language code.
++                       * this driver only handles one language, you can
++                       * add string tables for other languages, using
++                       * any UTF-8 characters
++                       */
++                      value = usb_gadget_get_string (&stringtab,
++                                      ctrl->wValue & 0xff, req->buf);
++                      if (value >= 0) {
++                              value = min (ctrl->wLength, (u16) value);
++                      }
++                      break;
++              }
++              break;
++
++      /* currently two configs, two speeds */
++      case USB_REQ_SET_CONFIGURATION:
++              if (ctrl->bRequestType != 0)
++                      goto unknown;
++
++              spin_lock (&dev->lock);
++      &nbs