diff -urN linux-2.6.25/arch/arm/boot/compressed/head-xscale.S linux-2.6.25-vpac1/arch/arm/boot/compressed/head-xscale.S
--- linux-2.6.25/arch/arm/boot/compressed/head-xscale.S	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/arch/arm/boot/compressed/head-xscale.S	2008-04-24 15:12:17.000000000 +0200
@@ -37,6 +37,11 @@
 		mov	r7, #MACH_TYPE_COTULLA_IDP
 #endif
 
+#ifdef CONFIG_MACH_VPAC270
+                mov     r7, #(MACH_TYPE_VPAC270 & 0xFF00)
+                add     r7, r7, #(MACH_TYPE_VPAC270 & 0xFF)
+#endif
+
 #ifdef CONFIG_ARCH_IXP2000
 		mov	r1, #-1
 		mov	r0, #0xd6000000
diff -urN linux-2.6.25/arch/arm/configs/vpac270_defconfig linux-2.6.25-vpac1/arch/arm/configs/vpac270_defconfig
--- linux-2.6.25/arch/arm/configs/vpac270_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.25-vpac1/arch/arm/configs/vpac270_defconfig	2008-05-06 18:47:29.000000000 +0200
@@ -0,0 +1,1283 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.25-vpac1
+# Tue May  6 15:44:30 2008
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_ZONE_DMA=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_SHMEM is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_CLASSIC_RCU=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION is not set
+# CONFIG_ARCH_PNX4008 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM7X00A is not set
+
+#
+# Intel PXA2xx/PXA3xx Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_LOGICPD_PXA270 is not set
+# CONFIG_MACH_MAINSTONE is not set
+CONFIG_MACH_VPAC270=y
+# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_PXA_SHARPSL is not set
+# CONFIG_ARCH_PXA_ESERIES is not set
+# CONFIG_MACH_TRIZEPS4 is not set
+# CONFIG_MACH_EM_X270 is not set
+# CONFIG_MACH_COLIBRI is not set
+# CONFIG_MACH_ZYLONITE is not set
+# CONFIG_MACH_LITTLETON is not set
+# CONFIG_MACH_ARMCORE is not set
+# CONFIG_MACH_MAGICIAN is not set
+# CONFIG_MACH_PCM027 is not set
+CONFIG_PXA27x=y
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_OUTER_CACHE is not set
+CONFIG_IWMMXT=y
+CONFIG_XSCALE_PMU=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_LOAD_CIS is not set
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_PCMCIA_PXA2XX=y
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x20000
+CONFIG_ZBOOT_ROM_BSS=0xa0800000
+CONFIG_ZBOOT_ROM=y
+CONFIG_CMDLINE="mem=32M root=/dev/nfs ip=dhcp console=ttyS0,38400"
+# CONFIG_KEXEC is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+# CONFIG_CPU_FREQ_STAT is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+# CONFIG_CPU_FREQ_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
+CONFIG_IEEE80211=y
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=y
+# CONFIG_IEEE80211_CRYPT_CCMP is not set
+# CONFIG_IEEE80211_CRYPT_TKIP is not set
+# CONFIG_IEEE80211_SOFTMAC is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+# CONFIG_MTD_CFI_I2 is not set
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PXA2XX is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_VPAC270=y
+# CONFIG_MTD_SHARP_SL is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=2
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_BLK_DEV_PLATFORM is not set
+# CONFIG_BLK_DEV_IDE_VPAC270 is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_DEBUGLEVEL=4
+# CONFIG_SMC911X is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+# CONFIG_PCMCIA_RAYCS is not set
+# CONFIG_LIBERTAS is not set
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+CONFIG_HOSTAP=y
+# CONFIG_HOSTAP_FIRMWARE is not set
+CONFIG_HOSTAP_CS=y
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_NET_PCMCIA is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_IPWIRELESS is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_PXA=y
+# CONFIG_I2C_PXA_SLAVE is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+CONFIG_HAVE_GPIO_LIB=y
+
+#
+# GPIO Support
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+CONFIG_FB_PXA_ANALOG=y
+# CONFIG_FB_PXA_TX14D14VM1BBA is not set
+# CONFIG_FB_PXA_VGA is not set
+CONFIG_FB_PXA_SVGA=y
+# CONFIG_FB_PXA_XGA is not set
+# CONFIG_FB_PXA_BPP8 is not set
+CONFIG_FB_PXA_BPP16=y
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_MBX is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+# CONFIG_SND_PCM_OSS_PLUGINS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_AC97_CODEC=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+CONFIG_SND_PXA2XX_PCM=y
+CONFIG_SND_PXA2XX_AC97=y
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# SoC Audio support for SuperH
+#
+
+#
+# ALSA SoC audio for Freescale SOCs
+#
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=y
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_GADGET is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+# CONFIG_SDIO_UART is not set
+
+#
+# MMC/SD Host Controller Drivers
+#
+CONFIG_MMC_PXA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_VPAC270=y
+# CONFIG_LEDS_GPIO is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+# CONFIG_LEDS_TRIGGER_IDE_DISK is not set
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+# CONFIG_RTC_INTF_PROC is not set
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_SA1100 is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_SAMPLES is not set
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+# CONFIG_CRYPTO_SEQIV is not set
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_HW is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff -urN linux-2.6.25/arch/arm/mach-pxa/cpu-pxa.c linux-2.6.25-vpac1/arch/arm/mach-pxa/cpu-pxa.c
--- linux-2.6.25/arch/arm/mach-pxa/cpu-pxa.c	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/arch/arm/mach-pxa/cpu-pxa.c	2008-04-29 19:16:48.000000000 +0200
@@ -12,7 +12,7 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
+ * 
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
@@ -21,12 +21,13 @@
  *   31-Jul-2002 : Initial version [FB]
  *   29-Jan-2003 : added PXA255 support [FB]
  *   20-Apr-2003 : ported to v2.5 (Dustin McIntire, Sensoria Corp.)
- *
+ *   11-Jan-2006 : v2.6, support for PXA27x processor up to 624MHz (Bill Reese, Hewlett Packard)
+ * 
  * Note:
  *   This driver may change the memory bus clock rate, but will not do any
  *   platform specific access timing changes... for example if you have flash
  *   memory connected to CS0, you will need to register a platform specific
- *   notifier which will adjust the memory access strobes to maintain a
+ *   notifier which will adjust the memory access strobes to maintain a 
  *   minimum strobe width.
  *
  */
@@ -38,258 +39,374 @@
 #include <linux/cpufreq.h>
 
 #include <asm/hardware.h>
+
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/pxa2xx-regs.h>
 
+/*
+ * This comes from generic.h in this directory.
+ */
+extern unsigned int get_clk_frequency_khz(int info);
+
+//#define DEBUG  7
+
 #ifdef DEBUG
-static unsigned int freq_debug;
-module_param(freq_debug, uint, 0);
-MODULE_PARM_DESC(freq_debug, "Set the debug messages to on=1/off=0");
+  static unsigned int freq_debug = DEBUG;
+  module_param(freq_debug, int, 0644);
+  MODULE_PARM_DESC(freq_debug, "Set the debug messages to on=1/off=0");
 #else
-#define freq_debug  0
-#endif
+  #define freq_debug  0
+#endif  
 
-typedef struct {
-	unsigned int khz;
-	unsigned int membus;
-	unsigned int cccr;
-	unsigned int div2;
+typedef struct
+{
+  unsigned int khz;     /* CPU frequency                                   */
+  unsigned int membus;  /* memory bus frequency                            */
+  unsigned int cccr;    /* new CCLKCFG setting                             */
+  unsigned int div2;    /* alter memory controller settings to divide by 2 */
+  unsigned int cclkcfg; /* new CCLKCFG setting                             */
 } pxa_freqs_t;
 
 /* Define the refresh period in mSec for the SDRAM and the number of rows */
 #define SDRAM_TREF          64      /* standard 64ms SDRAM */
-#define SDRAM_ROWS          4096    /* 64MB=8192 32MB=4096 */
-#define MDREFR_DRI(x)       (((x) * SDRAM_TREF) / (SDRAM_ROWS * 32))
+#if defined(CONFIG_MACH_H4700) || defined(CONFIG_ARCH_H2200)
+#define SDRAM_ROWS          8192    /* hx4700 uses 2 64Mb DRAMs, 8912 rows */
+#else
+#define SDRAM_ROWS          4096    /* 64MB=8192 32MB=4096 */ 
+#endif
+#define MDREFR_DRI(x)       (((x*SDRAM_TREF/SDRAM_ROWS - 31)/32))
 
 #define CCLKCFG_TURBO       0x1
 #define CCLKCFG_FCS         0x2
-#define PXA25x_MIN_FREQ     99500
-#define PXA25x_MAX_FREQ     398100
+#define CCLKCFG_HALFTURBO   0x4
+#define CCLKCFG_FASTBUS     0x8
 #define MDREFR_DB2_MASK     (MDREFR_K2DB2 | MDREFR_K1DB2)
 #define MDREFR_DRI_MASK     0xFFF
+#define PXA25x_CCLKCFG      CCLKCFG_TURBO | CCLKCFG_FCS
 
+/*
+ * For the PXA27x:
+ * Control variables are A, L, 2N for CCCR; B, HT, T for CLKCFG.
+ *
+ * A = 0 => memory controller clock from table 3-7,
+ * A = 1 => memory controller clock = system bus clock
+ * Run mode frequency   = 13 MHz * L
+ * Turbo mode frequency = 13 MHz * L * N
+ * System bus frequency = 13 MHz * L / (B + 1)
+ * System initialized by bootldr to:
+ *
+ * In CCCR: 
+ * A = 1
+ * L = 16         oscillator to run mode ratio
+ * 2N = 6         2 * (turbo mode to run mode ratio)
+ *
+ * In CCLKCFG:
+ * B = 1          Fast bus mode
+ * HT = 0         Half-Turbo mode
+ * T = 1          Turbo mode
+ * 
+ * For now, just support some of the combinations in table 3-7 of
+ * PXA27x Processor Family Developer's Manual to simplify frequency
+ * change sequences.
+ * 
+ * Specify 2N in the PXA27x_CCCR macro, not N!
+ */
+#define PXA27x_CCCR(A, L, N2) (A << 25 | N2 << 7 | L)
+#define PXA27x_CCLKCFG(B, HT, T) (B << 3 |  HT << 2 | CCLKCFG_FCS | T)
 
-/* Use the run mode frequencies for the CPUFREQ_POLICY_PERFORMANCE policy */
-static pxa_freqs_t pxa255_run_freqs[] =
-{
-    /* CPU   MEMBUS  CCCR  DIV2*/
-    { 99500,  99500, 0x121, 1}, /* run= 99, turbo= 99, PXbus=50,  SDRAM=50 */
-    {132700, 132700, 0x123, 1}, /* run=133, turbo=133, PXbus=66,  SDRAM=66 */
-    {199100,  99500, 0x141, 0}, /* run=199, turbo=199, PXbus=99,  SDRAM=99 */
-    {265400, 132700, 0x143, 1}, /* run=265, turbo=265, PXbus=133, SDRAM=66 */
-    {331800, 165900, 0x145, 1}, /* run=331, turbo=331, PXbus=166, SDRAM=83 */
-    {398100,  99500, 0x161, 0}, /* run=398, turbo=398, PXbus=196, SDRAM=99 */
-    {0,}
-};
-#define NUM_RUN_FREQS ARRAY_SIZE(pxa255_run_freqs)
-
-static struct cpufreq_frequency_table pxa255_run_freq_table[NUM_RUN_FREQS+1];
-
-/* Use the turbo mode frequencies for the CPUFREQ_POLICY_POWERSAVE policy */
-static pxa_freqs_t pxa255_turbo_freqs[] =
+/*
+ * Valid frequency assignments
+ */
+static pxa_freqs_t pxa2xx_freqs[] =
 {
     /* CPU   MEMBUS  CCCR  DIV2*/
-    { 99500, 99500,  0x121, 1}, /* run=99,  turbo= 99, PXbus=50, SDRAM=50 */
-    {199100, 99500,  0x221, 0}, /* run=99,  turbo=199, PXbus=50, SDRAM=99 */
-    {298500, 99500,  0x321, 0}, /* run=99,  turbo=287, PXbus=50, SDRAM=99 */
-    {298600, 99500,  0x1c1, 0}, /* run=199, turbo=287, PXbus=99, SDRAM=99 */
-    {398100, 99500,  0x241, 0}, /* run=199, turbo=398, PXbus=99, SDRAM=99 */
-    {0,}
+#if defined(CONFIG_PXA25x)
+#if defined(CONFIG_PXA25x_ALTERNATE_FREQS)
+    { 99500, 99500,  0x121, 1, PXA25x_CCLKCFG}, /* run=99,  turbo= 99, PXbus=50, SDRAM=50 */
+    {199100, 99500,  0x221, 0, PXA25x_CCLKCFG}, /* run=99,  turbo=199, PXbus=50, SDRAM=99 */
+    {298500, 99500,  0x321, 0, PXA25x_CCLKCFG}, /* run=99,  turbo=287, PXbus=50, SDRAM=99 */
+    {298600, 99500,  0x1c1, 0, PXA25x_CCLKCFG}, /* run=199, turbo=287, PXbus=99, SDRAM=99 */
+    {398100, 99500,  0x241, 0, PXA25x_CCLKCFG}  /* run=199, turbo=398, PXbus=99, SDRAM=99 */
+#else
+    { 99500,  99500, 0x121, 1, PXA25x_CCLKCFG}, /* run= 99, turbo= 99, PXbus=50,  SDRAM=50 */
+    {132700, 132700, 0x123, 1, PXA25x_CCLKCFG}, /* run=133, turbo=133, PXbus=66,  SDRAM=66 */
+    {199100,  99500, 0x141, 0, PXA25x_CCLKCFG}, /* run=199, turbo=199, PXbus=99,  SDRAM=99 */
+    {265400, 132700, 0x143, 1, PXA25x_CCLKCFG}, /* run=265, turbo=265, PXbus=133, SDRAM=66 */
+    {331800, 165900, 0x145, 1, PXA25x_CCLKCFG}, /* run=331, turbo=331, PXbus=166, SDRAM=83 */
+    {398100,  99500, 0x161, 0, PXA25x_CCLKCFG}  /* run=398, turbo=398, PXbus=196, SDRAM=99 */
+#endif
+#elif defined(CONFIG_PXA27x)
+    {104000, 104000, PXA27x_CCCR(1,  8, 2), 0, PXA27x_CCLKCFG(1, 0, 1)},
+    {156000, 104000, PXA27x_CCCR(1,  8, 6), 0, PXA27x_CCLKCFG(1, 1, 1)},
+    {208000, 208000, PXA27x_CCCR(0, 16, 2), 1, PXA27x_CCLKCFG(0, 0, 1)},
+    {312000, 208000, PXA27x_CCCR(1, 16, 3), 1, PXA27x_CCLKCFG(1, 0, 1)},
+    {416000, 208000, PXA27x_CCCR(1, 16, 4), 1, PXA27x_CCLKCFG(1, 0, 1)},
+    {520000, 208000, PXA27x_CCCR(1, 16, 5), 1, PXA27x_CCLKCFG(1, 0, 1)},
+    {624000, 208000, PXA27x_CCCR(1, 16, 6), 1, PXA27x_CCLKCFG(1, 0, 1)}
+#endif
 };
-#define NUM_TURBO_FREQS ARRAY_SIZE(pxa255_turbo_freqs)
-
-static struct cpufreq_frequency_table pxa255_turbo_freq_table[NUM_TURBO_FREQS+1];
+#define NUM_FREQS (sizeof(pxa2xx_freqs)/sizeof(pxa_freqs_t))
 
-extern unsigned get_clk_frequency_khz(int info);
+static struct cpufreq_frequency_table pxa2xx_freq_table[NUM_FREQS+1];
 
 /* find a valid frequency point */
 static int pxa_verify_policy(struct cpufreq_policy *policy)
 {
-	struct cpufreq_frequency_table *pxa_freqs_table;
-	int ret;
+    int ret;
 
-	if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
-		pxa_freqs_table = pxa255_run_freq_table;
-	} else if (policy->policy == CPUFREQ_POLICY_POWERSAVE) {
-		pxa_freqs_table = pxa255_turbo_freq_table;
-	} else {
-		printk("CPU PXA: Unknown policy found. "
-		       "Using CPUFREQ_POLICY_PERFORMANCE\n");
-		pxa_freqs_table = pxa255_run_freq_table;
-	}
-
-	ret = cpufreq_frequency_table_verify(policy, pxa_freqs_table);
-
-	if (freq_debug)
-		pr_debug("Verified CPU policy: %dKhz min to %dKhz max\n",
-		       policy->min, policy->max);
+    ret=cpufreq_frequency_table_verify(policy, pxa2xx_freq_table);
+    
+    if(freq_debug) {
+        printk("Verified CPU policy: %dKhz min to %dKhz max\n",
+            policy->min, policy->max);
+    }
 
-	return ret;
+    return ret;
 }
 
 static int pxa_set_target(struct cpufreq_policy *policy,
-			   unsigned int target_freq,
-			   unsigned int relation)
+                 unsigned int target_freq,
+                 unsigned int relation)
 {
-	struct cpufreq_frequency_table *pxa_freqs_table;
-	pxa_freqs_t *pxa_freq_settings;
-	struct cpufreq_freqs freqs;
-	unsigned int idx;
-	unsigned long flags;
-	unsigned int unused, preset_mdrefr, postset_mdrefr;
-	void *ramstart = phys_to_virt(0xa0000000);
-
-	/* Get the current policy */
-	if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
-		pxa_freq_settings = pxa255_run_freqs;
-		pxa_freqs_table   = pxa255_run_freq_table;
-	} else if (policy->policy == CPUFREQ_POLICY_POWERSAVE) {
-		pxa_freq_settings = pxa255_turbo_freqs;
-		pxa_freqs_table   = pxa255_turbo_freq_table;
-	} else {
-		printk("CPU PXA: Unknown policy found. "
-		       "Using CPUFREQ_POLICY_PERFORMANCE\n");
-		pxa_freq_settings = pxa255_run_freqs;
-		pxa_freqs_table   = pxa255_run_freq_table;
-	}
-
-	/* Lookup the next frequency */
-	if (cpufreq_frequency_table_target(policy, pxa_freqs_table,
-	                                   target_freq, relation, &idx)) {
-		return -EINVAL;
-	}
-
-	freqs.old = policy->cur;
-	freqs.new = pxa_freq_settings[idx].khz;
-	freqs.cpu = policy->cpu;
-
-	if (freq_debug)
-		pr_debug(KERN_INFO "Changing CPU frequency to %d Mhz, (SDRAM %d Mhz)\n",
-		       freqs.new / 1000, (pxa_freq_settings[idx].div2) ?
-		       (pxa_freq_settings[idx].membus / 2000) :
-		       (pxa_freq_settings[idx].membus / 1000));
-
-	/*
-	 * Tell everyone what we're about to do...
-	 * you should add a notify client with any platform specific
-	 * Vcc changing capability
-	 */
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
-	/* Calculate the next MDREFR.  If we're slowing down the SDRAM clock
-	 * we need to preset the smaller DRI before the change.  If we're speeding
-	 * up we need to set the larger DRI value after the change.
-	 */
-	preset_mdrefr = postset_mdrefr = MDREFR;
-	if ((MDREFR & MDREFR_DRI_MASK) > MDREFR_DRI(pxa_freq_settings[idx].membus)) {
-		preset_mdrefr = (preset_mdrefr & ~MDREFR_DRI_MASK) |
-		                MDREFR_DRI(pxa_freq_settings[idx].membus);
-	}
-	postset_mdrefr = (postset_mdrefr & ~MDREFR_DRI_MASK) |
-		            MDREFR_DRI(pxa_freq_settings[idx].membus);
-
-	/* If we're dividing the memory clock by two for the SDRAM clock, this
-	 * must be set prior to the change.  Clearing the divide must be done
-	 * after the change.
-	 */
-	if (pxa_freq_settings[idx].div2) {
-		preset_mdrefr  |= MDREFR_DB2_MASK;
-		postset_mdrefr |= MDREFR_DB2_MASK;
-	} else {
-		postset_mdrefr &= ~MDREFR_DB2_MASK;
-	}
-
-	local_irq_save(flags);
-
-	/* Set new the CCCR */
-	CCCR = pxa_freq_settings[idx].cccr;
-
-	asm volatile("							\n\
-		ldr	r4, [%1]		/* load MDREFR */	\n\
-		b	2f						\n\
-		.align	5 						\n\
-1:									\n\
-		str	%4, [%1]		/* preset the MDREFR */	\n\
-		mcr	p14, 0, %2, c6, c0, 0	/* set CCLKCFG[FCS] */	\n\
-		str	%5, [%1]		/* postset the MDREFR */ \n\
-									\n\
-		b	3f						\n\
-2:		b	1b						\n\
-3:		nop							\n\
-	  "
-	  : "=&r" (unused)
-	  : "r" (&MDREFR), "r" (CCLKCFG_TURBO|CCLKCFG_FCS), "r" (ramstart),
-	    "r" (preset_mdrefr), "r" (postset_mdrefr)
-	  : "r4", "r5");
-	local_irq_restore(flags);
-
-	/*
-	 * Tell everyone what we've just done...
-	 * you should add a notify client with any platform specific
-	 * SDRAM refresh timer adjustments
-	 */
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+    int idx;
+    cpumask_t cpus_allowed, allowedcpuset;
+    int cpu = policy->cpu;
+    struct cpufreq_freqs freqs;
+    unsigned long flags;
+    unsigned int unused;
+    unsigned int preset_mdrefr, postset_mdrefr, cclkcfg;
+
+    if(freq_debug) {
+      printk ("CPU PXA: target freq %d\n", target_freq);
+      printk ("CPU PXA: relation %d\n", relation);
+    }
+
+    /*
+     * Save this threads cpus_allowed mask.
+     */
+    cpus_allowed = current->cpus_allowed;
+
+    /*
+     * Bind to the specified CPU.  When this call returns,
+     * we should be running on the right CPU.
+     */
+    cpus_clear (allowedcpuset);
+    cpu_set (cpu, allowedcpuset);
+    set_cpus_allowed(current, allowedcpuset);
+    BUG_ON(cpu != smp_processor_id());
+
+    /* Lookup the next frequency */
+    if (cpufreq_frequency_table_target(policy, pxa2xx_freq_table, 
+                                       target_freq, relation, &idx)) {
+      return -EINVAL;
+    }
+
+    freqs.old = policy->cur;
+    freqs.new = pxa2xx_freqs[idx].khz;
+    freqs.cpu = policy->cpu;  
+    if(freq_debug) {
+        printk(KERN_INFO "Changing CPU frequency to %d Mhz, (SDRAM %d Mhz)\n", 
+            freqs.new/1000, (pxa2xx_freqs[idx].div2) ? 
+            (pxa2xx_freqs[idx].membus/2000) : 
+            (pxa2xx_freqs[idx].membus/1000));
+    }
+
+    /* 
+     * Tell everyone what we're about to do... 
+     * you should add a notify client with any platform specific 
+     * Vcc changing capability
+     */
+    cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+    /* Calculate the next MDREFR.  If we're slowing down the SDRAM clock
+     * we need to preset the smaller DRI before the change.  If we're speeding
+     * up we need to set the larger DRI value after the change.  
+     */
+    preset_mdrefr = postset_mdrefr = MDREFR;
+    if((MDREFR & MDREFR_DRI_MASK) > MDREFR_DRI(pxa2xx_freqs[idx].membus)) {    
+        preset_mdrefr = (preset_mdrefr & ~MDREFR_DRI_MASK) | 
+                        MDREFR_DRI(pxa2xx_freqs[idx].membus);
+    }
+    postset_mdrefr = (postset_mdrefr & ~MDREFR_DRI_MASK) | 
+                    MDREFR_DRI(pxa2xx_freqs[idx].membus);
+    
+    /* If we're dividing the memory clock by two for the SDRAM clock, this
+     * must be set prior to the change.  Clearing the divide must be done
+     * after the change.
+     */
+    if(pxa2xx_freqs[idx].div2) {
+      /*
+       * Potentially speeding up memory clock, so slow down the memory
+       * before speeding up the clock.
+       */
+      preset_mdrefr  |= MDREFR_DB2_MASK | MDREFR_K0DB4;
+      preset_mdrefr  &= ~MDREFR_K0DB2;
+
+      postset_mdrefr |= MDREFR_DB2_MASK | MDREFR_K0DB4;
+      postset_mdrefr &= ~MDREFR_K0DB2;
+    } else { 
+      /*
+       * Potentially slowing down memory clock.  Wait until after the change
+       * to speed up the memory.
+       */
+      postset_mdrefr &= ~MDREFR_DB2_MASK; 
+      postset_mdrefr &= ~MDREFR_K0DB4;
+      postset_mdrefr |= MDREFR_K0DB2;
+    }
+
+    cclkcfg = pxa2xx_freqs[idx].cclkcfg;
+
+    if (freq_debug) {
+      printk (KERN_INFO "CPU PXA writing 0x%08x to CCCR\n",
+              pxa2xx_freqs[idx].cccr);
+      printk (KERN_INFO "CPU PXA writing 0x%08x to CCLKCFG\n",
+              pxa2xx_freqs[idx].cclkcfg);
+      printk (KERN_INFO "CPU PXA writing 0x%08x to MDREFR before change\n",
+              preset_mdrefr);
+      printk (KERN_INFO "CPU PXA writing 0x%08x to MDREFR after change\n",
+              postset_mdrefr);
+    }
+    
+    local_irq_save(flags);
+    
+    /* Set new the CCCR */
+    CCCR = pxa2xx_freqs[idx].cccr;
+
+    /*
+     * Should really set both of PMCR[xIDAE] while changing the core frequency
+     */
+
+    /*
+     * TODO: On the PXA27x: If we're setting half-turbo mode and changing the
+     * core frequency at the same time we must split it up into two operations.
+     * The current values in the pxa2xx_freqs table don't do this, so the code
+     * is unimplemented.
+     */
+
+    __asm__ __volatile__("                                  \
+        ldr r4, [%1] ;  /* load MDREFR */                   \
+        b   2f ;                                            \
+        .align  5 ;                                         \
+1:                                                          \
+        str %3, [%1] ;          /* preset the MDREFR */     \
+        mcr p14, 0, %2, c6, c0, 0 ; /* set CCLKCFG[FCS] */  \
+        str %4, [%1] ;          /* postset the MDREFR */    \
+                                                            \
+        b   3f       ;                                      \
+2:      b   1b       ;                                      \
+3:      nop          ;                                      \
+        "                                                                            
+        : "=&r" (unused)                                                             
+        : "r" (&MDREFR), "r" (cclkcfg), \
+          "r" (preset_mdrefr), "r" (postset_mdrefr)             
+        : "r4", "r5");
+    local_irq_restore(flags);
+
+    if (freq_debug) {
+      printk (KERN_INFO "CPU PXA Frequency change successful\n");
+      printk (KERN_INFO "CPU PXA new CCSR 0x%08x\n", CCSR);
+    }
+
+    /*
+     * Restore the CPUs allowed mask.
+     */
+    set_cpus_allowed(current, cpus_allowed);
+
+    /* 
+     * Tell everyone what we've just done... 
+     * you should add a notify client with any platform specific 
+     * SDRAM refresh timer adjustments
+     */
+    cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
-	return 0;
+    return 0;
 }
 
-static unsigned int pxa_cpufreq_get(unsigned int cpu)
+static int pxa_cpufreq_init(struct cpufreq_policy *policy)
 {
-	return get_clk_frequency_khz(0);
+    cpumask_t cpus_allowed, allowedcpuset;
+    unsigned int cpu = policy->cpu;
+    int i;
+    unsigned int cclkcfg;
+
+    cpus_allowed = current->cpus_allowed;
+
+    cpus_clear (allowedcpuset);
+    cpu_set (cpu, allowedcpuset);
+    set_cpus_allowed(current, allowedcpuset);
+    BUG_ON(cpu != smp_processor_id());
+
+    /* set default governor and cpuinfo */
+    policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+    policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
+    policy->cur = get_clk_frequency_khz(0); /* current freq */
+
+    /* Generate the cpufreq_frequency_table struct */
+    for(i=0;i<NUM_FREQS;i++) {
+        pxa2xx_freq_table[i].frequency = pxa2xx_freqs[i].khz;
+        pxa2xx_freq_table[i].index = i;    
+    }
+    pxa2xx_freq_table[i].frequency = CPUFREQ_TABLE_END;
+
+    /*
+     * Set the policy's minimum and maximum frequencies from the tables
+     * just constructed.  This sets cpuinfo.mxx_freq, min and max.
+     */
+    cpufreq_frequency_table_cpuinfo (policy, pxa2xx_freq_table);
+    
+    set_cpus_allowed(current, cpus_allowed);
+    printk(KERN_INFO "PXA CPU frequency change support initialized\n");
+
+    if (freq_debug) {
+      printk (KERN_INFO "PXA CPU initial CCCR 0x%08x\n", CCCR);
+      asm 
+	(
+	 "mrc p14, 0, %0, c6, c0, 0 ; /* read CCLKCFG from CP14 */ "
+	 : "=r" (cclkcfg) : 
+	 );
+      printk ("PXA CPU initial CCLKCFG 0x%08x\n", cclkcfg);
+      printk ("PXA CPU initial MDREFR  0x%08x\n", MDREFR);
+    }
+
+    return 0;
 }
 
-static int pxa_cpufreq_init(struct cpufreq_policy *policy)
+static unsigned int pxa_cpufreq_get(unsigned int cpu)
 {
-	int i;
+    cpumask_t cpumask_saved;
+    unsigned int cur_freq;
+
+    cpumask_saved = current->cpus_allowed;
+    set_cpus_allowed(current, cpumask_of_cpu(cpu));
+    BUG_ON(cpu != smp_processor_id());
 
-	/* set default policy and cpuinfo */
-	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
-	policy->policy = CPUFREQ_POLICY_PERFORMANCE;
-	policy->cpuinfo.max_freq = PXA25x_MAX_FREQ;
-	policy->cpuinfo.min_freq = PXA25x_MIN_FREQ;
-	policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
-	policy->cur = get_clk_frequency_khz(0);    /* current freq */
-	policy->min = policy->max = policy->cur;
-
-	/* Generate the run cpufreq_frequency_table struct */
-	for (i = 0; i < NUM_RUN_FREQS; i++) {
-		pxa255_run_freq_table[i].frequency = pxa255_run_freqs[i].khz;
-		pxa255_run_freq_table[i].index = i;
-	}
-
-	pxa255_run_freq_table[i].frequency = CPUFREQ_TABLE_END;
-	/* Generate the turbo cpufreq_frequency_table struct */
-	for (i = 0; i < NUM_TURBO_FREQS; i++) {
-		pxa255_turbo_freq_table[i].frequency = pxa255_turbo_freqs[i].khz;
-		pxa255_turbo_freq_table[i].index = i;
-	}
-	pxa255_turbo_freq_table[i].frequency = CPUFREQ_TABLE_END;
+    cur_freq = get_clk_frequency_khz(0);
 
-	printk(KERN_INFO "PXA CPU frequency change support initialized\n");
+    set_cpus_allowed(current, cpumask_saved);
 
-	return 0;
+    return cur_freq;
 }
 
 static struct cpufreq_driver pxa_cpufreq_driver = {
-	.verify	= pxa_verify_policy,
-	.target	= pxa_set_target,
-	.init	= pxa_cpufreq_init,
-	.get	= pxa_cpufreq_get,
-	.name	= "PXA25x",
+    .verify     = pxa_verify_policy,
+    .target     = pxa_set_target,
+    .init       = pxa_cpufreq_init,
+    .get        = pxa_cpufreq_get,
+#if defined(CONFIG_PXA25x)
+    .name       = "PXA25x",
+#elif defined(CONFIG_PXA27x)
+    .name       = "PXA27x",
+#endif
 };
 
 static int __init pxa_cpu_init(void)
 {
-	int ret = -ENODEV;
-	if (cpu_is_pxa25x())
-		ret = cpufreq_register_driver(&pxa_cpufreq_driver);
-	return ret;
+    return cpufreq_register_driver(&pxa_cpufreq_driver);
 }
 
 static void __exit pxa_cpu_exit(void)
 {
-	if (cpu_is_pxa25x())
-		cpufreq_unregister_driver(&pxa_cpufreq_driver);
+    cpufreq_unregister_driver(&pxa_cpufreq_driver);
 }
 
 
@@ -298,3 +415,4 @@
 MODULE_LICENSE("GPL");
 module_init(pxa_cpu_init);
 module_exit(pxa_cpu_exit);
+
diff -urN linux-2.6.25/arch/arm/mach-pxa/Kconfig linux-2.6.25-vpac1/arch/arm/mach-pxa/Kconfig
--- linux-2.6.25/arch/arm/mach-pxa/Kconfig	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/arch/arm/mach-pxa/Kconfig	2008-04-24 15:12:18.000000000 +0200
@@ -36,6 +36,11 @@
 	bool "Intel HCDDBBVA0 Development Platform"
 	select PXA27x
 
+config MACH_VPAC270
+	bool "Voipac PXA270 Module"
+	select PXA27x
+	select IWMMXT
+
 config ARCH_PXA_IDP
 	bool "Accelent Xscale IDP"
 	select PXA25x
diff -urN linux-2.6.25/arch/arm/mach-pxa/Makefile linux-2.6.25-vpac1/arch/arm/mach-pxa/Makefile
--- linux-2.6.25/arch/arm/mach-pxa/Makefile	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/arch/arm/mach-pxa/Makefile	2008-05-02 10:32:51.000000000 +0200
@@ -25,6 +25,7 @@
 obj-$(CONFIG_MACH_PCM027)	+= pcm027.o
 obj-$(CONFIG_MACH_PCM990_BASEBOARD)	+= pcm990-baseboard.o
 obj-$(CONFIG_MACH_TOSA)		+= tosa.o
+obj-$(CONFIG_MACH_VPAC270)	+= vpac270.o
 obj-$(CONFIG_MACH_EM_X270)	+= em-x270.o
 obj-$(CONFIG_MACH_MAGICIAN)	+= magician.o
 obj-$(CONFIG_ARCH_PXA_ESERIES)	+= eseries.o
diff -urN linux-2.6.25/arch/arm/mach-pxa/vpac270.c linux-2.6.25-vpac1/arch/arm/mach-pxa/vpac270.c
--- linux-2.6.25/arch/arm/mach-pxa/vpac270.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.25-vpac1/arch/arm/mach-pxa/vpac270.c	2008-05-02 09:11:10.000000000 +0200
@@ -0,0 +1,439 @@
+ /*
+ *  linux/arch/arm/mach-pxa/vpac270.c
+ *
+ *  Support for Voipac PXA270 module
+ *
+ *  Copyright (c) 2006 Voipac Technologies <support@voipac.com>
+ *  
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/bitops.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <asm/arch/pxa2xx_spi.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/flash.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/vpac270.h>
+#include <asm/arch/audio.h>
+#include <asm/arch/pxafb.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/i2c.h>
+#include <asm/arch/irda.h>
+#include <asm/arch/ohci.h>
+#include <asm/arch/udc.h>
+
+#include "generic.h"
+
+#include <linux/dm9000.h>
+
+
+static void __init vpac270_init_irq(void)
+{
+	pxa27x_init_irq();
+
+	/* setup extra vpac270 irqs */
+	set_irq_type(VPAC270_ETH_IRQ, IRQT_RISING);
+	set_irq_type(VPAC270_IDE_IRQ, IRQT_RISING);
+}
+
+static struct resource dm9000_resources[] = {
+    [0] = {
+	.start	= (VPAC270_ETH_PHYS + 0x300),
+	.end	= (VPAC270_ETH_PHYS + 0x300 + VPAC270_ETH_SIZE - 1),
+        .flags  = IORESOURCE_MEM,
+    },
+    [1] = {
+        .start  = (VPAC270_ETH_IRQ),
+        .end    = (VPAC270_ETH_IRQ),
+        .flags  = IORESOURCE_IRQ,
+    },
+};
+
+static struct dm9000_plat_data dm9000_setup = {
+    .flags          = 0		//DM9000_PLATF_16BITONLY
+};
+
+static struct platform_device dm9000_device = {
+    .name           = "dm9000",
+    .id             = 0,
+    .num_resources  = ARRAY_SIZE(dm9000_resources),
+    .resource       = dm9000_resources,
+    .dev            = {
+        .platform_data = &dm9000_setup,
+    }
+};
+#ifdef CONFIG_SPI_PXA2XX
+static struct resource pxa_ssp_resources[] = {
+        [0] = {
+                .start  = __PREG(SSCR0_P(1)),
+                .end    = __PREG(SSCR0_P(1)) + 0x14,
+                .flags  = IORESOURCE_MEM,
+        },
+        [1] = {
+                .start  = IRQ_SSP,
+                .end    = IRQ_SSP,
+                .flags  = IORESOURCE_IRQ,
+        },
+};
+
+static struct pxa2xx_spi_master pxa_ssp_master_info = {
+        .ssp_type       = PXA25x_SSP,
+        .clock_enable   = CKEN_SSP,
+        .num_chipselect = 1,
+};
+
+static struct platform_device vpac270_ssp_device = {
+        .name           = "pxa2xx-spi",
+        .id             = 1,
+        .resource       = pxa_ssp_resources,
+        .num_resources  = ARRAY_SIZE(pxa_ssp_resources),
+        .dev = {
+                .platform_data  = &pxa_ssp_master_info,
+        },
+};
+#endif
+#ifdef CONFIG_SND_PXA2XX_AC97
+static struct platform_device pxa_audio_device = {
+	.name           = "pxa2xx-ac97",
+	.id             = -1,
+};
+#endif
+#ifdef CONFIG_SERIO_VPAC270
+static struct platform_device vpac270kb_device = {
+	.name           = "vpac270ps2",
+	.id             = 0,
+};
+
+static struct platform_device vpac270ms_device = {
+	.name           = "vpac270ps2",
+	.id             = 1,
+};
+#endif
+#ifdef CONFIG_LEDS_VPAC270
+static struct platform_device vpac270led_device = {
+	.name		= "vpac270-led",
+	.id		= -1,
+};
+#endif
+static struct platform_device *devices[] __initdata = {
+	&dm9000_device,
+#ifdef CONFIG_SND_PXA2XX_AC97
+	&pxa_audio_device,
+#endif
+#ifdef CONFIG_SPI_PXA2XX
+	&vpac270_ssp_device,
+#endif
+#ifdef CONFIG_SERIO_VPAC270
+	&vpac270ms_device,
+	&vpac270kb_device,
+#endif
+#ifdef CONFIG_LEDS_VPAC270
+    	&vpac270led_device,
+#endif
+};
+
+/*
+ * MMC/SD Device
+ *
+ */
+static struct pxamci_platform_data vpac270_mci_platform_data;
+
+static int vpac270_mci_init(struct device *dev, irqreturn_t (*detect_int)(int, void *), void *data)
+{
+    int err;
+
+    printk("Voipac PXA270 MMC/SD setup ");
+	/* setup GPIO for PXA2xx MMC controller	*/
+	pxa_gpio_mode(GPIO32_MMCCLK_MD);
+	pxa_gpio_mode(GPIO112_MMCCMD_MD);
+	pxa_gpio_mode(GPIO92_MMCDAT0_MD);
+	pxa_gpio_mode(GPIO109_MMCDAT1_MD);
+	pxa_gpio_mode(GPIO110_MMCDAT2_MD);
+	pxa_gpio_mode(GPIO111_MMCDAT3_MD);
+
+	pxa_gpio_mode(GPIO_MMC_CD_IRQ | GPIO_IN);
+
+        vpac270_mci_platform_data.detect_delay = msecs_to_jiffies(250);
+
+	err = request_irq(VPAC270_MMC_CD_IRQ, detect_int, 0,
+			     "MMC card detect", data);
+	if (err) {
+		printk(KERN_ERR "vpac270_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
+		return -1;
+	}
+
+	set_irq_type(VPAC270_MMC_CD_IRQ, IRQT_BOTHEDGE);
+
+    printk("done.\n");
+	return 0;
+}
+
+static struct pxamci_platform_data vpac270_mci_platform_data = {
+	.ocr_mask	= MMC_VDD_32_33|MMC_VDD_33_34,
+	.init 		= vpac270_mci_init,
+};
+
+#ifdef CONFIG_FB_PXA
+
+#ifdef CONFIG_FB_PXA_BPP8
+#define FB_PXA_BPP 8
+#else
+#define FB_PXA_BPP 16
+#endif
+
+static struct pxafb_mode_info  vpac270_fb_mode_info[] __initdata = {
+#if defined(CONFIG_FB_PXA_TX14D14VM1BBA)
+/*	VGA 640x480 18bit, pclk=26MHz	*/
+{
+        .pixclock               = 57693,	// PCD=3
+        .xres                   = 640,
+        .yres                   = 480,
+        .bpp                    = 8,
+        .hsync_len              = 32,
+        .left_margin            = 144,
+        .right_margin           = 32,
+        .vsync_len              = 2,
+        .upper_margin           = 13,
+        .lower_margin           = 30,
+        .sync                   = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+},
+#elif defined(CONFIG_FB_PXA_VGA)
+/*	VGA 640x480 16bit, pclk=26MHz	*/
+{
+        .pixclock               = 57693,	// PCD=3
+        .xres                   = 640,
+        .yres                   = 480,
+        .bpp                    = FB_PXA_BPP,
+        .hsync_len              = 64,
+        .left_margin            = 96,
+        .right_margin           = 48,
+        .vsync_len              = 2,
+        .upper_margin           = 33,
+        .lower_margin           = 10,
+        .sync                   = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+},
+#elif defined(CONFIG_FB_PXA_SVGA)
+/*	SVGA 800x600 16bit, pclk=34.6MHz	*/
+{
+        .pixclock               = 38462,	// PCD=2
+        .xres                   = 800,
+        .yres                   = 600,
+        .bpp                    = FB_PXA_BPP,
+        .hsync_len              = 8,
+        .left_margin            = 128,
+        .right_margin           = 48,
+        .vsync_len              = 1,
+        .upper_margin           = 33,
+        .lower_margin           = 1,
+        .sync                   = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+},
+#elif defined(CONFIG_FB_PXA_XGA)
+/*	XGA 1024x768 16bit, pclk=52.0MHz	*/
+{
+        .pixclock               = 19231,	// PCD=1
+        .xres                   = 1024,
+        .yres                   = 768,
+        .bpp                    = FB_PXA_BPP,
+        .hsync_len              = 63,
+        .left_margin            = 220,
+        .right_margin           = 8,
+        .vsync_len              = 1,
+        .upper_margin           = 33,
+        .lower_margin           = 2,
+        .sync                   = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+},
+#endif
+};
+
+static struct pxafb_mach_info vpac270_fb_mach_info __initdata = {
+	.modes			= vpac270_fb_mode_info,
+	.num_modes		= ARRAY_SIZE(vpac270_fb_mode_info),
+        .lccr0                  = 0x043008f8,
+        .lccr3                  = 0x0040ff00,
+#if defined(CONFIG_FB_PXA_TX14D14VM1BBA)
+	.lccr4			= LCCR4_PAL_FOR_2,
+#else
+	.lccr4			= LCCR4_PAL_FOR_0,
+#endif
+};
+#endif	// CONFIG_FB_PXA
+
+static int vpac270_ohci_init(struct device *dev)
+{
+        /* setup Port1 GPIO pin. */
+        pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN);  /* USBHPWR1 */
+        pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */
+	pxa_gpio_mode(119 | GPIO_ALT_FN_1_IN);
+    	pxa_gpio_mode(120 | GPIO_ALT_FN_2_OUT);
+
+        /* Set the Power Control Polarity Low and Power Sense
+           Polarity Low to active low. */
+        UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
+                ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
+
+	UP2OCR = UP2OCR_HXS | UP2OCR_HXOE | UP2OCR_DPPDE | UP2OCR_DMPDE;
+
+        return 0;
+}
+
+static struct pxaohci_platform_data vpac270_ohci_platform_data = {
+        .port_mode      = PMM_GLOBAL_MODE,	//PMM_PERPORT_MODE, PMM_NPS_MODE,
+        .init           = vpac270_ohci_init,
+};
+
+/* USB Device Controller */
+
+static int
+udc_detect(void)
+{
+	 printk ("UDC detect\n");
+//	if (core_funcs.udc_detect != NULL)
+//		return core_funcs.udc_detect();
+//	else
+		return 0;
+}
+
+static void
+udc_enable(int cmd) 
+{
+	switch (cmd)
+	{
+		case PXA2XX_UDC_CMD_DISCONNECT:
+			printk (KERN_NOTICE "UDC cmd disconnect\n");
+
+			UP2OCR = (UP2OCR | UP2OCR_HXS| UP2OCR_HXOE | UP2OCR_DPPDE | UP2OCR_DMPDE) &
+				~(UP2OCR_DPPUE | UP2OCR_DMPUE | UP2OCR_DPPUBE | UP2OCR_DMPUBE);
+			break;
+
+		case PXA2XX_UDC_CMD_CONNECT:
+			printk (KERN_NOTICE "UDC cmd connect\n");
+
+			UP2OCR = (UP2OCR | UP2OCR_HXOE | UP2OCR_DPPUE) &
+				~(UP2OCR_HXS | UP2OCR_DMPUE | UP2OCR_DPPUBE |
+				 UP2OCR_DMPUBE | UP2OCR_DPPDE | UP2OCR_DMPDE);
+			break;
+	}
+}
+
+static struct pxa2xx_udc_mach_info hx4700_udc_mach_info = {
+	.udc_is_connected = udc_detect,
+	.udc_command      = udc_enable,
+};
+
+static struct i2c_board_info __initdata vpac270_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("rtc-ds1307", 0x68),
+		.type   = "ds1339",
+	}
+};
+
+static void __init vpac270_init(void)
+{
+    /* reset UCB1400 */
+    GPSR2 &= ~(1u << 31);
+    pxa_gpio_mode(GPIO_AC97_RESET | GPIO_OUT);
+    udelay(12);
+    pxa_set_mci_info(&vpac270_mci_platform_data);
+    platform_add_devices(devices, ARRAY_SIZE(devices));
+    pxa_set_i2c_info(NULL);
+    i2c_register_board_info(0, vpac270_i2c_devices, ARRAY_SIZE(vpac270_i2c_devices));
+#ifdef CONFIG_FB_PXA
+    set_pxa_fb_info(&vpac270_fb_mach_info);
+#if defined(CONFIG_FB_PXA_TX14D14VM1BBA)
+    pxa_gpio_mode(86 | GPIO_ALT_FN_2_OUT);
+    pxa_gpio_mode(87 | GPIO_ALT_FN_2_OUT);
+    LCCR4 = 0x800b0000;
+#else
+    LCCR4 = 0x800a0000;
+#endif
+#endif
+    pxa_set_ohci_info(&vpac270_ohci_platform_data);
+    pxa_set_udc_info( &hx4700_udc_mach_info );
+
+    GPDR(VPAC270_LCD_BLO_GPIO) |= GPIO_bit(VPAC270_LCD_BLO_GPIO);
+    GPSR(VPAC270_LCD_BLO_GPIO) |= GPIO_bit(VPAC270_LCD_BLO_GPIO);
+
+}
+
+static struct map_desc vpac270_io_desc[] __initdata = {
+ /* virtual         physical            length              type */
+/*{ VPAC270_FLASH,  VPAC270_FLASH_PHYS, VPAC270_FLASH_SIZE, MT_DEVICE },
+  { VPAC270_ETH_BASE, VPAC270_ETH_PHYS, VPAC270_ETH_SIZE,   MT_DEVICE },*/
+//  { 0xf0000000, __phys_to_pfn(0x0c000000), 0x04000000, MT_DEVICE },
+};
+
+static void __init vpac270_map_io(void)
+{
+	pxa_map_io();
+	iotable_init(vpac270_io_desc, ARRAY_SIZE(vpac270_io_desc));
+
+	/* enabling FFUART */
+	CKEN |= CKEN_FFUART;
+	pxa_gpio_mode(GPIO34_FFRXD_MD);
+	pxa_gpio_mode(GPIO100_FFCTS_MD);
+	pxa_gpio_mode(GPIO10_FFDCD_MD);
+	pxa_gpio_mode(GPIO33_FFDSR_MD);
+	pxa_gpio_mode(GPIO38_FFRI_MD);
+	pxa_gpio_mode(GPIO39_FFTXD_MD);
+	pxa_gpio_mode(GPIO40_FFDTR_MD);
+	pxa_gpio_mode(GPIO27_FFRTS_MD);
+
+	/* enabling BTUART */
+	CKEN |= CKEN_BTUART;
+	pxa_gpio_mode(GPIO42_BTRXD_MD);
+	pxa_gpio_mode(GPIO43_BTTXD_MD);
+	pxa_gpio_mode(GPIO44_BTCTS_MD);
+	pxa_gpio_mode(GPIO45_BTRTS_MD);
+
+	/* This is for the Davicom chip select */
+	pxa_gpio_mode(GPIO78_nCS_2_MD);
+
+	/* bring hdd out of reset */
+	GPCR(GPIO_PCMCIA1_RESET) |= GPIO_bit(GPIO_PCMCIA1_RESET);       // disable reset
+
+	/* setup sleep mode values */
+	PWER  = 0x00000002;
+	PFER  = 0x00000000;
+	PRER  = 0x00000002;
+	PGSR0 = 0x00008000;
+	PGSR1 = 0x003F0202;
+	PGSR2 = 0x0001C000;
+	PCFR |= PCFR_OPDE;
+}
+
+MACHINE_START(VPAC270, "Voipac PXA270 Module")
+        /* Maintainer: Voipac Technologies <support@voipac.com> */
+        .phys_io        = 0x40000000,
+        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.boot_params	= 0xa0000100,
+        .map_io         = vpac270_map_io,
+        .init_irq       = vpac270_init_irq,
+        .timer          = &pxa_timer,
+        .init_machine   = vpac270_init,
+MACHINE_END
+
diff -urN linux-2.6.25/arch/arm/Makefile linux-2.6.25-vpac1/arch/arm/Makefile
--- linux-2.6.25/arch/arm/Makefile	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/arch/arm/Makefile	2008-04-24 15:12:18.000000000 +0200
@@ -20,7 +20,7 @@
 
 # Do not use arch/arm/defconfig - it's always outdated.
 # Select a platform tht is kept up-to-date
-KBUILD_DEFCONFIG := versatile_defconfig
+KBUILD_DEFCONFIG := vpac270_defconfig
 
 # defines filename extension depending memory manement type.
 ifeq ($(CONFIG_MMU),)
diff -urN linux-2.6.25/drivers/cpufreq/Kconfig linux-2.6.25-vpac1/drivers/cpufreq/Kconfig
--- linux-2.6.25/drivers/cpufreq/Kconfig	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/cpufreq/Kconfig	2008-05-02 12:14:40.000000000 +0200
@@ -16,7 +16,7 @@
 if CPU_FREQ
 
 config CPU_FREQ_TABLE
-	tristate
+	def_tristate m
 
 config CPU_FREQ_DEBUG
 	bool "Enable CPUfreq debugging"
diff -urN linux-2.6.25/drivers/ide/arm/Makefile linux-2.6.25-vpac1/drivers/ide/arm/Makefile
--- linux-2.6.25/drivers/ide/arm/Makefile	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/ide/arm/Makefile	2008-04-24 15:17:16.000000000 +0200
@@ -2,6 +2,7 @@
 obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)	+= icside.o
 obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)	+= rapide.o
 obj-$(CONFIG_BLK_DEV_IDE_BAST)		+= bast-ide.o
+obj-$(CONFIG_BLK_DEV_IDE_VPAC270)	+= vpac270-ide.o
 obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710)	+= palm_bk3710.o
 
 ifeq ($(CONFIG_IDE_ARM), m)
diff -urN linux-2.6.25/drivers/ide/arm/vpac270-ide.c linux-2.6.25-vpac1/drivers/ide/arm/vpac270-ide.c
--- linux-2.6.25/drivers/ide/arm/vpac270-ide.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.25-vpac1/drivers/ide/arm/vpac270-ide.c	2008-05-02 16:14:28.000000000 +0200
@@ -0,0 +1,268 @@
+/* linux/drivers/ide/arm/vpac270-ide.c
+ *
+ * Copyright (c) 2006 Voipac Technologies <support@voipac.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+//#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/errno.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/scatterlist.h>
+
+#include <asm/dma.h>
+#include <asm/io.h>
+
+#include <asm/arch/vpac270.h>
+
+/* list of registered interfaces */
+static ide_hwif_t *vpac270_hwif;
+
+#define IDE_BASE_PHYS	0x0c000000
+//#define DMA_IRQ_DETECT IRQ_GPIO(80)
+#define GPIO80_DREQ_1_MD         (80 | GPIO_ALT_FN_1_IN)
+
+static void vpac270_set_dma_mode(ide_drive_t *drive, u8 xfer_mode)
+{
+        int cycle_time = 0, use_dma_info = 0;
+
+        switch (xfer_mode) {
+        case XFER_MW_DMA_2:
+                cycle_time = 120;
+                use_dma_info = 1;
+                break;
+
+        case XFER_MW_DMA_1:
+                cycle_time = 250;
+                use_dma_info = 1;
+                break;
+
+        case XFER_MW_DMA_0:
+                cycle_time = 480;
+                break;
+
+        case XFER_SW_DMA_2:
+        case XFER_SW_DMA_1:
+        case XFER_SW_DMA_0:
+                cycle_time = 480;
+                break;
+
+	default:
+		return;
+        }
+
+        if (use_dma_info && drive->id->eide_dma_time > cycle_time)
+                cycle_time = drive->id->eide_dma_time;
+
+        drive->drive_data = cycle_time;
+
+        printk("%s: %s selected (peak %dMB/s)\n", drive->name,
+                ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
+}
+
+static int vpac270_dma_setup(ide_drive_t *drive)
+{
+        ide_hwif_t *hwif = HWIF(drive);
+        struct request *rq = hwif->hwgroup->rq;
+	
+	blk_queue_max_segment_size( drive->queue, (DCMD_LENGTH & 0xfffffe00) );
+	ide_map_sg(drive, rq);
+
+        hwif->sg_dma_direction = (rq_data_dir(rq) == READ)?
+				DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+	if( hwif->sg_nents > 0)
+	{
+		int i = 0;
+		int dma = hwif->dma;
+		struct scatterlist *sg = hwif->sg_table;
+
+		pxa_dma_desc *ddadr = (void *) hwif->dmatable_dma;
+		pxa_dma_desc *ddptr = (void *) hwif->dmatable_cpu;
+
+		DCSR(dma) = 0;
+		
+		do
+		{
+        	        u32 length = sg->length;
+
+			sg->dma_address = dma_map_page( NULL, sg_page(sg), sg->offset,
+					length, hwif->sg_dma_direction);
+			
+			ddptr->ddadr = (u32) ++ddadr;	// next DDADR
+
+			if(hwif->sg_dma_direction == DMA_FROM_DEVICE)
+			{
+				ddptr->dsadr = 0xc000020;	// DSADR
+				ddptr->dtadr = sg->dma_address;	// DTADR
+				ddptr->dcmd = (DCMD_INCTRGADDR | DCMD_BURST32 | DCMD_FLOWSRC |
+						DCMD_WIDTH2 | (DCMD_LENGTH & length));
+			}
+			else
+			{
+				ddptr->dsadr = sg->dma_address;	// DSADR
+				ddptr->dtadr = 0xc000020;	// DTADR
+				ddptr->dcmd = (DCMD_INCSRCADDR | DCMD_BURST32 | DCMD_FLOWTRG |
+						DCMD_WIDTH2 | (DCMD_LENGTH & length));
+			}
+			sg++;
+		}
+		while( ++i < hwif->sg_nents && ddptr++);
+
+		ddptr->ddadr = DDADR_STOP;
+
+		DDADR(dma) = hwif->dmatable_dma;
+
+		DRQSR1 = DRQSR_REQCLR;
+		DRCMR1 = dma | DRCMR_MAPVLD;
+	        
+		DCSR(dma) = DCSR_RUN;
+        	drive->waiting_for_dma = 1;
+	}
+        return 0;
+}
+
+static void vpac270_dma_exec_cmd(ide_drive_t *drive, u8 cmd)
+{
+	ide_execute_command(drive, cmd, &ide_dma_intr, 2 * WAIT_CMD, NULL);
+}
+
+static void vpac270_dma_start(ide_drive_t *drive)
+{
+}
+
+static int vpac270_dma_end(ide_drive_t *drive)
+{
+        ide_hwif_t *hwif = HWIF(drive);
+        int dma = hwif->dma;
+	
+	drive->waiting_for_dma = 0;
+
+	while (!(DCSR(dma) & DCSR_STOPSTATE))
+		cpu_relax();
+	DCSR(dma) = 0;
+
+	dma_unmap_sg( NULL, hwif->sg_table, hwif->sg_nents,
+			hwif->sg_dma_direction);
+	return 0;
+}
+
+static int vpac270_dma_test_irq(ide_drive_t *drive)
+{
+	return (GPLR(GPIO_IDE_IRQ) & GPIO_bit(GPIO_IDE_IRQ));
+}
+
+static void vpac270_dma_timeout(ide_drive_t *drive)
+{
+        ide_hwif_t *hwif = HWIF(drive);
+        int dma = hwif->dma;
+printk("%s:%d\n",__FUNCTION__,__LINE__);
+printk("%s:%d DCSR(%d)=%08x\n",__FUNCTION__,__LINE__,dma,DCSR(dma));
+        printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
+
+        if (vpac270_dma_test_irq(drive))
+                return;
+
+        ide_dump_status(drive, "DMA timeout",
+                HWIF(drive)->INB(IDE_STATUS_REG));
+
+        vpac270_dma_end(drive);
+}
+
+static void vpac270_dma_lostirq(ide_drive_t *drive)
+{
+printk("%s:%d\n",__FUNCTION__,__LINE__);
+        printk(KERN_ERR "%s: IRQ lost\n", drive->name);
+}
+
+static void vpac270_pxa_dma_irq(int dma, void *dummy)
+{
+printk("%s:%d DCSR(%d)=%08x\n",__FUNCTION__,__LINE__,dma,DCSR(dma));
+printk("%s:%d DRQSR1=0x%08x\n",__FUNCTION__,__LINE__,DRQSR1);
+
+	DCSR(dma) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
+}
+
+static void vpac270_dma_host_set(ide_drive_t *drive, int on)
+{
+}
+
+static void vpac270_dma_init(ide_hwif_t *hwif)
+{
+        printk("    %s: SG-DMA", hwif->name);
+
+	pxa_gpio_mode(GPIO80_DREQ_1_MD);
+
+        hwif->mwdma_mask        = 7;
+        hwif->swdma_mask        = 7;
+
+        hwif->dmatable_cpu      = NULL;
+        hwif->dmatable_dma      = 0;
+        hwif->set_dma_mode      = vpac270_set_dma_mode;
+
+	hwif->dma_host_set      = vpac270_dma_host_set;
+        hwif->dma_setup         = vpac270_dma_setup;
+        hwif->dma_exec_cmd      = vpac270_dma_exec_cmd;
+        hwif->dma_start         = vpac270_dma_start;
+        hwif->ide_dma_end       = vpac270_dma_end;
+        hwif->ide_dma_test_irq  = vpac270_dma_test_irq;
+        hwif->dma_timeout   = vpac270_dma_timeout;
+        hwif->dma_lost_irq   = vpac270_dma_lostirq;
+
+	hwif->noprobe = 0;
+	hwif->chipset = ide_unknown;
+	hwif->channel     = 0;
+	hwif->serialized  = 1;
+	hwif->dma      = pxa_request_dma( hwif->name, DMA_PRIO_LOW,
+						vpac270_pxa_dma_irq, NULL);
+
+	hwif->dmatable_cpu = dma_alloc_coherent( NULL, (PRD_ENTRIES * 4 * sizeof(u32)),
+							&hwif->dmatable_dma, GFP_ATOMIC);
+	
+        printk(" capable, dma=%d\n", hwif->dma);
+}
+
+static int __init vpac270_ide_init(void)
+{
+	u32 base = (u32) ioremap( IDE_BASE_PHYS, 0x200);;
+
+	printk("Voipac PXA270 IDE driver, (c) 2006 Voipac Technologies\n");
+
+	if( base)
+	{
+		int i;
+		hw_regs_t hw;
+
+                memset(&hw, 0, sizeof(hw));
+
+		for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+			hw.io_ports[i] = (base + 0x120 + 2*i);
+
+		hw.io_ports[IDE_CONTROL_OFFSET] = (base + 0x15c);
+       	        hw.irq = VPAC270_IDE_IRQ;
+
+                ide_register_hw(&hw, NULL, &vpac270_hwif);
+
+		vpac270_dma_init( vpac270_hwif);
+        }
+	return 0;
+}
+
+module_init(vpac270_ide_init);
+
+MODULE_AUTHOR("Voipac Technologies <support@voipac.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Voipac PXA270 IDE driver");
+
diff -urN linux-2.6.25/drivers/ide/Kconfig linux-2.6.25-vpac1/drivers/ide/Kconfig
--- linux-2.6.25/drivers/ide/Kconfig	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/ide/Kconfig	2008-04-24 15:12:18.000000000 +0200
@@ -927,6 +927,11 @@
 	help
 	  Enables the H8300 IDE driver.
 
+config BLK_DEV_IDE_VPAC270
+	tristate "Voipac PXA270 IDE support"
+	depends on ARM && (ARCH_PXA || MACH_VPAC270)
+	select BLK_DEV_IDEDMA
+
 config BLK_DEV_GAYLE
 	tristate "Amiga Gayle IDE interface support"
 	depends on AMIGA
diff -urN linux-2.6.25/drivers/input/serio/Kconfig linux-2.6.25-vpac1/drivers/input/serio/Kconfig
--- linux-2.6.25/drivers/input/serio/Kconfig	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/input/serio/Kconfig	2008-04-24 15:12:18.000000000 +0200
@@ -88,6 +88,17 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called rpckbd.
 
+config SERIO_VPAC270
+	tristate "Voipac PXA270 PS/2 controller"
+	depends on MACH_VPAC270
+	default y
+	help
+	  Say Y here if you have the Voipac PXA270 board and want to use
+	  an AT keyboard/mouse connected to its PS/2 controller.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called vpac270ps2.
+
 config SERIO_AMBAKMI
 	tristate "AMBA KMI keyboard controller"
 	depends on ARM_AMBA
diff -urN linux-2.6.25/drivers/input/serio/Makefile linux-2.6.25-vpac1/drivers/input/serio/Makefile
--- linux-2.6.25/drivers/input/serio/Makefile	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/input/serio/Makefile	2008-04-24 15:12:18.000000000 +0200
@@ -10,6 +10,7 @@
 obj-$(CONFIG_SERIO_SERPORT)	+= serport.o
 obj-$(CONFIG_SERIO_CT82C710)	+= ct82c710.o
 obj-$(CONFIG_SERIO_RPCKBD)	+= rpckbd.o
+obj-$(CONFIG_SERIO_VPAC270)	+= vpac270ps2.o
 obj-$(CONFIG_SERIO_SA1111)	+= sa1111ps2.o
 obj-$(CONFIG_SERIO_AMBAKMI)	+= ambakmi.o
 obj-$(CONFIG_SERIO_Q40KBD)	+= q40kbd.o
diff -urN linux-2.6.25/drivers/input/serio/vpac270ps2.c linux-2.6.25-vpac1/drivers/input/serio/vpac270ps2.c
--- linux-2.6.25/drivers/input/serio/vpac270ps2.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.25-vpac1/drivers/input/serio/vpac270ps2.c	2008-04-24 15:12:18.000000000 +0200
@@ -0,0 +1,384 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/serio.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/hardware/iomd.h>
+#include <asm/system.h>
+
+#define VPAC270_SCL1_GPIO       14
+#define VPAC270_SCL1_IRQ        IRQ_GPIO(VPAC270_SCL1_GPIO)
+#define VPAC270_SDA1_GPIO       19
+
+#define VPAC270_SCL2_GPIO       82 
+#define VPAC270_SCL2_IRQ        IRQ_GPIO(VPAC270_SCL2_GPIO)
+#define VPAC270_SDA2_GPIO       106
+
+static int kb_parity;
+static int kb_bitcount;
+static unsigned char kb_scan;  // holds the scan code
+
+static int ms_parity;
+static int ms_bitcount;
+static unsigned char ms_scan;  // holds the scan code
+
+static irqreturn_t vpac270kb_interrupt(int irq, void *dev_id)
+{
+	struct serio *port = dev_id;
+//printk("%s:%d\n",__FUNCTION__,__LINE__);
+	if( kb_bitcount > 0)
+	{
+	        if(--kb_bitcount > 0)  // all bits received
+	        {
+			// check parity bit
+			if( kb_bitcount == 1 && (GPLR0 & GPIO_bit(VPAC270_SDA1_GPIO)) )
+				kb_parity++;
+
+        	        // bit 2 to 9 is data
+        	        // 10 parity bit, 1 start bit and 11 stop bit are ignored
+                	if(kb_bitcount < 10 && kb_bitcount > 1)
+	                {
+        	                kb_scan = (kb_scan >> 1);
+                	        // keyboard data is connected to PORT3, bit3
+                        	if(GPLR0 & GPIO_bit(VPAC270_SDA1_GPIO))
+				{
+					kb_parity++;
+	                                kb_scan = kb_scan | 0x80;
+				}
+        	        }
+	        }
+        	else
+	        {
+			GPDR0 |= GPIO_bit(VPAC270_SCL1_GPIO);	// inhibit ps/2 device
+			GPCR0 = GPIO_bit(VPAC270_SCL1_GPIO);
+
+//			printk("%s:%d scan=%x, parity=%d\n",__FUNCTION__,__LINE__,kb_scan,kb_parity);
+
+	                kb_bitcount = 11;
+
+			serio_interrupt(port, kb_scan, (kb_parity & 1)? 0 : SERIO_PARITY);
+
+			kb_parity = 0;
+
+			GPDR0 &= ~GPIO_bit(VPAC270_SCL1_GPIO);	// enable
+        	}
+	}
+	else
+	{
+		if( ++kb_bitcount < 0)            // all bits received
+		{
+			if( kb_bitcount == -2)
+				kb_scan = ~kb_parity;
+
+			// 8 data bits and parity bit
+			if( kb_bitcount < -1)
+			{
+				// set/reset data line
+				if( kb_scan & 0x01)
+				{
+					kb_parity++;
+					GPSR0 |= GPIO_bit(VPAC270_SDA1_GPIO);
+				}
+				else
+					GPCR0 |= GPIO_bit(VPAC270_SDA1_GPIO);
+				kb_scan = (kb_scan >> 1);
+			}
+			else
+			{
+				// handle stop condition
+				GPDR0 &= ~GPIO_bit(VPAC270_SDA1_GPIO);
+			}
+		}
+		else
+		{
+			// setup rx mode
+			GPDR0 &= ~GPIO_bit(VPAC270_SDA1_GPIO);
+			kb_bitcount = 11;
+			kb_parity = 0;
+
+//			printk("%s:%d tx complete\n",__FUNCTION__,__LINE__);
+		}
+	}
+        return IRQ_HANDLED;
+}
+
+static irqreturn_t vpac270ms_interrupt(int irq, void *dev_id)
+{
+	struct serio *port = dev_id;
+//printk("%s:%d\n",__FUNCTION__,__LINE__);
+	if( ms_bitcount > 0)
+	{
+	        if(--ms_bitcount > 0)  // all bits received
+	        {
+			// check parity bit
+			if( ms_bitcount == 1 && (GPLR3 & GPIO_bit(VPAC270_SDA2_GPIO)) )
+				ms_parity++;
+
+        	        // bit 2 to 9 is data
+        	        // 10 parity bit, 1 start bit and 11 stop bit are ignored
+                	if(ms_bitcount < 10 && ms_bitcount > 1)
+	                {
+        	                ms_scan = (ms_scan >> 1);
+                	        // keyboard data is connected to PORT3, bit3
+                        	if(GPLR3 & GPIO_bit(VPAC270_SDA2_GPIO))
+				{
+					ms_parity++;
+	                                ms_scan = ms_scan | 0x80;
+				}
+        	        }
+	        }
+        	else
+	        {
+			GPDR2 |= GPIO_bit(VPAC270_SCL2_GPIO);	// inhibit ps/2 device
+			GPCR2 = GPIO_bit(VPAC270_SCL2_GPIO);
+
+//			printk("%s:%d scan=%x, parity=%d\n",__FUNCTION__,__LINE__,ms_scan,ms_parity);
+
+	                ms_bitcount = 11;
+
+			serio_interrupt(port, ms_scan, (ms_parity & 1)? 0 : SERIO_PARITY);
+
+			ms_parity = 0;
+
+			GPDR2 &= ~GPIO_bit(VPAC270_SCL2_GPIO);	// enable
+        	}
+	}
+	else
+	{
+		if( ++ms_bitcount < 0)            // all bits received
+		{
+			if( ms_bitcount == -2)
+				ms_scan = ~ms_parity;
+
+			// 8 data bits and parity bit
+			if( ms_bitcount < -1)
+			{
+				// set/reset data line
+				if( ms_scan & 0x01)
+				{
+					ms_parity++;
+					GPSR3 |= GPIO_bit(VPAC270_SDA2_GPIO);
+				}
+				else
+					GPCR3 |= GPIO_bit(VPAC270_SDA2_GPIO);
+				ms_scan = (ms_scan >> 1);
+			}
+			else
+			{
+				// handle stop condition
+				GPDR3 &= ~GPIO_bit(VPAC270_SDA2_GPIO);
+			}
+		}
+		else
+		{
+			// setup rx mode
+			GPDR3 &= ~GPIO_bit(VPAC270_SDA2_GPIO);
+			ms_bitcount = 11;
+			ms_parity = 0;
+
+//			printk("%s:%d tx complete\n",__FUNCTION__,__LINE__);
+		}
+	}
+        return IRQ_HANDLED;
+}
+
+static int vpac270kb_write(struct serio *port, unsigned char val)
+{
+//printk("%s:%d val=%x\n",__FUNCTION__,__LINE__,val);
+
+	// setup clk gpio pin as output and set it to low
+	GPDR0 |= GPIO_bit(VPAC270_SCL1_GPIO);
+	GPCR0 = GPIO_bit(VPAC270_SCL1_GPIO);
+
+	// wait min 100us
+	udelay(120);
+
+	// setup data gpio pin as output and set it to low
+	GPDR0 |= GPIO_bit(VPAC270_SDA1_GPIO);
+	GPCR0 = GPIO_bit(VPAC270_SDA1_GPIO);
+
+	// set scan and setup tx mode
+	kb_parity = 0;
+	kb_bitcount = -11;
+	kb_scan = val;
+
+	// setup clk gpio pin as input (clk transitions to high by pullup)
+	GPDR0 &= ~GPIO_bit(VPAC270_SCL1_GPIO);
+
+	return 0;
+}
+
+static int vpac270ms_write(struct serio *port, unsigned char val)
+{
+//printk("%s:%d val=%x\n",__FUNCTION__,__LINE__,val);
+
+	// setup clk gpio pin as output and set it to low
+	GPDR2 |= GPIO_bit(VPAC270_SCL2_GPIO);
+	GPCR2 = GPIO_bit(VPAC270_SCL2_GPIO);
+
+	// wait min 100us
+	udelay(120);
+
+	// setup data gpio pin as output and set it to low
+	GPDR3 |= GPIO_bit(VPAC270_SDA2_GPIO);
+	GPCR3 = GPIO_bit(VPAC270_SDA2_GPIO);
+
+	// set scan and setup tx mode
+	ms_parity = 0;
+	ms_bitcount = -11;
+	ms_scan = val;
+
+	// setup clk gpio pin as input (clk transitions to high by pullup)
+	GPDR2 &= ~GPIO_bit(VPAC270_SCL2_GPIO);
+
+	return 0;
+}
+
+static int vpac270kb_open(struct serio *port)
+{
+//printk("%s:%d\n",__FUNCTION__,__LINE__);
+        pxa_gpio_mode(VPAC270_SCL1_GPIO | GPIO_IN);
+        pxa_gpio_mode(VPAC270_SDA1_GPIO | GPIO_IN);
+
+        if (request_irq( VPAC270_SCL1_IRQ, vpac270kb_interrupt,
+                                SA_INTERRUPT, "vpac270kb", port))
+        {
+                printk(KERN_WARNING "%s: failed to request IRQ: %d!\n", __FUNCTION__, VPAC270_SCL1_IRQ);
+        }
+
+        set_irq_type(VPAC270_SCL1_IRQ, IRQT_FALLING);
+
+	kb_parity = 0;
+	kb_bitcount = 11;
+
+	return 0;
+}
+
+static int vpac270ms_open(struct serio *port)
+{
+//printk("%s:%d\n",__FUNCTION__,__LINE__);
+        pxa_gpio_mode(VPAC270_SCL2_GPIO | GPIO_IN);
+        pxa_gpio_mode(VPAC270_SDA2_GPIO | GPIO_IN);
+
+        if (request_irq( VPAC270_SCL2_IRQ, vpac270ms_interrupt,
+                                SA_INTERRUPT, "vpac270ms", port))
+        {
+                printk(KERN_WARNING "%s: failed to request IRQ: %d!\n", __FUNCTION__, VPAC270_SCL2_IRQ);
+        }
+
+        set_irq_type(VPAC270_SCL2_IRQ, IRQT_FALLING);
+
+	ms_parity = 0;
+	ms_bitcount = 11;
+
+	return 0;
+}
+
+static void vpac270kb_close(struct serio *port)
+{
+//printk("%s:%d\n",__FUNCTION__,__LINE__);
+	free_irq( VPAC270_SCL1_IRQ, port);
+}
+
+static void vpac270ms_close(struct serio *port)
+{
+//printk("%s:%d\n",__FUNCTION__,__LINE__);
+	free_irq( VPAC270_SCL2_IRQ, port);
+}
+
+/*
+ * Allocate and initialize serio structure for subsequent registration
+ * with serio core.
+ */
+static int __devinit vpac270ps2_probe(struct platform_device *dev)
+{
+	struct serio *serio;
+//printk("%s:%d\n",__FUNCTION__,__LINE__);
+
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!serio)
+		return -ENOMEM;
+
+	memset(serio, 0, sizeof(struct serio));
+	serio->id.type	= SERIO_8042;
+
+	if( dev->id == 0)
+	{
+		serio->write		= vpac270kb_write;
+		serio->open		= vpac270kb_open;
+		serio->close		= vpac270kb_close;
+		serio->dev.parent	= &dev->dev;
+		strlcpy(serio->name, "Voipac PXA270 PS/2 keyboard port", sizeof(serio->name));
+		strlcpy(serio->phys, "vpac270/serio0", sizeof(serio->phys));
+	} else {
+		serio->write		= vpac270ms_write;
+		serio->open		= vpac270ms_open;
+		serio->close		= vpac270ms_close;
+		serio->dev.parent	= &dev->dev;
+		strlcpy(serio->name, "Voipac PXA270 PS/2 mouse port", sizeof(serio->name));
+		strlcpy(serio->phys, "vpac270/serio1", sizeof(serio->phys));
+	}
+
+	platform_set_drvdata(dev, serio);
+	serio_register_port(serio);
+
+	return 0;
+}
+
+static int __devexit vpac270ps2_remove(struct platform_device *dev)
+{
+	struct serio *serio = platform_get_drvdata(dev);
+
+	serio_unregister_port(serio);
+
+	return 0;
+}
+
+static struct platform_driver vpac270ps2_driver = {
+	.probe		= vpac270ps2_probe,
+	.remove		= __devexit_p(vpac270ps2_remove),
+	.driver		= {
+		.name	= "vpac270ps2",
+	},
+};
+
+static int __init vpac270ps2_init(void)
+{
+	return platform_driver_register(&vpac270ps2_driver);
+}
+
+static void __exit vpac270ps2_exit(void)
+{
+	platform_driver_unregister(&vpac270ps2_driver);
+}
+
+module_init(vpac270ps2_init);
+module_exit(vpac270ps2_exit);
+
+MODULE_AUTHOR("Voipac Technologies <support@voipac.com>");
+MODULE_DESCRIPTION("Voipac PXA270 PS/2 controller driver");
+MODULE_LICENSE("GPL");
+
diff -urN linux-2.6.25/drivers/leds/Kconfig linux-2.6.25-vpac1/drivers/leds/Kconfig
--- linux-2.6.25/drivers/leds/Kconfig	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/leds/Kconfig	2008-04-24 15:12:18.000000000 +0200
@@ -25,6 +25,13 @@
 	  This option enables support for LEDs driven using outputs
 	  of the dedicated PWM controller found on newer Atmel SOCs.
 
+config LEDS_VPAC270
+	tristate "LED Support for the Voipac PXA270 baseboard"
+	depends on LEDS_CLASS && MACH_VPAC270
+	help
+	  This option enables support for the LED on Voipac
+	  Technologies PXA270 developement baseboard.
+
 config LEDS_CORGI
 	tristate "LED Support for the Sharp SL-C7x0 series"
 	depends on LEDS_CLASS && PXA_SHARP_C7xx
diff -urN linux-2.6.25/drivers/leds/leds-vpac270.c linux-2.6.25-vpac1/drivers/leds/leds-vpac270.c
--- linux-2.6.25/drivers/leds/leds-vpac270.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.25-vpac1/drivers/leds/leds-vpac270.c	2008-04-24 15:12:18.000000000 +0200
@@ -0,0 +1,90 @@
+/*
+ * LED Triggers Core
+ *
+ * Copyright (c) 2006 Voipac Technologies <support@voipac.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/arch/vpac270.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+//#include <asm/hardware/scoop.h>
+
+#define VPAC270_GPIO_LED_ORANGE	GPIO15_nCS_1
+
+static void vpac270led_set(struct led_classdev *led_cdev, enum led_brightness value)
+{
+	if (value)
+		GPSR0 = GPIO_bit(VPAC270_GPIO_LED_ORANGE);
+	else
+		GPCR0 = GPIO_bit(VPAC270_GPIO_LED_ORANGE);
+}
+
+static struct led_classdev vpac270_orange_led = {
+	.name			= "vpac270:orange",
+	.default_trigger	= "heartbeat",
+	.brightness_set		= vpac270led_set,
+};
+
+#ifdef CONFIG_PM
+static int vpac270led_suspend(struct platform_device *dev, pm_message_t state)
+{
+	led_classdev_suspend(&vpac270_orange_led);
+	return 0;
+}
+
+static int vpac270led_resume(struct platform_device *dev)
+{
+	led_classdev_resume(&vpac270_orange_led);
+	return 0;
+}
+#endif
+
+static int vpac270led_probe(struct platform_device *pdev)
+{
+	return led_classdev_register(&pdev->dev, &vpac270_orange_led);
+}
+
+static int vpac270led_remove(struct platform_device *pdev)
+{
+	led_classdev_unregister(&vpac270_orange_led);
+	return 0;
+}
+
+static struct platform_driver vpac270led_driver = {
+	.probe		= vpac270led_probe,
+	.remove		= vpac270led_remove,
+#ifdef CONFIG_PM
+	.suspend	= vpac270led_suspend,
+	.resume		= vpac270led_resume,
+#endif
+	.driver		= {
+		.name		= "vpac270-led",
+	},
+};
+
+static int __init vpac270led_init(void)
+{
+	return platform_driver_register(&vpac270led_driver);
+}
+
+static void __exit vpac270led_exit(void)
+{
+ 	platform_driver_unregister(&vpac270led_driver);
+}
+
+module_init(vpac270led_init);
+module_exit(vpac270led_exit);
+
+MODULE_AUTHOR("Voipac Technologies <support@voipac.com>");
+MODULE_DESCRIPTION("Voipac PXA270 LED driver");
+MODULE_LICENSE("GPL");
diff -urN linux-2.6.25/drivers/leds/Makefile linux-2.6.25-vpac1/drivers/leds/Makefile
--- linux-2.6.25/drivers/leds/Makefile	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/leds/Makefile	2008-04-24 15:15:33.000000000 +0200
@@ -6,6 +6,7 @@
 
 # LED Platform Drivers
 obj-$(CONFIG_LEDS_ATMEL_PWM)		+= leds-atmel-pwm.o
+obj-$(CONFIG_LEDS_VPAC270)		+= leds-vpac270.o
 obj-$(CONFIG_LEDS_CORGI)		+= leds-corgi.o
 obj-$(CONFIG_LEDS_LOCOMO)		+= leds-locomo.o
 obj-$(CONFIG_LEDS_SPITZ)		+= leds-spitz.o
diff -urN linux-2.6.25/drivers/mtd/maps/Kconfig linux-2.6.25-vpac1/drivers/mtd/maps/Kconfig
--- linux-2.6.25/drivers/mtd/maps/Kconfig	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/mtd/maps/Kconfig	2008-04-24 15:12:18.000000000 +0200
@@ -477,6 +477,13 @@
 	  This enables access to the flash chips on the Hynix evaluation boards.
 	  If you have such a board, say 'Y'.
 
+config MTD_VPAC270
+	tristate "Voipac PXA270  module flash mapping"
+	depends on MACH_VPAC270 && MTD_CFI && MTD_PARTITIONS
+	help
+	  This enables access to the flash memory on the Voipac PXA270 module.
+	  If you have such a module, say 'Y'.
+
 config MTD_MPC1211
 	tristate "CFI Flash device mapped on Interface MPC-1211"
 	depends on SH_MPC1211 && MTD_CFI
diff -urN linux-2.6.25/drivers/mtd/maps/Makefile linux-2.6.25-vpac1/drivers/mtd/maps/Makefile
--- linux-2.6.25/drivers/mtd/maps/Makefile	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/mtd/maps/Makefile	2008-04-24 15:12:18.000000000 +0200
@@ -68,3 +68,4 @@
 obj-$(CONFIG_MTD_OMAP_NOR)	+= omap_nor.o
 obj-$(CONFIG_MTD_MTX1)		+= mtx-1_flash.o
 obj-$(CONFIG_MTD_INTEL_VR_NOR)	+= intel_vr_nor.o
+obj-$(CONFIG_MTD_VPAC270)	+= vpac270.o
diff -urN linux-2.6.25/drivers/mtd/maps/vpac270.c linux-2.6.25-vpac1/drivers/mtd/maps/vpac270.c
--- linux-2.6.25/drivers/mtd/maps/vpac270.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.25-vpac1/drivers/mtd/maps/vpac270.c	2008-04-24 22:10:26.000000000 +0200
@@ -0,0 +1,142 @@
+/*
+ * Map driver for the Voipac PXA270 module
+ *
+ * Modified from drivers/mtd/maps/iq80310.c
+ * Orignal Author:	Nicolas Pitre
+ *
+ * Copyright:   (C) 2001 MontaVista Software Inc.
+ * Copyright (c) 2006 Voipac Technologies <support@voipac.com>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+
+
+#define ROM_ADDR 0x00000000
+#define WINDOW_SIZE 	64*1024*1024
+
+#ifdef CONFIG_PM
+struct pm_dev       *flash_pmdev;
+#endif
+
+static struct map_info vpac270_map = {
+	.name = 		"Voipac PXA270 Flash",
+	.size = 		WINDOW_SIZE,
+	.bankwidth =		2,
+	.phys = 		ROM_ADDR
+};
+
+static struct mtd_partition vpac270_partitions[] = {
+	{
+		name:		"Bootloader",
+		size:		0x00020000, /* 128kB u-boot and config params */
+		offset:		0,
+		/*mask_flags:	MTD_WRITEABLE   force read-only */
+	},{
+		name:		"Kernel",
+		size:		0x00140000, /* 1MB for kernel */
+		offset:		0x00020000,
+	},{
+		name:		"Filesystem",	/* the rest for filesystem */
+		size:		MTDPART_SIZ_FULL,
+		offset:		0x00160000
+	}
+};
+
+static struct mtd_info *mymtd;
+
+#ifdef VPAC270_PARTS_PARSING
+static struct mtd_partition *parsed_parts;
+static int nr_parsed_parts;
+
+static const char* probes[] = { "RedBoot", "cmdlinepart", NULL };
+#endif
+
+#include <linux/mtd/cfi.h>
+
+static int __init init_vpac270(void)
+{
+	printk( "Probing Voipac PXA270 flash at physical address 0x%08x (%d-bit buswidth)\n",
+		vpac270_map.phys, vpac270_map.bankwidth * 8 );
+
+	vpac270_map.virt = ioremap(vpac270_map.phys, vpac270_map.size);
+	if (!vpac270_map.virt) {
+		printk("Failed to ioremap\n");
+		return -EIO;
+	}
+
+	simple_map_init(&vpac270_map);
+
+	mymtd = do_map_probe("cfi_probe", &vpac270_map);
+	if (!mymtd) {
+		iounmap((void *)vpac270_map.virt);
+		return -ENXIO;
+	}
+	mymtd->owner = THIS_MODULE;
+
+#ifdef DO_FLASH_UNLOCK
+	/* Unlock the flash device. */
+	for (i = 0; i < mymtd->numeraseregions; i++) {
+		int j;
+		for( j = 0; j < mymtd->eraseregions[i].numblocks; j++) {
+			mymtd->unlock(mymtd, mymtd->eraseregions[i].offset +
+				      j * mymtd->eraseregions[i].erasesize,
+				      mymtd->eraseregions[i].erasesize);
+		}
+	}
+#endif
+
+#ifdef VPAC270_PARTS_PARSING
+	ret = parse_mtd_partitions(mymtd, probes, &parsed_parts, 0);
+
+	if (ret > 0)
+		nr_parsed_parts = ret;
+#endif
+
+	if (!mymtd) {
+		printk(KERN_WARNING "%s is absent.  Skipping\n", vpac270_map.name);
+#ifdef VPAC270_PARTS_PARSING
+	} else if (nr_parsed_parts) {
+		add_mtd_partitions(mymtd, parsed_parts, nr_parsed_parts);
+#endif
+	} else {
+		add_mtd_partitions(mymtd, vpac270_partitions, ARRAY_SIZE(vpac270_partitions));
+	}
+
+	return 0;
+}
+
+static void __exit cleanup_vpac270(void)
+{
+	if (mymtd) {
+#ifdef VPAC270_PARTS_PARSING
+		if (nr_parsed_parts)
+			del_mtd_partitions(mymtd);
+		else
+#endif
+			del_mtd_device(mymtd);
+
+		map_destroy(mymtd);
+#ifdef VPAC270_PARTS_PARSING
+		if (parsed_parts)
+			kfree(parsed_parts);
+#endif
+	}
+
+	if (vpac270_map.virt)
+		iounmap((void *)vpac270_map.virt);
+}
+
+module_init(init_vpac270);
+module_exit(cleanup_vpac270);
+
diff -urN linux-2.6.25/drivers/net/dm9000.c linux-2.6.25-vpac1/drivers/net/dm9000.c
--- linux-2.6.25/drivers/net/dm9000.c	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/net/dm9000.c	2008-04-29 17:46:06.000000000 +0200
@@ -43,6 +43,7 @@
 /* Board/System/Debug information/definition ---------------- */
 
 #define DM9000_PHY		0x40	/* PHY address 0x01 */
+#define DM9000_TIMER_WUT (HZ*2) /* timer wakeup time : 2 second */
 
 #define CARDNAME "dm9000"
 #define PFX CARDNAME ": "
@@ -117,6 +118,8 @@
 
 	struct mutex	 addr_lock;	/* phy and eeprom access lock */
 
+	struct delayed_work timer; /* Interface status timer. */
+
 	spinlock_t lock;
 
 	struct mii_if_info mii;
@@ -144,6 +147,7 @@
 static int dm9000_stop(struct net_device *);
 static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd);
 
+static void dm9000_timer(struct work_struct * work);
 static void dm9000_init_dm9000(struct net_device *);
 
 static irqreturn_t dm9000_interrupt(int, void *);
@@ -540,9 +544,10 @@
 		ret = -ENODEV;
 		goto out;
 	} else if (pdev->num_resources == 2) {
-		base = pdev->resource[0].start;
+		iosize = 4;
+		base = (unsigned long) ioremap(pdev->resource[0].start, 8);
 
-		if (!request_mem_region(base, 4, ndev->name)) {
+		if (!request_mem_region(base, 8, ndev->name)) {
 			ret = -EBUSY;
 			goto out;
 		}
@@ -550,8 +555,9 @@
 		ndev->base_addr = base;
 		ndev->irq = pdev->resource[1].start;
 		db->io_addr = (void __iomem *)base;
-		db->io_data = (void __iomem *)(base + 4);
+		db->io_data = (void __iomem *)(base + iosize);
 
+		db->irq_res  = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 		/* ensure at least we have a default set of IO routines */
 		dm9000_set_io(db, 2);
 
@@ -607,11 +613,11 @@
 
 		ndev->base_addr = (unsigned long)db->io_addr;
 		ndev->irq	= db->irq_res->start;
-
-		/* ensure at least we have a default set of IO routines */
-		dm9000_set_io(db, iosize);
 	}
 
+	/* ensure at least we have a default set of IO routines */
+	dm9000_set_io(db, iosize);
+
 	/* check to see if anything is being over-ridden */
 	if (pdata != NULL) {
 		/* check to see if the driver wants to over-ride the
@@ -743,7 +749,7 @@
 	 * may work, and tell the user that this is a problem */
 
 	if (irqflags == IRQF_TRIGGER_NONE) {
-		dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");
+//		dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");
 		irqflags = DEFAULT_TRIGGER;
 	}
 	
@@ -762,6 +768,10 @@
 	mii_check_media(&db->mii, netif_msg_link(db), 1);
 	netif_start_queue(dev);
 
+	/* Start the media status timer running. */
+	INIT_DELAYED_WORK(&db->timer, dm9000_timer);
+	schedule_delayed_work(&db->timer, DM9000_TIMER_WUT);
+
 	return 0;
 }
 
@@ -876,6 +886,9 @@
 {
 	board_info_t *db = (board_info_t *) ndev->priv;
 
+	/* Delete the timer and make sure it's not running right now! */
+	cancel_delayed_work_sync(&db->timer);
+
 	if (netif_msg_ifdown(db))
 		dev_dbg(db->dev, "shutting down %s\n", ndev->name);
 
@@ -965,6 +978,15 @@
 	return IRQ_HANDLED;
 }
 
+/* Two second timer to poll the media status -- the DM9000 doesn't provide a
+ * status interrupt, so this has to be polled. */
+static void dm9000_timer(struct work_struct * work)
+{
+	board_info_t *db = container_of(work, board_info_t, timer);
+	mii_check_media(&db->mii, netif_msg_link(db), 0);
+	schedule_delayed_work(&db->timer, DM9000_TIMER_WUT);
+}
+
 struct dm9000_rxhdr {
 	u8	RxPktReady;
 	u8	RxStatus;
diff -urN linux-2.6.25/drivers/net/wireless/hostap/hostap_cs.c linux-2.6.25-vpac1/drivers/net/wireless/hostap/hostap_cs.c
--- linux-2.6.25/drivers/net/wireless/hostap/hostap_cs.c	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/net/wireless/hostap/hostap_cs.c	2008-04-24 15:12:18.000000000 +0200
@@ -31,7 +31,7 @@
 MODULE_LICENSE("GPL");
 
 
-static int ignore_cis_vcc;
+static int ignore_cis_vcc = 1;
 module_param(ignore_cis_vcc, int, 0444);
 MODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry");
 
@@ -822,6 +822,7 @@
 	PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777),
 	PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000),
 	PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002),
+	PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002),
 	PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x3301),
 	PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002),
 	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030b),
@@ -834,7 +835,9 @@
 	PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300),
 /*	PCMCIA_DEVICE_MANF_CARD(0xc00f, 0x0000),    conflict with pcnet_cs */
 	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002),
+	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0004),
 	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005),
+	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0007),
 	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0010),
 	PCMCIA_DEVICE_MANF_CARD(0x0126, 0x0002),
 	PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0xd601, 0x0005, "ADLINK 345 CF",
diff -urN linux-2.6.25/drivers/pcmcia/Makefile linux-2.6.25-vpac1/drivers/pcmcia/Makefile
--- linux-2.6.25/drivers/pcmcia/Makefile	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/pcmcia/Makefile	2008-04-24 15:12:18.000000000 +0200
@@ -71,4 +71,5 @@
 pxa2xx_cs-$(CONFIG_MACH_MAINSTONE)		+= pxa2xx_mainstone.o
 pxa2xx_cs-$(CONFIG_PXA_SHARPSL)			+= pxa2xx_sharpsl.o
 pxa2xx_cs-$(CONFIG_MACH_ARMCORE)		+= pxa2xx_cm_x270.o
+pxa2xx_cs-$(CONFIG_MACH_VPAC270)		+= pxa2xx_vpac270.o
 
diff -urN linux-2.6.25/drivers/pcmcia/pxa2xx_vpac270.c linux-2.6.25-vpac1/drivers/pcmcia/pxa2xx_vpac270.c
--- linux-2.6.25/drivers/pcmcia/pxa2xx_vpac270.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.25-vpac1/drivers/pcmcia/pxa2xx_vpac270.c	2008-04-24 15:12:18.000000000 +0200
@@ -0,0 +1,246 @@
+/*
+ * linux26/drivers/pcmcia/pxa2xx_vpac270.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Copyright (c) 2002 Accelent Systems, Inc. All Rights Reserved
+ * Copyright (c) 2006 Voipac Technologies <support@voipac.com>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/delay.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/vpac270.h>
+
+#include "soc_common.h"
+
+//#define DEBUG_COL_PCMCIA
+
+#ifdef DEBUG_COL_PCMCIA
+#define MARK printk(KERN_INFO "%s: %d\n", __FUNCTION__, __LINE__);
+#else
+//#define MARK (0)
+#endif
+#ifdef PCMCIA_DEBUG
+int pc_debug = PCMCIA_DEBUG;
+#endif
+
+static struct pcmcia_irqs irqs[] = {
+    { 0, VPAC270_PCMCIA0_CD_IRQ, "CF CD"},
+    { 1, VPAC270_PCMCIA1_CD_IRQ, "PCMCIA CD"},
+};
+
+
+static int vpac270_pcmcia_init_dev(struct soc_pcmcia_socket *skt)
+{
+    printk("Voipac PXA270 PCMCIA\n");
+    /* set power GPIO; switch off */
+    GPCR(GPIO_PCMCIA_POW_EN) |= GPIO_bit(GPIO_PCMCIA_POW_EN);
+    GPDR(GPIO_PCMCIA_POW_EN) |= GPIO_bit(GPIO_PCMCIA_POW_EN);
+
+    /* set PCMCIA AFs */
+    GPSR(GPIO_PCMCIA_NPOE) |= GPIO_bit(GPIO_PCMCIA_NPOE);
+    pxa_gpio_mode(GPIO_PCMCIA_NPOE | GPIO_PCMCIA_NPOE_AF);
+
+    GPSR(GPIO_PCMCIA_NPIOR) |= GPIO_bit(GPIO_PCMCIA_NPIOR);
+    pxa_gpio_mode(GPIO_PCMCIA_NPIOR | GPIO_PCMCIA_NPIOR_AF);
+
+    GPSR(GPIO_PCMCIA_NPIOW) |= GPIO_bit(GPIO_PCMCIA_NPIOW);
+    pxa_gpio_mode(GPIO_PCMCIA_NPIOW | GPIO_PCMCIA_NPIOW_AF);
+
+    GPSR(GPIO_PCMCIA_NPCE1) |= GPIO_bit(GPIO_PCMCIA_NPCE1);
+    pxa_gpio_mode(GPIO_PCMCIA_NPCE1 | GPIO_PCMCIA_NPCE1_AF);
+
+    GPCR(GPIO_PCMCIA_NPCE2) |= GPIO_bit(GPIO_PCMCIA_NPCE2);
+    pxa_gpio_mode(GPIO_PCMCIA_NPCE2 | GPIO_PCMCIA_NPCE2_AF);
+
+    GPSR(GPIO_PCMCIA_NPREG) |= GPIO_bit(GPIO_PCMCIA_NPREG);
+    pxa_gpio_mode(GPIO_PCMCIA_NPREG | GPIO_PCMCIA_NPREG_AF);
+
+    pxa_gpio_mode(GPIO_PCMCIA_NPWAIT | GPIO_PCMCIA_NPWAIT_AF);
+
+    pxa_gpio_mode(GPIO_PCMCIA_NPIOIS16 | GPIO_PCMCIA_NPIOIS16_AF);
+
+    GPSR(GPIO_PCMCIA_PSKTSEL) |= GPIO_bit(GPIO_PCMCIA_PSKTSEL);
+    pxa_gpio_mode(GPIO_PCMCIA_PSKTSEL | GPIO_PCMCIA_PSKTSEL_AF);
+
+    /* set other PCMCIA GPIOs */
+    GPCR(GPIO_PCMCIA0_RESET) |= GPIO_bit(GPIO_PCMCIA0_RESET);
+    GPDR(GPIO_PCMCIA0_RESET) |= GPIO_bit(GPIO_PCMCIA0_RESET);
+    GPCR(GPIO_PCMCIA1_RESET) |= GPIO_bit(GPIO_PCMCIA1_RESET);
+    GPDR(GPIO_PCMCIA1_RESET) |= GPIO_bit(GPIO_PCMCIA1_RESET);
+
+//    GPDR(GPIO_PCMCIA0_BVD1) &= ~GPIO_bit(GPIO_PCMCIA0_BVD1);
+//    GPDR(GPIO_PCMCIA0_BVD2) &= ~GPIO_bit(GPIO_PCMCIA0_BVD2);
+
+    /* switch power on */
+    PCC_PWR_ON();
+
+    /* set interrupts */
+	GPDR(GPIO_PCMCIA0_CD_IRQ) &= ~GPIO_bit(GPIO_PCMCIA0_CD_IRQ);
+	set_irq_type(GPIO_PCMCIA0_CD_IRQ, VPAC270_PCMCIA_CD_EDGE);
+
+	GPDR(GPIO_PCMCIA0_RDY_IRQ) &= ~GPIO_bit(GPIO_PCMCIA0_RDY_IRQ);
+	set_irq_type(GPIO_PCMCIA0_RDY_IRQ, VPAC270_PCMCIA_RDY_EDGE);
+
+	GPDR(GPIO_PCMCIA1_CD_IRQ) &= ~GPIO_bit(GPIO_PCMCIA1_CD_IRQ);
+	set_irq_type(GPIO_PCMCIA1_CD_IRQ, VPAC270_PCMCIA_CD_EDGE);
+
+	GPDR(GPIO_PCMCIA1_RDY_IRQ) &= ~GPIO_bit(GPIO_PCMCIA1_RDY_IRQ);
+	set_irq_type(GPIO_PCMCIA1_RDY_IRQ, VPAC270_PCMCIA_RDY_EDGE);
+
+        if (skt->irq == NO_IRQ)
+                skt->irq = skt->nr ? VPAC270_PCMCIA1_RDY_IRQ : VPAC270_PCMCIA0_RDY_IRQ;
+
+        return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+}
+
+static void vpac270_pcmcia_shutdown(struct soc_pcmcia_socket *skt)
+{
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+
+    /* switch power off */
+    PCC_PWR_OFF();
+}
+
+static void vpac270_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+                                        struct pcmcia_state *state)
+{
+	//memset(state, 0, sizeof(*state));
+
+	switch( skt->nr)
+	{
+	case 0:
+		state->detect = (PCC0_DETECT) ? 0 : 1;
+		state->ready =  (PCC0_READY) ? 1 : 0;
+		break;
+
+	case 1:
+		state->detect = (PCC1_DETECT) ? 0 : 1;
+		state->ready =  (PCC1_READY) ? 1 : 0;
+		break;
+
+	default:
+		return;
+	}
+/*
+    printk(KERN_INFO "CF status: detect: %u, ready: %u\n",
+           GPLR(84) & GPIO_bit(84),
+           GPLR(1) & GPIO_bit(1));
+*/
+
+	state->bvd1   = 1;	//PCC_BVD1() ? 1 : 0;
+	state->bvd2   = 1;	//PCC_BVD2() ? 1 : 0;
+	state->wrprot = 0; /* r/w all the time */
+	state->vs_3v  = PCC_VS3V() ? 1 : 0;
+	state->vs_Xv  = PCC_VS5V() ? 1 : 0;
+}
+
+static int vpac270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+                                           socket_state_t const *state)
+{
+    unsigned long flags;
+
+    local_irq_save(flags);
+	/* configure Vcc and Vpp */
+    if (state->Vcc == 0 && state->Vpp == 0)
+    {
+        PCC_PWR_OFF();
+    }
+    else if (state->Vcc == 33 && state->Vpp < 50)
+    {
+        PCC_PWR_ON();
+    }
+    else
+    {
+        printk(KERN_ERR "%s(): unsupported Vcc %u Vpp %u combination\n",
+               __FUNCTION__, state->Vcc, state->Vpp);
+        return -1;
+    }
+
+    /* reset PCMCIA if requested */
+    if (state->flags & SS_RESET)
+    {
+	if( skt->nr == 0)
+	    GPSR(GPIO_PCMCIA0_RESET) |= GPIO_bit(GPIO_PCMCIA0_RESET);
+	else
+	    GPSR(GPIO_PCMCIA1_RESET) |= GPIO_bit(GPIO_PCMCIA1_RESET);
+    } else {
+	if( skt->nr == 0)
+	    GPCR(GPIO_PCMCIA0_RESET) |= GPIO_bit(GPIO_PCMCIA0_RESET);
+	else
+	    GPCR(GPIO_PCMCIA1_RESET) |= GPIO_bit(GPIO_PCMCIA1_RESET);
+    }
+
+    local_irq_restore(flags);
+    udelay(200);
+
+	return 0;
+}
+
+static void vpac270_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+}
+
+static void vpac270_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+}
+
+struct pcmcia_low_level vpac270_pcmcia_ops = { 
+    .owner             = THIS_MODULE,
+    .hw_init           = vpac270_pcmcia_init_dev,
+    .hw_shutdown       = vpac270_pcmcia_shutdown,
+    .socket_state      = vpac270_pcmcia_socket_state,
+    .configure_socket  = vpac270_pcmcia_configure_socket,
+    .socket_init       = vpac270_pcmcia_socket_init,
+    .socket_suspend    = vpac270_pcmcia_socket_suspend,
+    .first             = 0,
+    .nr                = 2
+};
+
+static struct platform_device *vpac270_pcmcia_device;
+
+static int __init vpac270_pcmcia_init(void)
+{
+    int ret;
+
+    vpac270_pcmcia_device = kmalloc(sizeof(*vpac270_pcmcia_device), GFP_KERNEL);
+    if (!vpac270_pcmcia_device)
+        return -ENOMEM;
+    memset(vpac270_pcmcia_device, 0, sizeof(*vpac270_pcmcia_device));
+    vpac270_pcmcia_device->name = "pxa2xx-pcmcia";
+    vpac270_pcmcia_device->dev.platform_data = &vpac270_pcmcia_ops;
+
+    ret = platform_device_register(vpac270_pcmcia_device);
+    if (ret)
+        kfree(vpac270_pcmcia_device);
+
+    return ret;
+}
+
+static void __exit vpac270_pcmcia_exit(void)
+{
+    /* Are there still references to vpac270_pcmcia_device?
+     * I don't know, so I'd better not free it.
+     * Actually, I don't really care, as I don't really support
+     * this driver as module anyway...
+     */
+    platform_device_unregister(vpac270_pcmcia_device);
+}
+
+module_init(vpac270_pcmcia_init);
+module_exit(vpac270_pcmcia_exit);
+
+MODULE_DESCRIPTION("Voipac PXA270 CF Support");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Voipac Technologies <support@voipac.com>");
diff -urN linux-2.6.25/drivers/usb/gadget/char.c linux-2.6.25-vpac1/drivers/usb/gadget/char.c
--- linux-2.6.25/drivers/usb/gadget/char.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.25-vpac1/drivers/usb/gadget/char.c	2008-04-24 15:12:18.000000000 +0200
@@ -0,0 +1,911 @@
+/*
+ * char.c -- Character Gadget
+ *
+ * Copyright (C) 2003-2005 Joshua Wise.
+ * Portions 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.
+ */
+
+#define DEBUG 1
+#define VERBOSE
+#define DBUFMAX 8192
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.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/utsname.h>
+#include <linux/device.h>
+#include <linux/moduleparam.h>
+#include <linux/tty.h>
+#include <linux/poll.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/fs.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+
+#include <linux/usb_ch9.h>
+#include <linux/usb_gadget.h>
+
+struct gchar_dev {
+	spinlock_t		lock;
+	struct usb_gadget	*gadget;
+	struct usb_request	*req;		/* for control responses */
+	struct usb_ep		*in_ep, *out_ep;
+	
+	int			configured;
+	
+	unsigned char		databuf[DBUFMAX];
+	int			databuflen;
+	spinlock_t		buflock;
+	wait_queue_head_t	wait;
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int gchar_bind_misc(struct gchar_dev *dev);
+static int gchar_unbind_misc(struct gchar_dev *dev);
+
+/*-------------------------------------------------------------------------*/
+
+static const char shortname [] = "char";
+static const char longname [] = "Character Gadget";
+
+static const char charmode [] = "Character mode";
+
+/*-------------------------------------------------------------------------*/
+
+#define EP0_MAXPACKET		16
+static const char *EP_OUT_NAME;
+static const char *EP_IN_NAME;
+
+/*-------------------------------------------------------------------------*/
+
+/* any hub supports this steady state bus power consumption */
+#define MAX_USB_POWER	100	/* mA */
+
+/* big enough to hold our biggest descriptor */
+#define USB_BUFSIZ	256
+
+/*-------------------------------------------------------------------------*/
+
+#define xprintk(d,level,fmt,args...)	dev_printk(level , &(d)->gadget->dev , fmt , ## args)
+
+#ifdef DEBUG
+#  undef DEBUG
+#  define DEBUG(dev,fmt,args...)	printk(KERN_DEBUG "gchar: " fmt , ## args)
+#else
+#  define DEBUG(dev,fmt,args...)	do { } while (0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#  define VDEBUG			DEBUG
+#else
+#  define VDEBUG(dev,fmt,args...)	do { } while (0)
+#endif /* VERBOSE */
+
+#define ERROR(dev,fmt,args...)		printk(KERN_ERR "gchar: " fmt , ## args)
+#define WARN(dev,fmt,args...)		printk(KERN_WARNING "gchar: " fmt , ## args)
+#define INFO(dev,fmt,args...)		printk(KERN_INFO "gchar: " fmt , ## args)
+
+/*-------------------------------------------------------------------------*/
+
+static unsigned buflen = 1536;
+static unsigned qlen = 4;
+
+module_param (buflen, uint, S_IRUGO|S_IWUSR);
+module_param (qlen, uint, S_IRUGO|S_IWUSR);
+
+/*-------------------------------------------------------------------------*/
+
+#define DRIVER_VENDOR_NUM	0x6666		/* Experimental */
+#define DRIVER_PRODUCT_NUM	0xB007		/* Bootloader */
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * 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_CHAR			250
+
+/*
+ * This device advertises one configuration.
+ */
+#define	CONFIG_CHAR		1
+
+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),
+	.bcdDevice =		__constant_cpu_to_le16 (0x0000),
+	.iManufacturer =	STRING_MANUFACTURER,
+	.iProduct =		STRING_PRODUCT,
+	.iSerialNumber =	STRING_SERIAL,
+	.bNumConfigurations =	1,
+};
+
+static const struct usb_config_descriptor
+char_config = {
+	.bLength =		sizeof char_config,
+	.bDescriptorType =	USB_DT_CONFIG,
+
+	/* compute wTotalLength on the fly */
+	.bNumInterfaces =	1,
+	.bConfigurationValue =	CONFIG_CHAR,
+	.iConfiguration =	STRING_CHAR,
+	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER | 0 /* no wakeup support */,
+	.bMaxPower =		(MAX_USB_POWER + 1) / 2,
+};
+
+/* one interface in each configuration */
+
+static const struct usb_interface_descriptor
+char_intf = {
+	.bLength =		sizeof char_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
+	.iInterface =		STRING_CHAR,
+};
+
+/* two full speed bulk endpoints; their use is config-dependent */
+
+static struct usb_endpoint_descriptor
+fs_char_in_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor
+fs_char_out_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+/* if there's no high speed support, maxpacket doesn't change. */
+static char				manufacturer [50];
+static char				serial [40];
+
+/* static strings, in iso 8859/1 */
+static struct usb_string		strings [] = {
+	{ STRING_MANUFACTURER, manufacturer, },
+	{ STRING_PRODUCT, longname, },
+	{ STRING_SERIAL, serial, },
+	{ STRING_CHAR, charmode, },
+	{  }			/* end of list */
+};
+
+static struct usb_gadget_strings	stringtab = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings,
+};
+
+static int
+config_buf (enum usb_device_speed speed,
+		u8 *buf, u8 type, unsigned index)
+{
+	const unsigned	config_len = USB_DT_CONFIG_SIZE
+				+ USB_DT_INTERFACE_SIZE
+				+ 2 * USB_DT_ENDPOINT_SIZE;
+
+	/* two configurations will always be index 0 and index 1 */
+	if (index > 1)
+		return -EINVAL;
+	if (config_len > USB_BUFSIZ)
+		return -EDOM;
+
+	/* config (or other speed config) */
+	memcpy (buf, &char_config, USB_DT_CONFIG_SIZE);
+	buf [1] = type;
+	((struct usb_config_descriptor *) buf)->wTotalLength
+		= __constant_cpu_to_le16 (config_len);
+	buf += USB_DT_CONFIG_SIZE;
+
+	/* one interface */
+	memcpy (buf, &char_intf, USB_DT_INTERFACE_SIZE);
+	buf += USB_DT_INTERFACE_SIZE;
+
+	/* the endpoints in that interface (at that speed) */
+	memcpy (buf, &fs_char_in_desc, USB_DT_ENDPOINT_SIZE);
+	buf += USB_DT_ENDPOINT_SIZE;
+	memcpy (buf, &fs_char_out_desc, USB_DT_ENDPOINT_SIZE);
+	buf += USB_DT_ENDPOINT_SIZE;
+
+	return config_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);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void gchar_complete (struct usb_ep *ep, struct usb_request *req)
+{
+	struct gchar_dev	*dev = ep->driver_data;
+	int			status = req->status;
+
+	switch (status) {
+
+	case 0: 			/* normal completion? */
+		if (ep != dev->out_ep) {
+			ERROR (dev, "complete: invalid endpoint --> %s (%d/%d)\n", ep->name, req->actual, req->length);
+			free_ep_req (ep, req);
+			return;
+		}
+
+		/* it looks like you've got a packet! */
+		req->length = req->actual;
+		
+		spin_lock(&dev->buflock);
+		{
+			int cpylen;
+			
+			cpylen = ((dev->databuflen+req->actual) < DBUFMAX) ? req->actual : (DBUFMAX - dev->databuflen);
+			memcpy(&dev->databuf[dev->databuflen], req->buf, cpylen);
+			dev->databuflen += cpylen;
+		}
+		spin_unlock(&dev->buflock);
+		wake_up_interruptible(&dev->wait);
+		
+		/* queue the buffer for some later OUT packet */
+		req->length = buflen;
+		status = usb_ep_queue (dev->out_ep, req, GFP_ATOMIC);
+		if (status == 0)
+			return;
+		
+		/* FALLTHROUGH */
+	default:
+		ERROR (dev, "%s gchar recv complete --> %d, %d/%d\n", ep->name,
+				status, req->actual, req->length);
+		/* FALLTHROUGH */
+
+	/* NOTE:  since this driver doesn't maintain an explicit record
+	 * of requests it submitted (just maintains qlen count), we
+	 * rely on the hardware driver to clean up on disconnect or
+	 * endpoint disable.
+	 */
+	case -ECONNABORTED: 		/* hardware forced ep reset */
+	case -ECONNRESET:		/* request dequeued */
+	case -ESHUTDOWN:		/* disconnect from host */
+		
+		return;
+	}
+}
+
+static int
+set_char_config (struct gchar_dev *dev, int gfp_flags)
+{
+	int			result = 0;
+	struct usb_ep		*ep;
+	struct usb_gadget	*gadget = dev->gadget;
+
+	gadget_for_each_ep (ep, gadget) {
+		/* one endpoint writes data back IN to the host */
+		if (strcmp (ep->name, EP_IN_NAME) == 0) {
+			result = usb_ep_enable (ep, &fs_char_in_desc);
+			if (result == 0) {
+				ep->driver_data = dev;
+				dev->in_ep = ep;
+				continue;
+			}
+
+		/* one endpoint just reads OUT packets */
+		} else if (strcmp (ep->name, EP_OUT_NAME) == 0) {
+			result = usb_ep_enable (ep, &fs_char_out_desc);
+			if (result == 0) {
+				ep->driver_data = dev;
+				dev->out_ep = ep;
+				continue;
+			}
+
+		/* ignore any other endpoints */
+		} else
+			continue;
+
+		/* stop on error */
+		ERROR (dev, "can't enable %s, result %d\n", ep->name, result);
+		break;
+	}
+
+	/* allocate a bunch of read buffers and queue them all at once.
+	 * we buffer at most 'qlen' transfers; fewer if any need more
+	 * than 'buflen' bytes each.
+	 */
+	if (result == 0) {
+		struct usb_request	*req;
+		unsigned		i;
+
+		ep = dev->out_ep;
+		for (i = 0; i < qlen && result == 0; i++) {
+			DEBUG (dev, "%s alloc req of size %d (%d/%d)\n", ep->name, buflen, i, qlen);
+			req = alloc_ep_req (ep, buflen);
+			if (req) {
+				req->complete = gchar_complete;
+				result = usb_ep_queue (ep, req, GFP_ATOMIC);
+				if (result)
+					DEBUG (dev, "%s queue req --> %d\n",
+							ep->name, result);
+			} else
+				result = -ENOMEM;
+		}
+		
+	}
+
+	/* caller is responsible for cleanup on error */
+	return result;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void gchar_reset_config (struct gchar_dev *dev)
+{
+	if (dev->configured == 0)
+		return;
+
+	DEBUG (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->configured = 0;
+}
+
+/* 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
+gchar_set_config (struct gchar_dev *dev, unsigned number, int gfp_flags)
+{
+	int			result = 0;
+	struct usb_gadget	*gadget = dev->gadget;
+
+#if 0
+	if (dev->configured)
+		return 0;
+#endif
+
+#ifdef CONFIG_USB_CHAR_SA1100
+	if (dev->configured) {
+		/* tx fifo is full, but we can't clear it...*/
+		INFO (dev, "can't change configurations\n");
+		return -ESPIPE;
+	}
+#endif
+	gchar_reset_config (dev);
+
+	switch (number) {
+	case CONFIG_CHAR:
+		result = set_char_config (dev, gfp_flags);
+		break;
+	default:
+		result = -EINVAL;
+		/* FALL THROUGH */
+	case 0:
+		return result;
+	}
+
+	if (!result && (!dev->in_ep || !dev->out_ep))
+		result = -ENODEV;
+	if (result)
+		gchar_reset_config (dev);
+	else {
+		char *speed;
+
+		switch (gadget->speed) {
+		case USB_SPEED_LOW:	speed = "low"; break;
+		case USB_SPEED_FULL:	speed = "full"; break;
+		case USB_SPEED_HIGH:	speed = "high"; break;
+		default: 		speed = "?"; break;
+		}
+
+		dev->configured = 1;
+		INFO (dev, "%s speed\n", speed);
+	}
+	return result;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void gchar_setup_complete (struct usb_ep *ep, struct usb_request *req)
+{
+	if (req->status || req->actual != req->length)
+		DEBUG ((struct gchar_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
+gchar_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+{
+	struct gchar_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.
+	 */
+	switch (ctrl->bRequest) {
+
+	case USB_REQ_GET_DESCRIPTOR:
+		if (ctrl->bRequestType != USB_DIR_IN)
+			break;
+		switch (ctrl->wValue >> 8) {
+
+		case USB_DT_DEVICE:
+			value = min (ctrl->wLength, (u16) sizeof device_desc);
+			memcpy (req->buf, &device_desc, value);
+			break;
+		case USB_DT_CONFIG:
+			value = config_buf (gadget->speed, 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 others even if they don't use iso8859/1
+			 */
+			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)
+			break;
+		spin_lock (&dev->lock);
+		value = gchar_set_config (dev, ctrl->wValue, GFP_ATOMIC);
+		spin_unlock (&dev->lock);
+		break;
+	case USB_REQ_GET_CONFIGURATION:
+		if (ctrl->bRequestType != USB_DIR_IN)
+			break;
+		*(u8 *)req->buf = dev->configured ? CONFIG_CHAR : 0;
+		value = min (ctrl->wLength, (u16) 1);
+		break;
+	case USB_REQ_SET_INTERFACE:
+		if (ctrl->bRequestType != USB_RECIP_INTERFACE)
+			break;
+		spin_lock (&dev->lock);
+		if (dev->configured && ctrl->wIndex == 0 && ctrl->wValue == 0) {
+			u8 config = dev->configured ? CONFIG_CHAR : 0;
+
+			gchar_reset_config (dev);
+			gchar_set_config (dev, config, GFP_ATOMIC);
+			value = 0;
+		}
+		spin_unlock (&dev->lock);
+		break;
+	case USB_REQ_GET_INTERFACE:
+		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
+			break;
+		if (!dev->configured)
+			break;
+		if (ctrl->wIndex != 0) {
+			value = -EDOM;
+			break;
+		}
+		*(u8 *)req->buf = 0;
+		value = min (ctrl->wLength, (u16) 1);
+		break;
+
+	default:
+		VDEBUG (dev,
+			"unknown control req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			ctrl->wValue, ctrl->wIndex, ctrl->wLength);
+	}
+
+	/* respond with data transfer before status phase? */
+	if (value >= 0) {
+		req->length = value;
+		value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
+		if (value < 0) {
+			DEBUG (dev, "ep_queue --> %d\n", value);
+			req->status = 0;
+			gchar_setup_complete (gadget->ep0, req);
+		}
+	}
+
+	/* device either stalls (value < 0) or reports success */
+	return value;
+}
+
+static void
+gchar_disconnect (struct usb_gadget *gadget)
+{
+	struct gchar_dev	*dev = get_gadget_data (gadget);
+	unsigned long		flags;
+
+	spin_lock_irqsave (&dev->lock, flags);
+	gchar_reset_config (dev);
+
+	/* a more significant application might have some non-usb
+	 * activities to quiesce here, saving resources like power
+	 * or pushing the notification up a network stack.
+	 */
+	spin_unlock_irqrestore (&dev->lock, flags);
+
+	/* next we may get setup() calls to enumerate new connections;
+	 * or an unbind() during shutdown (including removing module).
+	 */
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void
+gchar_unbind (struct usb_gadget *gadget)
+{
+	struct gchar_dev	*dev = get_gadget_data (gadget);
+
+	DEBUG (dev, "unbind\n");
+
+	/* we've already been disconnected ... no i/o is active */
+	if (dev->req)
+		free_ep_req (gadget->ep0, dev->req);
+	kfree (dev);
+	set_gadget_data (gadget, NULL);
+	
+	gchar_unbind_misc(dev);
+	
+}
+
+static int
+gchar_bind (struct usb_gadget *gadget)
+{
+	struct gchar_dev	*dev;
+	struct usb_ep		*ep;
+	int err;
+
+	usb_ep_autoconfig_reset (gadget);
+	
+	ep = usb_ep_autoconfig (gadget, &fs_char_in_desc);
+	if (!ep) {
+autoconf_fail:
+		printk(KERN_ERR "%s: can't autoconfigure on %s\n", shortname, gadget->name);
+		return -ENODEV;
+	}
+	EP_IN_NAME = ep->name;
+	ep->driver_data = ep;	/* claim */
+	
+	ep = usb_ep_autoconfig (gadget, &fs_char_out_desc);
+	if (!ep)
+		goto autoconf_fail;
+	EP_OUT_NAME = ep->name;
+	ep->driver_data = ep;	/* claim */
+
+	dev = kmalloc (sizeof *dev, SLAB_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	memset (dev, 0, sizeof *dev);
+	spin_lock_init (&dev->lock);
+	spin_lock_init (&dev->buflock);
+	dev->gadget = gadget;
+	init_waitqueue_head (&dev->wait);
+
+	set_gadget_data (gadget, dev);
+
+	/* preallocate control response and buffer */
+	dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
+	if (!dev->req)
+		goto enomem;
+	dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
+				&dev->req->dma, GFP_KERNEL);
+	if (!dev->req->buf)
+		goto enomem;
+
+	dev->req->complete = gchar_setup_complete;
+	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
+	gadget->ep0->driver_data = dev;
+
+	snprintf (manufacturer, sizeof manufacturer, "%s %s with %s",
+		system_utsname.sysname, system_utsname.release,
+		gadget->name);
+	
+	/* grab a misc device */
+	if ((err = gchar_bind_misc(dev))) {
+		gchar_unbind(gadget);
+		return err;
+	}
+	
+	return 0;
+
+enomem:
+	gchar_unbind (gadget);
+	return -ENOMEM;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_gadget_driver gchar_driver = {
+	.speed		= USB_SPEED_FULL,
+	.function	= (char *) longname,
+	.bind		= gchar_bind,
+	.unbind		= gchar_unbind,
+
+	.setup		= gchar_setup,
+	.disconnect	= gchar_disconnect,
+
+	.driver 	= {
+		.name		= (char *) shortname,
+		// .shutdown = ...
+		// .suspend = ...
+		// .resume = ...
+	},
+};
+
+MODULE_AUTHOR ("Joshua Wise/David Brownell");
+MODULE_LICENSE ("Dual BSD/GPL");
+
+static ssize_t read_gchar(struct file* file, char __user *buf, size_t count, loff_t *ppos)
+{
+	struct gchar_dev *dev = (struct gchar_dev *)file->private_data;
+	ssize_t readcnt;
+	DECLARE_WAITQUEUE(wait, current);
+	
+	add_wait_queue(&dev->wait, &wait);
+	current->state = TASK_INTERRUPTIBLE;
+
+	do {
+		if (dev->databuflen != 0)
+			break;
+
+		if (file->f_flags & O_NONBLOCK)
+		{
+			readcnt = -EAGAIN;
+			goto out;
+		}
+
+		schedule();
+		if (signal_pending(current))
+		{
+			readcnt = -ERESTARTSYS;
+			goto out;
+		}
+	} while (1);
+
+	spin_lock_irq(&dev->buflock);
+		readcnt = (count > dev->databuflen) ? dev->databuflen : count;
+		copy_to_user(buf, dev->databuf, readcnt);
+		memmove(dev->databuf, dev->databuf+readcnt, dev->databuflen-readcnt);
+		dev->databuflen -= readcnt;
+	spin_unlock_irq(&dev->buflock);
+
+out:
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&dev->wait, &wait);
+
+	return readcnt;
+}
+
+static void gchar_send_complete (struct usb_ep *ep, struct usb_request *req)
+{
+	free_ep_req(ep, req);
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define USBC_MINOR		240
+#define USBC_MAX_DEVICES	1
+
+static ssize_t write_gchar(struct file* file, const char __user *buf, size_t count, loff_t* ppos)
+{
+	struct gchar_dev *dev = (struct gchar_dev *)file->private_data;
+	struct usb_request *req;
+	int result;
+	
+	if (!dev->configured)
+		return count;
+	
+	req = alloc_ep_req (dev->in_ep, count);
+	if (!req)
+		return -ENOMEM;
+		
+	req->complete = gchar_send_complete;
+	req->length = req->actual = count;
+	req->zero = 0;
+	
+	copy_from_user(req->buf, buf, count);
+	
+	result = usb_ep_queue (dev->in_ep, req, GFP_ATOMIC);
+	if (result)
+		DEBUG (dev, "%s queue req --> %d\n",
+				dev->in_ep->name, result);
+		
+	return count;
+}
+
+static unsigned int poll_gchar( struct file * filp, poll_table *wait )
+{
+	struct gchar_dev *dev = (struct gchar_dev *)filp->private_data;
+	
+	poll_wait(filp, &dev->wait, wait);
+	
+	if (dev->databuflen)
+		return POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM;
+	return POLLOUT | POLLWRNORM;
+}
+
+/*-------------------------------------------------------------------------*/
+
+struct gchar_dev *gc_devs[USBC_MAX_DEVICES];
+
+static int open_gchar(struct inode *inode, struct file *file)
+{
+	struct gchar_dev *dev = gc_devs[iminor(inode)-USBC_MINOR];
+	
+	if (!dev->configured && !dev->databuflen)
+		return -ENXIO;
+
+	file->private_data = (void*)dev;
+	nonseekable_open(inode, file);
+
+	return 0;
+}
+
+static struct file_operations gchar_fops = {
+	.llseek		= no_llseek,
+	.read		= read_gchar,
+	.write		= write_gchar,
+	.poll		= poll_gchar,
+	.open		= open_gchar
+};
+
+static struct miscdevice gchar_misc_device = {
+	USBC_MINOR, "usbchar", &gchar_fops
+};
+
+static int gchar_bind_misc(struct gchar_dev *dev)
+{
+	int error;
+	
+	if ((error = misc_register(&gchar_misc_device)))
+	{
+		printk("gchar: Unable to register device 10, %d. Errno: %d\n", USBC_MINOR, error);
+		return error;
+	}
+
+	gc_devs[gchar_misc_device.minor-USBC_MINOR] = dev;
+	return 0;
+}
+
+static int gchar_unbind_misc(struct gchar_dev *dev)
+{
+	misc_deregister (&gchar_misc_device);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int __init gchar_init (void)
+{
+	/* a real value would likely come through some id prom
+	 * or module option.  this one takes at least two packets.
+	 */
+	strlcpy (serial, "hp iPAQ: Linux As Bootloader    ", sizeof serial);
+
+	return usb_gadget_register_driver (&gchar_driver);
+}
+module_init (gchar_init);
+
+static void __exit cleanup (void)
+{
+	usb_gadget_unregister_driver (&gchar_driver);
+	
+}
+module_exit (cleanup);
diff -urN linux-2.6.25/drivers/usb/gadget/config.c linux-2.6.25-vpac1/drivers/usb/gadget/config.c
--- linux-2.6.25/drivers/usb/gadget/config.c	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/usb/gadget/config.c	2008-04-24 15:12:18.000000000 +0200
@@ -25,7 +25,7 @@
 #include <linux/device.h>
 
 #include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
+#include <linux/usb_gadget.h>
 
 
 /**
@@ -50,7 +50,7 @@
 		return -EINVAL;
 
 	/* fill buffer from src[] until null descriptor ptr */
-	for (; NULL != *src; src++) {
+	for (; 0 != *src; src++) {
 		unsigned		len = (*src)->bLength;
 
 		if (len > buflen)
diff -urN linux-2.6.25/drivers/usb/gadget/dummy_hcd.c linux-2.6.25-vpac1/drivers/usb/gadget/dummy_hcd.c
--- linux-2.6.25/drivers/usb/gadget/dummy_hcd.c	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/usb/gadget/dummy_hcd.c	2008-04-24 15:12:18.000000000 +0200
@@ -34,11 +34,14 @@
  * bypassing some hardware (and driver) issues.  UML could help too.
  */
 
+#define DEBUG
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/timer.h>
@@ -46,7 +49,7 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/usb.h>
-#include <linux/usb/gadget.h>
+#include <linux/usb_gadget.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -497,6 +500,38 @@
 	kfree (req);
 }
 
+static void *
+dummy_alloc_buffer (
+	struct usb_ep *_ep,
+	unsigned bytes,
+	dma_addr_t *dma,
+	gfp_t mem_flags
+) {
+	char			*retval;
+	struct dummy_ep		*ep;
+	struct dummy		*dum;
+
+	ep = usb_ep_to_dummy_ep (_ep);
+	dum = ep_to_dummy (ep);
+
+	if (!dum->driver)
+		return NULL;
+	retval = kmalloc (bytes, mem_flags);
+	*dma = (dma_addr_t) retval;
+	return retval;
+}
+
+static void
+dummy_free_buffer (
+	struct usb_ep *_ep,
+	void *buf,
+	dma_addr_t dma,
+	unsigned bytes
+) {
+	if (bytes)
+		kfree (buf);
+}
+
 static void
 fifo_complete (struct usb_ep *ep, struct usb_request *req)
 {
@@ -627,6 +662,10 @@
 	.alloc_request	= dummy_alloc_request,
 	.free_request	= dummy_free_request,
 
+	.alloc_buffer	= dummy_alloc_buffer,
+	.free_buffer	= dummy_free_buffer,
+	/* map, unmap, ... eventually hook the "generic" dma calls */
+
 	.queue		= dummy_queue,
 	.dequeue	= dummy_dequeue,
 
@@ -947,13 +986,13 @@
 
 static int dummy_urb_enqueue (
 	struct usb_hcd			*hcd,
+	struct usb_host_endpoint	*ep,
 	struct urb			*urb,
 	gfp_t				mem_flags
 ) {
 	struct dummy	*dum;
 	struct urbp	*urbp;
 	unsigned long	flags;
-	int		rc;
 
 	if (!urb->transfer_buffer && urb->transfer_buffer_length)
 		return -EINVAL;
@@ -965,11 +1004,6 @@
 
 	dum = hcd_to_dummy (hcd);
 	spin_lock_irqsave (&dum->lock, flags);
-	rc = usb_hcd_link_urb_to_ep(hcd, urb);
-	if (rc) {
-		kfree(urbp);
-		goto done;
-	}
 
 	if (!dum->udev) {
 		dum->udev = urb->dev;
@@ -986,35 +1020,36 @@
 	if (!timer_pending (&dum->timer))
 		mod_timer (&dum->timer, jiffies + 1);
 
- done:
-	spin_unlock_irqrestore(&dum->lock, flags);
-	return rc;
+	spin_unlock_irqrestore (&dum->lock, flags);
+	return 0;
 }
 
-static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+static int dummy_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
 {
 	struct dummy	*dum;
 	unsigned long	flags;
-	int		rc;
 
 	/* giveback happens automatically in timer callback,
 	 * so make sure the callback happens */
 	dum = hcd_to_dummy (hcd);
 	spin_lock_irqsave (&dum->lock, flags);
-
-	rc = usb_hcd_check_unlink_urb(hcd, urb, status);
-	if (!rc && dum->rh_state != DUMMY_RH_RUNNING &&
-			!list_empty(&dum->urbp_list))
+	if (dum->rh_state != DUMMY_RH_RUNNING && !list_empty(&dum->urbp_list))
 		mod_timer (&dum->timer, jiffies);
-
 	spin_unlock_irqrestore (&dum->lock, flags);
-	return rc;
+	return 0;
+}
+
+static void maybe_set_status (struct urb *urb, int status)
+{
+	spin_lock (&urb->lock);
+	if (urb->status == -EINPROGRESS)
+		urb->status = status;
+	spin_unlock (&urb->lock);
 }
 
 /* transfer up to a frame's worth; caller must own lock */
 static int
-transfer(struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit,
-		int *status)
+transfer (struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit)
 {
 	struct dummy_request	*req;
 
@@ -1077,20 +1112,24 @@
 		 *
 		 * partially filling a buffer optionally blocks queue advances
 		 * (so completion handlers can clean up the queue) but we don't
-		 * need to emulate such data-in-flight.
+		 * need to emulate such data-in-flight.  so we only show part
+		 * of the URB_SHORT_NOT_OK effect: completion status.
 		 */
 		if (is_short) {
 			if (host_len == dev_len) {
 				req->req.status = 0;
-				*status = 0;
+				maybe_set_status (urb, 0);
 			} else if (to_host) {
 				req->req.status = 0;
 				if (dev_len > host_len)
-					*status = -EOVERFLOW;
+					maybe_set_status (urb, -EOVERFLOW);
 				else
-					*status = 0;
+					maybe_set_status (urb,
+						(urb->transfer_flags
+							& URB_SHORT_NOT_OK)
+						? -EREMOTEIO : 0);
 			} else if (!to_host) {
-				*status = 0;
+				maybe_set_status (urb, 0);
 				if (host_len > dev_len)
 					req->req.status = -EOVERFLOW;
 				else
@@ -1104,8 +1143,9 @@
 				req->req.status = 0;
 			if (urb->transfer_buffer_length == urb->actual_length
 					&& !(urb->transfer_flags
-						& URB_ZERO_PACKET))
-				*status = 0;
+						& URB_ZERO_PACKET)) {
+				maybe_set_status (urb, 0);
+			}
 		}
 
 		/* device side completion --> continuable */
@@ -1121,7 +1161,7 @@
 		}
 
 		/* host side completion --> terminate */
-		if (*status != -EINPROGRESS)
+		if (urb->status != -EINPROGRESS)
 			break;
 
 		/* rescan to continue with any other queued i/o */
@@ -1232,12 +1272,12 @@
 		u8			address;
 		struct dummy_ep		*ep = NULL;
 		int			type;
-		int			status = -EINPROGRESS;
 
 		urb = urbp->urb;
-		if (urb->unlinked)
+		if (urb->status != -EINPROGRESS) {
+			/* likely it was just unlinked */
 			goto return_urb;
-		else if (dum->rh_state != DUMMY_RH_RUNNING)
+		} else if (dum->rh_state != DUMMY_RH_RUNNING)
 			continue;
 		type = usb_pipetype (urb->pipe);
 
@@ -1258,7 +1298,7 @@
 			dev_dbg (dummy_dev(dum),
 				"no ep configured for urb %p\n",
 				urb);
-			status = -EPROTO;
+			maybe_set_status (urb, -EPROTO);
 			goto return_urb;
 		}
 
@@ -1273,7 +1313,7 @@
 			/* NOTE: must not be iso! */
 			dev_dbg (dummy_dev(dum), "ep %s halted, urb %p\n",
 					ep->ep.name, urb);
-			status = -EPIPE;
+			maybe_set_status (urb, -EPIPE);
 			goto return_urb;
 		}
 		/* FIXME make sure both ends agree on maxpacket */
@@ -1291,7 +1331,7 @@
 			w_value = le16_to_cpu(setup.wValue);
 			if (le16_to_cpu(setup.wLength) !=
 					urb->transfer_buffer_length) {
-				status = -EOVERFLOW;
+				maybe_set_status (urb, -EOVERFLOW);
 				goto return_urb;
 			}
 
@@ -1321,7 +1361,7 @@
 				if (setup.bRequestType != Dev_Request)
 					break;
 				dum->address = w_value;
-				status = 0;
+				maybe_set_status (urb, 0);
 				dev_dbg (udc_dev(dum), "set_address = %d\n",
 						w_value);
 				value = 0;
@@ -1348,7 +1388,7 @@
 					if (value == 0) {
 						dum->devstatus |=
 							(1 << w_value);
-						status = 0;
+						maybe_set_status (urb, 0);
 					}
 
 				} else if (setup.bRequestType == Ep_Request) {
@@ -1360,7 +1400,7 @@
 					}
 					ep2->halted = 1;
 					value = 0;
-					status = 0;
+					maybe_set_status (urb, 0);
 				}
 				break;
 			case USB_REQ_CLEAR_FEATURE:
@@ -1370,7 +1410,7 @@
 						dum->devstatus &= ~(1 <<
 							USB_DEVICE_REMOTE_WAKEUP);
 						value = 0;
-						status = 0;
+						maybe_set_status (urb, 0);
 						break;
 					default:
 						value = -EOPNOTSUPP;
@@ -1385,7 +1425,7 @@
 					}
 					ep2->halted = 0;
 					value = 0;
-					status = 0;
+					maybe_set_status (urb, 0);
 				}
 				break;
 			case USB_REQ_GET_STATUS:
@@ -1422,7 +1462,7 @@
 					urb->actual_length = min (2,
 						urb->transfer_buffer_length);
 					value = 0;
-					status = 0;
+					maybe_set_status (urb, 0);
 				}
 				break;
 			}
@@ -1449,7 +1489,7 @@
 					dev_dbg (udc_dev(dum),
 						"setup --> %d\n",
 						value);
-				status = -EPIPE;
+				maybe_set_status (urb, -EPIPE);
 				urb->actual_length = 0;
 			}
 
@@ -1466,7 +1506,7 @@
 			 * report random errors, to debug drivers.
 			 */
 			limit = max (limit, periodic_bytes (dum, ep));
-			status = -ENOSYS;
+			maybe_set_status (urb, -ENOSYS);
 			break;
 
 		case PIPE_INTERRUPT:
@@ -1480,23 +1520,23 @@
 		default:
 		treat_control_like_bulk:
 			ep->last_io = jiffies;
-			total = transfer(dum, urb, ep, limit, &status);
+			total = transfer (dum, urb, ep, limit);
 			break;
 		}
 
 		/* incomplete transfer? */
-		if (status == -EINPROGRESS)
+		if (urb->status == -EINPROGRESS)
 			continue;
 
 return_urb:
+		urb->hcpriv = NULL;
 		list_del (&urbp->urbp_list);
 		kfree (urbp);
 		if (ep)
 			ep->already_seen = ep->setup_stage = 0;
 
-		usb_hcd_unlink_urb_from_ep(dummy_to_hcd(dum), urb);
 		spin_unlock (&dum->lock);
-		usb_hcd_giveback_urb(dummy_to_hcd(dum), urb, status);
+		usb_hcd_giveback_urb (dummy_to_hcd(dum), urb);
 		spin_lock (&dum->lock);
 
 		goto restart;
@@ -1730,7 +1770,8 @@
 
 	spin_lock_irq (&dum->lock);
 	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
-		rc = -ESHUTDOWN;
+		dev_warn (&hcd->self.root_hub->dev, "HC isn't running!\n");
+		rc = -ENODEV;
 	} else {
 		dum->rh_state = DUMMY_RH_RUNNING;
 		set_link_state (dum);
diff -urN linux-2.6.25/drivers/usb/gadget/epautoconf.c linux-2.6.25-vpac1/drivers/usb/gadget/epautoconf.c
--- linux-2.6.25/drivers/usb/gadget/epautoconf.c	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/usb/gadget/epautoconf.c	2008-04-24 15:12:18.000000000 +0200
@@ -28,7 +28,7 @@
 #include <linux/string.h>
 
 #include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
+#include <linux/usb_gadget.h>
 
 #include "gadget_chips.h"
 
@@ -71,7 +71,7 @@
 	u16		max;
 
 	/* endpoint already claimed? */
-	if (NULL != ep->driver_data)
+	if (0 != ep->driver_data)
 		return 0;
 
 	/* only support ep0 for portable CONTROL traffic */
@@ -132,7 +132,7 @@
 	 * where it's an output parameter representing the full speed limit.
 	 * the usb spec fixes high speed bulk maxpacket at 512 bytes.
 	 */
-	max = 0x7ff & le16_to_cpu(desc->wMaxPacketSize);
+	max = 0x7ff & le16_to_cpup (&desc->wMaxPacketSize);
 	switch (type) {
 	case USB_ENDPOINT_XFER_INT:
 		/* INT:  limit 64 bytes full speed, 1024 high speed */
@@ -230,12 +230,17 @@
  */
 struct usb_ep * __devinit usb_ep_autoconfig (
 	struct usb_gadget		*gadget,
-	struct usb_endpoint_descriptor	*desc
+	struct usb_endpoint_descriptor	*desc,
+	struct usb_endpoint_config *epconfig, int numconfigs
 )
 {
 	struct usb_ep	*ep;
 	u8		type;
 
+	/* Use device specific ep allocation code if provided */
+	if (gadget->ops->ep_alloc)
+		return gadget->ops->ep_alloc(gadget, desc, epconfig, numconfigs);
+
 	type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
 
 	/* First, apply chip-specific "best usage" knowledge.
diff -urN linux-2.6.25/drivers/usb/gadget/ether.c linux-2.6.25-vpac1/drivers/usb/gadget/ether.c
--- linux-2.6.25/drivers/usb/gadget/ether.c	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/usb/gadget/ether.c	2008-04-24 15:12:18.000000000 +0200
@@ -19,18 +19,41 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-/* #define VERBOSE_DEBUG */
 
+// #define DEBUG 1
+// #define VERBOSE
+
+#include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.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/utsname.h>
 #include <linux/device.h>
+#include <linux/moduleparam.h>
 #include <linux/ctype.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/unaligned.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/cdc.h>
-#include <linux/usb/gadget.h>
+#include <linux/usb_gadget.h>
+
+#include <linux/random.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
 
 #include "gadget_chips.h"
 
@@ -236,7 +259,8 @@
 #endif
 
 #ifdef CONFIG_USB_GADGET_PXA27X
-#define DEV_CONFIG_CDC
+//#define DEV_CONFIG_CDC
+#define	DEV_CONFIG_SUBSET
 #endif
 
 #ifdef CONFIG_USB_GADGET_S3C2410
@@ -255,13 +279,10 @@
 #define DEV_CONFIG_CDC
 #endif
 
-#ifdef CONFIG_USB_GADGET_ATMEL_USBA
+#ifdef CONFIG_USB_GADGET_HUSB2DEV
 #define DEV_CONFIG_CDC
 #endif
 
-#ifdef CONFIG_USB_GADGET_FSL_USB2
-#define DEV_CONFIG_CDC
-#endif
 
 /* For CDC-incapable hardware, choose the simple cdc subset.
  * Anything that talks bulk (without notable bugs) can do this.
@@ -270,7 +291,7 @@
 #define	DEV_CONFIG_SUBSET
 #endif
 
-#ifdef CONFIG_USB_GADGET_SUPERH
+#ifdef CONFIG_USB_GADGET_SH
 #define	DEV_CONFIG_SUBSET
 #endif
 
@@ -279,14 +300,6 @@
 #define	DEV_CONFIG_SUBSET
 #endif
 
-#ifdef CONFIG_USB_GADGET_M66592
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_AMD5536UDC
-#define	DEV_CONFIG_CDC
-#endif
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -334,15 +347,15 @@
 #define qlen(gadget) \
 	(DEFAULT_QLEN*((gadget->speed == USB_SPEED_HIGH) ? qmult : 1))
 
+/* also defer IRQs on highspeed TX */
+#define TX_DELAY	qmult
+
 static inline int BITRATE(struct usb_gadget *g)
 {
 	return (g->speed == USB_SPEED_HIGH) ? HS_BPS : FS_BPS;
 }
 
 #else	/* full speed (low speed doesn't do bulk) */
-
-#define qmult		1
-
 #define	DEVSPEED	USB_SPEED_FULL
 
 #define qlen(gadget) DEFAULT_QLEN
@@ -368,7 +381,7 @@
 	do { } while (0)
 #endif /* DEBUG */
 
-#ifdef VERBOSE_DEBUG
+#ifdef VERBOSE
 #define VDEBUG	DEBUG
 #else
 #define VDEBUG(dev,fmt,args...) \
@@ -808,6 +821,8 @@
 };
 #endif
 
+#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.
@@ -910,15 +925,18 @@
 
 
 /* maxpacket and other transfer characteristics vary by speed. */
-static inline struct usb_endpoint_descriptor *
-ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
-		struct usb_endpoint_descriptor *fs)
-{
-	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
-		return hs;
-	return fs;
+#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) (((void)(g)), (fs))
+
+static inline void __init hs_subset_descriptors(void)
+{
 }
 
+#endif	/* !CONFIG_USB_GADGET_DUALSPEED */
 
 /*-------------------------------------------------------------------------*/
 
@@ -962,19 +980,22 @@
  * complications: class descriptors, and an altsetting.
  */
 static int
-config_buf(struct usb_gadget *g, u8 *buf, u8 type, unsigned index, int is_otg)
+config_buf (enum usb_device_speed speed,
+	u8 *buf, u8 type,
+	unsigned index, int is_otg)
 {
 	int					len;
 	const struct usb_config_descriptor	*config;
 	const struct usb_descriptor_header	**function;
-	int					hs = 0;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	int				hs = (speed == USB_SPEED_HIGH);
 
-	if (gadget_is_dualspeed(g)) {
-		hs = (g->speed == USB_SPEED_HIGH);
-		if (type == USB_DT_OTHER_SPEED_CONFIG)
-			hs = !hs;
-	}
+	if (type == USB_DT_OTHER_SPEED_CONFIG)
+		hs = !hs;
 #define which_fn(t)	(hs ? hs_ ## t ## _function : fs_ ## t ## _function)
+#else
+#define	which_fn(t)	(fs_ ## t ## _function)
+#endif
 
 	if (index >= device_desc.bNumConfigurations)
 		return -EINVAL;
@@ -1187,7 +1208,7 @@
 		if (number)
 			eth_reset_config (dev);
 		usb_gadget_vbus_draw(dev->gadget,
-				gadget_is_otg(dev->gadget) ? 8 : 100);
+				dev->gadget->is_otg ? 8 : 100);
 	} else {
 		char *speed;
 		unsigned power;
@@ -1320,6 +1341,10 @@
 	/* done sending after USB_CDC_GET_ENCAPSULATED_RESPONSE */
 }
 
+#ifdef CONFIG_USB_GADGET_PXA27X
+int write_ep0_zlp(void);
+#endif
+
 static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req)
 {
 	struct eth_dev          *dev = ep->driver_data;
@@ -1330,6 +1355,10 @@
 	status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf);
 	if (status < 0)
 		ERROR(dev, "%s: rndis parse error %d\n", __FUNCTION__, status);
+
+#ifdef CONFIG_USB_GADGET_PXA27X
+	write_ep0_zlp();
+#endif
 	spin_unlock(&dev->lock);
 }
 
@@ -1369,22 +1398,24 @@
 			value = min (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(gadget))
+			if (!gadget->is_dualspeed)
 				break;
 			value = min (wLength, (u16) sizeof dev_qualifier);
 			memcpy (req->buf, &dev_qualifier, value);
 			break;
 
 		case USB_DT_OTHER_SPEED_CONFIG:
-			if (!gadget_is_dualspeed(gadget))
+			if (!gadget->is_dualspeed)
 				break;
 			// FALLTHROUGH
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
 		case USB_DT_CONFIG:
-			value = config_buf(gadget, req->buf,
+			value = config_buf (gadget->speed, req->buf,
 					wValue >> 8,
 					wValue & 0xff,
-					gadget_is_otg(gadget));
+					gadget->is_otg);
 			if (value >= 0)
 				value = min (wLength, (u16) value);
 			break;
@@ -1553,12 +1584,12 @@
 				&& rndis_control_intf.bInterfaceNumber
 					== wIndex) {
 			u8 *buf;
-			u32 n;
 
 			/* return the result */
-			buf = rndis_get_next_response(dev->rndis_config, &n);
+			buf = rndis_get_next_response (dev->rndis_config,
+						       &value);
 			if (buf) {
-				memcpy(req->buf, buf, n);
+				memcpy (req->buf, buf, value);
 				req->complete = rndis_response_complete;
 				rndis_free_response(dev->rndis_config, buf);
 				value = n;
@@ -1692,8 +1723,7 @@
 		size += sizeof (struct rndis_packet_msg_type);
 	size -= size % dev->out_ep->maxpacket;
 
-	skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags);
-	if (skb == NULL) {
+	if ((skb = alloc_skb (size + NET_IP_ALIGN, gfp_flags)) == 0) {
 		DEBUG (dev, "no rx skb\n");
 		goto enomem;
 	}
@@ -1715,8 +1745,7 @@
 		defer_kevent (dev, WORK_RX_MEMORY);
 	if (retval) {
 		DEBUG (dev, "rx submit --> %d\n", retval);
-		if (skb)
-			dev_kfree_skb_any(skb);
+		dev_kfree_skb_any (skb);
 		spin_lock(&dev->req_lock);
 		list_add (&req->list, &dev->rx_reqs);
 		spin_unlock(&dev->req_lock);
@@ -1747,6 +1776,7 @@
 			break;
 		}
 
+		skb->dev = dev->net;
 		skb->protocol = eth_type_trans (skb, dev->net);
 		dev->stats.rx_packets++;
 		dev->stats.rx_bytes += skb->len;
@@ -1958,20 +1988,8 @@
 	}
 
 	spin_lock_irqsave(&dev->req_lock, flags);
-	/*
-	 * this freelist can be empty if an interrupt triggered disconnect()
-	 * and reconfigured the gadget (shutting down this queue) after the
-	 * network stack decided to xmit but before we got the spinlock.
-	 */
-	if (list_empty(&dev->tx_reqs)) {
-		spin_unlock_irqrestore(&dev->req_lock, flags);
-		return 1;
-	}
-
 	req = container_of (dev->tx_reqs.next, struct usb_request, list);
 	list_del (&req->list);
-
-	/* temporarily stop TX queue when the freelist empties */
 	if (list_empty (&dev->tx_reqs))
 		netif_stop_queue (net);
 	spin_unlock_irqrestore(&dev->req_lock, flags);
@@ -2007,11 +2025,12 @@
 
 	req->length = length;
 
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
 	/* throttle highspeed IRQ rate back slightly */
-	if (gadget_is_dualspeed(dev->gadget))
-		req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH)
-			? ((atomic_read(&dev->tx_qlen) % qmult) != 0)
-			: 0;
+	req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH)
+		? ((atomic_read (&dev->tx_qlen) % TX_DELAY) != 0)
+		: 0;
+#endif
 
 	retval = usb_ep_queue (dev->in_ep, req, GFP_ATOMIC);
 	switch (retval) {
@@ -2168,7 +2187,8 @@
 	}
 
 	if (rndis_active(dev)) {
-		rndis_set_param_medium(dev->rndis_config, NDIS_MEDIUM_802_3, 0);
+		rndis_set_param_medium (dev->rndis_config,
+					NDIS_MEDIUM_802_3, 0);
 		(void) rndis_signal_disconnect (dev->rndis_config);
 	}
 
@@ -2266,7 +2286,8 @@
 	struct eth_dev		*dev;
 	struct net_device	*net;
 	u8			cdc = 1, zlp = 1, rndis = 1;
-	struct usb_ep		*in_ep, *out_ep, *status_ep = NULL;
+	struct usb_ep		*in_ep = NULL , *out_ep = NULL, *status_ep = NULL;
+	struct usb_endpoint_config ep_config[2];
 	int			status = -ENOMEM;
 	int			gcnum;
 
@@ -2365,7 +2386,30 @@
 
 	/* all we really need is bulk IN/OUT */
 	usb_ep_autoconfig_reset (gadget);
-	in_ep = usb_ep_autoconfig (gadget, &fs_source_desc);
+
+	ep_config[0].config = DEV_CONFIG_VALUE;
+#if 	defined(DEV_CONFIG_CDC)
+	ep_config[0].interface = data_intf.bInterfaceNumber;
+	ep_config[0].altinterface = data_intf.bAlternateSetting;
+#else 	/* DEV_CONFIG_SUBSET */
+	ep_config[0].interface = subset_data_intf.bInterfaceNumber;
+	ep_config[0].altinterface = subset_data_intf.bAlternateSetting;
+#endif
+
+#ifdef	CONFIG_USB_ETH_RNDIS
+	ep_config[1].config = DEV_RNDIS_CONFIG_VALUE;
+#ifdef CONFIG_USB_GADGET_PXA27X
+	ep_config[1].interface = 0;
+#else
+	ep_config[1].interface = rndis_data_intf.bInterfaceNumber;
+#endif
+	ep_config[1].altinterface = rndis_data_intf.bAlternateSetting;
+
+	in_ep = usb_ep_autoconfig(gadget, &fs_source_desc, &ep_config[0], 2);
+#else
+	in_ep = usb_ep_autoconfig(gadget, &fs_source_desc, &ep_config[0], 1);
+#endif
+
 	if (!in_ep) {
 autoconf_fail:
 		dev_err (&gadget->dev,
@@ -2375,7 +2419,12 @@
 	}
 	in_ep->driver_data = in_ep;	/* claim */
 
-	out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
+#ifdef CONFIG_USB_ETH_RNDIS
+	out_ep = usb_ep_autoconfig(gadget, &fs_sink_desc, &ep_config[0], 2);
+#else
+	out_ep = usb_ep_autoconfig(gadget, &fs_sink_desc, &ep_config[0], 1);
+#endif
+
 	if (!out_ep)
 		goto autoconf_fail;
 	out_ep->driver_data = out_ep;	/* claim */
@@ -2385,7 +2434,25 @@
 	 * Since some hosts expect one, try to allocate one anyway.
 	 */
 	if (cdc || rndis) {
-		status_ep = usb_ep_autoconfig (gadget, &fs_status_desc);
+#ifdef DEV_CONFIG_CDC
+		ep_config[0].config = DEV_CONFIG_VALUE;
+		ep_config[0].interface = control_intf.bInterfaceNumber;
+		ep_config[0].altinterface = control_intf.bAlternateSetting;
+#endif
+#ifdef CONFIG_USB_ETH_RNDIS
+		ep_config[1].config = DEV_RNDIS_CONFIG_VALUE;
+		ep_config[1].interface = rndis_control_intf.bInterfaceNumber;
+		ep_config[1].altinterface = rndis_control_intf.bAlternateSetting;
+#endif
+
+#if defined(DEV_CONFIG_CDC) && defined(CONFIG_USB_ETH_RNDIS)
+		status_ep = usb_ep_autoconfig(gadget, &fs_status_desc, &ep_config[0], 2);
+#elif defined(CONFIG_USB_ETH_RNDIS)
+		status_ep = usb_ep_autoconfig(gadget, &fs_status_desc, &ep_config[1], 1);
+#else
+		status_ep = usb_ep_autoconfig(gadget, &fs_status_desc, &ep_config[0], 1);
+#endif
+
 		if (status_ep) {
 			status_ep->driver_data = status_ep;	/* claim */
 		} else if (rndis) {
@@ -2422,28 +2489,26 @@
 	if (rndis)
 		device_desc.bNumConfigurations = 2;
 
-	if (gadget_is_dualspeed(gadget)) {
-		if (rndis)
-			dev_qualifier.bNumConfigurations = 2;
-		else if (!cdc)
-			dev_qualifier.bDeviceClass = USB_CLASS_VENDOR_SPEC;
-
-		/* assumes ep0 uses the same value for both speeds ... */
-		dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
-
-		/* and that all endpoints are dual-speed */
-		hs_source_desc.bEndpointAddress =
-				fs_source_desc.bEndpointAddress;
-		hs_sink_desc.bEndpointAddress =
-				fs_sink_desc.bEndpointAddress;
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
+	if (rndis)
+		dev_qualifier.bNumConfigurations = 2;
+	else if (!cdc)
+		dev_qualifier.bDeviceClass = USB_CLASS_VENDOR_SPEC;
+
+	/* assumes ep0 uses the same value for both speeds ... */
+	dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
+
+	/* and that all endpoints are dual-speed */
+	hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
+	hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
 #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-		if (status_ep)
-			hs_status_desc.bEndpointAddress =
-					fs_status_desc.bEndpointAddress;
+	if (status_ep)
+		hs_status_desc.bEndpointAddress =
+				fs_status_desc.bEndpointAddress;
 #endif
-	}
+#endif	/* DUALSPEED */
 
-	if (gadget_is_otg(gadget)) {
+	if (gadget->is_otg) {
 		otg_descriptor.bmAttributes |= USB_OTG_HNP,
 		eth_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 		eth_config.bMaxPower = 4;
@@ -2465,6 +2530,7 @@
 
 	/* network device setup */
 	dev->net = net;
+//	SET_MODULE_OWNER (net);
 	strcpy (net->name, "usb%d");
 	dev->cdc = cdc;
 	dev->zlp = zlp;
@@ -2579,11 +2645,12 @@
 		if (rndis_set_param_dev (dev->rndis_config, dev->net,
 					 &dev->stats, &dev->cdc_filter))
 			goto fail0;
-		if (rndis_set_param_vendor(dev->rndis_config, vendorID,
-					manufacturer))
+		if (rndis_set_param_vendor (dev->rndis_config, vendorID,
+					    manufacturer))
 			goto fail0;
-		if (rndis_set_param_medium(dev->rndis_config,
-					NDIS_MEDIUM_802_3, 0))
+		if (rndis_set_param_medium (dev->rndis_config,
+					    NDIS_MEDIUM_802_3,
+					    0))
 			goto fail0;
 		INFO (dev, "RNDIS ready\n");
 	}
diff -urN linux-2.6.25/drivers/usb/gadget/file_storage.c linux-2.6.25-vpac1/drivers/usb/gadget/file_storage.c
--- linux-2.6.25/drivers/usb/gadget/file_storage.c	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/usb/gadget/file_storage.c	2008-04-24 15:12:18.000000000 +0200
@@ -1,7 +1,7 @@
 /*
  * file_storage.c -- File-backed USB Storage Gadget, for USB development
  *
- * Copyright (C) 2003-2007 Alan Stern
+ * Copyright (C) 2003-2005 Alan Stern
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -217,11 +217,17 @@
  */
 
 
-/* #define VERBOSE_DEBUG */
-/* #define DUMP_MSGS */
+#undef DEBUG
+#undef VERBOSE
+#undef DUMP_MSGS
+
 
+#include <asm/system.h>
+#include <asm/uaccess.h>
 
+#include <linux/bitops.h>
 #include <linux/blkdev.h>
+#include <linux/compiler.h>
 #include <linux/completion.h>
 #include <linux/dcache.h>
 #include <linux/delay.h>
@@ -229,10 +235,18 @@
 #include <linux/fcntl.h>
 #include <linux/file.h>
 #include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/kref.h>
 #include <linux/kthread.h>
 #include <linux/limits.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pagemap.h>
 #include <linux/rwsem.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
@@ -240,7 +254,7 @@
 #include <linux/utsname.h>
 
 #include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
+#include <linux/usb_gadget.h>
 
 #include "gadget_chips.h"
 
@@ -249,7 +263,7 @@
 
 #define DRIVER_DESC		"File-backed Storage Gadget"
 #define DRIVER_NAME		"g_file_storage"
-#define DRIVER_VERSION		"7 August 2007"
+#define DRIVER_VERSION		"28 November 2005"
 
 static const char longname[] = DRIVER_DESC;
 static const char shortname[] = DRIVER_NAME;
@@ -323,8 +337,8 @@
 static struct {
 	char		*file[MAX_LUNS];
 	int		ro[MAX_LUNS];
-	unsigned int	num_filenames;
-	unsigned int	num_ros;
+	int		num_filenames;
+	int		num_ros;
 	unsigned int	nluns;
 
 	int		removable;
@@ -551,7 +565,7 @@
 
 #define backing_file_is_open(curlun)	((curlun)->filp != NULL)
 
-static struct lun *dev_to_lun(struct device *dev)
+static inline struct lun *dev_to_lun(struct device *dev)
 {
 	return container_of(dev, struct lun, dev);
 }
@@ -572,6 +586,7 @@
 
 struct fsg_buffhd {
 	void				*buf;
+	dma_addr_t			dma;
 	enum fsg_buffer_state		state;
 	struct fsg_buffhd		*next;
 
@@ -658,6 +673,7 @@
 	int			thread_wakeup_needed;
 	struct completion	thread_notifier;
 	struct task_struct	*thread_task;
+	sigset_t		thread_signal_mask;
 
 	int			cmnd_size;
 	u8			cmnd[MAX_COMMAND_SIZE];
@@ -684,13 +700,13 @@
 
 typedef void (*fsg_routine_t)(struct fsg_dev *);
 
-static int exception_in_progress(struct fsg_dev *fsg)
+static int inline exception_in_progress(struct fsg_dev *fsg)
 {
 	return (fsg->state > FSG_STATE_IDLE);
 }
 
 /* Make bulk-out requests be divisible by the maxpacket size */
-static void set_bulk_out_req_length(struct fsg_dev *fsg,
+static void inline set_bulk_out_req_length(struct fsg_dev *fsg,
 		struct fsg_buffhd *bh, unsigned int length)
 {
 	unsigned int	rem;
@@ -716,36 +732,50 @@
 static void dump_msg(struct fsg_dev *fsg, const char *label,
 		const u8 *buf, unsigned int length)
 {
-	if (length < 512) {
-		DBG(fsg, "%s, length %u:\n", label, length);
-		print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET,
-				16, 1, buf, length, 0);
+	unsigned int	start, num, i;
+	char		line[52], *p;
+
+	if (length >= 512)
+		return;
+	DBG(fsg, "%s, length %u:\n", label, length);
+
+	start = 0;
+	while (length > 0) {
+		num = min(length, 16u);
+		p = line;
+		for (i = 0; i < num; ++i) {
+			if (i == 8)
+				*p++ = ' ';
+			sprintf(p, " %02x", buf[i]);
+			p += 3;
+		}
+		*p = 0;
+		printk(KERN_DEBUG "%6x: %s\n", start, line);
+		buf += num;
+		start += num;
+		length -= num;
 	}
 }
 
-static void dump_cdb(struct fsg_dev *fsg)
+static void inline dump_cdb(struct fsg_dev *fsg)
 {}
 
 #else
 
-static void dump_msg(struct fsg_dev *fsg, const char *label,
+static void inline dump_msg(struct fsg_dev *fsg, const char *label,
 		const u8 *buf, unsigned int length)
 {}
 
-#ifdef VERBOSE_DEBUG
-
-static void dump_cdb(struct fsg_dev *fsg)
+static void inline dump_cdb(struct fsg_dev *fsg)
 {
-	print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE,
-			16, 1, fsg->cmnd, fsg->cmnd_size, 0);
-}
-
-#else
+	int	i;
+	char	cmdbuf[3*MAX_COMMAND_SIZE + 1];
 
-static void dump_cdb(struct fsg_dev *fsg)
-{}
+	for (i = 0; i < fsg->cmnd_size; ++i)
+		sprintf(cmdbuf + i*3, " %02x", fsg->cmnd[i]);
+	VDBG(fsg, "SCSI CDB: %s\n", cmdbuf);
+}
 
-#endif /* VERBOSE_DEBUG */
 #endif /* DUMP_MSGS */
 
 
@@ -768,24 +798,24 @@
 
 /* Routines for unaligned data access */
 
-static u16 get_be16(u8 *buf)
+static u16 inline get_be16(u8 *buf)
 {
 	return ((u16) buf[0] << 8) | ((u16) buf[1]);
 }
 
-static u32 get_be32(u8 *buf)
+static u32 inline get_be32(u8 *buf)
 {
 	return ((u32) buf[0] << 24) | ((u32) buf[1] << 16) |
 			((u32) buf[2] << 8) | ((u32) buf[3]);
 }
 
-static void put_be16(u8 *buf, u16 val)
+static void inline put_be16(u8 *buf, u16 val)
 {
 	buf[0] = val >> 8;
 	buf[1] = val;
 }
 
-static void put_be32(u8 *buf, u32 val)
+static void inline put_be32(u8 *buf, u32 val)
 {
 	buf[0] = val >> 24;
 	buf[1] = val >> 16;
@@ -909,6 +939,8 @@
 #define FS_FUNCTION_PRE_EP_ENTRIES	2
 
 
+#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.
@@ -971,14 +1003,14 @@
 #define HS_FUNCTION_PRE_EP_ENTRIES	2
 
 /* Maxpacket and other transfer characteristics vary by speed. */
-static struct usb_endpoint_descriptor *
-ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
-		struct usb_endpoint_descriptor *hs)
-{
-	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
-		return hs;
-	return fs;
-}
+#define ep_desc(g,fs,hs)	(((g)->speed==USB_SPEED_HIGH) ? (hs) : (fs))
+
+#else
+
+/* If there's no high speed support, always use the full-speed descriptor. */
+#define ep_desc(g,fs,hs)	fs
+
+#endif	/* !CONFIG_USB_GADGET_DUALSPEED */
 
 
 /* The CBI specification limits the serial string to 12 uppercase hexadecimal
@@ -1010,22 +1042,26 @@
 static int populate_config_buf(struct usb_gadget *gadget,
 		u8 *buf, u8 type, unsigned index)
 {
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 	enum usb_device_speed			speed = gadget->speed;
+#endif
 	int					len;
 	const struct usb_descriptor_header	**function;
 
 	if (index > 0)
 		return -EINVAL;
 
-	if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG)
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	if (type == USB_DT_OTHER_SPEED_CONFIG)
 		speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed;
-	if (gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH)
+	if (speed == USB_SPEED_HIGH)
 		function = hs_function;
 	else
+#endif
 		function = fs_function;
 
 	/* for now, don't advertise srp-only devices */
-	if (!gadget_is_otg(gadget))
+	if (!gadget->is_otg)
 		function++;
 
 	len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);
@@ -1247,7 +1283,6 @@
 	struct usb_request	*req = fsg->ep0req;
 	int			value = -EOPNOTSUPP;
 	u16			w_index = le16_to_cpu(ctrl->wIndex);
-	u16                     w_value = le16_to_cpu(ctrl->wValue);
 	u16			w_length = le16_to_cpu(ctrl->wLength);
 
 	if (!fsg->config)
@@ -1261,7 +1296,7 @@
 			if (ctrl->bRequestType != (USB_DIR_OUT |
 					USB_TYPE_CLASS | USB_RECIP_INTERFACE))
 				break;
-			if (w_index != 0 || w_value != 0) {
+			if (w_index != 0) {
 				value = -EDOM;
 				break;
 			}
@@ -1277,7 +1312,7 @@
 			if (ctrl->bRequestType != (USB_DIR_IN |
 					USB_TYPE_CLASS | USB_RECIP_INTERFACE))
 				break;
-			if (w_index != 0 || w_value != 0) {
+			if (w_index != 0) {
 				value = -EDOM;
 				break;
 			}
@@ -1296,7 +1331,7 @@
 			if (ctrl->bRequestType != (USB_DIR_OUT |
 					USB_TYPE_CLASS | USB_RECIP_INTERFACE))
 				break;
-			if (w_index != 0 || w_value != 0) {
+			if (w_index != 0) {
 				value = -EDOM;
 				break;
 			}
@@ -1347,9 +1382,10 @@
 			value = sizeof device_desc;
 			memcpy(req->buf, &device_desc, value);
 			break;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 		case USB_DT_DEVICE_QUALIFIER:
 			VDBG(fsg, "get device qualifier\n");
-			if (!gadget_is_dualspeed(fsg->gadget))
+			if (!fsg->gadget->is_dualspeed)
 				break;
 			value = sizeof dev_qualifier;
 			memcpy(req->buf, &dev_qualifier, value);
@@ -1357,12 +1393,15 @@
 
 		case USB_DT_OTHER_SPEED_CONFIG:
 			VDBG(fsg, "get other-speed config descriptor\n");
-			if (!gadget_is_dualspeed(fsg->gadget))
+			if (!fsg->gadget->is_dualspeed)
 				break;
 			goto get_config;
+#endif
 		case USB_DT_CONFIG:
 			VDBG(fsg, "get configuration descriptor\n");
-get_config:
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+		get_config:
+#endif
 			value = populate_config_buf(fsg->gadget,
 					req->buf,
 					w_value >> 8,
@@ -1595,8 +1634,7 @@
 		/* Wait for the next buffer to become available */
 		bh = fsg->next_buffhd_to_fill;
 		while (bh->state != BUF_STATE_EMPTY) {
-			rc = sleep_thread(fsg);
-			if (rc)
+			if ((rc = sleep_thread(fsg)) != 0)
 				return rc;
 		}
 
@@ -1835,8 +1873,7 @@
 		}
 
 		/* Wait for something to happen */
-		rc = sleep_thread(fsg);
-		if (rc)
+		if ((rc = sleep_thread(fsg)) != 0)
 			return rc;
 	}
 
@@ -2320,8 +2357,7 @@
 
 		/* Wait for the next buffer to be free */
 		while (bh->state != BUF_STATE_EMPTY) {
-			rc = sleep_thread(fsg);
-			if (rc)
+			if ((rc = sleep_thread(fsg)) != 0)
 				return rc;
 		}
 
@@ -2381,8 +2417,7 @@
 		}
 
 		/* Otherwise wait for something to happen */
-		rc = sleep_thread(fsg);
-		if (rc)
+		if ((rc = sleep_thread(fsg)) != 0)
 			return rc;
 	}
 	return 0;
@@ -2504,8 +2539,7 @@
 	/* Wait for the next buffer to become available */
 	bh = fsg->next_buffhd_to_fill;
 	while (bh->state != BUF_STATE_EMPTY) {
-		rc = sleep_thread(fsg);
-		if (rc)
+		if ((rc = sleep_thread(fsg)) != 0)
 			return rc;
 	}
 
@@ -2565,6 +2599,7 @@
 
 		fsg->intr_buffhd = bh;		// Point to the right buffhd
 		fsg->intreq->buf = bh->inreq->buf;
+		fsg->intreq->dma = bh->inreq->dma;
 		fsg->intreq->context = bh;
 		start_transfer(fsg, fsg->intr_in, fsg->intreq,
 				&fsg->intreq_busy, &bh->state);
@@ -2725,10 +2760,9 @@
 	/* Wait for the next buffer to become available for data or status */
 	bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill;
 	while (bh->state != BUF_STATE_EMPTY) {
-		rc = sleep_thread(fsg);
-		if (rc)
+		if ((rc = sleep_thread(fsg)) != 0)
 			return rc;
-	}
+		}
 	fsg->phase_error = 0;
 	fsg->short_packet_received = 0;
 
@@ -2960,7 +2994,7 @@
 
 	/* Is the CBW meaningful? */
 	if (cbw->Lun >= MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG ||
-			cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
+			cbw->Length < 6 || cbw->Length > MAX_COMMAND_SIZE) {
 		DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
 				"cmdlen %u\n",
 				cbw->Lun, cbw->Flags, cbw->Length);
@@ -3000,10 +3034,9 @@
 		/* Wait for the next buffer to become available */
 		bh = fsg->next_buffhd_to_fill;
 		while (bh->state != BUF_STATE_EMPTY) {
-			rc = sleep_thread(fsg);
-			if (rc)
+			if ((rc = sleep_thread(fsg)) != 0)
 				return rc;
-		}
+			}
 
 		/* Queue a request to read a Bulk-only CBW */
 		set_bulk_out_req_length(fsg, bh, USB_BULK_CB_WRAP_LEN);
@@ -3017,10 +3050,9 @@
 
 		/* Wait for the CBW to arrive */
 		while (bh->state != BUF_STATE_FULL) {
-			rc = sleep_thread(fsg);
-			if (rc)
+			if ((rc = sleep_thread(fsg)) != 0)
 				return rc;
-		}
+			}
 		smp_rmb();
 		rc = received_cbw(fsg, bh);
 		bh->state = BUF_STATE_EMPTY;
@@ -3029,10 +3061,9 @@
 
 		/* Wait for the next command to arrive */
 		while (fsg->cbbuf_cmnd_size == 0) {
-			rc = sleep_thread(fsg);
-			if (rc)
+			if ((rc = sleep_thread(fsg)) != 0)
 				return rc;
-		}
+			}
 
 		/* Is the previous status interrupt request still busy?
 		 * The host is allowed to skip reading the status,
@@ -3157,6 +3188,7 @@
 		if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0)
 			goto reset;
 		bh->inreq->buf = bh->outreq->buf = bh->buf;
+		bh->inreq->dma = bh->outreq->dma = bh->dma;
 		bh->inreq->context = bh->outreq->context = bh;
 		bh->inreq->complete = bulk_in_complete;
 		bh->outreq->complete = bulk_out_complete;
@@ -3232,7 +3264,8 @@
 	/* Clear the existing signals.  Anything but SIGUSR1 is converted
 	 * into a high-priority EXIT exception. */
 	for (;;) {
-		sig = dequeue_signal_lock(current, &current->blocked, &info);
+		sig = dequeue_signal_lock(current, &fsg->thread_signal_mask,
+				&info);
 		if (!sig)
 			break;
 		if (sig != SIGUSR1) {
@@ -3385,13 +3418,10 @@
 
 	/* Allow the thread to be killed by a signal, but set the signal mask
 	 * to block everything but INT, TERM, KILL, and USR1. */
-	allow_signal(SIGINT);
-	allow_signal(SIGTERM);
-	allow_signal(SIGKILL);
-	allow_signal(SIGUSR1);
-
-	/* Allow the thread to be frozen */
-	set_freezable();
+	siginitsetinv(&fsg->thread_signal_mask, sigmask(SIGINT) |
+			sigmask(SIGTERM) | sigmask(SIGKILL) |
+			sigmask(SIGUSR1));
+	sigprocmask(SIG_SETMASK, &fsg->thread_signal_mask, NULL);
 
 	/* Arrange for userspace references to be interpreted as kernel
 	 * pointers.  That way we can pass a kernel pointer to a routine
@@ -3553,8 +3583,7 @@
 	return sprintf(buf, "%d\n", curlun->ro);
 }
 
-static ssize_t show_file(struct device *dev, struct device_attribute *attr,
-		char *buf)
+static ssize_t show_file(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lun	*curlun = dev_to_lun(dev);
 	struct fsg_dev	*fsg = dev_get_drvdata(dev);
@@ -3581,8 +3610,7 @@
 }
 
 
-static ssize_t store_ro(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
+static ssize_t store_ro(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	ssize_t		rc = count;
 	struct lun	*curlun = dev_to_lun(dev);
@@ -3606,8 +3634,7 @@
 	return rc;
 }
 
-static ssize_t store_file(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
+static ssize_t store_file(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct lun	*curlun = dev_to_lun(dev);
 	struct fsg_dev	*fsg = dev_get_drvdata(dev);
@@ -3694,12 +3721,19 @@
 	}
 
 	/* Free the data buffers */
-	for (i = 0; i < NUM_BUFFERS; ++i)
-		kfree(fsg->buffhds[i].buf);
+	for (i = 0; i < NUM_BUFFERS; ++i) {
+		struct fsg_buffhd	*bh = &fsg->buffhds[i];
+
+		if (bh->buf)
+			usb_ep_free_buffer(fsg->bulk_in, bh->buf, bh->dma,
+					mod_data.buflen);
+	}
 
 	/* Free the request and buffer for endpoint 0 */
 	if (req) {
-		kfree(req->buf);
+		if (req->buf)
+			usb_ep_free_buffer(fsg->ep0, req->buf,
+					req->dma, EP0_BUFSIZE);
 		usb_ep_free_request(fsg->ep0, req);
 	}
 
@@ -3801,6 +3835,7 @@
 	struct usb_ep		*ep;
 	struct usb_request	*req;
 	char			*pathbuf, *p;
+	struct usb_endpoint_config ep_config;
 
 	fsg->gadget = gadget;
 	set_gadget_data(gadget, fsg);
@@ -3819,7 +3854,7 @@
 	/* Find out how many LUNs there should be */
 	i = mod_data.nluns;
 	if (i == 0)
-		i = max(mod_data.num_filenames, 1u);
+		i = max(mod_data.num_filenames, 1);
 	if (i > MAX_LUNS) {
 		ERROR(fsg, "invalid number of LUNs: %d\n", i);
 		rc = -EINVAL;
@@ -3871,21 +3906,25 @@
 	}
 
 	/* Find all the endpoints we will use */
+	ep_config.config = CONFIG_VALUE;
+	ep_config.interface = intf_desc.bInterfaceNumber;
+	ep_config.altinterface = intf_desc.bAlternateSetting;
+
 	usb_ep_autoconfig_reset(gadget);
-	ep = usb_ep_autoconfig(gadget, &fs_bulk_in_desc);
+	ep = usb_ep_autoconfig(gadget, &fs_bulk_in_desc, &ep_config, 1);
 	if (!ep)
 		goto autoconf_fail;
 	ep->driver_data = fsg;		// claim the endpoint
 	fsg->bulk_in = ep;
 
-	ep = usb_ep_autoconfig(gadget, &fs_bulk_out_desc);
+	ep = usb_ep_autoconfig(gadget, &fs_bulk_out_desc, &ep_config, 1);
 	if (!ep)
 		goto autoconf_fail;
 	ep->driver_data = fsg;		// claim the endpoint
 	fsg->bulk_out = ep;
 
 	if (transport_is_cbi()) {
-		ep = usb_ep_autoconfig(gadget, &fs_intr_in_desc);
+		ep = usb_ep_autoconfig(gadget, &fs_intr_in_desc, &ep_config, 1);
 		if (!ep)
 			goto autoconf_fail;
 		ep->driver_data = fsg;		// claim the endpoint
@@ -3904,23 +3943,22 @@
 	intf_desc.bInterfaceProtocol = mod_data.transport_type;
 	fs_function[i + FS_FUNCTION_PRE_EP_ENTRIES] = NULL;
 
-	if (gadget_is_dualspeed(gadget)) {
-		hs_function[i + HS_FUNCTION_PRE_EP_ENTRIES] = NULL;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	hs_function[i + HS_FUNCTION_PRE_EP_ENTRIES] = NULL;
 
-		/* Assume ep0 uses the same maxpacket value for both speeds */
-		dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
+	/* Assume ep0 uses the same maxpacket value for both speeds */
+	dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
 
-		/* Assume endpoint addresses are the same for both speeds */
-		hs_bulk_in_desc.bEndpointAddress =
-				fs_bulk_in_desc.bEndpointAddress;
-		hs_bulk_out_desc.bEndpointAddress =
-				fs_bulk_out_desc.bEndpointAddress;
-		hs_intr_in_desc.bEndpointAddress =
-				fs_intr_in_desc.bEndpointAddress;
-	}
+	/* Assume that all endpoint addresses are the same for both speeds */
+	hs_bulk_in_desc.bEndpointAddress = fs_bulk_in_desc.bEndpointAddress;
+	hs_bulk_out_desc.bEndpointAddress = fs_bulk_out_desc.bEndpointAddress;
+	hs_intr_in_desc.bEndpointAddress = fs_intr_in_desc.bEndpointAddress;
+#endif
 
-	if (gadget_is_otg(gadget))
-		otg_desc.bmAttributes |= USB_OTG_HNP;
+	if (gadget->is_otg) {
+		otg_desc.bmAttributes |= USB_OTG_HNP,
+		config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	}
 
 	rc = -ENOMEM;
 
@@ -3928,7 +3966,8 @@
 	fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL);
 	if (!req)
 		goto out;
-	req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL);
+	req->buf = usb_ep_alloc_buffer(fsg->ep0, EP0_BUFSIZE,
+			&req->dma, GFP_KERNEL);
 	if (!req->buf)
 		goto out;
 	req->complete = ep0_complete;
@@ -3940,7 +3979,8 @@
 		/* Allocate for the bulk-in endpoint.  We assume that
 		 * the buffer will also work with the bulk-out (and
 		 * interrupt-in) endpoint. */
-		bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL);
+		bh->buf = usb_ep_alloc_buffer(fsg->bulk_in, mod_data.buflen,
+				&bh->dma, GFP_KERNEL);
 		if (!bh->buf)
 			goto out;
 		bh->next = bh + 1;
@@ -4000,7 +4040,7 @@
 	DBG(fsg, "removable=%d, stall=%d, buflen=%u\n",
 			mod_data.removable, mod_data.can_stall,
 			mod_data.buflen);
-	DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task));
+	DBG(fsg, "I/O thread pid: %d\n", fsg->thread_task->pid);
 
 	set_bit(REGISTERED, &fsg->atomic_bitflags);
 
diff -urN linux-2.6.25/drivers/usb/gadget/gadget_chips.h linux-2.6.25-vpac1/drivers/usb/gadget/gadget_chips.h
--- linux-2.6.25/drivers/usb/gadget/gadget_chips.h	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/usb/gadget/gadget_chips.h	2008-04-24 15:12:18.000000000 +0200
@@ -8,8 +8,6 @@
  * (And avoiding all runtime comparisons in typical one-choice configs!)
  *
  * NOTE:  some of these controller drivers may not be available yet.
- * Some are available on 2.4 kernels; several are available, but not
- * yet pushed in the 2.6 mainline tree.
  */
 #ifdef CONFIG_USB_GADGET_NET2280
 #define	gadget_is_net2280(g)	!strcmp("net2280", (g)->name)
@@ -17,12 +15,6 @@
 #define	gadget_is_net2280(g)	0
 #endif
 
-#ifdef CONFIG_USB_GADGET_AMD5536UDC
-#define	gadget_is_amd5536udc(g)	!strcmp("amd5536udc", (g)->name)
-#else
-#define	gadget_is_amd5536udc(g)	0
-#endif
-
 #ifdef CONFIG_USB_GADGET_DUMMY_HCD
 #define	gadget_is_dummy(g)	!strcmp("dummy_udc", (g)->name)
 #else
@@ -32,7 +24,11 @@
 #ifdef CONFIG_USB_GADGET_PXA2XX
 #define	gadget_is_pxa(g)	!strcmp("pxa2xx_udc", (g)->name)
 #else
-#define	gadget_is_pxa(g)	0
+#    ifdef CONFIG_USB_GADGET_PXA27X
+#        define	gadget_is_pxa(g)	!strcmp("pxa27x_udc", (g)->name)
+#    else
+#        define	gadget_is_pxa(g)	0
+#    endif
 #endif
 
 #ifdef CONFIG_USB_GADGET_GOKU
@@ -41,14 +37,12 @@
 #define	gadget_is_goku(g)	0
 #endif
 
-/* SH3 UDC -- not yet ported 2.4 --> 2.6 */
 #ifdef CONFIG_USB_GADGET_SUPERH
 #define	gadget_is_sh(g)		!strcmp("sh_udc", (g)->name)
 #else
 #define	gadget_is_sh(g)		0
 #endif
 
-/* not yet stable on 2.6 (would help "original Zaurus") */
 #ifdef CONFIG_USB_GADGET_SA1100
 #define	gadget_is_sa1100(g)	!strcmp("sa1100_udc", (g)->name)
 #else
@@ -61,7 +55,6 @@
 #define	gadget_is_lh7a40x(g)	0
 #endif
 
-/* handhelds.org tree (?) */
 #ifdef CONFIG_USB_GADGET_MQ11XX
 #define	gadget_is_mq11xx(g)	!strcmp("mq11xx_udc", (g)->name)
 #else
@@ -74,24 +67,22 @@
 #define	gadget_is_omap(g)	0
 #endif
 
-/* not yet ported 2.4 --> 2.6 */
 #ifdef CONFIG_USB_GADGET_N9604
 #define	gadget_is_n9604(g)	!strcmp("n9604_udc", (g)->name)
 #else
 #define	gadget_is_n9604(g)	0
 #endif
 
-/* various unstable versions available */
 #ifdef CONFIG_USB_GADGET_PXA27X
 #define	gadget_is_pxa27x(g)	!strcmp("pxa27x_udc", (g)->name)
 #else
 #define	gadget_is_pxa27x(g)	0
 #endif
 
-#ifdef CONFIG_USB_GADGET_ATMEL_USBA
-#define gadget_is_atmel_usba(g)	!strcmp("atmel_usba_udc", (g)->name)
+#ifdef CONFIG_USB_GADGET_HUSB2DEV
+#define gadget_is_husb2dev(g)	!strcmp("husb2_udc", (g)->name)
 #else
-#define gadget_is_atmel_usba(g)	0
+#define gadget_is_husb2dev(g)	0
 #endif
 
 #ifdef CONFIG_USB_GADGET_S3C2410
@@ -106,21 +97,13 @@
 #define gadget_is_at91(g)	0
 #endif
 
-/* status unclear */
 #ifdef CONFIG_USB_GADGET_IMX
 #define gadget_is_imx(g)	!strcmp("imx_udc", (g)->name)
 #else
 #define gadget_is_imx(g)	0
 #endif
 
-#ifdef CONFIG_USB_GADGET_FSL_USB2
-#define gadget_is_fsl_usb2(g)	!strcmp("fsl-usb2-udc", (g)->name)
-#else
-#define gadget_is_fsl_usb2(g)	0
-#endif
-
 /* Mentor high speed function controller */
-/* from Montavista kernel (?) */
 #ifdef CONFIG_USB_GADGET_MUSBHSFC
 #define gadget_is_musbhsfc(g)	!strcmp("musbhsfc_udc", (g)->name)
 #else
@@ -134,20 +117,12 @@
 #define gadget_is_musbhdrc(g)	0
 #endif
 
-/* from Montavista kernel (?) */
 #ifdef CONFIG_USB_GADGET_MPC8272
 #define gadget_is_mpc8272(g)	!strcmp("mpc8272_udc", (g)->name)
 #else
 #define gadget_is_mpc8272(g)	0
 #endif
 
-#ifdef CONFIG_USB_GADGET_M66592
-#define	gadget_is_m66592(g)	!strcmp("m66592_udc", (g)->name)
-#else
-#define	gadget_is_m66592(g)	0
-#endif
-
-
 // CONFIG_USB_GADGET_SX2
 // CONFIG_USB_GADGET_AU1X00
 // ...
@@ -204,13 +179,7 @@
 		return 0x16;
 	else if (gadget_is_mpc8272(gadget))
 		return 0x17;
-	else if (gadget_is_atmel_usba(gadget))
+	else if (gadget_is_husb2dev(gadget))
 		return 0x18;
-	else if (gadget_is_fsl_usb2(gadget))
-		return 0x19;
-	else if (gadget_is_amd5536udc(gadget))
-		return 0x20;
-	else if (gadget_is_m66592(gadget))
-		return 0x21;
 	return -ENOENT;
 }
diff -urN linux-2.6.25/drivers/usb/gadget/gmidi.c linux-2.6.25-vpac1/drivers/usb/gadget/gmidi.c
--- linux-2.6.25/drivers/usb/gadget/gmidi.c	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/usb/gadget/gmidi.c	2008-04-24 15:12:18.000000000 +0200
@@ -18,18 +18,24 @@
  * http://www.usb.org/developers/devclass_docs/midi10.pdf
  */
 
-/* #define VERBOSE_DEBUG */
+#define DEBUG 1
+// #define VERBOSE
 
+#include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
 #include <linux/utsname.h>
 #include <linux/device.h>
+#include <linux/moduleparam.h>
 
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <sound/rawmidi.h>
 
 #include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
+#include <linux/usb_gadget.h>
 #include <linux/usb/audio.h>
 #include <linux/usb/midi.h>
 
@@ -132,16 +138,30 @@
 static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req);
 
 
-#define DBG(d, fmt, args...) \
-	dev_dbg(&(d)->gadget->dev , fmt , ## args)
-#define VDBG(d, fmt, args...) \
-	dev_vdbg(&(d)->gadget->dev , fmt , ## args)
-#define ERROR(d, fmt, args...) \
-	dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARN(d, fmt, args...) \
-	dev_warn(&(d)->gadget->dev , fmt , ## args)
-#define INFO(d, fmt, args...) \
-	dev_info(&(d)->gadget->dev , fmt , ## args)
+#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 = 256;
@@ -404,7 +424,7 @@
 	return len;
 }
 
-static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
+static struct usb_request* alloc_ep_req(struct usb_ep *ep, unsigned length)
 {
 	struct usb_request	*req;
 
@@ -434,7 +454,7 @@
  * Receives a chunk of MIDI data.
  */
 static void gmidi_read_data(struct usb_ep *ep, int cable,
-				   uint8_t *data, int length)
+				   uint8_t* data, int length)
 {
 	struct gmidi_device *dev = ep->driver_data;
 	/* cable is ignored, because for now we only have one. */
@@ -520,7 +540,7 @@
 {
 	int err = 0;
 	struct usb_request *req;
-	struct usb_ep *ep;
+	struct usb_ep* ep;
 	unsigned i;
 
 	err = usb_ep_enable(dev->in_ep, &bulk_in_desc);
@@ -607,7 +627,7 @@
 
 	if (gadget_is_sa1100(gadget) && dev->config) {
 		/* tx fifo is full, but we can't clear it...*/
-		ERROR(dev, "can't change configurations\n");
+		INFO(dev, "can't change configurations\n");
 		return -ESPIPE;
 	}
 	gmidi_reset_config(dev);
@@ -822,7 +842,7 @@
 static void /* __init_or_exit */ gmidi_unbind(struct usb_gadget *gadget)
 {
 	struct gmidi_device *dev = get_gadget_data(gadget);
-	struct snd_card *card;
+	struct snd_card* card;
 
 	DBG(dev, "unbind\n");
 
@@ -846,12 +866,12 @@
 	return 0;
 }
 
-static void gmidi_transmit_packet(struct usb_request *req, uint8_t p0,
+static void gmidi_transmit_packet(struct usb_request* req, uint8_t p0,
 					uint8_t p1, uint8_t p2, uint8_t p3)
 {
 	unsigned length = req->length;
-	u8 *buf = (u8 *)req->buf + length;
 
+	uint8_t* buf = (uint8_t*)req->buf + length;
 	buf[0] = p0;
 	buf[1] = p1;
 	buf[2] = p2;
@@ -862,8 +882,8 @@
 /*
  * Converts MIDI commands to USB MIDI packets.
  */
-static void gmidi_transmit_byte(struct usb_request *req,
-				struct gmidi_in_port *port, uint8_t b)
+static void gmidi_transmit_byte(struct usb_request* req,
+				struct gmidi_in_port* port, uint8_t b)
 {
 	uint8_t p0 = port->cable;
 
@@ -960,10 +980,10 @@
 	}
 }
 
-static void gmidi_transmit(struct gmidi_device *dev, struct usb_request *req)
+static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req)
 {
-	struct usb_ep *ep = dev->in_ep;
-	struct gmidi_in_port *port = &dev->in_port;
+	struct usb_ep* ep = dev->in_ep;
+	struct gmidi_in_port* port = &dev->in_port;
 
 	if (!ep) {
 		return;
@@ -999,14 +1019,14 @@
 
 static void gmidi_in_tasklet(unsigned long data)
 {
-	struct gmidi_device *dev = (struct gmidi_device *)data;
+	struct gmidi_device* dev = (struct gmidi_device*)data;
 
 	gmidi_transmit(dev, NULL);
 }
 
 static int gmidi_in_open(struct snd_rawmidi_substream *substream)
 {
-	struct gmidi_device *dev = substream->rmidi->private_data;
+	struct gmidi_device* dev = substream->rmidi->private_data;
 
 	VDBG(dev, "gmidi_in_open\n");
 	dev->in_substream = substream;
@@ -1016,15 +1036,13 @@
 
 static int gmidi_in_close(struct snd_rawmidi_substream *substream)
 {
-	struct gmidi_device *dev = substream->rmidi->private_data;
-
 	VDBG(dev, "gmidi_in_close\n");
 	return 0;
 }
 
 static void gmidi_in_trigger(struct snd_rawmidi_substream *substream, int up)
 {
-	struct gmidi_device *dev = substream->rmidi->private_data;
+	struct gmidi_device* dev = substream->rmidi->private_data;
 
 	VDBG(dev, "gmidi_in_trigger %d\n", up);
 	dev->in_port.active = up;
@@ -1035,7 +1053,7 @@
 
 static int gmidi_out_open(struct snd_rawmidi_substream *substream)
 {
-	struct gmidi_device *dev = substream->rmidi->private_data;
+	struct gmidi_device* dev = substream->rmidi->private_data;
 
 	VDBG(dev, "gmidi_out_open\n");
 	dev->out_substream = substream;
@@ -1044,15 +1062,13 @@
 
 static int gmidi_out_close(struct snd_rawmidi_substream *substream)
 {
-	struct gmidi_device *dev = substream->rmidi->private_data;
-
 	VDBG(dev, "gmidi_out_close\n");
 	return 0;
 }
 
 static void gmidi_out_trigger(struct snd_rawmidi_substream *substream, int up)
 {
-	struct gmidi_device *dev = substream->rmidi->private_data;
+	struct gmidi_device* dev = substream->rmidi->private_data;
 
 	VDBG(dev, "gmidi_out_trigger %d\n", up);
 	if (up) {
@@ -1231,11 +1247,17 @@
 	tasklet_init(&dev->tasklet, gmidi_in_tasklet, (unsigned long)dev);
 
 	/* preallocate control response and buffer */
-	dev->req = alloc_ep_req(gadget->ep0, USB_BUFSIZ);
+	dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
 	if (!dev->req) {
 		err = -ENOMEM;
 		goto fail;
 	}
+	dev->req->buf = usb_ep_alloc_buffer(gadget->ep0, USB_BUFSIZ,
+				&dev->req->dma, GFP_KERNEL);
+	if (!dev->req->buf) {
+		err = -ENOMEM;
+		goto fail;
+	}
 
 	dev->req->complete = gmidi_setup_complete;
 
diff -urN linux-2.6.25/drivers/usb/gadget/inode.c linux-2.6.25-vpac1/drivers/usb/gadget/inode.c
--- linux-2.6.25/drivers/usb/gadget/inode.c	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/usb/gadget/inode.c	2008-04-24 15:12:18.000000000 +0200
@@ -20,7 +20,8 @@
  */
 
 
-/* #define VERBOSE_DEBUG */
+// #define	DEBUG			/* data to help fault diagnosis */
+// #define	VERBOSE		/* extra debug messages (success too) */
 
 #include <linux/init.h>
 #include <linux/module.h>
@@ -36,8 +37,8 @@
 #include <linux/device.h>
 #include <linux/moduleparam.h>
 
-#include <linux/usb/gadgetfs.h>
-#include <linux/usb/gadget.h>
+#include <linux/usb_gadgetfs.h>
+#include <linux/usb_gadget.h>
 
 
 /*
@@ -252,7 +253,7 @@
 	do { } while (0)
 #endif /* DEBUG */
 
-#ifdef VERBOSE_DEBUG
+#ifdef VERBOSE
 #define VDEBUG	DBG
 #else
 #define VDEBUG(dev,fmt,args...) \
@@ -922,7 +923,7 @@
 	struct dev_data		*dev = ep->driver_data;
 
 	if (req->buf != dev->rbuf) {
-		kfree(req->buf);
+		usb_ep_free_buffer (ep, req->buf, req->dma, req->length);
 		req->buf = dev->rbuf;
 		req->dma = DMA_ADDR_INVALID;
 	}
@@ -962,8 +963,8 @@
 		return -EBUSY;
 	}
 	if (len > sizeof (dev->rbuf))
-		req->buf = kmalloc(len, GFP_ATOMIC);
-	if (req->buf == NULL) {
+		req->buf = usb_ep_alloc_buffer (ep, len, &req->dma, GFP_ATOMIC);
+	if (req->buf == 0) {
 		req->buf = dev->rbuf;
 		return -ENOMEM;
 	}
@@ -1009,12 +1010,11 @@
 			/* assume that was SET_CONFIGURATION */
 			if (dev->current_config) {
 				unsigned power;
-
-				if (gadget_is_dualspeed(dev->gadget)
-						&& (dev->gadget->speed
-							== USB_SPEED_HIGH))
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
+				if (dev->gadget->speed == USB_SPEED_HIGH)
 					power = dev->hs_config->bMaxPower;
 				else
+#endif
 					power = dev->config->bMaxPower;
 				usb_gadget_vbus_draw(dev->gadget, 2 * power);
 			}
@@ -1355,23 +1355,26 @@
 config_buf (struct dev_data *dev, u8 type, unsigned index)
 {
 	int		len;
-	int		hs = 0;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	int		hs;
+#endif
 
 	/* only one configuration */
 	if (index > 0)
 		return -EINVAL;
 
-	if (gadget_is_dualspeed(dev->gadget)) {
-		hs = (dev->gadget->speed == USB_SPEED_HIGH);
-		if (type == USB_DT_OTHER_SPEED_CONFIG)
-			hs = !hs;
-	}
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	hs = (dev->gadget->speed == USB_SPEED_HIGH);
+	if (type == USB_DT_OTHER_SPEED_CONFIG)
+		hs = !hs;
 	if (hs) {
 		dev->req->buf = dev->hs_config;
-		len = le16_to_cpu(dev->hs_config->wTotalLength);
-	} else {
+		len = le16_to_cpup (&dev->hs_config->wTotalLength);
+	} else
+#endif
+	{
 		dev->req->buf = dev->config;
-		len = le16_to_cpu(dev->config->wTotalLength);
+		len = le16_to_cpup (&dev->config->wTotalLength);
 	}
 	((u8 *)dev->req->buf) [1] = type;
 	return len;
@@ -1390,13 +1393,13 @@
 	spin_lock (&dev->lock);
 	dev->setup_abort = 0;
 	if (dev->state == STATE_DEV_UNCONNECTED) {
-		if (gadget_is_dualspeed(gadget)
-				&& gadget->speed == USB_SPEED_HIGH
-				&& dev->hs_config == NULL) {
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
+		if (gadget->speed == USB_SPEED_HIGH && dev->hs_config == 0) {
 			spin_unlock(&dev->lock);
 			ERROR (dev, "no high speed config??\n");
 			return -EINVAL;
 		}
+#endif	/* CONFIG_USB_GADGET_DUALSPEED */
 
 		dev->state = STATE_DEV_CONNECTED;
 		dev->dev->bMaxPacketSize0 = gadget->ep0->maxpacket;
@@ -1466,12 +1469,13 @@
 			// user mode expected to disable endpoints
 		} else {
 			u8	config, power;
-
-			if (gadget_is_dualspeed(gadget)
-					&& gadget->speed == USB_SPEED_HIGH) {
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
+			if (gadget->speed == USB_SPEED_HIGH) {
 				config = dev->hs_config->bConfigurationValue;
 				power = dev->hs_config->bMaxPower;
-			} else {
+			} else
+#endif
+			{
 				config = dev->config->bConfigurationValue;
 				power = dev->config->bMaxPower;
 			}
@@ -1501,7 +1505,7 @@
 		}
 		break;
 
-#ifndef	CONFIG_USB_GADGET_PXA2XX
+#ifndef	CONFIG_USB_GADGETFS_PXA2XX
 	/* PXA automagically handles this request too */
 	case USB_REQ_GET_CONFIGURATION:
 		if (ctrl->bRequestType != 0x80)
@@ -1881,7 +1885,7 @@
 
 	/* full or low speed config */
 	dev->config = (void *) kbuf;
-	total = le16_to_cpu(dev->config->wTotalLength);
+	total = le16_to_cpup (&dev->config->wTotalLength);
 	if (!is_valid_config (dev->config) || total >= length)
 		goto fail;
 	kbuf += total;
@@ -1890,7 +1894,7 @@
 	/* optional high speed config */
 	if (kbuf [1] == USB_DT_CONFIG) {
 		dev->hs_config = (void *) kbuf;
-		total = le16_to_cpu(dev->hs_config->wTotalLength);
+		total = le16_to_cpup (&dev->hs_config->wTotalLength);
 		if (!is_valid_config (dev->hs_config) || total >= length)
 			goto fail;
 		kbuf += total;
diff -urN linux-2.6.25/drivers/usb/gadget/Kconfig linux-2.6.25-vpac1/drivers/usb/gadget/Kconfig
--- linux-2.6.25/drivers/usb/gadget/Kconfig	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/usb/gadget/Kconfig	2008-05-04 13:22:49.000000000 +0200
@@ -197,11 +197,48 @@
 # don't waste memory for the other endpoints
 config USB_PXA2XX_SMALL
 	depends on USB_GADGET_PXA2XX
-	bool
+	bool "Handle only three endpoints (driver smaller by 1K)"
 	default n if USB_ETH_RNDIS
 	default y if USB_ZERO
 	default y if USB_ETH
 	default y if USB_G_SERIAL
+	help
+	   Use this option if you're really really short on memory
+	   and your gadget driver needs only one IN and one OUT bulk
+	   endpoints. This is enough for most simple gadgets (gadget
+	   zero, serial, ethernet and such).
+
+config USB_GADGET_PXA27X
+	boolean "PXA 27x"
+	depends on ARCH_PXA && PXA27x
+	help
+	   Intel's PXA 27x series XScale ARM-5TE processors include
+	   an integrated full speed USB 1.1 device controller.  
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "pxa27x_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_PXA27X
+	tristate
+	depends on USB_GADGET_PXA27X
+	default USB_GADGET
+	select USB_GADGET_SELECTED
+
+config USB_PXA27X_DMA
+	bool # "Use DMA support"
+	depends on USB_GADGET_PXA27X
+	default n
+
+config USB_PXA2XX_GPIO
+	boolean "Use GPIOs to control pxa2xx_udc driver"
+	depends on (USB_GADGET_PXA2XX || USB_GADGET_PXA27X)
+	help
+	    pxa2xx_udc requires machine-specific methods to handle
+	    connection detection and pull up control. Many machines
+	    use GPIOs for these. This driver allows to just specify
+	    these GPIOs, without writing duplicate functions to 
+	    get/set these GPIOs.
 
 config USB_GADGET_M66592
 	boolean "Renesas M66592 USB Peripheral Controller"
@@ -485,6 +522,8 @@
 	   XP, you'll need to download drivers from Microsoft's website; a URL
 	   is given in comments found in that info file.
 
+	   This breaks ETH support on PXA hosts.
+
 config USB_GADGETFS
 	tristate "Gadget Filesystem (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
@@ -549,6 +588,11 @@
 	  Say "y" to link the driver statically, or "m" to build a
 	  dynamically linked module called "g_midi".
 
+config USB_G_CHAR
+	tristate "Character Gadget"
+	help
+	  Character Gadget is what usb-char used to be. Have fun.
+
 config USB_G_PRINTER
 	tristate "Printer Gadget"
 	help
diff -urN linux-2.6.25/drivers/usb/gadget/Makefile linux-2.6.25-vpac1/drivers/usb/gadget/Makefile
--- linux-2.6.25/drivers/usb/gadget/Makefile	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/usb/gadget/Makefile	2008-04-24 15:12:18.000000000 +0200
@@ -13,6 +13,7 @@
 obj-$(CONFIG_USB_OMAP)		+= omap_udc.o
 obj-$(CONFIG_USB_LH7A40X)	+= lh7a40x_udc.o
 obj-$(CONFIG_USB_S3C2410)	+= s3c2410_udc.o
+obj-$(CONFIG_USB_PXA27X)	+= pxa27x_udc.o
 obj-$(CONFIG_USB_AT91)		+= at91_udc.o
 obj-$(CONFIG_USB_ATMEL_USBA)	+= atmel_usba_udc.o
 obj-$(CONFIG_USB_FSL_USB2)	+= fsl_usb2_udc.o
@@ -30,6 +31,7 @@
 					epautoconf.o
 g_printer-objs			:= printer.o usbstring.o config.o \
 					epautoconf.o
+g_char-objs			:= usbstring.o char.o epautoconf.o
 
 ifeq ($(CONFIG_USB_ETH_RNDIS),y)
 	g_ether-objs		+= rndis.o
@@ -42,4 +44,6 @@
 obj-$(CONFIG_USB_G_SERIAL)	+= g_serial.o
 obj-$(CONFIG_USB_G_PRINTER)	+= g_printer.o
 obj-$(CONFIG_USB_MIDI_GADGET)	+= g_midi.o
+obj-$(CONFIG_USB_G_CHAR)	+= g_char.o
 
+obj-$(CONFIG_USB_PXA2XX_GPIO)	+= pxa2xx_udc_gpio.o
diff -urN linux-2.6.25/drivers/usb/gadget/pxa27x_udc.c linux-2.6.25-vpac1/drivers/usb/gadget/pxa27x_udc.c
--- linux-2.6.25/drivers/usb/gadget/pxa27x_udc.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.25-vpac1/drivers/usb/gadget/pxa27x_udc.c	2008-04-24 15:12:18.000000000 +0200
@@ -0,0 +1,2439 @@
+/*
+ * Handles the Intel 27x USB Device Controller (UDC)
+ *
+ * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker)
+ * Copyright (C) 2003 Robert Schwebel, Pengutronix
+ * Copyright (C) 2003 Benedikt Spranger, Pengutronix
+ * Copyright (C) 2003 David Brownell
+ * Copyright (C) 2003 Joshua Wise
+ * Copyright (C) 2004 Intel Corporation
+ * Copyright (C) 2005 SDG Systems, LLC  (Aric Blumer)
+ * Copyright (C) 2005-2006 Openedhand Ltd. (Richard Purdie)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#undef	DEBUG
+//#define DEBUG 1
+ //#define	VERBOSE	DBG_VERBOSE
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/mm.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/byteorder.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/gpio.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <asm/unaligned.h>
+#include <asm/hardware.h>
+#include <asm/arch/pxa-regs.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb_gadget.h>
+
+#include <asm/arch/udc.h>
+
+/*
+ * This driver handles the USB Device Controller (UDC) in Intel's PXA 27x
+ * series processors.
+ *
+ * Such controller drivers work with a gadget driver.  The gadget driver
+ * returns descriptors, implements configuration and data protocols used
+ * by the host to interact with this device, and allocates endpoints to
+ * the different protocol interfaces.  The controller driver virtualizes
+ * usb hardware so that the gadget drivers will be more portable.
+ *
+ * This UDC hardware wants to implement a bit too much USB protocol. The
+ * biggest issue is that the endpoints have to be setup before the controller
+ * can be enabled and each endpoint can only have one configuration, interface
+ * and alternative interface number. Once enabled, these cannot be changed
+ * without a controller reset.
+ *
+ * Intel Errata #22 mentions issues when changing alternate interface.
+ * The exact meaning of this remains uncertain as gadget drivers using alternate
+ * interfaces such as CDC-Ethernet appear to work...
+ */
+
+#define	DRIVER_VERSION	"01-01-2006"
+#define	DRIVER_DESC	"PXA 27x USB Device Controller driver"
+
+static const char driver_name [] = "pxa27x_udc";
+
+static const char ep0name [] = "ep0";
+
+
+#define	USE_DMA
+//#define	DISABLE_TEST_MODE
+
+#ifdef CONFIG_PROC_FS
+#define	UDC_PROC_FILE
+#endif
+
+#include "pxa27x_udc.h"
+
+#ifdef	USE_DMA
+static int use_dma = 1;
+module_param(use_dma, bool, 0);
+MODULE_PARM_DESC(use_dma, "true to use dma");
+
+static void dma_nodesc_handler(int dmach, void *_ep);
+static void kick_dma(struct pxa27x_ep *ep, struct pxa27x_request *req);
+
+#define	DMASTR " (dma support)"
+
+#else	/* !USE_DMA */
+#define	DMASTR " (pio only)"
+#endif
+
+#ifdef	CONFIG_USB_PXA27X_SMALL
+#define SIZE_STR	" (small)"
+#else
+#define SIZE_STR	""
+#endif
+
+#ifdef DISABLE_TEST_MODE
+/* (mode == 0) == no undocumented chip tweaks
+ * (mode & 1)  == double buffer bulk IN
+ * (mode & 2)  == double buffer bulk OUT
+ * ... so mode = 3 (or 7, 15, etc) does it for both
+ */
+static ushort fifo_mode = 0;
+module_param(fifo_mode, ushort, 0);
+MODULE_PARM_DESC (fifo_mode, "pxa27x udc fifo mode");
+#endif
+
+#define UDCISR0_IR0	 0x3
+#define UDCISR_INT_MASK	 (UDC_INT_FIFOERROR | UDC_INT_PACKETCMP)
+#define UDCICR_INT_MASK	 UDCISR_INT_MASK
+
+#define UDCCSR_MASK	(UDCCSR_FST | UDCCSR_DME)
+
+static void pxa27x_ep_fifo_flush(struct usb_ep *ep);
+static void nuke(struct pxa27x_ep *, int status);
+static void udc_init_ep(struct pxa27x_udc *dev);
+
+
+/*
+ * Endpoint Functions
+ */
+static void pio_irq_enable(int ep_num)
+{
+        if (ep_num < 16)
+                UDCICR0 |= 3 << (ep_num * 2);
+        else {
+                ep_num -= 16;
+                UDCICR1 |= 3 << (ep_num * 2);
+	}
+}
+
+static void pio_irq_disable(int ep_num)
+{
+        ep_num &= 0xf;
+        if (ep_num < 16)
+                UDCICR0 &= ~(3 << (ep_num * 2));
+        else {
+                ep_num -= 16;
+                UDCICR1 &= ~(3 << (ep_num * 2));
+        }
+}
+
+/* The UDCCR reg contains mask and interrupt status bits,
+ * so using '|=' isn't safe as it may ack an interrupt.
+ */
+#define UDCCR_MASK_BITS (UDCCR_OEN | UDCCR_UDE)
+
+static inline void udc_set_mask_UDCCR(int mask)
+{
+	UDCCR = (UDCCR & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS);
+}
+
+static inline void udc_clear_mask_UDCCR(int mask)
+{
+	UDCCR = (UDCCR & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS);
+}
+
+static inline void udc_ack_int_UDCCR(int mask)
+{
+	/* udccr contains the bits we dont want to change */
+	__u32 udccr = UDCCR & UDCCR_MASK_BITS;
+
+	UDCCR = udccr | (mask & ~UDCCR_MASK_BITS);
+}
+
+/*
+ * Endpoint enable/disable
+ *
+ * Not much to do here as the ep_alloc function sets up most things. Once
+ * enabled, not much of the pxa27x configuration can be changed.
+ *
+ */
+static int pxa27x_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+{
+	struct pxa27x_virt_ep *virt_ep = container_of(_ep, struct pxa27x_virt_ep, usb_ep);
+	struct pxa27x_ep *ep = virt_ep->pxa_ep;
+	struct pxa27x_udc       *dev;
+
+	if (!_ep || !desc || _ep->name == ep0name
+			|| desc->bDescriptorType != USB_DT_ENDPOINT
+			|| ep->fifo_size < le16_to_cpu(desc->wMaxPacketSize)) {
+		dev_err(ep->dev->dev, "%s, bad ep or descriptor\n", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	/* xfer types must match, except that interrupt ~= bulk */
+	if( ep->ep_type != USB_ENDPOINT_XFER_BULK
+			&& desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
+		dev_err(ep->dev->dev, "%s, %s type mismatch\n", __FUNCTION__, _ep->name);
+		return -EINVAL;
+	}
+
+	/* hardware _could_ do smaller, but driver doesn't */
+	if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
+				&& le16_to_cpu (desc->wMaxPacketSize)
+						!= BULK_FIFO_SIZE)
+			|| !desc->wMaxPacketSize) {
+		dev_err(ep->dev->dev, "%s, bad %s maxpacket\n", __FUNCTION__, _ep->name);
+		return -ERANGE;
+	}
+
+	dev = ep->dev;
+	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
+		dev_err(ep->dev->dev, "%s, bogus device state\n", __FUNCTION__);
+		return -ESHUTDOWN;
+	}
+
+	ep->desc = desc;
+	ep->dma = -1;
+	ep->stopped = 0;
+	ep->pio_irqs = ep->dma_irqs = 0;
+	ep->usb_ep->maxpacket = le16_to_cpu(desc->wMaxPacketSize);
+
+	/* flush fifo (mostly for OUT buffers) */
+	pxa27x_ep_fifo_flush(_ep);
+
+	/* ... reset halt state too, if we could ... */
+
+#ifdef USE_DMA
+	/* for (some) bulk and ISO endpoints, try to get a DMA channel and
+	 * bind it to the endpoint.  otherwise use PIO.
+	 */
+	dev_dbg(ep->dev->dev, "%s: called attributes=%d\n", __FUNCTION__, ep->ep_type);
+	switch (ep->ep_type) {
+	case USB_ENDPOINT_XFER_ISOC:
+		if (le16_to_cpu(desc->wMaxPacketSize) % 32)
+			break;
+		// fall through
+	case USB_ENDPOINT_XFER_BULK:
+		if (!use_dma || !ep->reg_drcmr)
+			break;
+		ep->dma = pxa_request_dma((char *)_ep->name, (le16_to_cpu(desc->wMaxPacketSize) > 64)
+				? DMA_PRIO_MEDIUM : DMA_PRIO_LOW, dma_nodesc_handler, ep);
+		if (ep->dma >= 0) {
+			*ep->reg_drcmr = DRCMR_MAPVLD | ep->dma;
+			dev_dbg(ep->dev->dev, "%s using dma%d\n", _ep->name, ep->dma);
+		}
+	default:
+		break;
+	}
+#endif
+	DBG(DBG_VERBOSE, "enabled %s\n", _ep->name);
+	return 0;
+}
+
+static int pxa27x_ep_disable(struct usb_ep *_ep)
+{
+	struct pxa27x_virt_ep *virt_ep = container_of(_ep, struct pxa27x_virt_ep, usb_ep);
+	struct pxa27x_ep *ep = virt_ep->pxa_ep;
+	unsigned long flags;
+
+	if (!_ep || !ep->desc) {
+		dev_err(ep->dev->dev, "%s, %s not enabled\n", __FUNCTION__,
+			_ep ? _ep->name : NULL);
+		return -EINVAL;
+	}
+	local_irq_save(flags);
+	nuke(ep, -ESHUTDOWN);
+
+#ifdef	USE_DMA
+	if (ep->dma >= 0) {
+		*ep->reg_drcmr = 0;
+		pxa_free_dma(ep->dma);
+		ep->dma = -1;
+	}
+#endif
+
+	/* flush fifo (mostly for IN buffers) */
+	pxa27x_ep_fifo_flush(_ep);
+
+	ep->desc = 0;
+	ep->stopped = 1;
+
+	local_irq_restore(flags);
+	DBG(DBG_VERBOSE, "%s disabled\n", _ep->name);
+	return 0;
+}
+
+
+
+/* for the pxa27x, these can just wrap kmalloc/kfree.  gadget drivers
+ * must still pass correctly initialized endpoints, since other controller
+ * drivers may care about how it's currently set up (dma issues etc).
+ */
+
+/*
+ * 	pxa27x_ep_alloc_request - allocate a request data structure
+ */
+static struct usb_request *
+pxa27x_ep_alloc_request(struct usb_ep *_ep, unsigned gfp_flags)
+{
+	struct pxa27x_request *req;
+
+	req = kzalloc(sizeof *req, gfp_flags);
+	if (!req)
+		return 0;
+
+	INIT_LIST_HEAD(&req->queue);
+	return &req->req;
+}
+
+
+/*
+ * 	pxa27x_ep_free_request - deallocate a request data structure
+ */
+static void
+pxa27x_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct pxa27x_request *req;
+
+	req = container_of(_req, struct pxa27x_request, req);
+	WARN_ON(!list_empty(&req->queue));
+	kfree(req);
+}
+
+
+/* PXA cache needs flushing with DMA I/O (it's dma-incoherent), but there's
+ * no device-affinity and the heap works perfectly well for i/o buffers.
+ * It wastes much less memory than dma_alloc_coherent() would, and even
+ * prevents cacheline (32 bytes wide) sharing problems.
+ */
+static void *
+pxa27x_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes, dma_addr_t *dma, unsigned gfp_flags)
+{
+	char			*retval;
+
+	retval = kmalloc(bytes, gfp_flags & ~(__GFP_DMA|__GFP_HIGHMEM));
+	if (retval)
+		*dma = virt_to_bus(retval);
+	return retval;
+}
+
+static void
+pxa27x_ep_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes)
+{
+	kfree(buf);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ *	done - retire a request; caller blocked irqs
+ */
+static void done(struct pxa27x_ep *ep, struct pxa27x_request *req, int status)
+{
+	list_del_init(&req->queue);
+	if (likely (req->req.status == -EINPROGRESS))
+		req->req.status = status;
+	else
+		status = req->req.status;
+
+	if (status && status != -ESHUTDOWN)
+		DBG(DBG_VERBOSE, "complete %s req %p stat %d len %u/%u\n",
+			ep->usb_ep->name, &req->req, status,
+			req->req.actual, req->req.length);
+
+	/* don't modify queue heads during completion callback */
+	req->req.complete(ep->usb_ep, &req->req);
+}
+
+
+static inline void ep0_idle(struct pxa27x_udc *dev)
+{
+	dev->ep0state = EP0_IDLE;
+}
+
+static int write_packet(volatile u32 *uddr, struct pxa27x_request *req, unsigned max)
+{
+	u32		*buf;
+	int	length, count, remain;
+
+	buf = (u32*)(req->req.buf + req->req.actual);
+	prefetch(buf);
+
+	/* how big will this packet be? */
+	length = min(req->req.length - req->req.actual, max);
+	req->req.actual += length;
+
+	remain = length & 0x3;
+	count = length & ~(0x3);
+
+	//dev_dbg(ep->dev->dev, "Length %d, Remain %d, Count %d\n",length, remain, count);
+
+	while (likely(count)) {
+		//dev_dbg(ep->dev->dev, "Sending:0x%x\n", *buf);
+		*uddr = *buf++;
+		count -= 4;
+	}
+
+	if (remain) {
+		volatile u8* reg=(u8*)uddr;
+		char *rd =(u8*)buf;
+
+		while (remain--) {
+			*reg=*rd++;
+		}
+	}
+
+	return length;
+}
+
+/*
+ * write to an IN endpoint fifo, as many packets as possible.
+ * irqs will use this to write the rest later.
+ * caller guarantees at least one packet buffer is ready (or a zlp).
+ */
+static int
+write_fifo(struct pxa27x_ep *ep, struct pxa27x_request *req)
+{
+	unsigned max;
+
+	max = le16_to_cpu(ep->desc->wMaxPacketSize);
+	do {
+		int count, is_last, is_short;
+
+		//dev_dbg(ep->dev->dev, "write_fifo7 %x\n", *ep->reg_udccsr);
+
+		if (*ep->reg_udccsr & UDCCSR_PC)	{
+			//dev_dbg(ep->dev->dev, "Transmit Complete\n");
+			*ep->reg_udccsr = UDCCSR_PC | (*ep->reg_udccsr & UDCCSR_MASK);
+		}
+
+		if (*ep->reg_udccsr & UDCCSR_TRN)	{
+			//dev_dbg(ep->dev->dev, "Clearing Underrun\n");
+			*ep->reg_udccsr = UDCCSR_TRN | (*ep->reg_udccsr & UDCCSR_MASK);
+		}
+		//dev_dbg(ep->dev->dev, "write_fifo8 %x\n", *ep->reg_udccsr);
+
+		count = write_packet(ep->reg_udcdr, req, max);
+
+		/* last packet is usually short (or a zlp) */
+		if (unlikely (count != max))
+			is_last = is_short = 1;
+		else {
+			if (likely(req->req.length != req->req.actual)
+					|| req->req.zero)
+				is_last = 0;
+			else
+				is_last = 1;
+			/* interrupt/iso maxpacket may not fill the fifo */
+			is_short = unlikely (max < ep->fifo_size);
+		}
+
+		//dev_dbg(ep->dev->dev, "write_fifo0 %x\n", *ep->reg_udccsr);
+
+		dev_dbg(ep->dev->dev, "wrote %s count:%d bytes%s%s %d left %p\n",
+			ep->usb_ep->name, count,
+			is_last ? "/L" : "", is_short ? "/S" : "",
+			req->req.length - req->req.actual, &req->req);
+
+		/* let loose that packet. maybe try writing another one,
+		 * double buffering might work.
+		 */
+		*ep->reg_udccsr = UDCCSR_PC;
+		if (is_short)
+			*ep->reg_udccsr = UDCCSR_SP | (*ep->reg_udccsr & UDCCSR_MASK);
+
+		dev_dbg(ep->dev->dev, "write_fifo0.5 %x\n", *ep->reg_udccsr);
+
+		/* requests complete when all IN data is in the FIFO */
+		if (is_last) {
+			done(ep, req, 0);
+			if (list_empty(&ep->queue) || unlikely(ep->dma >= 0)) {
+				pio_irq_disable(ep->pxa_ep_num);
+				//dev_dbg(ep->dev->dev, "write_fifo1 %x\n", *ep->reg_udccsr);
+#ifdef USE_DMA
+				/* unaligned data and zlps couldn't use dma */
+				if (unlikely(!list_empty(&ep->queue))) {
+					req = list_entry(ep->queue.next,
+						struct pxa27x_request, queue);
+					kick_dma(ep,req);
+					return 0;
+				}
+#endif
+			}
+			//dev_dbg(ep->dev->dev, "write_fifo2 %x\n", *ep->reg_udccsr);
+			return 1;
+		}
+
+		// TODO experiment: how robust can fifo mode tweaking be?
+		// double buffering is off in the default fifo mode, which
+		// prevents TFS from being set here.
+
+	} while (*ep->reg_udccsr & UDCCSR_FS);
+	//dev_dbg(ep->dev->dev, "write_fifo2 %x\n", *ep->reg_udccsr);
+	return 0;
+}
+
+/* caller asserts req->pending (ep0 irq status nyet cleared); starts
+ * ep0 data stage.  these chips want very simple state transitions.
+ */
+static inline
+void ep0start(struct pxa27x_udc *dev, u32 flags, const char *tag)
+{
+	UDCCSR0 = flags|UDCCSR0_SA|UDCCSR0_OPC;
+	UDCISR0 = UDCICR_INT(0, UDC_INT_FIFOERROR | UDC_INT_PACKETCMP);
+	dev->req_pending = 0;
+	DBG(DBG_VERY_NOISY, "%s %s, %02x/%02x\n",
+		__FUNCTION__, tag, UDCCSR0, flags);
+}
+
+static int
+write_ep0_fifo(struct pxa27x_ep *ep, struct pxa27x_request *req)
+{
+	unsigned	count;
+	int		is_short;
+
+	count = write_packet(&UDCDR0, req, EP0_FIFO_SIZE);
+	ep->dev->stats.write.bytes += count;
+
+	/* last packet "must be" short (or a zlp) */
+	is_short = (count != EP0_FIFO_SIZE);
+
+	DBG(DBG_VERY_NOISY, "ep0in %d bytes %d left %p\n", count,
+		req->req.length - req->req.actual, &req->req);
+
+	if (unlikely (is_short)) {
+		if (ep->dev->req_pending)
+			ep0start(ep->dev, UDCCSR0_IPR, "short IN");
+		else
+			UDCCSR0 = UDCCSR0_IPR;
+
+		count = req->req.length;
+		done(ep, req, 0);
+		ep0_idle(ep->dev);
+#if 0
+		/* This seems to get rid of lost status irqs in some cases:
+		 * host responds quickly, or next request involves config
+		 * change automagic, or should have been hidden, or ...
+		 *
+		 * FIXME get rid of all udelays possible...
+		 */
+		if (count >= EP0_FIFO_SIZE) {
+			count = 100;
+			do {
+				if ((UDCCSR0 & UDCCSR0_OPC) != 0) {
+					/* clear OPC, generate ack */
+					UDCCSR0 = UDCCSR0_OPC;
+					break;
+				}
+				count--;
+				udelay(1);
+			} while (count);
+		}
+#endif
+	} else if (ep->dev->req_pending)
+		ep0start(ep->dev, 0, "IN");
+	return is_short;
+}
+
+
+/*
+ * read_fifo -  unload packet(s) from the fifo we use for usb OUT
+ * transfers and put them into the request.  caller should have made
+ * sure there's at least one packet ready.
+ *
+ * returns true if the request completed because of short packet or the
+ * request buffer having filled (and maybe overran till end-of-packet).
+ */
+static int read_fifo(struct pxa27x_ep *ep, struct pxa27x_request *req)
+{
+	for (;;) {
+		u32		*buf;
+		int	bufferspace, count, is_short;
+
+		/* make sure there's a packet in the FIFO.*/
+		if (unlikely ((*ep->reg_udccsr & UDCCSR_PC) == 0))
+			break;
+		buf =(u32*) (req->req.buf + req->req.actual);
+		prefetchw(buf);
+		bufferspace = req->req.length - req->req.actual;
+
+		/* read all bytes from this packet */
+		if (likely (*ep->reg_udccsr & UDCCSR_BNE)) {
+			count = 0x3ff & *ep->reg_udcbcr;
+			req->req.actual += min(count, bufferspace);
+		} else /* zlp */
+			count = 0;
+
+		is_short = (count < ep->usb_ep->maxpacket);
+		dev_dbg(ep->dev->dev, "read %s udccsr:%02x, count:%d bytes%s req %p %d/%d\n",
+			ep->usb_ep->name, *ep->reg_udccsr, count,
+			is_short ? "/S" : "",
+			&req->req, req->req.actual, req->req.length);
+
+		count = min(count, bufferspace);
+		while (likely (count > 0)) {
+			*buf++ = *ep->reg_udcdr;
+			count -= 4;
+		}
+		dev_dbg(ep->dev->dev, "Buf:0x%p\n", req->req.buf);
+
+		*ep->reg_udccsr =  UDCCSR_PC;
+		/* RPC/RSP/RNE could now reflect the other packet buffer */
+
+		/* completion */
+		if (is_short || req->req.actual == req->req.length) {
+			done(ep, req, 0);
+			if (list_empty(&ep->queue))
+				pio_irq_disable(ep->pxa_ep_num);
+			return 1;
+		}
+
+		/* finished that packet.  the next one may be waiting... */
+	}
+	return 0;
+}
+
+/*
+ * special ep0 version of the above.  no UBCR0 or double buffering; status
+ * handshaking is magic.  most device protocols don't need control-OUT.
+ * CDC vendor commands (and RNDIS), mass storage CB/CBI, and some other
+ * protocols do use them.
+ */
+static int read_ep0_fifo(struct pxa27x_ep *ep, struct pxa27x_request *req)
+{
+	u32		*buf, word;
+	unsigned	bufferspace;
+
+	buf = (u32*) (req->req.buf + req->req.actual);
+	bufferspace = req->req.length - req->req.actual;
+
+	while (UDCCSR0 & UDCCSR0_RNE) {
+		word = UDCDR0;
+
+		if (unlikely (bufferspace == 0)) {
+			/* this happens when the driver's buffer
+			 * is smaller than what the host sent.
+			 * discard the extra data.
+			 */
+			if (req->req.status != -EOVERFLOW)
+				dev_info(ep->dev->dev, "%s overflow\n", ep->usb_ep->name);
+			req->req.status = -EOVERFLOW;
+		} else {
+			*buf++ = word;
+			req->req.actual += 4;
+			bufferspace -= 4;
+		}
+	}
+
+	UDCCSR0 = UDCCSR0_OPC ;
+
+	/* completion */
+	if (req->req.actual >= req->req.length)
+		return 1;
+
+	/* finished that packet.  the next one may be waiting... */
+	return 0;
+}
+
+#ifdef	USE_DMA
+
+#define	MAX_IN_DMA	((DCMD_LENGTH + 1) - BULK_FIFO_SIZE)
+static void kick_dma(struct pxa27x_ep *ep, struct pxa27x_request *req)
+{
+	u32	dcmd = 0;
+	u32	len = req->req.length;
+	u32	buf = req->req.dma;
+	u32	fifo = io_v2p((u32)ep->reg_udcdr);
+
+	buf += req->req.actual;
+	len -= req->req.actual;
+	ep->dma_con = 0;
+
+	DMSG("%s: req:0x%p length:%d, actual:%d dma:%d\n",
+			__FUNCTION__, &req->req, req->req.length,
+			req->req.actual,ep->dma);
+
+	/* no-descriptor mode can be simple for bulk-in, iso-in, iso-out */
+	DCSR(ep->dma) = DCSR_NODESC;
+	if (buf & 0x3)
+		DALGN |= 1 << ep->dma;
+	else
+		DALGN &= ~(1 << ep->dma);
+
+	if (ep->dir_in) {
+		DSADR(ep->dma) = buf;
+		DTADR(ep->dma) = fifo;
+		if (len > MAX_IN_DMA) {
+			len= MAX_IN_DMA;
+			ep->dma_con =1 ;
+		} else if (len >= ep->usb_ep->maxpacket) {
+			if ((ep->dma_con = (len % ep->usb_ep->maxpacket) != 0))
+				len = ep->usb_ep->maxpacket;
+		}
+		 dcmd = len | DCMD_BURST32 | DCMD_WIDTH4 | DCMD_ENDIRQEN
+			| DCMD_FLOWTRG | DCMD_INCSRCADDR;
+	} else {
+		DSADR(ep->dma) = fifo;
+		DTADR(ep->dma) = buf;
+		dcmd = len | DCMD_BURST32 | DCMD_WIDTH4 | DCMD_ENDIRQEN
+			| DCMD_FLOWSRC | DCMD_INCTRGADDR;
+	}
+	*ep->reg_udccsr = UDCCSR_DME;
+	DCMD(ep->dma) = dcmd;
+	DCSR(ep->dma) =  DCSR_NODESC | DCSR_EORIRQEN \
+				| ((ep->dir_in) ? DCSR_STOPIRQEN : 0);
+	*ep->reg_drcmr = ep->dma | DRCMR_MAPVLD;
+	DCSR(ep->dma) |= DCSR_RUN;
+}
+
+static void cancel_dma(struct pxa27x_ep *ep)
+{
+	struct pxa27x_request	*req;
+	u32			tmp;
+
+	if (DCSR(ep->dma) == 0 || list_empty(&ep->queue))
+		return;
+
+	DMSG("hehe dma:%d,dcsr:0x%x\n", ep->dma, DCSR(ep->dma));
+	DCSR(ep->dma) = 0;
+	while ((DCSR(ep->dma) & DCSR_STOPSTATE) == 0)
+		cpu_relax();
+
+	req = list_entry(ep->queue.next, struct pxa27x_request, queue);
+	tmp = DCMD(ep->dma) & DCMD_LENGTH;
+	req->req.actual = req->req.length - tmp;
+
+	/* the last tx packet may be incomplete, so flush the fifo.
+	 * FIXME correct req.actual if we can
+	 */
+	*ep->reg_udccsr = UDCCSR_FEF;
+}
+
+static void dma_nodesc_handler(int dmach, void *_ep)
+{
+	struct pxa27x_ep	*ep = _ep;
+	struct pxa27x_request	*req, *req_next;
+	u32			dcsr, tmp, completed;
+
+	local_irq_disable();
+
+	req = list_entry(ep->queue.next, struct pxa27x_request, queue);
+
+	DMSG("%s, buf:0x%p\n",__FUNCTION__, req->req.buf);
+
+	ep->dma_irqs++;
+	ep->dev->stats.irqs++;
+
+	completed = 0;
+
+	dcsr = DCSR(dmach);
+	DCSR(ep->dma) &= ~DCSR_RUN;
+
+	if (dcsr & DCSR_BUSERR) {
+		DCSR(dmach) = DCSR_BUSERR;
+		dev_err(ep->dev->dev, "DMA Bus Error\n");
+		req->req.status = -EIO;
+		completed = 1;
+	} else if (dcsr & DCSR_ENDINTR) {
+		DCSR(dmach) = DCSR_ENDINTR;
+		if (ep->dir_in) {
+			tmp = req->req.length - req->req.actual;
+			/* Last packet is a short one*/
+			if (tmp < ep->usb_ep->maxpacket) {
+				int count = 0;
+
+				*ep->reg_udccsr = UDCCSR_SP | \
+					(*ep->reg_udccsr & UDCCSR_MASK);
+				/*Wait for packet out */
+				while( (count++ < 10000) && \
+					!(*ep->reg_udccsr & UDCCSR_FS));
+				if (count >= 10000)
+					DMSG("Failed to send packet\n");
+				else
+					DMSG("%s: short packet sent len:%d,"
+					"length:%d,actual:%d\n", __FUNCTION__,
+					tmp, req->req.length, req->req.actual);
+				req->req.actual = req->req.length;
+				completed = 1;
+			/* There are still packets to transfer */
+			} else if ( ep->dma_con) {
+				DMSG("%s: more packets,length:%d,actual:%d\n",
+					 __FUNCTION__,req->req.length,
+					 req->req.actual);
+				req->req.actual += ep->usb_ep->maxpacket;
+				completed = 0;
+			} else {
+				DMSG("%s: no more packets,length:%d,"
+					"actual:%d\n", __FUNCTION__,
+					req->req.length, req->req.actual);
+				req->req.actual = req->req.length;
+				completed = 1;
+			}
+		} else {
+			req->req.actual = req->req.length;
+			completed = 1;
+		}
+	} else if (dcsr & DCSR_EORINTR) { //Only happened in OUT DMA
+		int remain,udccsr ;
+
+		DCSR(dmach) = DCSR_EORINTR;
+		remain = DCMD(dmach) & DCMD_LENGTH;
+		req->req.actual = req->req.length - remain;
+
+		udccsr = *ep->reg_udccsr;
+		if (udccsr & UDCCSR_SP) {
+			*ep->reg_udccsr = UDCCSR_PC | (udccsr & UDCCSR_MASK);
+			completed = 1;
+		}
+		DMSG("%s: length:%d actual:%d\n",
+				__FUNCTION__, req->req.length, req->req.actual);
+	} else
+		DMSG("%s: Others dma:%d DCSR:0x%x DCMD:0x%x\n",
+				__FUNCTION__, dmach, DCSR(dmach), DCMD(dmach));
+
+	if (likely(completed)) {
+		if (req->queue.next != &ep->queue) {
+			req_next = list_entry(req->queue.next,
+					struct pxa27x_request, queue);
+			kick_dma(ep, req_next);
+		}
+		done(ep, req, 0);
+	} else {
+		kick_dma(ep, req);
+	}
+
+	local_irq_enable();
+}
+
+#endif
+/*-------------------------------------------------------------------------*/
+
+static int
+pxa27x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
+{
+	struct pxa27x_virt_ep *virt_ep;
+	struct pxa27x_ep *ep;
+	struct pxa27x_request	*req;
+	struct pxa27x_udc	*dev;
+	unsigned long		flags;
+
+	virt_ep = container_of(_ep, struct pxa27x_virt_ep, usb_ep);
+	ep = virt_ep->pxa_ep;
+
+	req = container_of(_req, struct pxa27x_request, req);
+	if (unlikely (!_req || !_req->complete || !_req->buf||
+			!list_empty(&req->queue))) {
+		DMSG("%s, bad params\n", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	if (unlikely (!_ep || (!ep->desc && _ep->name != ep0name))) {
+		DMSG("%s, bad ep\n", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	DMSG("%s, ep point %d is queue\n", __FUNCTION__, ep->ep_num);
+
+	dev = ep->dev;
+	if (unlikely (!dev->driver
+			|| dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+		DMSG("%s, bogus device state\n", __FUNCTION__);
+		return -ESHUTDOWN;
+	}
+
+	/* iso is always one packet per request, that's the only way
+	 * we can report per-packet status.  that also helps with dma.
+	 */
+	if (unlikely (ep->ep_type == USB_ENDPOINT_XFER_ISOC
+			&& req->req.length > le16_to_cpu
+						(ep->desc->wMaxPacketSize)))
+		return -EMSGSIZE;
+
+#ifdef	USE_DMA
+	// FIXME caller may already have done the dma mapping
+	if (ep->dma >= 0) {
+		_req->dma = dma_map_single(dev->dev, _req->buf, _req->length,
+			(ep->dir_in) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+	}
+#endif
+
+	DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n",
+	     _ep->name, _req, _req->length, _req->buf);
+
+	local_irq_save(flags);
+
+	_req->status = -EINPROGRESS;
+	_req->actual = 0;
+
+	/* kickstart this i/o queue? */
+	if (list_empty(&ep->queue) && !ep->stopped) {
+		if (ep->desc == 0 /* ep0 */) {
+			unsigned	length = _req->length;
+
+			switch (dev->ep0state) {
+			case EP0_IN_DATA_PHASE:
+				dev->stats.write.ops++;
+				if (write_ep0_fifo(ep, req))
+					req = 0;
+				break;
+
+			case EP0_OUT_DATA_PHASE:
+				dev->stats.read.ops++;
+				if (dev->req_pending)
+					ep0start(dev, UDCCSR0_IPR, "OUT");
+				if (length == 0 || ((UDCCSR0 & UDCCSR0_RNE) != 0
+						&& read_ep0_fifo(ep, req))) {
+					ep0_idle(dev);
+					done(ep, req, 0);
+					req = 0;
+				}
+				break;
+			case EP0_NO_ACTION:
+				ep0_idle(dev);
+				req=0;
+				break;
+			default:
+				DMSG("ep0 i/o, odd state %d\n", dev->ep0state);
+				local_irq_restore (flags);
+				return -EL2HLT;
+			}
+#ifdef USE_DMA
+		/* either start dma or prime pio pump */
+		} else if (ep->dma >= 0) {
+			kick_dma(ep, req);
+#endif
+		/* can the FIFO can satisfy the request immediately? */
+		} else if (ep->dir_in && (*ep->reg_udccsr & UDCCSR_FS) != 0
+				&& write_fifo(ep, req)) {
+			req = 0;
+		} else if ((*ep->reg_udccsr & UDCCSR_FS) != 0
+				&& read_fifo(ep, req)) {
+			req = 0;
+		}
+		DMSG("req:%p,ep->desc:%p,ep->dma:%d\n", req, ep->desc, ep->dma);
+		if (likely (req && ep->desc) && ep->dma < 0)
+			pio_irq_enable(ep->pxa_ep_num);
+	}
+
+	/* pio or dma irq handler advances the queue. */
+	if (likely (req != 0))
+		list_add_tail(&req->queue, &ep->queue);
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+
+/*
+ * 	nuke - dequeue ALL requests
+ */
+static void nuke(struct pxa27x_ep *ep, int status)
+{
+	struct pxa27x_request *req;
+
+	/* called with irqs blocked */
+#ifdef	USE_DMA
+	if (ep->dma >= 0 && !ep->stopped)
+		cancel_dma(ep);
+#endif
+	while (!list_empty(&ep->queue)) {
+		req = list_entry(ep->queue.next, struct pxa27x_request, queue);
+		done(ep, req, status);
+	}
+	if (ep->desc)
+		pio_irq_disable(ep->pxa_ep_num);
+}
+
+
+/* dequeue JUST ONE request */
+static int pxa27x_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct pxa27x_virt_ep *virt_ep = container_of(_ep, struct pxa27x_virt_ep, usb_ep);
+	struct pxa27x_ep *ep = virt_ep->pxa_ep;
+	struct pxa27x_request	*req;
+	unsigned long		flags;
+
+	if (!_ep || _ep->name == ep0name)
+		return -EINVAL;
+
+	local_irq_save(flags);
+
+	/* make sure it's actually queued on this endpoint */
+	list_for_each_entry(req, &ep->queue, queue) {
+		if (&req->req == _req)
+			break;
+	}
+	if (&req->req != _req) {
+		local_irq_restore(flags);
+		return -EINVAL;
+	}
+
+#ifdef	USE_DMA
+	if (ep->dma >= 0 && ep->queue.next == &req->queue && !ep->stopped) {
+		cancel_dma(ep);
+		done(ep, req, -ECONNRESET);
+		/* restart i/o */
+		if (!list_empty(&ep->queue)) {
+			req = list_entry(ep->queue.next,
+					struct pxa27x_request, queue);
+			kick_dma(ep, req);
+		}
+	} else
+#endif
+		done(ep, req, -ECONNRESET);
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int pxa27x_ep_set_halt(struct usb_ep *_ep, int value)
+{
+	struct pxa27x_virt_ep *virt_ep = container_of(_ep, struct pxa27x_virt_ep, usb_ep);
+	struct pxa27x_ep *ep = virt_ep->pxa_ep;
+	unsigned long		flags;
+
+	DMSG("%s is called\n", __FUNCTION__);
+	if (unlikely (!_ep || (!ep->desc && _ep->name != ep0name))
+			|| ep->ep_type == USB_ENDPOINT_XFER_ISOC) {
+		DMSG("%s, bad ep\n", __FUNCTION__);
+		return -EINVAL;
+	}
+	if (value == 0) {
+		/* this path (reset toggle+halt) is needed to implement
+		 * SET_INTERFACE on normal hardware.  but it can't be
+		 * done from software on the PXA UDC, and the hardware
+		 * forgets to do it as part of SET_INTERFACE automagic.
+		 */
+		DMSG("only host can clear %s halt\n", _ep->name);
+		return -EROFS;
+	}
+
+	local_irq_save(flags);
+
+	if (ep->dir_in	&& ((*ep->reg_udccsr & UDCCSR_FS) == 0
+			   || !list_empty(&ep->queue))) {
+		local_irq_restore(flags);
+		return -EAGAIN;
+	}
+
+	/* FST bit is the same for control, bulk in, bulk out, interrupt in */
+	*ep->reg_udccsr = UDCCSR_FST|UDCCSR_FEF;
+
+	/* ep0 needs special care */
+	if (!ep->desc) {
+		start_watchdog(ep->dev);
+		ep->dev->req_pending = 0;
+		ep->dev->ep0state = EP0_STALL;
+
+ 	/* and bulk/intr endpoints like dropping stalls too */
+ 	} else {
+ 		unsigned i;
+ 		for (i = 0; i < 1000; i += 20) {
+ 			if (*ep->reg_udccsr & UDCCSR_SST)
+ 				break;
+ 			udelay(20);
+ 		}
+  	}
+ 	local_irq_restore(flags);
+
+	DBG(DBG_VERBOSE, "%s halt\n", _ep->name);
+	return 0;
+}
+
+static int pxa27x_ep_fifo_status(struct usb_ep *_ep)
+{
+	struct pxa27x_virt_ep *virt_ep = container_of(_ep, struct pxa27x_virt_ep, usb_ep);
+	struct pxa27x_ep *ep = virt_ep->pxa_ep;
+
+	if (!_ep) {
+		DMSG("%s, bad ep\n", __FUNCTION__);
+		return -ENODEV;
+	}
+	/* pxa can't report unclaimed bytes from IN fifos */
+	if (ep->dir_in)
+		return -EOPNOTSUPP;
+	if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN
+			|| (*ep->reg_udccsr & UDCCSR_FS) == 0)
+		return 0;
+	else
+		return (*ep->reg_udcbcr & 0xfff) + 1;
+}
+
+static void pxa27x_ep_fifo_flush(struct usb_ep *_ep)
+{
+	struct pxa27x_virt_ep *virt_ep = container_of(_ep, struct pxa27x_virt_ep, usb_ep);
+	struct pxa27x_ep *ep = virt_ep->pxa_ep;
+
+	DMSG("pxa27x_ep_fifo_flush\n");
+
+	if (!_ep || _ep->name == ep0name || !list_empty(&ep->queue)) {
+		DMSG("%s, bad ep\n", __FUNCTION__);
+		return;
+	}
+
+	/* toggle and halt bits stay unchanged */
+
+	/* for OUT, just read and discard the FIFO contents. */
+	if (!ep->dir_in) {
+		while (((*ep->reg_udccsr) & UDCCSR_BNE) != 0)
+			(void) *ep->reg_udcdr;
+		return;
+	}
+
+	/* most IN status is the same, but ISO can't stall */
+	*ep->reg_udccsr = UDCCSR_PC|UDCCSR_FST|UDCCSR_TRN
+		| (ep->ep_type == USB_ENDPOINT_XFER_ISOC)
+			? 0 : UDCCSR_SST;
+}
+
+
+static struct usb_ep_ops pxa27x_ep_ops = {
+	.enable		= pxa27x_ep_enable,
+	.disable	= pxa27x_ep_disable,
+
+	.alloc_request	= pxa27x_ep_alloc_request,
+	.free_request	= pxa27x_ep_free_request,
+
+	.alloc_buffer	= pxa27x_ep_alloc_buffer,
+	.free_buffer	= pxa27x_ep_free_buffer,
+
+	.queue		= pxa27x_ep_queue,
+	.dequeue	= pxa27x_ep_dequeue,
+
+	.set_halt	= pxa27x_ep_set_halt,
+	.fifo_status	= pxa27x_ep_fifo_status,
+	.fifo_flush	= pxa27x_ep_fifo_flush,
+};
+
+
+/* ---------------------------------------------------------------------------
+ * 	device-scoped parts of the api to the usb controller hardware
+ * ---------------------------------------------------------------------------
+ */
+
+static inline unsigned int validate_fifo_size(u8 bmAttributes)
+{
+	switch (bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+	case USB_ENDPOINT_XFER_CONTROL:
+		return EP0_FIFO_SIZE;
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		return ISO_FIFO_SIZE;
+		break;
+	case USB_ENDPOINT_XFER_BULK:
+		return BULK_FIFO_SIZE;
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		return INT_FIFO_SIZE;
+		break;
+	default:
+		break;
+	}
+}
+
+static void pxa27x_ep_free(struct usb_gadget *gadget, struct usb_ep *_ep)
+{
+	struct pxa27x_udc *dev = the_controller;
+	struct pxa27x_virt_ep *virt_ep;
+	int i;
+
+	virt_ep = container_of(_ep, struct pxa27x_virt_ep, usb_ep);
+
+	for (i = 1; i < UDC_EP_NUM; i++) {
+		if (dev->ep[i].usb_ep == &virt_ep->usb_ep) {
+			if (dev->ep[i].desc) {
+				virt_ep->pxa_ep = &dev->ep[i];
+				pxa27x_ep_disable(&virt_ep->usb_ep);
+			}
+			dev->ep[i].usb_ep = NULL;
+		}
+	}
+
+	if (!list_empty(&virt_ep->usb_ep.ep_list))
+		list_del_init(&virt_ep->usb_ep.ep_list);
+
+	kfree(virt_ep->usb_ep.name);
+	kfree(virt_ep);
+}
+
+static void pxa27x_ep_freeall(struct usb_gadget *gadget)
+{
+	struct pxa27x_udc *dev = the_controller;
+	int i;
+
+	for (i = 1; i < UDC_EP_NUM; i++) {
+		if(dev->ep[i].usb_ep)
+			pxa27x_ep_free(gadget, dev->ep[i].usb_ep);
+	}
+}
+
+#define NAME_SIZE 18
+
+static int pxa27x_find_free_ep(struct pxa27x_udc *dev)
+{
+	int i;
+	for (i = 1; i < UDC_EP_NUM; i++) {
+		if(!dev->ep[i].assigned)
+			return i;
+	}
+	return -1;
+}
+
+/*
+ * Endpoint Allocation/Configuration
+ *
+ * pxa27x endpoint configuration is fixed when the device is enabled. Any pxa
+ * endpoint is only active in one configuration, interface and alternate
+ * interface combination so to support gadget drivers, we map one usb_ep to
+ * one of several pxa ep's. One pxa endpoint is assigned per configuration
+ * combination.
+ */
+static struct usb_ep* pxa27x_ep_alloc(struct usb_gadget *gadget, struct usb_endpoint_descriptor *desc,
+	struct usb_endpoint_config *epconfig, int configs)
+{
+	struct pxa27x_udc *dev = the_controller;
+	struct pxa27x_virt_ep *virt_ep;
+	unsigned int i, fifo_size;
+	char *name;
+
+	if (unlikely(configs < 1)) {
+		dev_err(dev->dev, "%s: Error in config data\n", __FUNCTION__);
+		return NULL;
+	}
+
+	virt_ep = kmalloc(sizeof(struct pxa27x_virt_ep), GFP_KERNEL);
+	name = kmalloc(NAME_SIZE, GFP_KERNEL);
+	if (!virt_ep || !name) {
+		dev_err(dev->dev, "%s: -ENOMEM\n", __FUNCTION__);
+		kfree(name);
+		kfree(virt_ep);
+		return NULL;
+	}
+
+	if (!(desc->wMaxPacketSize)) {
+		fifo_size = validate_fifo_size(desc->bmAttributes);
+		desc->wMaxPacketSize = fifo_size;
+	} else {
+		fifo_size = desc->wMaxPacketSize;
+	}
+
+	DMSG("pxa27x_ep_alloc:  bLength: %d, bDescriptorType: %x, bEndpointAddress: %x,\n"
+	     	"  bmAttributes: %x, wMaxPacketSize: %d\n", desc->bLength,
+		desc->bDescriptorType, desc->bEndpointAddress, desc->bmAttributes,
+		desc->wMaxPacketSize);
+
+	if (!(desc->bEndpointAddress & 0xF))
+		desc->bEndpointAddress |= dev->ep_num;
+
+	for (i = 0; i < configs; i++)
+	{
+		struct pxa27x_ep *pxa_ep;
+		int j;
+
+		DMSG("pxa27x_ep_alloc:  config: %d, interface: %d, altinterface: %x,\n",
+			epconfig->config, epconfig->interface, epconfig->altinterface);
+
+		j = pxa27x_find_free_ep(dev);
+
+		if (unlikely(j < 0)) {
+			dev_err(dev->dev, "pxa27x_ep_alloc: Failed to find a spare endpoint\n");
+			pxa27x_ep_free(gadget, &virt_ep->usb_ep);
+			return NULL;
+		}
+
+		pxa_ep = &dev->ep[j];
+
+		if (i == 0)
+			virt_ep->pxa_ep = pxa_ep;
+
+		pxa_ep->assigned = 1;
+		pxa_ep->ep_num = dev->ep_num;
+		pxa_ep->pxa_ep_num = j;
+		pxa_ep->usb_ep = &virt_ep->usb_ep;
+		pxa_ep->dev = dev;
+		pxa_ep->desc = desc;
+		pxa_ep->pio_irqs = pxa_ep->dma_irqs = 0;
+		pxa_ep->dma = -1;
+
+		pxa_ep->fifo_size = fifo_size;
+		pxa_ep->dir_in = (desc->bEndpointAddress & USB_DIR_IN) ? 1 : 0;
+		pxa_ep->ep_type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+		pxa_ep->stopped = 1;
+		pxa_ep->dma_con = 0;
+		pxa_ep->config = epconfig->config;
+		pxa_ep->interface = epconfig->interface;
+		pxa_ep->aisn = epconfig->altinterface;
+
+		pxa_ep->reg_udccsr = &UDCCSR0 + j;
+		pxa_ep->reg_udcbcr = &UDCBCR0 + j;
+		pxa_ep->reg_udcdr = &UDCDR0 + j ;
+		pxa_ep->reg_udccr = &UDCCRA - 1 + j;
+#ifdef USE_DMA
+		pxa_ep->reg_drcmr = &DRCMR24 + j;
+#endif
+
+		/* Configure UDCCR */
+		*pxa_ep->reg_udccr = ((pxa_ep->config << UDCCONR_CN_S) & UDCCONR_CN)
+			| ((pxa_ep->interface << UDCCONR_IN_S) & UDCCONR_IN)
+			| ((pxa_ep->aisn << UDCCONR_AISN_S) & UDCCONR_AISN)
+			| ((dev->ep_num << UDCCONR_EN_S) & UDCCONR_EN)
+			| ((pxa_ep->ep_type << UDCCONR_ET_S) & UDCCONR_ET)
+			| ((pxa_ep->dir_in) ? UDCCONR_ED : 0)
+			| ((min(pxa_ep->fifo_size, (unsigned)desc->wMaxPacketSize) << UDCCONR_MPS_S ) & UDCCONR_MPS)
+			| UDCCONR_EE;
+//			| UDCCONR_DE | UDCCONR_EE;
+
+
+
+#ifdef USE_DMA
+		/* Only BULK use DMA */
+		if ((pxa_ep->ep_type & USB_ENDPOINT_XFERTYPE_MASK)\
+				== USB_ENDPOINT_XFER_BULK)
+			*pxa_ep->reg_udccsr = UDCCSR_DME;
+#endif
+
+		DMSG("UDCCR: 0x%p is 0x%x\n", pxa_ep->reg_udccr,*pxa_ep->reg_udccr);
+
+		epconfig++;
+	}
+
+	/* Fill ep name*/
+	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+		case USB_ENDPOINT_XFER_BULK:
+			sprintf(name, "ep%d%s-bulk", dev->ep_num,
+				((desc->bEndpointAddress & USB_DIR_IN) ? "in":"out"));
+			break;
+		case USB_ENDPOINT_XFER_INT:
+			sprintf(name, "ep%d%s-intr", dev->ep_num,
+				((desc->bEndpointAddress & USB_DIR_IN) ? "in":"out"));
+			break;
+		default:
+			sprintf(name, "ep%d%s", dev->ep_num,
+				((desc->bEndpointAddress & USB_DIR_IN) ? "in":"out"));
+			break;
+	}
+
+	virt_ep->desc = desc;
+	virt_ep->usb_ep.name = name;
+	virt_ep->usb_ep.ops = &pxa27x_ep_ops;
+	virt_ep->usb_ep.maxpacket = min((ushort)fifo_size, desc->wMaxPacketSize);
+
+	list_add_tail(&virt_ep->usb_ep.ep_list, &gadget->ep_list);
+
+	dev->ep_num++;
+	return &virt_ep->usb_ep;
+}
+
+static int pxa27x_udc_get_frame(struct usb_gadget *_gadget)
+{
+	return (UDCFNR & 0x7FF);
+}
+
+static int pxa27x_udc_wakeup(struct usb_gadget *_gadget)
+{
+	/* host may not have enabled remote wakeup */
+	if ((UDCCR & UDCCR_DWRE) == 0)
+		return -EHOSTUNREACH;
+	udc_set_mask_UDCCR(UDCCR_UDR);
+	return 0;
+}
+
+static const struct usb_gadget_ops pxa27x_udc_ops = {
+	.ep_alloc	= pxa27x_ep_alloc,
+	.get_frame	= pxa27x_udc_get_frame,
+	.wakeup		= pxa27x_udc_wakeup,
+	// current versions must always be self-powered
+};
+
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef UDC_PROC_FILE
+
+static const char proc_node_name [] = "driver/udc";
+
+static int
+udc_proc_read(char *page, char **start, off_t off, int count,
+		int *eof, void *_dev)
+{
+	char			*buf = page;
+	struct pxa27x_udc	*dev = _dev;
+	char			*next = buf;
+	unsigned		size = count;
+	unsigned long		flags;
+	int			i, t;
+	u32			tmp;
+
+	if (off != 0)
+		return 0;
+
+	local_irq_save(flags);
+
+	/* basic device status */
+	t = scnprintf(next, size, DRIVER_DESC "\n"
+		"%s version: %s\nGadget driver: %s\n",
+		driver_name, DRIVER_VERSION SIZE_STR DMASTR,
+		dev->driver ? dev->driver->driver.name : "(none)");
+	size -= t;
+	next += t;
+
+	/* registers for device and ep0 */
+	t = scnprintf(next, size,
+		"uicr %02X.%02X, usir %02X.%02x, ufnr %02X\n",
+		UDCICR1, UDCICR0, UDCISR1, UDCISR0, UDCFNR);
+	size -= t;
+	next += t;
+
+	tmp = UDCCR;
+	t = scnprintf(next, size,"udccr %02X =%s%s%s%s%s%s%s%s%s%s, con=%d,inter=%d,altinter=%d\n", tmp,
+		(tmp & UDCCR_OEN) ? " oen":"",
+		(tmp & UDCCR_AALTHNP) ? " aalthnp":"",
+		(tmp & UDCCR_AHNP) ? " rem" : "",
+		(tmp & UDCCR_BHNP) ? " rstir" : "",
+		(tmp & UDCCR_DWRE) ? " dwre" : "",
+		(tmp & UDCCR_SMAC) ? " smac" : "",
+		(tmp & UDCCR_EMCE) ? " emce" : "",
+		(tmp & UDCCR_UDR) ? " udr" : "",
+		(tmp & UDCCR_UDA) ? " uda" : "",
+		(tmp & UDCCR_UDE) ? " ude" : "",
+		(tmp & UDCCR_ACN) >> UDCCR_ACN_S,
+		(tmp & UDCCR_AIN) >> UDCCR_AIN_S,
+		(tmp & UDCCR_AAISN)>> UDCCR_AAISN_S );
+
+	size -= t;
+	next += t;
+
+	tmp = UDCCSR0;
+	t = scnprintf(next, size,
+		"udccsr0 %02X =%s%s%s%s%s%s%s\n", tmp,
+		(tmp & UDCCSR0_SA) ? " sa" : "",
+		(tmp & UDCCSR0_RNE) ? " rne" : "",
+		(tmp & UDCCSR0_FST) ? " fst" : "",
+		(tmp & UDCCSR0_SST) ? " sst" : "",
+		(tmp & UDCCSR0_DME) ? " dme" : "",
+		(tmp & UDCCSR0_IPR) ? " ipr" : "",
+		(tmp & UDCCSR0_OPC) ? " opc" : "");
+	size -= t;
+	next += t;
+
+	if (!dev->driver)
+		goto done;
+
+	t = scnprintf(next, size, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n",
+		dev->stats.write.bytes, dev->stats.write.ops,
+		dev->stats.read.bytes, dev->stats.read.ops,
+		dev->stats.irqs);
+	size -= t;
+	next += t;
+
+	/* dump endpoint queues */
+	for (i = 0; i < UDC_EP_NUM; i++) {
+		struct pxa27x_ep	*ep = &dev->ep [i];
+		struct pxa27x_request	*req;
+		int			t;
+
+		if (i != 0) {
+			const struct usb_endpoint_descriptor	*d;
+
+			d = ep->desc;
+			if (!d)
+				continue;
+			tmp = *dev->ep [i].reg_udccsr;
+			t = scnprintf(next, size,
+				"%d max %d %s udccs %02x udccr:0x%x\n",
+				i, le16_to_cpu (d->wMaxPacketSize),
+				(ep->dma >= 0) ? "dma" : "pio", tmp,
+				*dev->ep[i].reg_udccr);
+			/* TODO translate all five groups of udccs bits! */
+
+		} else /* ep0 should only have one transfer queued */
+			t = scnprintf(next, size, "ep0 max 16 pio irqs %lu\n",
+				ep->pio_irqs);
+		if (t <= 0 || t > size)
+			goto done;
+		size -= t;
+		next += t;
+
+		if (list_empty(&ep->queue)) {
+			t = scnprintf(next, size, "\t(nothing queued)\n");
+			if (t <= 0 || t > size)
+				goto done;
+			size -= t;
+			next += t;
+			continue;
+		}
+		list_for_each_entry(req, &ep->queue, queue) {
+#ifdef	USE_DMA
+			if (ep->dma >= 0 && req->queue.prev == &ep->queue)
+				t = scnprintf(next, size, "\treq %p len %d/%d "
+					"buf %p (dma%d dcmd %08x)\n",
+					&req->req, req->req.actual,
+					req->req.length, req->req.buf,
+					ep->dma, DCMD(ep->dma)
+					/* low 13 bits == bytes-to-go */);
+			else
+#endif
+				t = scnprintf(next, size,
+					"\treq %p len %d/%d buf %p\n",
+					&req->req, req->req.actual,
+					req->req.length, req->req.buf);
+			if (t <= 0 || t > size)
+				goto done;
+			size -= t;
+			next += t;
+		}
+	}
+
+done:
+	local_irq_restore(flags);
+	*eof = 1;
+	return count - size;
+}
+
+#define create_proc_files() \
+	create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev)
+#define remove_proc_files() \
+	remove_proc_entry(proc_node_name, NULL)
+
+#else	/* !UDC_PROC_FILE */
+#define create_proc_files() do {} while (0)
+#define remove_proc_files() do {} while (0)
+
+#endif	/* UDC_PROC_FILE */
+
+/* "function" sysfs attribute */
+static ssize_t show_function(struct device *_dev, struct device_attribute *attr, char *buf)
+{
+	struct pxa27x_udc *dev = dev_get_drvdata(_dev);
+
+	if (!dev->driver || !dev->driver->function
+			|| strlen(dev->driver->function) > PAGE_SIZE)
+		return 0;
+	return scnprintf(buf, PAGE_SIZE, "%s\n", dev->driver->function);
+}
+static DEVICE_ATTR(function, S_IRUGO, show_function, NULL);
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * 	udc_disable - disable USB device controller
+ */
+static void udc_disable(struct pxa27x_udc *dev)
+{
+	UDCICR0 = UDCICR1 = 0x00000000;
+
+	udc_clear_mask_UDCCR(UDCCR_UDE);
+
+        /* Disable clock for USB device */
+	pxa_set_cken(CKEN_USB, 0);
+
+	ep0_idle(dev);
+	dev->gadget.speed = USB_SPEED_UNKNOWN;
+	if (dev->mach->gpio_pullup)
+		gpio_set_value(dev->mach->gpio_pullup, 0);
+	else if (dev->mach->udc_command)
+		dev->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
+}
+
+
+/*
+ * 	udc_reinit - initialize software state
+ */
+static void udc_reinit(struct pxa27x_udc *dev)
+{
+	u32	i;
+
+	dev->ep0state = EP0_IDLE;
+
+	/* basic endpoint records init */
+	for (i = 0; i < UDC_EP_NUM; i++) {
+		struct pxa27x_ep *ep = &dev->ep[i];
+
+		ep->stopped = 0;
+		ep->pio_irqs = ep->dma_irqs = 0;
+	}
+	dev->configuration = 0;
+	dev->interface = 0;
+	dev->alternate = 0;
+	/* the rest was statically initialized, and is read-only */
+}
+
+/* until it's enabled, this UDC should be completely invisible
+ * to any USB host.
+ */
+static void udc_enable(struct pxa27x_udc *dev)
+{
+	udc_clear_mask_UDCCR(UDCCR_UDE);
+
+        /* Enable clock for USB device */
+	pxa_set_cken(CKEN_USB, 1);
+
+	UDCICR0 = UDCICR1 = 0;
+
+	ep0_idle(dev);
+	dev->gadget.speed = USB_SPEED_FULL;
+	dev->stats.irqs = 0;
+
+	udc_set_mask_UDCCR(UDCCR_UDE);
+	udelay(2);
+	if (UDCCR & UDCCR_EMCE)
+		dev_err(dev->dev, "There are error in configuration, udc disabled\n");
+
+	/* caller must be able to sleep in order to cope
+	 * with startup transients.
+	 */
+	msleep(100);
+
+	/* enable suspend/resume and reset irqs */
+	UDCICR1 = UDCICR1_IECC | UDCICR1_IERU | UDCICR1_IESU | UDCICR1_IERS;
+
+	/* enable ep0 irqs */
+	UDCICR0 = UDCICR_INT(0,UDCICR_INT_MASK);
+	if (dev->mach->gpio_pullup)
+		gpio_set_value(dev->mach->gpio_pullup, 1);
+	else if (dev->mach->udc_command)
+		dev->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
+}
+
+
+/* when a driver is successfully registered, it will receive
+ * control requests including set_configuration(), which enables
+ * non-control requests.  then usb traffic follows until a
+ * disconnect is reported.  then a host may connect again, or
+ * the driver might get unbound.
+ */
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+	struct pxa27x_udc *dev = the_controller;
+	int retval;
+
+	if (!driver || driver->speed != USB_SPEED_FULL || !driver->bind
+			|| !driver->unbind || !driver->disconnect || !driver->setup)
+		return -EINVAL;
+	if (!dev)
+		return -ENODEV;
+	if (dev->driver)
+		return -EBUSY;
+
+	udc_disable(dev);
+	udc_init_ep(dev);
+	udc_reinit(dev);
+
+	/* first hook up the driver ... */
+	dev->driver = driver;
+	dev->gadget.dev.driver = &driver->driver;
+	dev->ep_num = 1;
+
+	retval = device_add(&dev->gadget.dev);
+	if (retval) {
+		DMSG("device_add error %d\n", retval);
+		goto add_fail;
+	}
+	retval = driver->bind(&dev->gadget);
+	if (retval) {
+		DMSG("bind to driver %s --> error %d\n",
+				driver->driver.name, retval);
+		goto bind_fail;
+	}
+	retval = device_create_file(dev->dev, &dev_attr_function);
+	if (retval) {
+		DMSG("device_create_file failed: %d\n", retval);
+		goto create_file_fail;
+	}
+
+	/* ... then enable host detection and ep0; and we're ready
+	 * for set_configuration as well as eventual disconnect.
+	 * NOTE:  this shouldn't power up until later.
+	 */
+	DMSG("registered gadget driver '%s'\n", driver->driver.name);
+	udc_enable(dev);
+	dump_state(dev);
+	return 0;
+
+create_file_fail:
+	driver->unbind(&dev->gadget);
+bind_fail:
+	device_del(&dev->gadget.dev);
+add_fail:
+	dev->driver = 0;
+	dev->gadget.dev.driver = 0;
+	return retval;
+}
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+static void
+stop_activity(struct pxa27x_udc *dev, struct usb_gadget_driver *driver)
+{
+	int i;
+
+	DMSG("Trace path 1\n");
+	/* don't disconnect drivers more than once */
+	if (dev->gadget.speed == USB_SPEED_UNKNOWN)
+		driver = 0;
+	dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+	/* prevent new request submissions, kill any outstanding requests  */
+	for (i = 0; i < UDC_EP_NUM; i++) {
+		struct pxa27x_ep *ep = &dev->ep[i];
+
+		ep->stopped = 1;
+		nuke(ep, -ESHUTDOWN);
+	}
+	del_timer_sync(&dev->timer);
+
+	/* report disconnect; the driver is already quiesced */
+	if (driver)
+		driver->disconnect(&dev->gadget);
+
+	/* re-init driver-visible data structures */
+	udc_reinit(dev);
+}
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+	struct pxa27x_udc	*dev = the_controller;
+
+	if (!dev)
+		return -ENODEV;
+	if (!driver || driver != dev->driver)
+		return -EINVAL;
+
+	local_irq_disable();
+	udc_disable(dev);
+	stop_activity(dev, driver);
+	local_irq_enable();
+
+	driver->unbind(&dev->gadget);
+	pxa27x_ep_freeall(&dev->gadget);
+	dev->driver = 0;
+
+	device_del(&dev->gadget.dev);
+	device_remove_file(dev->dev, &dev_attr_function);
+
+	DMSG("unregistered gadget driver '%s'\n", driver->driver.name);
+	dump_state(dev);
+	return 0;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+
+/*-------------------------------------------------------------------------*/
+
+static inline void clear_ep_state(struct pxa27x_udc *dev)
+{
+	unsigned i;
+
+	/* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint
+	 * fifos, and pending transactions mustn't be continued in any case.
+	 */
+	for (i = 1; i < UDC_EP_NUM; i++)
+		nuke(&dev->ep[i], -ECONNABORTED);
+}
+
+static void udc_watchdog(unsigned long _dev)
+{
+	struct pxa27x_udc	*dev = (void *)_dev;
+
+	local_irq_disable();
+	if (dev->ep0state == EP0_STALL
+			&& (UDCCSR0 & UDCCSR0_FST) == 0
+			&& (UDCCSR0 & UDCCSR0_SST) == 0) {
+		UDCCSR0 = UDCCSR0_FST|UDCCSR0_FTF;
+		DBG(DBG_VERBOSE, "ep0 re-stall\n");
+		start_watchdog(dev);
+	}
+	local_irq_enable();
+}
+
+static void handle_ep0(struct pxa27x_udc *dev)
+{
+	u32			udccsr0 = UDCCSR0;
+	struct pxa27x_ep	*ep = &dev->ep[0];
+	struct pxa27x_request	*req;
+	union {
+		struct usb_ctrlrequest	r;
+		u8			raw[8];
+		u32			word[2];
+	} u;
+
+	if (list_empty(&ep->queue))
+		req = 0;
+	else
+		req = list_entry(ep->queue.next, struct pxa27x_request, queue);
+
+	/* clear stall status */
+	if (udccsr0 & UDCCSR0_SST) {
+		nuke(ep, -EPIPE);
+		UDCCSR0 = UDCCSR0_SST;
+		del_timer(&dev->timer);
+		ep0_idle(dev);
+	}
+
+	/* previous request unfinished?  non-error iff back-to-back ... */
+	if ((udccsr0 & UDCCSR0_SA) != 0 && dev->ep0state != EP0_IDLE) {
+		nuke(ep, 0);
+		del_timer(&dev->timer);
+		ep0_idle(dev);
+	}
+
+	switch (dev->ep0state) {
+	case EP0_NO_ACTION:
+		dev_info(dev->dev, "%s: Busy\n", __FUNCTION__);
+		/*Fall through */
+	case EP0_IDLE:
+		/* late-breaking status? */
+		udccsr0 = UDCCSR0;
+
+		/* start control request? */
+		if (likely((udccsr0 & (UDCCSR0_OPC|UDCCSR0_SA|UDCCSR0_RNE))
+				== (UDCCSR0_OPC|UDCCSR0_SA|UDCCSR0_RNE))) {
+			int i;
+
+			nuke(ep, -EPROTO);
+			/* read SETUP packet */
+			for (i = 0; i < 2; i++) {
+				if (unlikely(!(UDCCSR0 & UDCCSR0_RNE))) {
+bad_setup:
+					DMSG("SETUP %d!\n", i);
+					goto stall;
+				}
+				u.word [i] =  UDCDR0;
+			}
+			if (unlikely((UDCCSR0 & UDCCSR0_RNE) != 0))
+				goto bad_setup;
+
+			le16_to_cpus(&u.r.wValue);
+			le16_to_cpus(&u.r.wIndex);
+			le16_to_cpus(&u.r.wLength);
+
+			DBG(DBG_VERBOSE, "SETUP %02x.%02x v%04x i%04x l%04x\n",
+				u.r.bRequestType, u.r.bRequest,
+				u.r.wValue, u.r.wIndex, u.r.wLength);
+			/* cope with automagic for some standard requests. */
+			dev->req_std = (u.r.bRequestType & USB_TYPE_MASK)
+						== USB_TYPE_STANDARD;
+			dev->req_config = 0;
+			dev->req_pending = 1;
+#if 0
+			switch (u.r.bRequest) {
+			/* hardware was supposed to hide this */
+			case USB_REQ_SET_CONFIGURATION:
+			case USB_REQ_SET_INTERFACE:
+			case USB_REQ_SET_ADDRESS:
+				dev_err(dev->dev, "Should not come here\n");
+				break;
+			}
+
+#endif
+			if (u.r.bRequestType & USB_DIR_IN)
+				dev->ep0state = EP0_IN_DATA_PHASE;
+			else
+				dev->ep0state = EP0_OUT_DATA_PHASE;
+			i = dev->driver->setup(&dev->gadget, &u.r);
+
+			if (i < 0) {
+				/* hardware automagic preventing STALL... */
+				if (dev->req_config) {
+					/* hardware sometimes neglects to tell
+					 * tell us about config change events,
+					 * so later ones may fail...
+					 */
+					WARN("config change %02x fail %d?\n",
+						u.r.bRequest, i);
+					return;
+					/* TODO experiment:  if has_cfr,
+					 * hardware didn't ACK; maybe we
+					 * could actually STALL!
+					 */
+				}
+				DBG(DBG_VERBOSE, "protocol STALL, "
+					"%02x err %d\n", UDCCSR0, i);
+stall:
+				/* the watchdog timer helps deal with cases
+				 * where udc seems to clear FST wrongly, and
+				 * then NAKs instead of STALLing.
+				 */
+				ep0start(dev, UDCCSR0_FST|UDCCSR0_FTF, "stall");
+				start_watchdog(dev);
+				dev->ep0state = EP0_STALL;
+
+			/* deferred i/o == no response yet */
+			} else if (dev->req_pending) {
+				if (likely(dev->ep0state == EP0_IN_DATA_PHASE
+						|| dev->req_std || u.r.wLength))
+					ep0start(dev, 0, "defer");
+				else
+					ep0start(dev, UDCCSR0_IPR, "defer/IPR");
+			}
+
+			/* expect at least one data or status stage irq */
+			return;
+
+		} else {
+			/* some random early IRQ:
+			 * - we acked FST
+			 * - IPR cleared
+			 * - OPC got set, without SA (likely status stage)
+			 */
+			UDCCSR0 = udccsr0 & (UDCCSR0_SA|UDCCSR0_OPC);
+		}
+		break;
+	case EP0_IN_DATA_PHASE:			/* GET_DESCRIPTOR etc */
+		if (udccsr0 & UDCCSR0_OPC) {
+			UDCCSR0 = UDCCSR0_OPC|UDCCSR0_FTF;
+			DBG(DBG_VERBOSE, "ep0in premature status\n");
+			if (req)
+				done(ep, req, 0);
+			ep0_idle(dev);
+		} else /* irq was IPR clearing */ {
+			if (req) {
+				/* this IN packet might finish the request */
+				(void) write_ep0_fifo(ep, req);
+			} /* else IN token before response was written */
+		}
+		break;
+	case EP0_OUT_DATA_PHASE:		/* SET_DESCRIPTOR etc */
+		if (udccsr0 & UDCCSR0_OPC) {
+			if (req) {
+				/* this OUT packet might finish the request */
+				if (read_ep0_fifo(ep, req))
+					done(ep, req, 0);
+				/* else more OUT packets expected */
+			} /* else OUT token before read was issued */
+		} else /* irq was IPR clearing */ {
+			DBG(DBG_VERBOSE, "ep0out premature status\n");
+			if (req)
+				done(ep, req, 0);
+			ep0_idle(dev);
+		}
+		break;
+	case EP0_STALL:
+		UDCCSR0 = UDCCSR0_FST;
+		break;
+		}
+	UDCISR0 = UDCISR_INT(0, UDCISR_INT_MASK);
+}
+
+
+static void handle_ep(struct pxa27x_ep *ep)
+{
+	struct pxa27x_request	*req;
+	int			completed;
+	u32			udccsr=0;
+
+	DMSG("%s is called\n", __FUNCTION__);
+	do {
+		completed = 0;
+		if (likely (!list_empty(&ep->queue))) {
+			req = list_entry(ep->queue.next,
+					struct pxa27x_request, queue);
+		} else
+			req = 0;
+
+//		udccsr = *ep->reg_udccsr;
+		DMSG("%s: req:%p, udcisr0:0x%x udccsr %p:0x%x\n", __FUNCTION__,
+				req, UDCISR0, ep->reg_udccsr, *ep->reg_udccsr);
+		if (unlikely(ep->dir_in)) {
+			udccsr = (UDCCSR_SST | UDCCSR_TRN) & *ep->reg_udccsr;
+			if (unlikely (udccsr))
+				*ep->reg_udccsr = udccsr;
+
+			if (req && likely ((*ep->reg_udccsr & UDCCSR_FS) != 0))
+				completed = write_fifo(ep, req);
+
+		} else {
+			udccsr = (UDCCSR_SST | UDCCSR_TRN) & *ep->reg_udccsr;
+			if (unlikely(udccsr))
+				*ep->reg_udccsr = udccsr;
+
+			/* fifos can hold packets, ready for reading... */
+			if (likely(req)) {
+				completed = read_fifo(ep, req);
+			} else {
+				pio_irq_disable (ep->pxa_ep_num);
+				*ep->reg_udccsr = UDCCSR_FEF;
+				DMSG("%s: no req for out data\n",
+						__FUNCTION__);
+			}
+		}
+		ep->pio_irqs++;
+	} while (completed);
+}
+
+static void pxa27x_update_eps(struct pxa27x_udc *dev)
+{
+	struct pxa27x_virt_ep *virt_ep;
+	int i;
+
+	for (i = 1; i < UDC_EP_NUM; i++) {
+		if(!dev->ep[i].assigned || !dev->ep[i].usb_ep)
+			continue;
+		virt_ep = container_of(dev->ep[i].usb_ep, struct pxa27x_virt_ep, usb_ep);
+
+		DMSG("%s, Updating eps %d:%d, %d:%d, %d:%d, %p,%p\n", __FUNCTION__, dev->ep[i].config, dev->configuration
+			,dev->ep[i].interface, dev->interface, dev->ep[i].aisn, dev->alternate, virt_ep->pxa_ep, &dev->ep[i]);
+
+		if(dev->ep[i].config == dev->configuration && virt_ep->pxa_ep != &dev->ep[i]) {
+			if ((dev->ep[i].interface == dev->interface &&
+				dev->ep[i].aisn == dev->alternate) || virt_ep->pxa_ep->config != dev->configuration) {
+
+			if (virt_ep->pxa_ep->desc) {
+				DMSG("%s, Changing end point to %d (en/dis)\n", __FUNCTION__, i);
+				pxa27x_ep_disable(&virt_ep->usb_ep);
+				virt_ep->pxa_ep = &dev->ep[i];
+				pxa27x_ep_enable(&virt_ep->usb_ep, virt_ep->desc);
+			} else {
+				DMSG("%s, Changing end point to %d (no en/dis)\n", __FUNCTION__, i);
+				virt_ep->pxa_ep = &dev->ep[i];
+			}
+			}
+		}
+	}
+}
+
+static void pxa27x_change_configuration(struct pxa27x_udc *dev)
+{
+	struct usb_ctrlrequest req ;
+
+	pxa27x_update_eps(dev);
+
+	req.bRequestType = 0;
+	req.bRequest = USB_REQ_SET_CONFIGURATION;
+	req.wValue = dev->configuration;
+	req.wIndex = 0;
+	req.wLength = 0;
+
+	dev->ep0state = EP0_NO_ACTION;
+	dev->driver->setup(&dev->gadget, &req);
+}
+
+static void pxa27x_change_interface(struct pxa27x_udc *dev)
+{
+	struct usb_ctrlrequest  req;
+
+	pxa27x_update_eps(dev);
+
+	req.bRequestType = USB_RECIP_INTERFACE;
+	req.bRequest = USB_REQ_SET_INTERFACE;
+	req.wValue = dev->alternate;
+	req.wIndex = dev->interface;
+	req.wLength = 0;
+
+	dev->ep0state = EP0_NO_ACTION;
+	dev->driver->setup(&dev->gadget, &req);
+}
+
+/*
+ *	pxa27x_udc_irq - interrupt handler
+ *
+ * avoid delays in ep0 processing. the control handshaking isn't always
+ * under software control (pxa250c0 and the pxa255 are better), and delays
+ * could cause usb protocol errors.
+ */
+static irqreturn_t pxa27x_udc_irq(int irq, void *_dev)
+{
+	struct pxa27x_udc	*dev = _dev;
+	int			handled;
+
+	dev->stats.irqs++;
+
+	DBG(DBG_VERBOSE, "Interrupt, UDCISR0:0x%08x, UDCISR1:0x%08x, "
+			"UDCCR:0x%08x\n", UDCISR0, UDCISR1, UDCCR);
+	do {
+		u32 udcir = UDCISR1 & 0xF8000000;
+
+		handled = 0;
+
+		/* SUSpend Interrupt Request */
+		if (unlikely(udcir & UDCISR1_IRSU)) {
+			UDCISR1 = UDCISR1_IRSU;
+			handled = 1;
+			DBG(DBG_VERBOSE, "USB suspend\n");
+			if (dev->gadget.speed != USB_SPEED_UNKNOWN
+					&& dev->driver
+					&& dev->driver->suspend)
+				dev->driver->suspend(&dev->gadget);
+			ep0_idle(dev);
+		}
+
+		/* RESume Interrupt Request */
+		if (unlikely(udcir & UDCISR1_IRRU)) {
+			UDCISR1 = UDCISR1_IRRU;
+			handled = 1;
+			DBG(DBG_VERBOSE, "USB resume\n");
+
+			if (dev->gadget.speed != USB_SPEED_UNKNOWN
+					&& dev->driver
+					&& dev->driver->resume)
+				dev->driver->resume(&dev->gadget);
+		}
+
+		if (unlikely(udcir & UDCISR1_IRCC)) {
+			unsigned config, interface, alternate;
+
+			handled = 1;
+			DBG(DBG_VERBOSE, "USB SET_CONFIGURATION or "
+				"SET_INTERFACE command received\n");
+
+			config = (UDCCR & UDCCR_ACN) >> UDCCR_ACN_S;
+
+			if (dev->configuration != config) {
+				dev->configuration = config;
+				pxa27x_change_configuration(dev) ;
+			}
+
+			interface = (UDCCR & UDCCR_AIN) >> UDCCR_AIN_S;
+			alternate = (UDCCR & UDCCR_AAISN) >> UDCCR_AAISN_S;
+
+			if ((dev->interface != interface) || (dev->alternate != alternate)) {
+				dev->interface = interface;
+				dev->alternate = alternate;
+				pxa27x_change_interface(dev);
+			}
+
+			UDCCR |= UDCCR_SMAC;
+
+			UDCISR1 = UDCISR1_IRCC;
+			DMSG("%s: con:%d,inter:%d,alt:%d\n",
+				__FUNCTION__, config,interface, alternate);
+		}
+
+		/* ReSeT Interrupt Request - USB reset */
+		if (unlikely(udcir & UDCISR1_IRRS)) {
+			UDCISR1 = UDCISR1_IRRS;
+			handled = 1;
+
+			if ((UDCCR & UDCCR_UDA) == 0) {
+				DBG(DBG_VERBOSE, "USB reset start\n");
+
+				/* reset driver and endpoints,
+				 * in case that's not yet done
+				 */
+				stop_activity(dev, dev->driver);
+			}
+			INFO("USB reset\n");
+			dev->gadget.speed = USB_SPEED_FULL;
+			memset(&dev->stats, 0, sizeof dev->stats);
+
+		} else {
+			u32	udcisr0 = UDCISR0 ;
+			u32	udcisr1 = UDCISR1 & 0xFFFF;
+			int	i;
+
+			if (unlikely (!udcisr0 && !udcisr1))
+				continue;
+
+			DBG(DBG_VERY_NOISY, "irq %02x.%02x\n", udcisr1,udcisr0);
+
+			/* control traffic */
+			if (udcisr0 & UDCISR0_IR0) {
+				dev->ep[0].pio_irqs++;
+				handle_ep0(dev);
+				handled = 1;
+			}
+
+			udcisr0 >>= 2;
+			/* endpoint data transfers */
+			for (i = 1; udcisr0!=0 && i < 16; udcisr0>>=2,i++) {
+				UDCISR0 = UDCISR_INT(i, UDCISR_INT_MASK);
+
+				if (udcisr0 & UDC_INT_FIFOERROR)
+					dev_err(dev->dev, " Endpoint %d Fifo error\n", i);
+				if (udcisr0 & UDC_INT_PACKETCMP) {
+					handle_ep(&dev->ep[i]);
+					handled = 1;
+				}
+
+			}
+
+			for (i = 0; udcisr1!=0 && i < 8; udcisr1 >>= 2, i++) {
+				UDCISR1 = UDCISR_INT(i, UDCISR_INT_MASK);
+
+				if (udcisr1 & UDC_INT_FIFOERROR) {
+					dev_err(dev->dev, "Endpoint %d fifo error\n", (i+16));
+				}
+
+				if (udcisr1 & UDC_INT_PACKETCMP) {
+					handle_ep(&dev->ep[i+16]);
+					handled = 1;
+				}
+			}
+		}
+
+		/* we could also ask for 1 msec SOF (SIR) interrupts */
+
+	} while (handled);
+	return IRQ_HANDLED;
+}
+
+int write_ep0_zlp(void)
+{
+	UDCCSR0 = UDCCSR0_IPR;
+	return 0;
+}
+EXPORT_SYMBOL(write_ep0_zlp);
+
+static void udc_init_ep(struct pxa27x_udc *dev)
+{
+	int i;
+
+	INIT_LIST_HEAD(&dev->gadget.ep_list);
+	INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+
+	for (i = 0; i < UDC_EP_NUM; i++) {
+		struct pxa27x_ep *ep = &dev->ep[i];
+
+		ep->dma = -1;
+		if (i != 0) {
+			memset(ep, 0, sizeof(*ep));
+		}
+		INIT_LIST_HEAD(&ep->queue);
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void nop_release(struct device *dev)
+{
+	DMSG("%s %s\n", __FUNCTION__, dev->bus_id);
+}
+
+/* this uses load-time allocation and initialization (instead of
+ * doing it at run-time) to save code, eliminate fault paths, and
+ * be more obviously correct.
+ */
+
+static struct pxa27x_udc memory = {
+	.gadget = {
+		.ops		= &pxa27x_udc_ops,
+		.ep0		= &memory.virt_ep0.usb_ep,
+		.name		= driver_name,
+		.dev = {
+			.bus_id		= "gadget",
+			.release	= nop_release,
+		},
+	},
+
+	/* control endpoint */
+	.virt_ep0 = {
+		.pxa_ep = &memory.ep[0],
+		.usb_ep = {
+			.name		= ep0name,
+			.ops		= &pxa27x_ep_ops,
+			.maxpacket	= EP0_FIFO_SIZE,
+		},
+	},
+
+	.ep[0] = {
+		.usb_ep 	= &memory.virt_ep0.usb_ep,
+		.dev		= &memory,
+		.reg_udccsr	= &UDCCSR0,
+		.reg_udcdr	= &UDCDR0,
+	},
+};
+
+#define CP15R0_VENDOR_MASK	0xffffe000
+#define CP15R0_XSCALE_VALUE	0x69054000	/* intel/arm/xscale */
+
+static int __init pxa27x_udc_probe(struct platform_device *_dev)
+{
+	struct pxa27x_udc *dev = &memory;
+	int retval;
+	u32 chiprev;
+
+	/* insist on Intel/ARM/XScale */
+	asm("mrc%? p15, 0, %0, c0, c0" : "=r" (chiprev));
+	if ((chiprev & CP15R0_VENDOR_MASK) != CP15R0_XSCALE_VALUE) {
+		printk(KERN_ERR "%s: not XScale!\n", driver_name);
+		return -ENODEV;
+	}
+	/* other non-static parts of init */
+	dev->dev = &_dev->dev;
+	dev->mach = _dev->dev.platform_data;
+
+	init_timer(&dev->timer);
+	dev->timer.function = udc_watchdog;
+	dev->timer.data = (unsigned long) dev;
+
+	device_initialize(&dev->gadget.dev);
+	dev->gadget.dev.parent = &_dev->dev;
+	dev->gadget.dev.dma_mask = _dev->dev.dma_mask;
+
+	the_controller = dev;
+	platform_set_drvdata(_dev, dev);
+
+	udc_disable(dev);
+	udc_init_ep(dev);
+	udc_reinit(dev);
+
+	/* irq setup after old hardware state is cleaned up */
+	retval = request_irq(IRQ_USB, pxa27x_udc_irq,
+			0, driver_name, dev);
+	if (retval != 0) {
+		dev_err(dev->dev, "%s: can't get irq %i, err %d\n",
+			driver_name, IRQ_USB, retval);
+		return -EBUSY;
+	}
+	dev->got_irq = 1;
+
+	create_proc_files();
+
+	return 0;
+}
+
+static int __exit pxa27x_udc_remove(struct platform_device *_dev)
+{
+	struct pxa27x_udc *dev = platform_get_drvdata(_dev);
+
+	udc_disable(dev);
+	remove_proc_files();
+	usb_gadget_unregister_driver(dev->driver);
+
+	pxa27x_ep_freeall(&dev->gadget);
+
+	if (dev->got_irq) {
+		free_irq(IRQ_USB, dev);
+		dev->got_irq = 0;
+	}
+	platform_set_drvdata(_dev, 0);
+	the_controller = 0;
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static void pxa27x_udc_shutdown(struct platform_device *_dev)
+{
+	struct pxa27x_udc *dev = platform_get_drvdata(_dev);
+
+        udc_disable(dev);
+}
+
+static int pxa27x_udc_suspend(struct platform_device *_dev, pm_message_t state)
+{
+	int i;
+	struct pxa27x_udc *dev = platform_get_drvdata(_dev);
+
+	DMSG("%s is called\n", __FUNCTION__);
+
+	dev->udccsr0 = UDCCSR0;
+	for(i=1; (i<UDC_EP_NUM); i++) {
+		if (dev->ep[i].assigned) {
+			struct pxa27x_ep *ep = &dev->ep[i];
+			ep->udccsr_value = *ep->reg_udccsr;
+			ep->udccr_value = *ep->reg_udccr;
+			DMSG("EP%d, udccsr:0x%x, udccr:0x%x\n",
+				i, *ep->reg_udccsr, *ep->reg_udccr);
+		}
+	}
+
+	udc_clear_mask_UDCCR(UDCCR_UDE);
+	pxa_set_cken(CKEN11_USB, 0);
+
+	return 0;
+}
+
+static int pxa27x_udc_resume(struct platform_device *_dev)
+{
+	int i;
+	struct pxa27x_udc *dev = platform_get_drvdata(_dev);
+
+	DMSG("%s is called\n", __FUNCTION__);
+	UDCCSR0 = dev->udccsr0 & (UDCCSR0_FST | UDCCSR0_DME);
+	for (i=1; i < UDC_EP_NUM; i++) {
+		if (dev->ep[i].assigned) {
+			struct pxa27x_ep *ep = &dev->ep[i];
+			*ep->reg_udccsr = ep->udccsr_value;
+			*ep->reg_udccr = ep->udccr_value;
+			DMSG("EP%d, udccsr:0x%x, udccr:0x%x\n",
+				i, *ep->reg_udccsr, *ep->reg_udccr);
+		}
+	}
+
+	udc_enable(dev);
+
+	/* OTGPH bit is set when sleep mode is entered.
+	 * it indicates that OTG pad is retaining its state.
+	 * Upon exit from sleep mode and before clearing OTGPH,
+	 * Software must configure the USB OTG pad, UDC, and UHC
+	 * to the state they were in before entering sleep mode.*/
+	PSSR  |= PSSR_OTGPH;
+
+	return 0;
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+static struct platform_driver udc_driver = {
+	.driver	   = {
+		.name = "pxa2xx-udc",
+	},
+	.probe     = pxa27x_udc_probe,
+	.remove    = __exit_p(pxa27x_udc_remove),
+#ifdef CONFIG_PM
+	.shutdown  = pxa27x_udc_shutdown,
+	.suspend   = pxa27x_udc_suspend,
+	.resume    = pxa27x_udc_resume
+#endif
+};
+
+static int __init udc_init(void)
+{
+	printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION);
+	return platform_driver_register(&udc_driver);
+}
+module_init(udc_init);
+
+static void __exit udc_exit(void)
+{
+	platform_driver_unregister(&udc_driver);
+}
+module_exit(udc_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Frank Becker, Robert Schwebel, David Brownell");
+MODULE_LICENSE("GPL");
diff -urN linux-2.6.25/drivers/usb/gadget/pxa27x_udc.h linux-2.6.25-vpac1/drivers/usb/gadget/pxa27x_udc.h
--- linux-2.6.25/drivers/usb/gadget/pxa27x_udc.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.25-vpac1/drivers/usb/gadget/pxa27x_udc.h	2008-04-24 15:12:18.000000000 +0200
@@ -0,0 +1,342 @@
+/*
+ * linux/drivers/usb/gadget/pxa27x_udc.h
+ * Intel PXA27x on-chip full speed USB device controller
+ *
+ * Copyright (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
+ * Copyright (C) 2003 David Brownell
+ * Copyright (C) 2004 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __LINUX_USB_GADGET_PXA27X_H
+#define __LINUX_USB_GADGET_PXA27X_H
+
+#include <linux/types.h>
+
+struct pxa27x_udc;
+
+struct pxa27x_ep {
+	struct usb_ep				ep;
+	struct pxa27x_udc			*dev;
+	struct usb_ep				*usb_ep;
+	const struct usb_endpoint_descriptor	*desc;
+
+	struct list_head			queue;
+	unsigned long				pio_irqs;
+	unsigned long				dma_irqs;
+	
+	int					dma; 
+	unsigned				fifo_size;
+	unsigned				ep_num;
+	unsigned				pxa_ep_num;
+	unsigned				ep_type;
+
+	unsigned				stopped : 1;
+	unsigned				dma_con : 1;
+	unsigned				dir_in : 1;
+	unsigned				assigned : 1;
+
+	unsigned				config;
+	unsigned				interface;
+	unsigned				aisn;
+	/* UDCCSR = UDC Control/Status Register for this EP
+	 * UBCR = UDC Byte Count Remaining (contents of OUT fifo)
+	 * UDCDR = UDC Endpoint Data Register (the fifo)
+	 * UDCCR = UDC Endpoint Configuration Registers
+	 * DRCM = DMA Request Channel Map
+	 */
+	volatile u32				*reg_udccsr;
+	volatile u32				*reg_udcbcr;
+	volatile u32				*reg_udcdr;
+	volatile u32				*reg_udccr;
+#ifdef USE_DMA
+	volatile u32				*reg_drcmr;
+#define	drcmr(n)  .reg_drcmr = & DRCMR ## n ,
+#else
+#define	drcmr(n)
+#endif
+
+#ifdef CONFIG_PM
+	unsigned				udccsr_value;
+	unsigned				udccr_value;
+#endif
+};
+
+struct pxa27x_virt_ep {
+	struct usb_ep				usb_ep;
+	const struct usb_endpoint_descriptor	*desc;
+	struct pxa27x_ep			*pxa_ep;
+};
+
+struct pxa27x_request {
+	struct usb_request			req;
+	struct list_head			queue;
+};
+
+enum ep0_state {
+	EP0_IDLE,
+	EP0_IN_DATA_PHASE,
+	EP0_OUT_DATA_PHASE,
+//	EP0_END_XFER,
+	EP0_STALL,
+	EP0_NO_ACTION
+};
+
+#define EP0_FIFO_SIZE	((unsigned)16)
+#define BULK_FIFO_SIZE	((unsigned)64)
+#define ISO_FIFO_SIZE	((unsigned)256)
+#define INT_FIFO_SIZE	((unsigned)8)
+
+struct udc_stats {
+	struct ep0stats {
+		unsigned long		ops;
+		unsigned long		bytes;
+	} read, write;
+	unsigned long			irqs;
+};
+
+#ifdef CONFIG_USB_PXA27X_SMALL
+/* when memory's tight, SMALL config saves code+data.  */
+//#undef	USE_DMA
+//#define	UDC_EP_NUM	3
+#endif
+
+#ifndef	UDC_EP_NUM
+#define	UDC_EP_NUM	24
+#endif
+
+struct pxa27x_udc {
+	struct usb_gadget			gadget;
+	struct usb_gadget_driver		*driver;
+
+	enum ep0_state				ep0state;
+	struct udc_stats			stats;
+	unsigned				got_irq : 1,
+						got_disc : 1,
+						has_cfr : 1,
+						req_pending : 1,
+						req_std : 1,
+						req_config : 1;
+
+#define start_watchdog(dev) mod_timer(&dev->timer, jiffies + (HZ/200))
+	struct timer_list			timer;
+
+	struct device				*dev;
+	struct pxa2xx_udc_mach_info		*mach;
+	u64					dma_mask;
+	struct pxa27x_virt_ep			virt_ep0;
+	struct pxa27x_ep			ep[UDC_EP_NUM];
+	unsigned int 				ep_num;
+
+	unsigned				configuration, 
+						interface, 
+						alternate;
+#ifdef CONFIG_PM
+	unsigned				udccsr0;
+#endif
+};
+
+/*-------------------------------------------------------------------------*/
+#if 0
+#ifdef DEBUG
+#define HEX_DISPLAY(n)	do { \
+	if (machine_is_mainstone())\
+		 { MST_LEDDAT1 = (n); } \
+	} while(0)
+
+#define HEX_DISPLAY1(n)	HEX_DISPLAY(n)
+
+#define HEX_DISPLAY2(n)	do { \
+	if (machine_is_mainstone()) \
+		{ MST_LEDDAT2 = (n); } \
+	} while(0)
+
+#endif /* DEBUG */
+#endif
+/*-------------------------------------------------------------------------*/
+
+/* LEDs are only for debug */
+#ifndef HEX_DISPLAY
+#define HEX_DISPLAY(n)		do {} while(0)
+#endif
+
+#ifndef LED_CONNECTED_ON
+#define LED_CONNECTED_ON	do {} while(0)
+#define LED_CONNECTED_OFF	do {} while(0)
+#endif
+#ifndef LED_EP0_ON
+#define LED_EP0_ON		do {} while (0)
+#define LED_EP0_OFF		do {} while (0)
+#endif
+
+static struct pxa27x_udc *the_controller;
+
+#if 0
+/*-------------------------------------------------------------------------*/
+
+
+/* one GPIO should be used to detect host disconnect */
+static inline int is_usb_connected(void)
+{
+	if (!the_controller->mach->udc_is_connected)
+		return 1;
+	return the_controller->mach->udc_is_connected();
+}
+
+/* one GPIO should force the host to see this device (or not) */
+static inline void make_usb_disappear(void)
+{
+	if (!the_controller->mach->udc_command)
+		return;
+	the_controller->mach->udc_command(PXA27X_UDC_CMD_DISCONNECT);
+}
+
+static inline void let_usb_appear(void)
+{
+	if (!the_controller->mach->udc_command)
+		return;
+	the_controller->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Debugging support vanishes in non-debug builds.  DBG_NORMAL should be
+ * mostly silent during normal use/testing, with no timing side-effects.
+ */
+#define DBG_NORMAL	1	/* error paths, device state transitions */
+#define DBG_VERBOSE	2	/* add some success path trace info */
+#define DBG_NOISY	3	/* ... even more: request level */
+#define DBG_VERY_NOISY	4	/* ... even more: packet level */
+
+#ifdef DEBUG
+
+static const char *state_name[] = {
+	"EP0_IDLE",
+	"EP0_IN_DATA_PHASE", "EP0_OUT_DATA_PHASE",
+	"EP0_END_XFER", "EP0_STALL"
+};
+
+#define DMSG(stuff...) printk(KERN_ERR "udc: " stuff)
+
+#ifdef VERBOSE
+#    define UDC_DEBUG DBG_VERBOSE
+#else
+#    define UDC_DEBUG DBG_NORMAL
+#endif
+
+static void __attribute__ ((__unused__))
+dump_udccr(const char *label)
+{
+	u32	udccr = UDCCR;
+	DMSG("%s 0x%08x =%s%s%s%s%s%s%s%s%s%s, con=%d,inter=%d,altinter=%d\n",
+		label, udccr,
+		(udccr & UDCCR_OEN) ? " oen":"",
+		(udccr & UDCCR_AALTHNP) ? " aalthnp":"",
+		(udccr & UDCCR_AHNP) ? " rem" : "",
+		(udccr & UDCCR_BHNP) ? " rstir" : "",
+		(udccr & UDCCR_DWRE) ? " dwre" : "",
+		(udccr & UDCCR_SMAC) ? " smac" : "",
+		(udccr & UDCCR_EMCE) ? " emce" : "",
+		(udccr & UDCCR_UDR) ? " udr" : "",
+		(udccr & UDCCR_UDA) ? " uda" : "",
+		(udccr & UDCCR_UDE) ? " ude" : "",
+		(udccr & UDCCR_ACN) >> UDCCR_ACN_S,
+		(udccr & UDCCR_AIN) >> UDCCR_AIN_S,
+		(udccr & UDCCR_AAISN)>> UDCCR_AAISN_S );
+}
+
+static void __attribute__ ((__unused__))
+dump_udccsr0(const char *label)
+{
+	u32		udccsr0 = UDCCSR0;
+
+	DMSG("%s %s 0x%08x =%s%s%s%s%s%s%s\n",
+		label, state_name[the_controller->ep0state], udccsr0,
+		(udccsr0 & UDCCSR0_SA) ? " sa" : "",
+		(udccsr0 & UDCCSR0_RNE) ? " rne" : "",
+		(udccsr0 & UDCCSR0_FST) ? " fst" : "",
+		(udccsr0 & UDCCSR0_SST) ? " sst" : "",
+		(udccsr0 & UDCCSR0_DME) ? " dme" : "",
+		(udccsr0 & UDCCSR0_IPR) ? " ipr" : "",
+		(udccsr0 & UDCCSR0_OPC) ? " opr" : "");
+}
+
+static void __attribute__ ((__unused__))
+dump_state(struct pxa27x_udc *dev)
+{
+	unsigned	i;
+
+	DMSG("%s, udcicr %02X.%02X, udcsir %02X.%02x, udcfnr %02X\n",
+		state_name[dev->ep0state],
+		UDCICR1, UDCICR0, UDCISR1, UDCISR0, UDCFNR);
+	dump_udccr("udccr");
+
+	if (!dev->driver) {
+		DMSG("no gadget driver bound\n");
+		return;
+	} else
+		DMSG("ep0 driver '%s'\n", dev->driver->driver.name);
+
+	
+	dump_udccsr0 ("udccsr0");
+	DMSG("ep0 IN %lu/%lu, OUT %lu/%lu\n",
+		dev->stats.write.bytes, dev->stats.write.ops,
+		dev->stats.read.bytes, dev->stats.read.ops);
+
+	for (i = 1; i < UDC_EP_NUM; i++) {
+		if (dev->ep [i].desc == 0)
+			continue;
+		DMSG ("udccs%d = %02x\n", i, *dev->ep->reg_udccsr);
+	}
+}
+
+#if 0
+static void dump_regs(u8 ep)
+{
+	DMSG("EP:%d UDCCSR:0x%08x UDCBCR:0x%08x\n UDCCR:0x%08x\n",
+		ep,UDCCSN(ep), UDCBCN(ep), UDCCN(ep));
+}
+static void dump_req (struct pxa27x_request *req)
+{
+	struct usb_request *r = &req->req;
+
+	DMSG("%s: buf:0x%08x length:%d dma:0x%08x actual:%d\n",
+			__FUNCTION__, (unsigned)r->buf, r->length,
+			r->dma,	r->actual);
+}
+#endif
+
+#else
+
+#define DMSG(stuff...)		do{}while(0)
+
+#define	dump_udccr(x)	do{}while(0)
+#define	dump_udccsr0(x)	do{}while(0)
+#define	dump_state(x)	do{}while(0)
+
+#define UDC_DEBUG ((unsigned)0)
+
+#endif
+
+#define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0)
+
+#define WARN(stuff...) printk(KERN_WARNING "udc: " stuff)
+#define INFO(stuff...) printk(KERN_INFO "udc: " stuff)
+
+
+#endif /* __LINUX_USB_GADGET_PXA27X_H */
diff -urN linux-2.6.25/drivers/usb/gadget/pxa2xx_udc_gpio.c linux-2.6.25-vpac1/drivers/usb/gadget/pxa2xx_udc_gpio.c
--- linux-2.6.25/drivers/usb/gadget/pxa2xx_udc_gpio.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.25-vpac1/drivers/usb/gadget/pxa2xx_udc_gpio.c	2008-04-24 15:12:18.000000000 +0200
@@ -0,0 +1,72 @@
+/*
+ * pxa2xx_udc_gpio.c: Generic driver for GPIO-controlled PXA2xx UDC.
+ * 
+ * */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/dpm.h>
+#include <asm/arch/udc.h>
+#include <asm/arch/pxa2xx_udc_gpio.h>
+
+static struct pxa2xx_udc_gpio_info *pdata;
+
+static void pda_udc_command(int cmd)
+{
+	switch (cmd) {
+		case PXA2XX_UDC_CMD_DISCONNECT:
+			DPM_DEBUG("pda_udc: Turning off port\n");
+			dpm_power(&pdata->power_ctrl, 0);
+			break;
+		case PXA2XX_UDC_CMD_CONNECT:
+			DPM_DEBUG("pda_udc: Turning on port\n");
+			dpm_power(&pdata->power_ctrl, 1);
+			break;
+		default:
+			printk("pda_udc: unknown command!\n");
+			break;
+	}
+}
+
+static int pda_udc_is_connected(void)
+{
+	int status = !!gpiodev_get_value(&pdata->detect_gpio) ^ pdata->detect_gpio_negative;
+	return status;
+}
+
+static struct pxa2xx_udc_mach_info pda_udc_info __initdata = {
+	.udc_is_connected = pda_udc_is_connected,
+	.udc_command      = pda_udc_command,
+};
+
+static int pda_udc_probe(struct platform_device * pdev)
+{
+        printk("pxa2xx-udc-gpio: Generic driver for GPIO-controlled PXA2xx UDC\n");
+	pdata = pdev->dev.platform_data;
+
+	pxa_set_udc_info(&pda_udc_info);
+	return 0;
+}
+
+static struct platform_driver pda_udc_driver = {
+	.driver	  = {
+		.name     = "pxa2xx-udc-gpio",
+	},
+	.probe    = pda_udc_probe,
+};
+
+static int __init pda_udc_init(void)
+{
+	return platform_driver_register(&pda_udc_driver);
+}
+
+#ifdef MODULE
+module_init(pda_udc_init);
+#else	/* start early for dependencies */
+fs_initcall(pda_udc_init);
+#endif
+
+MODULE_AUTHOR("Paul Sokolovsky <pmiscml@gmail.com>");
+MODULE_DESCRIPTION("Generic driver for GPIO-controlled PXA2xx UDC");
+MODULE_LICENSE("GPL");
diff -urN linux-2.6.25/drivers/usb/gadget/rndis.c linux-2.6.25-vpac1/drivers/usb/gadget/rndis.c
--- linux-2.6.25/drivers/usb/gadget/rndis.c	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/usb/gadget/rndis.c	2008-04-24 15:12:18.000000000 +0200
@@ -180,17 +180,13 @@
 	if (!resp) return -ENOMEM;
 
 	if (buf_len && rndis_debug > 1) {
-		DBG("query OID %08x value, len %d:\n", OID, buf_len);
+		DEBUG("query OID %08x value, len %d:\n", OID, buf_len);
 		for (i = 0; i < buf_len; i += 16) {
-			DBG("%03d: %08x %08x %08x %08x\n", i,
-				le32_to_cpu(get_unaligned((__le32 *)
-					&buf[i])),
-				le32_to_cpu(get_unaligned((__le32 *)
-					&buf[i + 4])),
-				le32_to_cpu(get_unaligned((__le32 *)
-					&buf[i + 8])),
-				le32_to_cpu(get_unaligned((__le32 *)
-					&buf[i + 12])));
+			DEBUG ("%03d: %08x %08x %08x %08x\n", i,
+				le32_to_cpup((__le32 *)&buf[i]),
+				le32_to_cpup((__le32 *)&buf[i + 4]),
+				le32_to_cpup((__le32 *)&buf[i + 8]),
+				le32_to_cpup((__le32 *)&buf[i + 12]));
 		}
 	}
 
@@ -204,7 +200,7 @@
 
 	/* mandatory */
 	case OID_GEN_SUPPORTED_LIST:
-		DBG("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
+		DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
 		length = sizeof (oid_supported_list);
 		count  = length / sizeof (u32);
 		for (i = 0; i < count; i++)
@@ -214,7 +210,7 @@
 
 	/* mandatory */
 	case OID_GEN_HARDWARE_STATUS:
-		DBG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__);
 		/* Bogus question!
 		 * Hardware must be ready to receive high level protocols.
 		 * BTW:
@@ -227,14 +223,14 @@
 
 	/* mandatory */
 	case OID_GEN_MEDIA_SUPPORTED:
-		DBG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
 		*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_GEN_MEDIA_IN_USE:
-		DBG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
 		/* one medium, one transport... (maybe you do it better) */
 		*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
 		retval = 0;
@@ -242,7 +238,7 @@
 
 	/* mandatory */
 	case OID_GEN_MAXIMUM_FRAME_SIZE:
-		DBG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].dev) {
 			*outbuf = cpu_to_le32 (
 				rndis_per_dev_params [configNr].dev->mtu);
@@ -253,7 +249,7 @@
 	/* mandatory */
 	case OID_GEN_LINK_SPEED:
 		if (rndis_debug > 1)
-			DBG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
+			DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].media_state
 				== NDIS_MEDIA_STATE_DISCONNECTED)
 			*outbuf = __constant_cpu_to_le32 (0);
@@ -265,7 +261,7 @@
 
 	/* mandatory */
 	case OID_GEN_TRANSMIT_BLOCK_SIZE:
-		DBG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].dev) {
 			*outbuf = cpu_to_le32 (
 				rndis_per_dev_params [configNr].dev->mtu);
@@ -275,7 +271,7 @@
 
 	/* mandatory */
 	case OID_GEN_RECEIVE_BLOCK_SIZE:
-		DBG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].dev) {
 			*outbuf = cpu_to_le32 (
 				rndis_per_dev_params [configNr].dev->mtu);
@@ -285,7 +281,7 @@
 
 	/* mandatory */
 	case OID_GEN_VENDOR_ID:
-		DBG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
 		*outbuf = cpu_to_le32 (
 			rndis_per_dev_params [configNr].vendorID);
 		retval = 0;
@@ -293,7 +289,7 @@
 
 	/* mandatory */
 	case OID_GEN_VENDOR_DESCRIPTION:
-		DBG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__);
 		length = strlen (rndis_per_dev_params [configNr].vendorDescr);
 		memcpy (outbuf,
 			rndis_per_dev_params [configNr].vendorDescr, length);
@@ -301,7 +297,7 @@
 		break;
 
 	case OID_GEN_VENDOR_DRIVER_VERSION:
-		DBG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
 		/* Created as LE */
 		*outbuf = rndis_driver_version;
 		retval = 0;
@@ -309,14 +305,14 @@
 
 	/* mandatory */
 	case OID_GEN_CURRENT_PACKET_FILTER:
-		DBG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
 		*outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_GEN_MAXIMUM_TOTAL_SIZE:
-		DBG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
 		retval = 0;
 		break;
@@ -324,14 +320,14 @@
 	/* mandatory */
 	case OID_GEN_MEDIA_CONNECT_STATUS:
 		if (rndis_debug > 1)
-			DBG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
+			DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
 		*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 						.media_state);
 		retval = 0;
 		break;
 
 	case OID_GEN_PHYSICAL_MEDIUM:
-		DBG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
@@ -341,7 +337,7 @@
 	 * versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
 	 */
 	case OID_GEN_MAC_OPTIONS:		/* from WinME */
-		DBG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32(
 			  NDIS_MAC_OPTION_RECEIVE_SERIALIZED
 			| NDIS_MAC_OPTION_FULL_DUPLEX);
@@ -353,7 +349,7 @@
 	/* mandatory */
 	case OID_GEN_XMIT_OK:
 		if (rndis_debug > 1)
-			DBG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
+			DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (
 			    rndis_per_dev_params [configNr].stats->tx_packets -
@@ -366,7 +362,7 @@
 	/* mandatory */
 	case OID_GEN_RCV_OK:
 		if (rndis_debug > 1)
-			DBG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
+			DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (
 			    rndis_per_dev_params [configNr].stats->rx_packets -
@@ -379,7 +375,7 @@
 	/* mandatory */
 	case OID_GEN_XMIT_ERROR:
 		if (rndis_debug > 1)
-			DBG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
+			DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->tx_errors);
@@ -390,7 +386,7 @@
 	/* mandatory */
 	case OID_GEN_RCV_ERROR:
 		if (rndis_debug > 1)
-			DBG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
+			DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->rx_errors);
@@ -400,7 +396,7 @@
 
 	/* mandatory */
 	case OID_GEN_RCV_NO_BUFFER:
-		DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->rx_dropped);
@@ -410,7 +406,7 @@
 
 #ifdef	RNDIS_OPTIONAL_STATS
 	case OID_GEN_DIRECTED_BYTES_XMIT:
-		DBG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__);
 		/*
 		 * Aunt Tilly's size of shoes
 		 * minus antarctica count of penguins
@@ -430,7 +426,7 @@
 		break;
 
 	case OID_GEN_DIRECTED_FRAMES_XMIT:
-		DBG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__);
 		/* dito */
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (
@@ -446,7 +442,7 @@
 		break;
 
 	case OID_GEN_MULTICAST_BYTES_XMIT:
-		DBG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->multicast*1234);
@@ -455,7 +451,7 @@
 		break;
 
 	case OID_GEN_MULTICAST_FRAMES_XMIT:
-		DBG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->multicast);
@@ -464,7 +460,7 @@
 		break;
 
 	case OID_GEN_BROADCAST_BYTES_XMIT:
-		DBG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->tx_packets/42*255);
@@ -473,7 +469,7 @@
 		break;
 
 	case OID_GEN_BROADCAST_FRAMES_XMIT:
-		DBG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->tx_packets/42);
@@ -482,19 +478,19 @@
 		break;
 
 	case OID_GEN_DIRECTED_BYTES_RCV:
-		DBG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 
 	case OID_GEN_DIRECTED_FRAMES_RCV:
-		DBG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 
 	case OID_GEN_MULTICAST_BYTES_RCV:
-		DBG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->multicast * 1111);
@@ -503,7 +499,7 @@
 		break;
 
 	case OID_GEN_MULTICAST_FRAMES_RCV:
-		DBG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->multicast);
@@ -512,7 +508,7 @@
 		break;
 
 	case OID_GEN_BROADCAST_BYTES_RCV:
-		DBG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->rx_packets/42*255);
@@ -521,7 +517,7 @@
 		break;
 
 	case OID_GEN_BROADCAST_FRAMES_RCV:
-		DBG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->rx_packets/42);
@@ -530,7 +526,7 @@
 		break;
 
 	case OID_GEN_RCV_CRC_ERROR:
-		DBG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->rx_crc_errors);
@@ -539,7 +535,7 @@
 		break;
 
 	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
-		DBG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
+		DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
@@ -549,7 +545,7 @@
 
 	/* mandatory */
 	case OID_802_3_PERMANENT_ADDRESS:
-		DBG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);
+		DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].dev) {
 			length = ETH_ALEN;
 			memcpy (outbuf,
@@ -561,7 +557,7 @@
 
 	/* mandatory */
 	case OID_802_3_CURRENT_ADDRESS:
-		DBG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);
+		DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].dev) {
 			length = ETH_ALEN;
 			memcpy (outbuf,
@@ -573,7 +569,7 @@
 
 	/* mandatory */
 	case OID_802_3_MULTICAST_LIST:
-		DBG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
+		DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
 		/* Multicast base address only */
 		*outbuf = __constant_cpu_to_le32 (0xE0000000);
 		retval = 0;
@@ -581,21 +577,21 @@
 
 	/* mandatory */
 	case OID_802_3_MAXIMUM_LIST_SIZE:
-		DBG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
+		DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
 		/* Multicast base address only */
 		*outbuf = __constant_cpu_to_le32 (1);
 		retval = 0;
 		break;
 
 	case OID_802_3_MAC_OPTIONS:
-		DBG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__);
+		DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__);
 		break;
 
 	/* ieee802.3 statistics OIDs (table 4-4) */
 
 	/* mandatory */
 	case OID_802_3_RCV_ERROR_ALIGNMENT:
-		DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__);
+		DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->rx_frame_errors);
@@ -605,51 +601,51 @@
 
 	/* mandatory */
 	case OID_802_3_XMIT_ONE_COLLISION:
-		DBG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
+		DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_802_3_XMIT_MORE_COLLISIONS:
-		DBG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
+		DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 
 #ifdef	RNDIS_OPTIONAL_STATS
 	case OID_802_3_XMIT_DEFERRED:
-		DBG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__);
+		DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__);
 		/* TODO */
 		break;
 
 	case OID_802_3_XMIT_MAX_COLLISIONS:
-		DBG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__);
+		DEBUG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__);
 		/* TODO */
 		break;
 
 	case OID_802_3_RCV_OVERRUN:
-		DBG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__);
+		DEBUG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__);
 		/* TODO */
 		break;
 
 	case OID_802_3_XMIT_UNDERRUN:
-		DBG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__);
+		DEBUG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__);
 		/* TODO */
 		break;
 
 	case OID_802_3_XMIT_HEARTBEAT_FAILURE:
-		DBG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__);
+		DEBUG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__);
 		/* TODO */
 		break;
 
 	case OID_802_3_XMIT_TIMES_CRS_LOST:
-		DBG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__);
+		DEBUG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__);
 		/* TODO */
 		break;
 
 	case OID_802_3_XMIT_LATE_COLLISIONS:
-		DBG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__);
+		DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__);
 		/* TODO */
 		break;
 #endif	/* RNDIS_OPTIONAL_STATS */
@@ -657,7 +653,7 @@
 #ifdef	RNDIS_PM
 	/* power management OIDs (table 4-5) */
 	case OID_PNP_CAPABILITIES:
-		DBG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__);
+		DEBUG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__);
 
 		/* for now, no wakeup capabilities */
 		length = sizeof (struct NDIS_PNP_CAPABILITIES);
@@ -665,8 +661,8 @@
 		retval = 0;
 		break;
 	case OID_PNP_QUERY_POWER:
-		DBG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__,
-				le32_to_cpu(get_unaligned((__le32 *)buf)) - 1);
+		DEBUG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__,
+				le32_to_cpup((__le32 *) buf) - 1);
 		/* only suspend is a real power state, and
 		 * it can't be entered by OID_PNP_SET_POWER...
 		 */
@@ -702,17 +698,13 @@
 		return -ENOMEM;
 
 	if (buf_len && rndis_debug > 1) {
-		DBG("set OID %08x value, len %d:\n", OID, buf_len);
+		DEBUG("set OID %08x value, len %d:\n", OID, buf_len);
 		for (i = 0; i < buf_len; i += 16) {
-			DBG("%03d: %08x %08x %08x %08x\n", i,
-				le32_to_cpu(get_unaligned((__le32 *)
-					&buf[i])),
-				le32_to_cpu(get_unaligned((__le32 *)
-					&buf[i + 4])),
-				le32_to_cpu(get_unaligned((__le32 *)
-					&buf[i + 8])),
-				le32_to_cpu(get_unaligned((__le32 *)
-					&buf[i + 12])));
+			DEBUG ("%03d: %08x %08x %08x %08x\n", i,
+				le32_to_cpup((__le32 *)&buf[i]),
+				le32_to_cpup((__le32 *)&buf[i + 4]),
+				le32_to_cpup((__le32 *)&buf[i + 8]),
+				le32_to_cpup((__le32 *)&buf[i + 12]));
 		}
 	}
 
@@ -726,9 +718,8 @@
 		 *	PROMISCUOUS, DIRECTED,
 		 *	MULTICAST, ALL_MULTICAST, BROADCAST
 		 */
-		*params->filter = (u16) le32_to_cpu(get_unaligned(
-				(__le32 *)buf));
-		DBG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
+		*params->filter = (u16) le32_to_cpup((__le32 *)buf);
+		DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
 			__FUNCTION__, *params->filter);
 
 		/* this call has a significant side effect:  it's
@@ -753,7 +744,7 @@
 
 	case OID_802_3_MULTICAST_LIST:
 		/* I think we can ignore this */
-		DBG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
+		DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
 		retval = 0;
 		break;
 #if 0
@@ -761,7 +752,7 @@
 		{
 		struct rndis_config_parameter	*param;
 		param = (struct rndis_config_parameter *) buf;
-		DBG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
+		DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
 			__FUNCTION__,
 			min(cpu_to_le32(param->ParameterNameLength),80),
 			buf + param->ParameterNameOffset);
@@ -777,8 +768,8 @@
 		 * resuming, Windows forces a reset, and then SET_POWER D0.
 		 * FIXME ... then things go batty; Windows wedges itself.
 		 */
-		i = le32_to_cpu(get_unaligned((__le32 *)buf));
-		DBG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1);
+		i = le32_to_cpup((__force __le32 *)buf);
+		DEBUG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1);
 		switch (i) {
 		case NdisDeviceStateD0:
 			*params->filter = params->saved_filter;
@@ -855,7 +846,7 @@
 	rndis_query_cmplt_type *resp;
 	rndis_resp_t            *r;
 
-	// DBG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID));
+	// DEBUG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID));
 	if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
 
 	/*
@@ -908,15 +899,15 @@
 	BufOffset = le32_to_cpu (buf->InformationBufferOffset);
 
 #ifdef	VERBOSE
-	DBG("%s: Length: %d\n", __FUNCTION__, BufLength);
-	DBG("%s: Offset: %d\n", __FUNCTION__, BufOffset);
-	DBG("%s: InfoBuffer: ", __FUNCTION__);
+	DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength);
+	DEBUG("%s: Offset: %d\n", __FUNCTION__, BufOffset);
+	DEBUG("%s: InfoBuffer: ", __FUNCTION__);
 
 	for (i = 0; i < BufLength; i++) {
-		DBG("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
+		DEBUG ("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
 	}
 
-	DBG("\n");
+	DEBUG ("\n");
 #endif
 
 	resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
@@ -1064,8 +1055,8 @@
 		return -ENOMEM;
 
 	tmp = (__le32 *) buf;
-	MsgType   = le32_to_cpu(get_unaligned(tmp++));
-	MsgLength = le32_to_cpu(get_unaligned(tmp++));
+	MsgType   = le32_to_cpup(tmp++);
+	MsgLength = le32_to_cpup(tmp++);
 
 	if (configNr >= RNDIS_MAX_CONFIGS)
 		return -ENOTSUPP;
@@ -1079,14 +1070,14 @@
 	/* For USB: responses may take up to 10 seconds */
 	switch (MsgType) {
 	case REMOTE_NDIS_INITIALIZE_MSG:
-		DBG("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
+		DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
 			__FUNCTION__ );
 		params->state = RNDIS_INITIALIZED;
 		return  rndis_init_response (configNr,
 					(rndis_init_msg_type *) buf);
 
 	case REMOTE_NDIS_HALT_MSG:
-		DBG("%s: REMOTE_NDIS_HALT_MSG\n",
+		DEBUG("%s: REMOTE_NDIS_HALT_MSG\n",
 			__FUNCTION__ );
 		params->state = RNDIS_UNINITIALIZED;
 		if (params->dev) {
@@ -1104,7 +1095,7 @@
 					(rndis_set_msg_type *) buf);
 
 	case REMOTE_NDIS_RESET_MSG:
-		DBG("%s: REMOTE_NDIS_RESET_MSG\n",
+		DEBUG("%s: REMOTE_NDIS_RESET_MSG\n",
 			__FUNCTION__ );
 		return rndis_reset_response (configNr,
 					(rndis_reset_msg_type *) buf);
@@ -1112,7 +1103,7 @@
 	case REMOTE_NDIS_KEEPALIVE_MSG:
 		/* For USB: host does this every 5 seconds */
 		if (rndis_debug > 1)
-			DBG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
+			DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
 				__FUNCTION__ );
 		return rndis_keepalive_response (configNr,
 						 (rndis_keepalive_msg_type *)
@@ -1128,7 +1119,7 @@
 		{
 			unsigned i;
 			for (i = 0; i < MsgLength; i += 16) {
-				DBG("%03d: "
+				DEBUG ("%03d: "
 					" %02x %02x %02x %02x"
 					" %02x %02x %02x %02x"
 					" %02x %02x %02x %02x"
@@ -1159,18 +1150,18 @@
 		if (!rndis_per_dev_params [i].used) {
 			rndis_per_dev_params [i].used = 1;
 			rndis_per_dev_params [i].ack = rndis_control_ack;
-			DBG("%s: configNr = %d\n", __FUNCTION__, i);
+			DEBUG("%s: configNr = %d\n", __FUNCTION__, i);
 			return i;
 		}
 	}
-	DBG("failed\n");
+	DEBUG("failed\n");
 
 	return -1;
 }
 
 void rndis_deregister (int configNr)
 {
-	DBG("%s: \n", __FUNCTION__ );
+	DEBUG("%s: \n", __FUNCTION__ );
 
 	if (configNr >= RNDIS_MAX_CONFIGS) return;
 	rndis_per_dev_params [configNr].used = 0;
@@ -1182,7 +1173,7 @@
 			 struct net_device_stats *stats,
 			 u16 *cdc_filter)
 {
-	DBG("%s:\n", __FUNCTION__ );
+	DEBUG("%s:\n", __FUNCTION__ );
 	if (!dev || !stats) return -1;
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
@@ -1195,7 +1186,7 @@
 
 int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
 {
-	DBG("%s:\n", __FUNCTION__ );
+	DEBUG("%s:\n", __FUNCTION__ );
 	if (!vendorDescr) return -1;
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
@@ -1207,7 +1198,7 @@
 
 int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
 {
-	DBG("%s: %u %u\n", __FUNCTION__, medium, speed);
+	DEBUG("%s: %u %u\n", __FUNCTION__, medium, speed);
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
 	rndis_per_dev_params [configNr].medium = medium;
@@ -1386,7 +1377,7 @@
 			break;
 		default:
 			if (fl_speed) p->speed = speed;
-			else DBG("%c is not valid\n", c);
+			else DEBUG ("%c is not valid\n", c);
 			break;
 		}
 
@@ -1415,12 +1406,12 @@
 		if (!(rndis_connect_state [i]
 				= create_proc_entry (name, 0660, NULL)))
 		{
-			DBG("%s :remove entries", __FUNCTION__);
+			DEBUG ("%s :remove entries", __FUNCTION__);
 			while (i) {
 				sprintf (name, NAME_TEMPLATE, --i);
 				remove_proc_entry (name, NULL);
 			}
-			DBG("\n");
+			DEBUG ("\n");
 			return -EIO;
 		}
 
diff -urN linux-2.6.25/drivers/usb/gadget/rndis.h linux-2.6.25-vpac1/drivers/usb/gadget/rndis.h
--- linux-2.6.25/drivers/usb/gadget/rndis.h	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/usb/gadget/rndis.h	2008-04-24 15:12:18.000000000 +0200
@@ -195,7 +195,7 @@
 	__le32	PerPacketInfoLength;
 	__le32	VcHandle;
 	__le32	Reserved;
-} __attribute__ ((packed));
+};
 
 struct rndis_config_parameter
 {
diff -urN linux-2.6.25/drivers/usb/gadget/serial.c linux-2.6.25-vpac1/drivers/usb/gadget/serial.c
--- linux-2.6.25/drivers/usb/gadget/serial.c	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/usb/gadget/serial.c	2008-05-04 14:29:28.000000000 +0200
@@ -17,15 +17,34 @@
  *
  */
 
+#include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.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/utsname.h>
+#include <linux/wait.h>
+#include <linux/proc_fs.h>
 #include <linux/device.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+#include <asm/uaccess.h>
+
 #include <linux/usb/ch9.h>
 #include <linux/usb/cdc.h>
-#include <linux/usb/gadget.h>
+#include <linux/usb_gadget.h>
 
 #include "gadget_chips.h"
 
@@ -70,29 +89,30 @@
 #define GS_DEFAULT_PARITY		USB_CDC_NO_PARITY
 #define GS_DEFAULT_CHAR_FORMAT		USB_CDC_1_STOP_BITS
 
-/* maxpacket and other transfer characteristics vary by speed. */
-static inline struct usb_endpoint_descriptor *
-choose_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
-		struct usb_endpoint_descriptor *fs)
-{
-	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
-		return hs;
-	return fs;
-}
-
+/* select highspeed/fullspeed, hiding highspeed if not configured */
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+#define GS_SPEED_SELECT(is_hs,hs,fs) ((is_hs) ? (hs) : (fs))
+#else
+#define GS_SPEED_SELECT(is_hs,hs,fs) (fs)
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
 
 /* debug settings */
-#ifdef DEBUG
+#ifdef GS_DEBUG
 static int debug = 1;
-#else
-#define	debug 0
-#endif
 
 #define gs_debug(format, arg...) \
 	do { if (debug) pr_debug(format, ## arg); } while (0)
 #define gs_debug_level(level, format, arg...) \
 	do { if (debug >= level) pr_debug(format, ## arg); } while (0)
 
+#else
+
+#define gs_debug(format, arg...) \
+      do { } while(0)
+#define gs_debug_level(level, format, arg...) \
+      do { } while(0)
+
+#endif /* GS_DEBUG */
 
 /* Thanks to NetChip Technologies for donating this product ID.
  *
@@ -127,10 +147,10 @@
 
 /* the port structure holds info for each port, one for each minor number */
 struct gs_port {
-	struct gs_dev		*port_dev;	/* pointer to device struct */
+	struct gs_dev 		*port_dev;	/* pointer to device struct */
 	struct tty_struct	*port_tty;	/* pointer to tty struct */
 	spinlock_t		port_lock;
-	int			port_num;
+	int 			port_num;
 	int			port_open_count;
 	int			port_in_use;	/* open/close in progress */
 	wait_queue_head_t	port_write_wait;/* waiting to write */
@@ -168,7 +188,7 @@
 /* tty driver */
 static int gs_open(struct tty_struct *tty, struct file *file);
 static void gs_close(struct tty_struct *tty, struct file *file);
-static int gs_write(struct tty_struct *tty,
+static int gs_write(struct tty_struct *tty, 
 	const unsigned char *buf, int count);
 static void gs_put_char(struct tty_struct *tty, unsigned char ch);
 static void gs_flush_chars(struct tty_struct *tty);
@@ -202,7 +222,7 @@
 static void gs_disconnect(struct usb_gadget *gadget);
 static int gs_set_config(struct gs_dev *dev, unsigned config);
 static void gs_reset_config(struct gs_dev *dev);
-static int gs_build_config_buf(u8 *buf, struct usb_gadget *g,
+static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed,
 		u8 type, unsigned int index, int is_otg);
 
 static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len,
@@ -239,7 +259,7 @@
 static const char *EP_OUT_NAME;
 static const char *EP_NOTIFY_NAME;
 
-static struct mutex gs_open_close_lock[GS_NUM_PORTS];
+static struct semaphore	gs_open_close_sem[GS_NUM_PORTS];
 
 static unsigned int read_q_size = GS_DEFAULT_READ_Q_SIZE;
 static unsigned int write_q_size = GS_DEFAULT_WRITE_Q_SIZE;
@@ -395,18 +415,18 @@
 };
 
 static const struct usb_cdc_call_mgmt_descriptor gs_call_mgmt_descriptor = {
-	.bLength =		sizeof(gs_call_mgmt_descriptor),
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_CALL_MANAGEMENT_TYPE,
-	.bmCapabilities =	0,
-	.bDataInterface =	1,	/* index of data interface */
+	.bLength =  		sizeof(gs_call_mgmt_descriptor),
+	.bDescriptorType = 	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType = 	USB_CDC_CALL_MANAGEMENT_TYPE,
+	.bmCapabilities = 	0,
+	.bDataInterface = 	1,	/* index of data interface */
 };
 
 static struct usb_cdc_acm_descriptor gs_acm_descriptor = {
-	.bLength =		sizeof(gs_acm_descriptor),
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_ACM_TYPE,
-	.bmCapabilities =	0,
+	.bLength =  		sizeof(gs_acm_descriptor),
+	.bDescriptorType = 	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType = 	USB_CDC_ACM_TYPE,
+	.bmCapabilities = 	0,
 };
 
 static const struct usb_cdc_union_desc gs_union_desc = {
@@ -416,7 +436,7 @@
 	.bMasterInterface0 =	0,	/* index of control interface */
 	.bSlaveInterface0 =	1,	/* index of data interface */
 };
-
+ 
 static struct usb_endpoint_descriptor gs_fullspeed_notify_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
@@ -462,6 +482,7 @@
 	NULL,
 };
 
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 static struct usb_endpoint_descriptor gs_highspeed_notify_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
@@ -515,13 +536,15 @@
 	NULL,
 };
 
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
+
 
 /* Module */
 MODULE_DESCRIPTION(GS_LONG_NAME);
 MODULE_AUTHOR("Al Borchers");
 MODULE_LICENSE("GPL");
 
-#ifdef DEBUG
+#ifdef GS_DEBUG
 module_param(debug, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on");
 #endif
@@ -574,7 +597,7 @@
 	tty_set_operations(gs_tty_driver, &gs_tty_ops);
 
 	for (i=0; i < GS_NUM_PORTS; i++)
-		mutex_init(&gs_open_close_lock[i]);
+		sema_init(&gs_open_close_sem[i], 1);
 
 	retval = tty_register_driver(gs_tty_driver);
 	if (retval) {
@@ -617,7 +640,7 @@
 	struct gs_port *port;
 	struct gs_dev *dev;
 	struct gs_buf *buf;
-	struct mutex *mtx;
+	struct semaphore *sem;
 	int ret;
 
 	port_num = tty->index;
@@ -734,12 +757,12 @@
 
 exit_unlock_port:
 	spin_unlock_irqrestore(&port->port_lock, flags);
-	mutex_unlock(mtx);
+	up(sem);
 	return ret;
 
 exit_unlock_dev:
 	spin_unlock_irqrestore(&dev->dev_lock, flags);
-	mutex_unlock(mtx);
+	up(sem);
 	return ret;
 
 }
@@ -761,7 +784,7 @@
 static void gs_close(struct tty_struct *tty, struct file *file)
 {
 	struct gs_port *port = tty->driver_data;
-	struct mutex *mtx;
+	struct semaphore *sem;
 
 	if (port == NULL) {
 		pr_err("gs_close: NULL port pointer\n");
@@ -770,8 +793,8 @@
 
 	gs_debug("gs_close: (%d,%p,%p)\n", port->port_num, tty, file);
 
-	mtx = &gs_open_close_lock[port->port_num];
-	mutex_lock(mtx);
+	sem = &gs_open_close_sem[port->port_num];
+	down(sem);
 
 	spin_lock_irq(&port->port_lock);
 
@@ -825,7 +848,7 @@
 
 exit:
 	spin_unlock_irq(&port->port_lock);
-	mutex_unlock(mtx);
+	up(sem);
 }
 
 /*
@@ -893,8 +916,7 @@
 		return;
 	}
 
-	gs_debug("gs_put_char: (%d,%p) char=0x%x, called from %p\n",
-		port->port_num, tty, ch, __builtin_return_address(0));
+	gs_debug("gs_put_char: (%d,%p) char=0x%x, called from %p, %p, %p\n", port->port_num, tty, ch, __builtin_return_address(0), __builtin_return_address(1), __builtin_return_address(2));
 
 	spin_lock_irqsave(&port->port_lock, flags);
 
@@ -1094,11 +1116,7 @@
 		len = gs_send_packet(dev, req->buf, ep->maxpacket);
 
 		if (len > 0) {
-			gs_debug_level(3, "gs_send: len=%d, 0x%2.2x "
-					"0x%2.2x 0x%2.2x ...\n", len,
-					*((unsigned char *)req->buf),
-					*((unsigned char *)req->buf+1),
-					*((unsigned char *)req->buf+2));
+gs_debug_level(3, "gs_send: len=%d, 0x%2.2x 0x%2.2x 0x%2.2x ...\n", len, *((unsigned char *)req->buf), *((unsigned char *)req->buf+1), *((unsigned char *)req->buf+2));
 			list_del(&req_entry->re_entry);
 			req->length = len;
 			spin_unlock_irqrestore(&dev->dev_lock, flags);
@@ -1249,7 +1267,7 @@
 
 	switch(req->status) {
 	case 0:
-		/* normal completion */
+ 		/* normal completion */
 		gs_recv_packet(dev, req->buf, req->actual);
 requeue:
 		req->length = ep->maxpacket;
@@ -1335,6 +1353,7 @@
 	struct usb_ep *ep;
 	struct gs_dev *dev;
 	int gcnum;
+	struct usb_endpoint_config ep_config[2];
 
 	/* Some controllers can't support CDC ACM:
 	 * - sh doesn't support multiple interfaces or configs;
@@ -1355,22 +1374,33 @@
 			__constant_cpu_to_le16(GS_VERSION_NUM|0x0099);
 	}
 
+	ep_config[0].config = GS_BULK_CONFIG_ID;
+	ep_config[0].interface = gs_bulk_interface_desc.bInterfaceNumber;
+	ep_config[0].altinterface = gs_bulk_interface_desc.bAlternateSetting;
+	ep_config[1].config = GS_ACM_CONFIG_ID;
+	ep_config[1].interface = gs_data_interface_desc.bInterfaceNumber;
+	ep_config[1].altinterface = gs_data_interface_desc.bAlternateSetting;
+
 	usb_ep_autoconfig_reset(gadget);
 
-	ep = usb_ep_autoconfig(gadget, &gs_fullspeed_in_desc);
+	ep = usb_ep_autoconfig(gadget, &gs_fullspeed_in_desc, &ep_config[0], 2);
 	if (!ep)
 		goto autoconf_fail;
 	EP_IN_NAME = ep->name;
 	ep->driver_data = ep;	/* claim the endpoint */
 
-	ep = usb_ep_autoconfig(gadget, &gs_fullspeed_out_desc);
+	ep = usb_ep_autoconfig(gadget, &gs_fullspeed_out_desc, &ep_config[0], 2);
 	if (!ep)
 		goto autoconf_fail;
 	EP_OUT_NAME = ep->name;
 	ep->driver_data = ep;	/* claim the endpoint */
 
 	if (use_acm) {
-		ep = usb_ep_autoconfig(gadget, &gs_fullspeed_notify_desc);
+		ep_config[0].config = GS_ACM_CONFIG_ID;
+		ep_config[0].interface = gs_control_interface_desc.bInterfaceNumber;
+		ep_config[0].altinterface = gs_control_interface_desc.bAlternateSetting;
+
+		ep = usb_ep_autoconfig(gadget, &gs_fullspeed_notify_desc, &ep_config[0], 1);
 		if (!ep) {
 			pr_err("gs_bind: cannot run ACM on %s\n", gadget->name);
 			goto autoconf_fail;
@@ -1385,30 +1415,29 @@
 		? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC;
 	gs_device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
 
-	if (gadget_is_dualspeed(gadget)) {
-		gs_qualifier_desc.bDeviceClass = use_acm
-			? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC;
-		/* assume ep0 uses the same packet size for both speeds */
-		gs_qualifier_desc.bMaxPacketSize0 =
-			gs_device_desc.bMaxPacketSize0;
-		/* assume endpoints are dual-speed */
-		gs_highspeed_notify_desc.bEndpointAddress =
-			gs_fullspeed_notify_desc.bEndpointAddress;
-		gs_highspeed_in_desc.bEndpointAddress =
-			gs_fullspeed_in_desc.bEndpointAddress;
-		gs_highspeed_out_desc.bEndpointAddress =
-			gs_fullspeed_out_desc.bEndpointAddress;
-	}
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	gs_qualifier_desc.bDeviceClass = use_acm
+		? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC;
+	/* assume ep0 uses the same packet size for both speeds */
+	gs_qualifier_desc.bMaxPacketSize0 = gs_device_desc.bMaxPacketSize0;
+	/* assume endpoints are dual-speed */
+	gs_highspeed_notify_desc.bEndpointAddress =
+		gs_fullspeed_notify_desc.bEndpointAddress;
+	gs_highspeed_in_desc.bEndpointAddress =
+		gs_fullspeed_in_desc.bEndpointAddress;
+	gs_highspeed_out_desc.bEndpointAddress =
+		gs_fullspeed_out_desc.bEndpointAddress;
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
 
 	usb_gadget_set_selfpowered(gadget);
 
-	if (gadget_is_otg(gadget)) {
+	if (gadget->is_otg) {
 		gs_otg_descriptor.bmAttributes |= USB_OTG_HNP,
 		gs_bulk_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 		gs_acm_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	gs_device = dev = kzalloc(sizeof(struct gs_dev), GFP_KERNEL);
+	gs_device = dev = kmalloc(sizeof(struct gs_dev), GFP_KERNEL);
 	if (dev == NULL)
 		return -ENOMEM;
 
@@ -1416,6 +1445,7 @@
 		init_utsname()->sysname, init_utsname()->release,
 		gadget->name);
 
+	memset(dev, 0, sizeof(struct gs_dev));
 	dev->dev_gadget = gadget;
 	spin_lock_init(&dev->dev_lock);
 	INIT_LIST_HEAD(&dev->dev_req_list);
@@ -1467,12 +1497,6 @@
 			dev->dev_ctrl_req = NULL;
 		}
 		gs_free_ports(dev);
-		if (dev->dev_notify_ep)
-			usb_ep_disable(dev->dev_notify_ep);
-		if (dev->dev_in_ep)
-			usb_ep_disable(dev->dev_in_ep);
-		if (dev->dev_out_ep)
-			usb_ep_disable(dev->dev_out_ep);
 		kfree(dev);
 		set_gadget_data(gadget, NULL);
 	}
@@ -1557,8 +1581,9 @@
 			memcpy(req->buf, &gs_device_desc, ret);
 			break;
 
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 		case USB_DT_DEVICE_QUALIFIER:
-			if (!gadget_is_dualspeed(gadget))
+			if (!gadget->is_dualspeed)
 				break;
 			ret = min(wLength,
 				(u16)sizeof(struct usb_qualifier_descriptor));
@@ -1566,13 +1591,14 @@
 			break;
 
 		case USB_DT_OTHER_SPEED_CONFIG:
-			if (!gadget_is_dualspeed(gadget))
+			if (!gadget->is_dualspeed)
 				break;
 			/* fall through */
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
 		case USB_DT_CONFIG:
-			ret = gs_build_config_buf(req->buf, gadget,
+			ret = gs_build_config_buf(req->buf, gadget->speed,
 				wValue >> 8, wValue & 0xff,
-				gadget_is_otg(gadget));
+				gadget->is_otg);
 			if (ret >= 0)
 				ret = min(wLength, (u16)ret);
 			break;
@@ -1677,12 +1703,14 @@
 
 	switch (ctrl->bRequest) {
 	case USB_CDC_REQ_SET_LINE_CODING:
-		/* FIXME Submit req to read the data; have its completion
-		 * handler copy that data to port->port_line_coding (iff
-		 * it's valid) and maybe pass it on.  Until then, fail.
-		 */
-		pr_warning("gs_setup: set_line_coding "
-				"unuspported\n");
+		ret = min(wLength,
+        		(u16)sizeof(struct usb_cdc_line_coding));
+		if (port) {
+		        spin_lock(&port->port_lock);
+	        	memcpy(&port->port_line_coding, req->buf, ret);
+		        spin_unlock(&port->port_lock);
+		}
+		ret = 0;
 		break;
 
 	case USB_CDC_REQ_GET_LINE_CODING:
@@ -1697,12 +1725,7 @@
 		break;
 
 	case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
-		/* FIXME Submit req to read the data; have its completion
-		 * handler use that to set the state (iff it's valid) and
-		 * maybe pass it on.  Until then, fail.
-		 */
-		pr_warning("gs_setup: set_control_line_state "
-				"unuspported\n");
+		ret = 0;
 		break;
 
 	default:
@@ -1814,7 +1837,8 @@
 
 		if (EP_NOTIFY_NAME
 		&& strcmp(ep->name, EP_NOTIFY_NAME) == 0) {
-			ep_desc = choose_ep_desc(gadget,
+			ep_desc = GS_SPEED_SELECT(
+				gadget->speed == USB_SPEED_HIGH,
 				&gs_highspeed_notify_desc,
 				&gs_fullspeed_notify_desc);
 			ret = usb_ep_enable(ep,ep_desc);
@@ -1831,8 +1855,9 @@
 		}
 
 		else if (strcmp(ep->name, EP_IN_NAME) == 0) {
-			ep_desc = choose_ep_desc(gadget,
-				&gs_highspeed_in_desc,
+			ep_desc = GS_SPEED_SELECT(
+				gadget->speed == USB_SPEED_HIGH,
+ 				&gs_highspeed_in_desc,
 				&gs_fullspeed_in_desc);
 			ret = usb_ep_enable(ep,ep_desc);
 			if (ret == 0) {
@@ -1848,7 +1873,8 @@
 		}
 
 		else if (strcmp(ep->name, EP_OUT_NAME) == 0) {
-			ep_desc = choose_ep_desc(gadget,
+			ep_desc = GS_SPEED_SELECT(
+				gadget->speed == USB_SPEED_HIGH,
 				&gs_highspeed_out_desc,
 				&gs_fullspeed_out_desc);
 			ret = usb_ep_enable(ep,ep_desc);
@@ -1970,11 +1996,11 @@
  * Builds the config descriptors in the given buffer and returns the
  * length, or a negative error number.
  */
-static int gs_build_config_buf(u8 *buf, struct usb_gadget *g,
+static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed,
 	u8 type, unsigned int index, int is_otg)
 {
 	int len;
-	int high_speed = 0;
+	int high_speed;
 	const struct usb_config_descriptor *config_desc;
 	const struct usb_descriptor_header **function;
 
@@ -1982,22 +2008,20 @@
 		return -EINVAL;
 
 	/* other speed switches high and full speed */
-	if (gadget_is_dualspeed(g)) {
-		high_speed = (g->speed == USB_SPEED_HIGH);
-		if (type == USB_DT_OTHER_SPEED_CONFIG)
-			high_speed = !high_speed;
-	}
+	high_speed = (speed == USB_SPEED_HIGH);
+	if (type == USB_DT_OTHER_SPEED_CONFIG)
+		high_speed = !high_speed;
 
 	if (use_acm) {
 		config_desc = &gs_acm_config_desc;
-		function = high_speed
-			? gs_acm_highspeed_function
-			: gs_acm_fullspeed_function;
+		function = GS_SPEED_SELECT(high_speed,
+			gs_acm_highspeed_function,
+			gs_acm_fullspeed_function);
 	} else {
 		config_desc = &gs_bulk_config_desc;
-		function = high_speed
-			? gs_bulk_highspeed_function
-			: gs_bulk_fullspeed_function;
+		function = GS_SPEED_SELECT(high_speed,
+			gs_bulk_highspeed_function,
+			gs_bulk_fullspeed_function);
 	}
 
 	/* for now, don't advertise srp-only devices */
@@ -2211,7 +2235,7 @@
  *
  * Free the buffer and all associated memory.
  */
-static void gs_buf_free(struct gs_buf *gb)
+void gs_buf_free(struct gs_buf *gb)
 {
 	if (gb) {
 		kfree(gb->buf_buf);
@@ -2224,7 +2248,7 @@
  *
  * Clear out all data in the circular buffer.
  */
-static void gs_buf_clear(struct gs_buf *gb)
+void gs_buf_clear(struct gs_buf *gb)
 {
 	if (gb != NULL)
 		gb->buf_get = gb->buf_put;
@@ -2237,7 +2261,7 @@
  * Return the number of bytes of data available in the circular
  * buffer.
  */
-static unsigned int gs_buf_data_avail(struct gs_buf *gb)
+unsigned int gs_buf_data_avail(struct gs_buf *gb)
 {
 	if (gb != NULL)
 		return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size;
@@ -2251,7 +2275,7 @@
  * Return the number of bytes of space available in the circular
  * buffer.
  */
-static unsigned int gs_buf_space_avail(struct gs_buf *gb)
+unsigned int gs_buf_space_avail(struct gs_buf *gb)
 {
 	if (gb != NULL)
 		return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size;
@@ -2267,8 +2291,7 @@
  *
  * Return the number of bytes copied.
  */
-static unsigned int
-gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count)
+unsigned int gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count)
 {
 	unsigned int len;
 
@@ -2306,8 +2329,7 @@
  *
  * Return the number of bytes copied.
  */
-static unsigned int
-gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count)
+unsigned int gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count)
 {
 	unsigned int len;
 
diff -urN linux-2.6.25/drivers/usb/gadget/usbstring.c linux-2.6.25-vpac1/drivers/usb/gadget/usbstring.c
--- linux-2.6.25/drivers/usb/gadget/usbstring.c	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/usb/gadget/usbstring.c	2008-04-24 15:12:18.000000000 +0200
@@ -15,7 +15,7 @@
 #include <linux/init.h>
 
 #include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
+#include <linux/usb_gadget.h>
 
 #include <asm/unaligned.h>
 
diff -urN linux-2.6.25/drivers/usb/gadget/zero.c linux-2.6.25-vpac1/drivers/usb/gadget/zero.c
--- linux-2.6.25/drivers/usb/gadget/zero.c	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/usb/gadget/zero.c	2008-04-24 15:12:18.000000000 +0200
@@ -1,22 +1,38 @@
 /*
  * zero.c -- Gadget Zero, for USB development
  *
- * Copyright (C) 2003-2007 David Brownell
+ * Copyright (C) 2003-2004 David Brownell
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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.
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * 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.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 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.
  */
 
 
@@ -41,28 +57,41 @@
  * 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).
- *
- * Why is *this* driver using two configurations, rather than setting up
- * two interfaces with different functions?  To help verify that multiple
- * configuration infrastucture is working correctly; also, so that it can
- * work with low capability USB controllers without four bulk endpoints.
  */
 
-/* #define VERBOSE_DEBUG */
+#define DEBUG 1
+// #define VERBOSE
 
+#include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.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/utsname.h>
 #include <linux/device.h>
+#include <linux/moduleparam.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
 
 #include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
+#include <linux/usb_gadget.h>
 
 #include "gadget_chips.h"
 
 
 /*-------------------------------------------------------------------------*/
 
-#define DRIVER_VERSION		"Lughnasadh, 2007"
+#define DRIVER_VERSION		"St Patrick's Day 2004"
 
 static const char shortname [] = "zero";
 static const char longname [] = "Gadget Zero";
@@ -103,16 +132,30 @@
 	struct timer_list	resume;
 };
 
-#define DBG(d, fmt, args...) \
-	dev_dbg(&(d)->gadget->dev , fmt , ## args)
-#define VDBG(d, fmt, args...) \
-	dev_vdbg(&(d)->gadget->dev , fmt , ## args)
-#define ERROR(d, fmt, args...) \
-	dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARN(d, fmt, args...) \
-	dev_warn(&(d)->gadget->dev , fmt , ## args)
-#define INFO(d, fmt, args...) \
-	dev_info(&(d)->gadget->dev , fmt , ## args)
+#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)
 
 /*-------------------------------------------------------------------------*/
 
@@ -284,6 +327,8 @@
 	NULL,
 };
 
+#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.
@@ -339,20 +384,17 @@
 };
 
 /* maxpacket and other transfer characteristics vary by speed. */
-static inline struct usb_endpoint_descriptor *
-ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
-		struct usb_endpoint_descriptor *fs)
-{
-	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
-		return hs;
-	return fs;
-}
+#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
+
+#else
 
-static char manufacturer[50];
+/* if there's no high speed support, maxpacket doesn't change. */
+#define ep_desc(g,hs,fs) fs
 
-/* default serial number takes at least two packets */
-static char serial[] = "0123456789.0123456789.0123456789";
+#endif	/* !CONFIG_USB_GADGET_DUALSPEED */
 
+static char				manufacturer [50];
+static char				serial [40];
 
 /* static strings, in UTF-8 */
 static struct usb_string		strings [] = {
@@ -394,29 +436,30 @@
 	int				is_source_sink;
 	int				len;
 	const struct usb_descriptor_header **function;
-	int				hs = 0;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	int				hs = (gadget->speed == USB_SPEED_HIGH);
+#endif
 
 	/* two configurations will always be index 0 and index 1 */
 	if (index > 1)
 		return -EINVAL;
 	is_source_sink = loopdefault ? (index == 1) : (index == 0);
 
-	if (gadget_is_dualspeed(gadget)) {
-		hs = (gadget->speed == USB_SPEED_HIGH);
-		if (type == USB_DT_OTHER_SPEED_CONFIG)
-			hs = !hs;
-	}
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	if (type == USB_DT_OTHER_SPEED_CONFIG)
+		hs = !hs;
 	if (hs)
 		function = is_source_sink
 			? hs_source_sink_function
 			: hs_loopback_function;
 	else
+#endif
 		function = is_source_sink
 			? fs_source_sink_function
 			: fs_loopback_function;
 
 	/* for now, don't advertise srp-only devices */
-	if (!gadget_is_otg(gadget))
+	if (!gadget->is_otg)
 		function++;
 
 	len = usb_gadget_config_buf (is_source_sink
@@ -439,7 +482,8 @@
 	req = usb_ep_alloc_request (ep, GFP_ATOMIC);
 	if (req) {
 		req->length = length;
-		req->buf = kmalloc(length, GFP_ATOMIC);
+		req->buf = usb_ep_alloc_buffer (ep, length,
+				&req->dma, GFP_ATOMIC);
 		if (!req->buf) {
 			usb_ep_free_request (ep, req);
 			req = NULL;
@@ -450,25 +494,13 @@
 
 static void free_ep_req (struct usb_ep *ep, struct usb_request *req)
 {
-	kfree(req->buf);
+	if (req->buf)
+		usb_ep_free_buffer (ep, req->buf, req->dma, req->length);
 	usb_ep_free_request (ep, req);
 }
 
 /*-------------------------------------------------------------------------*/
 
-/*
- * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripherals,
- * this just sinks bulk packets OUT to the peripheral and sources them IN
- * to the host, optionally with specific data patterns.
- *
- * In terms of control messaging, this supports all the standard requests
- * plus two that support control-OUT tests.
- *
- * Note that because this doesn't queue more than one request at a time,
- * some other function must be used to test queueing logic.  The network
- * link (g_ether) is probably the best option for that.
- */
-
 /* optionally require specific source/sink data patterns  */
 
 static int
@@ -505,7 +537,12 @@
 	return 0;
 }
 
-static void reinit_write_data(struct usb_ep *ep, struct usb_request *req)
+static void
+reinit_write_data (
+	struct zero_dev		*dev,
+	struct usb_ep		*ep,
+	struct usb_request	*req
+)
 {
 	unsigned	i;
 	u8		*buf = req->buf;
@@ -532,16 +569,16 @@
 
 	switch (status) {
 
-	case 0:				/* normal completion? */
+	case 0: 			/* normal completion? */
 		if (ep == dev->out_ep) {
 			check_read_data (dev, ep, req);
 			memset (req->buf, 0x55, req->length);
 		} else
-			reinit_write_data(ep, req);
+			reinit_write_data (dev, ep, req);
 		break;
 
 	/* this endpoint is normally active while we're configured */
-	case -ECONNABORTED:		/* hardware forced ep reset */
+	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,
@@ -573,7 +610,8 @@
 	}
 }
 
-static struct usb_request *source_sink_start_ep(struct usb_ep *ep)
+static struct usb_request *
+source_sink_start_ep (struct usb_ep *ep, gfp_t gfp_flags)
 {
 	struct usb_request	*req;
 	int			status;
@@ -586,11 +624,11 @@
 	req->complete = source_sink_complete;
 
 	if (strcmp (ep->name, EP_IN_NAME) == 0)
-		reinit_write_data(ep, req);
+		reinit_write_data (ep->driver_data, ep, req);
 	else
 		memset (req->buf, 0x55, req->length);
 
-	status = usb_ep_queue(ep, req, GFP_ATOMIC);
+	status = usb_ep_queue (ep, req, gfp_flags);
 	if (status) {
 		struct zero_dev	*dev = ep->driver_data;
 
@@ -602,7 +640,8 @@
 	return req;
 }
 
-static int set_source_sink_config(struct zero_dev *dev)
+static int
+set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags)
 {
 	int			result = 0;
 	struct usb_ep		*ep;
@@ -617,7 +656,7 @@
 			result = usb_ep_enable (ep, d);
 			if (result == 0) {
 				ep->driver_data = dev;
-				if (source_sink_start_ep(ep) != NULL) {
+				if (source_sink_start_ep (ep, gfp_flags) != 0) {
 					dev->in_ep = ep;
 					continue;
 				}
@@ -631,7 +670,7 @@
 			result = usb_ep_enable (ep, d);
 			if (result == 0) {
 				ep->driver_data = dev;
-				if (source_sink_start_ep(ep) != NULL) {
+				if (source_sink_start_ep (ep, gfp_flags) != 0) {
 					dev->out_ep = ep;
 					continue;
 				}
@@ -663,7 +702,7 @@
 
 	switch (status) {
 
-	case 0:				/* normal completion? */
+	case 0: 			/* normal completion? */
 		if (ep == dev->out_ep) {
 			/* loop this OUT packet back IN to the host */
 			req->zero = (req->actual < req->length);
@@ -697,7 +736,7 @@
 	 * rely on the hardware driver to clean up on disconnect or
 	 * endpoint disable.
 	 */
-	case -ECONNABORTED:		/* hardware forced ep reset */
+	case -ECONNABORTED: 		/* hardware forced ep reset */
 	case -ECONNRESET:		/* request dequeued */
 	case -ESHUTDOWN:		/* disconnect from host */
 		free_ep_req (ep, req);
@@ -705,7 +744,8 @@
 	}
 }
 
-static int set_loopback_config(struct zero_dev *dev)
+static int
+set_loopback_config (struct zero_dev *dev, gfp_t gfp_flags)
 {
 	int			result = 0;
 	struct usb_ep		*ep;
@@ -805,7 +845,8 @@
  * 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)
+static int
+zero_set_config (struct zero_dev *dev, unsigned number, gfp_t gfp_flags)
 {
 	int			result = 0;
 	struct usb_gadget	*gadget = dev->gadget;
@@ -815,17 +856,17 @@
 
 	if (gadget_is_sa1100 (gadget) && dev->config) {
 		/* tx fifo is full, but we can't clear it...*/
-		ERROR(dev, "can't change configurations\n");
+		INFO (dev, "can't change configurations\n");
 		return -ESPIPE;
 	}
 	zero_reset_config (dev);
 
 	switch (number) {
 	case CONFIG_SOURCE_SINK:
-		result = set_source_sink_config(dev);
+		result = set_source_sink_config (dev, gfp_flags);
 		break;
 	case CONFIG_LOOPBACK:
-		result = set_loopback_config(dev);
+		result = set_loopback_config (dev, gfp_flags);
 		break;
 	default:
 		result = -EINVAL;
@@ -845,7 +886,7 @@
 		case USB_SPEED_LOW:	speed = "low"; break;
 		case USB_SPEED_FULL:	speed = "full"; break;
 		case USB_SPEED_HIGH:	speed = "high"; break;
-		default:		speed = "?"; break;
+		default: 		speed = "?"; break;
 		}
 
 		dev->config = number;
@@ -898,17 +939,19 @@
 			value = min (w_length, (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(gadget))
+			if (!gadget->is_dualspeed)
 				break;
 			value = min (w_length, (u16) sizeof dev_qualifier);
 			memcpy (req->buf, &dev_qualifier, value);
 			break;
 
 		case USB_DT_OTHER_SPEED_CONFIG:
-			if (!gadget_is_dualspeed(gadget))
+			if (!gadget->is_dualspeed)
 				break;
 			// FALLTHROUGH
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
 		case USB_DT_CONFIG:
 			value = config_buf (gadget, req->buf,
 					w_value >> 8,
@@ -942,7 +985,7 @@
 		else
 			VDBG (dev, "HNP inactive\n");
 		spin_lock (&dev->lock);
-		value = zero_set_config(dev, w_value);
+		value = zero_set_config (dev, w_value, GFP_ATOMIC);
 		spin_unlock (&dev->lock);
 		break;
 	case USB_REQ_GET_CONFIGURATION:
@@ -971,7 +1014,7 @@
 			 * use this "reset the config" shortcut.
 			 */
 			zero_reset_config (dev);
-			zero_set_config(dev, config);
+			zero_set_config (dev, config, GFP_ATOMIC);
 			value = 0;
 		}
 		spin_unlock (&dev->lock);
@@ -1100,6 +1143,7 @@
 	struct zero_dev		*dev;
 	struct usb_ep		*ep;
 	int			gcnum;
+	struct usb_endpoint_config ep_config[2];
 
 	/* FIXME this can't yet work right with SH ... it has only
 	 * one configuration, numbered one.
@@ -1112,7 +1156,15 @@
 	 * but there may also be important quirks to address.
 	 */
 	usb_ep_autoconfig_reset (gadget);
-	ep = usb_ep_autoconfig (gadget, &fs_source_desc);
+
+	ep_config[0].config = CONFIG_SOURCE_SINK;
+	ep_config[0].interface = source_sink_intf.bInterfaceNumber;
+	ep_config[0].altinterface = source_sink_intf.bAlternateSetting;
+	ep_config[1].config = CONFIG_LOOPBACK;
+	ep_config[1].interface = loopback_intf.bInterfaceNumber;
+	ep_config[1].altinterface = loopback_intf.bAlternateSetting;
+
+	ep = usb_ep_autoconfig(gadget, &fs_source_desc, &ep_config[0], 2);
 	if (!ep) {
 autoconf_fail:
 		pr_err("%s: can't autoconfigure on %s\n",
@@ -1121,8 +1173,8 @@
 	}
 	EP_IN_NAME = ep->name;
 	ep->driver_data = ep;	/* claim */
-
-	ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
+	
+	ep = usb_ep_autoconfig(gadget, &fs_sink_desc, &ep_config[0], 2);
 	if (!ep)
 		goto autoconf_fail;
 	EP_OUT_NAME = ep->name;
@@ -1157,7 +1209,8 @@
 	dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
 	if (!dev->req)
 		goto enomem;
-	dev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);
+	dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
+				&dev->req->dma, GFP_KERNEL);
 	if (!dev->req->buf)
 		goto enomem;
 
@@ -1165,18 +1218,16 @@
 
 	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
 
-	if (gadget_is_dualspeed(gadget)) {
-		/* assume ep0 uses the same value for both speeds ... */
-		dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
-
-		/* and that all endpoints are dual-speed */
-		hs_source_desc.bEndpointAddress =
-				fs_source_desc.bEndpointAddress;
-		hs_sink_desc.bEndpointAddress =
-				fs_sink_desc.bEndpointAddress;
-	}
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	/* assume ep0 uses the same value for both speeds ... */
+	dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
+
+	/* and that all endpoints are dual-speed */
+	hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
+	hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
+#endif
 
-	if (gadget_is_otg(gadget)) {
+	if (gadget->is_otg) {
 		otg_descriptor.bmAttributes |= USB_OTG_HNP,
 		source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 		loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
@@ -1254,18 +1305,23 @@
 	.suspend	= zero_suspend,
 	.resume		= zero_resume,
 
-	.driver		= {
+	.driver 	= {
 		.name		= (char *) shortname,
 		.owner		= THIS_MODULE,
 	},
 };
 
-MODULE_AUTHOR("David Brownell");
-MODULE_LICENSE("GPL");
+MODULE_AUTHOR ("David Brownell");
+MODULE_LICENSE ("Dual BSD/GPL");
 
 
 static int __init init (void)
 {
+	/* a real value would likely come through some id prom
+	 * or module option.  this one takes at least two packets.
+	 */
+	strlcpy (serial, "0123456789.0123456789.0123456789", sizeof serial);
+
 	return usb_gadget_register_driver (&zero_driver);
 }
 module_init (init);
diff -urN linux-2.6.25/drivers/video/Kconfig linux-2.6.25-vpac1/drivers/video/Kconfig
--- linux-2.6.25/drivers/video/Kconfig	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/video/Kconfig	2008-04-24 15:12:18.000000000 +0200
@@ -1742,6 +1742,51 @@
 
 	  If unsure, say N.
 
+choice
+
+	depends on FB_PXA
+	prompt	"PXA framebuffer device"
+	default	FB_PXA_ANALOG
+
+config	FB_PXA_ANALOG
+	bool "Analog DAC output"
+
+config FB_PXA_TX14D14VM1BBA
+	bool "HITACHI TX14D14VM1BBA"
+
+endchoice
+
+choice
+
+	depends on FB_PXA && FB_PXA_ANALOG
+	prompt "PXA framebuffer resolution"
+	default FB_PXA_SVGA
+
+config FB_PXA_VGA
+	bool "VGA 640x480"
+
+config FB_PXA_SVGA
+	bool "SVGA 800x600"
+
+config FB_PXA_XGA
+	bool "XGA 1024x768"
+
+endchoice
+
+choice
+
+	depends on FB_PXA && FB_PXA_ANALOG
+	prompt "PXA framebuffer bits per pixel"
+	default FB_PXA_BPP16
+
+config FB_PXA_BPP8
+	bool "8 bpp"
+
+config FB_PXA_BPP16
+	bool "16 bpp"
+
+endchoice
+
 config FB_PXA_PARAMETERS
 	bool "PXA LCD command line parameters"
 	default n
diff -urN linux-2.6.25/drivers/video/pxafb.c linux-2.6.25-vpac1/drivers/video/pxafb.c
--- linux-2.6.25/drivers/video/pxafb.c	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/drivers/video/pxafb.c	2008-04-24 15:12:18.000000000 +0200
@@ -1381,7 +1381,7 @@
 		goto failed;
 #endif
 
-#ifdef DEBUG_VAR
+#if DEBUG_VAR
         /* Check for various illegal bit-combinations. Currently only
 	 * a warning is given. */
 
diff -urN linux-2.6.25/include/asm-arm/arch-pxa/hardware.h linux-2.6.25-vpac1/include/asm-arm/arch-pxa/hardware.h
--- linux-2.6.25/include/asm-arm/arch-pxa/hardware.h	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/include/asm-arm/arch-pxa/hardware.h	2008-04-24 15:12:18.000000000 +0200
@@ -44,7 +44,20 @@
 
 #ifndef __ASSEMBLY__
 
+#if 0
 # define __REG(x)	(*((volatile u32 *)io_p2v(x)))
+#else
+/*
+ * This __REG() version gives the same results as the one above,  except
+ * that we are fooling gcc somehow so it generates far better and smaller
+ * assembly code for access to contigous registers.  It's a shame that gcc
+ * doesn't guess this by itself.
+ */
+#include <asm/types.h>
+typedef struct { volatile u32 offset[4096]; } __regbase;
+# define __REGP(x)	((__regbase *)((x)&~4095))->offset[((x)&4095)>>2]
+# define __REG(x)	__REGP(io_p2v(x))
+#endif
 
 /* With indexed regs we don't want to feed the index through io_p2v()
    especially if it is a variable, otherwise horrible code will result. */
@@ -213,4 +226,8 @@
 #define pcibios_assign_all_busses()	1
 #endif
 
+#ifdef CONFIG_MACH_VPAC270
+#include "vpac270.h"
+#endif
+
 #endif  /* _ASM_ARCH_HARDWARE_H */
diff -urN linux-2.6.25/include/asm-arm/arch-pxa/pxa-regs.h linux-2.6.25-vpac1/include/asm-arm/arch-pxa/pxa-regs.h
--- linux-2.6.25/include/asm-arm/arch-pxa/pxa-regs.h	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/include/asm-arm/arch-pxa/pxa-regs.h	2008-04-24 15:12:18.000000000 +0200
@@ -108,6 +108,14 @@
 #define DCSR_BUSERR	(1 << 0)	/* Bus Error Interrupt (read / write) */
 
 #define DALGN		__REG(0x400000a0)  /* DMA Alignment Register */
+
+#define DRQSR0		__REG(0x400000e0)  /* DMA Request Status Register 0 */
+#define DRQSR1		__REG(0x400000e4)  /* DMA Request Status Register 1 */
+#define DRQSR2		__REG(0x400000e8)  /* DMA Request Status Register 2 */
+
+#define DRQSR_REQCLR	(1 << 8)	/* Clear Pending Requests */
+#define DRQSR_REQPEND	0x0000001f
+
 #define DINT		__REG(0x400000f0)  /* DMA Interrupt Register */
 
 #define DRCMR(n)	(*(((n) < 64) ? \
@@ -276,6 +284,10 @@
 #define DCMD_WIDTH4	(3 << 14)	/* 4 byte width (Word) */
 #define DCMD_LENGTH	0x01fff		/* length mask (max = 8K - 1) */
 
+/* default combinations */
+#define DCMD_RXPCDR	(DCMD_INCTRGADDR|DCMD_FLOWSRC|DCMD_BURST32|DCMD_WIDTH4)
+#define DCMD_RXMCDR	(DCMD_INCTRGADDR|DCMD_FLOWSRC|DCMD_BURST32|DCMD_WIDTH4)
+#define DCMD_TXPCDR	(DCMD_INCSRCADDR|DCMD_FLOWTRG|DCMD_BURST32|DCMD_WIDTH4)
 
 /*
  * UARTs
@@ -1335,6 +1347,7 @@
 #define GPIO77_LCD_ACBIAS	77	/* LCD AC Bias */
 #define GPIO78_nCS_2		78	/* chip select 2 */
 #define GPIO79_nCS_3		79	/* chip select 3 */
+#define GPIO79_pSKTSEL		79	/* pSKTSEL - PC Card Socket select (PXA27xx)*/
 #define GPIO80_nCS_4		80	/* chip select 4 */
 #define GPIO81_NSCLK		81	/* NSSP clock */
 #define GPIO82_NSFRM		82	/* NSSP Frame */
@@ -1374,6 +1387,7 @@
 #define GPIO8_MMCCS0_MD		( 8 | GPIO_ALT_FN_1_OUT)
 #define GPIO9_MMCCS1_MD		( 9 | GPIO_ALT_FN_1_OUT)
 #define GPIO10_RTCCLK_MD	(10 | GPIO_ALT_FN_1_OUT)
+#define GPIO10_FFDCD_MD		(10 | GPIO_ALT_FN_1_IN)
 #define GPIO11_3_6MHz_MD	(11 | GPIO_ALT_FN_1_OUT)
 #define GPIO12_32KHz_MD		(12 | GPIO_ALT_FN_1_OUT)
 #define GPIO13_MBGNT_MD		(13 | GPIO_ALT_FN_2_OUT)
@@ -1389,6 +1403,7 @@
 #define GPIO25_STXD_MD		(25 | GPIO_ALT_FN_2_OUT)
 #define GPIO26_SRXD_MD		(26 | GPIO_ALT_FN_1_IN)
 #define GPIO27_SEXTCLK_MD	(27 | GPIO_ALT_FN_1_IN)
+#define GPIO27_FFRTS_MD		(27 | GPIO_ALT_FN_3_OUT)
 #define GPIO28_BITCLK_AC97_MD	(28 | GPIO_ALT_FN_1_IN)
 #define GPIO28_BITCLK_IN_I2S_MD	(28 | GPIO_ALT_FN_2_IN)
 #define GPIO28_BITCLK_OUT_I2S_MD	(28 | GPIO_ALT_FN_1_OUT)
@@ -1402,6 +1417,7 @@
 #define GPIO32_SYSCLK_I2S_MD	(32 | GPIO_ALT_FN_1_OUT)
 #define GPIO32_MMCCLK_MD		( 32 | GPIO_ALT_FN_2_OUT)
 #define GPIO33_nCS_5_MD		(33 | GPIO_ALT_FN_2_OUT)
+#define GPIO33_FFDSR_MD		(33 | GPIO_ALT_FN_2_IN)
 #define GPIO34_FFRXD_MD		(34 | GPIO_ALT_FN_1_IN)
 #define GPIO34_MMCCS0_MD	(34 | GPIO_ALT_FN_2_OUT)
 #define GPIO35_FFCTS_MD		(35 | GPIO_ALT_FN_1_IN)
@@ -1485,6 +1501,7 @@
 #define GPIO84_NSSP_RX      	(84 | GPIO_ALT_FN_2_IN)
 #define GPIO85_nPCE_1_MD	(85 | GPIO_ALT_FN_1_OUT)
 #define GPIO92_MMCDAT0_MD	(92 | GPIO_ALT_FN_1_OUT)
+#define GPIO100_FFCTS_MD	(100 | GPIO_ALT_FN_2_IN)
 #define GPIO102_nPCE_1_MD	(102 | GPIO_ALT_FN_1_OUT)
 #define GPIO104_pSKTSEL_MD	(104 | GPIO_ALT_FN_1_OUT)
 #define GPIO109_MMCDAT1_MD	(109 | GPIO_ALT_FN_1_OUT)
@@ -1690,6 +1707,7 @@
 #define LCCR3_4BPP (2 << 24)
 #define LCCR3_8BPP (3 << 24)
 #define LCCR3_16BPP (4 << 24)
+#define LCCR3_18BPP (5 << 24)
 
 #define LCCR3_PDFOR_0 (0 << 30)
 #define LCCR3_PDFOR_1 (1 << 30)
diff -urN linux-2.6.25/include/asm-arm/arch-pxa/vpac270.h linux-2.6.25-vpac1/include/asm-arm/arch-pxa/vpac270.h
--- linux-2.6.25/include/asm-arm/arch-pxa/vpac270.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.25-vpac1/include/asm-arm/arch-pxa/vpac270.h	2008-04-24 15:12:18.000000000 +0200
@@ -0,0 +1,253 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/vpac270.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Copyright (c) 2006 Voipac Technologies <support@voipac.com>
+ *
+ */
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/irqs.h>
+
+
+/*
+ * Note: include file for assembler and C
+ */
+
+/*
+ * Video settings
+ */
+
+#define VPAC270_ANALOG_VGA
+//#define VPAC270_LCD_PHILIPSLB
+
+#ifdef VPAC270_ANALOG_VGA
+/* set to 1 if you want these settings to be active */
+#define VPAC270_LCD_SETTINGS        1
+
+/* set to GPIO that switches on the backlight */
+#define VPAC270_LCD_BLO_GPIO        81
+
+/* set to 1 if the LCD is an active panel (TFT) or for VGA */
+#define VPAC270_LCD_ACTIVE          1
+
+/* set to 1 if the LCD panel is a dual-scan panel */
+#define VPAC270_LCD_DUAL            0
+
+/* set to 1 if the LCD BIAS pin should be active low (OEP) */
+#define VPAC270_BIAS_ACTIVE_LOW     0
+
+/* set to 1 if the data is sampled on the falling edge of the pixel clock PCP*/
+#define VPAC270_PIX_CLK_FALLING     0
+
+/* set to 3 if more than 16 bpp (PDFOR) */
+#define VPAC270_PIXEL_DATA_FORMAT   3
+
+/* the following settings can also be set using fbset */
+/* these are settings are for analog VGA */
+#define LCD_PIXCLOCK                    40000
+#define LCD_XRES                        640
+#define LCD_YRES                        480
+#define LCD_HORIZONTAL_SYNC_PULSE_WIDTH	64
+#define LCD_VERTICAL_SYNC_PULSE_WIDTH	2
+#define LCD_BEGIN_OF_LINE_WAIT_COUNT	96
+#define LCD_BEGIN_FRAME_WAIT_COUNT 	    33
+#define LCD_END_OF_LINE_WAIT_COUNT	    48
+#define LCD_END_OF_FRAME_WAIT_COUNT	    10
+#define LCD_SYNC                        0
+
+
+/* VGA timings:
+pixclk 0x1801050 Hz (25MHz) = 40000ps
+640x480 18BPP
+LCD_HORIZONTAL_SYNC_PULSE_WIDTH HSPW 0x40
+LCD_BEGIN_OF_LINE_WAIT_COUNT BLW 0x60
+LCD_END_OF_LINE_WAIT_COUNT ELW 0x30
+LCD_VERTICAL_SYNC_PULSE_WIDTH VSW 0x2
+LCD_BEGIN_FRAME_WAIT_COUNT BFW 0x21
+LCD_END_OF_FRAME_WAIT_COUNT EFW 0xa
+VPAC270_PIX_CLK_FALLING PCP 0
+FB_SYNC_HOR_HIGH_ACT_LOW HSP 1
+FB_SYNC_VERT_HIGH_ACT_LOW VSP 1
+VPAC270_LCD_DUAL SDS 0
+VPAC270_LCD_ACTIVE PAS 1
+VPAC270_BIAS_ACTIVE_LOW OEP 0
+*/
+
+#elif defined VPAC270_LCD_PHILIPSLB
+
+/* set to 1 if you want these settings to be active */
+#define VPAC270_LCD_SETTINGS        1
+
+/* set to GPIO that switches on the backlight */
+#define VPAC270_LCD_BLO_GPIO        81
+
+/* set to 1 if the LCD is an active panel (TFT) or for VGA */
+#define VPAC270_LCD_ACTIVE          1
+
+/* set to 1 if the LCD panel is a dual-scan panel */
+#define VPAC270_LCD_DUAL            0
+
+/* set to 1 if the LCD BIAS pin should be active low (OEP) */
+#define VPAC270_BIAS_ACTIVE_LOW     0
+
+/* set to 1 if the data is sampled on the falling edge of the pixel clock PCP*/
+#define VPAC270_PIX_CLK_FALLING     1
+
+/* set to 3 if more than 16 bpp (PDFOR) */
+#define VPAC270_PIXEL_DATA_FORMAT   3
+
+/* the following settings can also be set using fbset */
+/* these are settings are for analog VGA */
+#define LCD_PIXCLOCK                    40000
+#define LCD_XRES                        640
+#define LCD_YRES                        480
+#define LCD_HORIZONTAL_SYNC_PULSE_WIDTH	2
+#define LCD_VERTICAL_SYNC_PULSE_WIDTH	45
+#define LCD_BEGIN_OF_LINE_WAIT_COUNT	160
+#define LCD_BEGIN_FRAME_WAIT_COUNT 	    0
+#define LCD_END_OF_LINE_WAIT_COUNT	    2
+#define LCD_END_OF_FRAME_WAIT_COUNT	    0
+#define LCD_SYNC			(FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT)
+
+/* Philips LB064V02-A1 timings:
+pixclk 0x1801050 Hz (25MHz) = 40000ps
+640x480 18BPP
+LCD_HORIZONTAL_SYNC_PULSE_WIDTH HSPW 2
+LCD_BEGIN_OF_LINE_WAIT_COUNT BLW 160
+LCD_END_OF_LINE_WAIT_COUNT ELW 2
+LCD_VERTICAL_SYNC_PULSE_WIDTH VSW 45
+LCD_BEGIN_FRAME_WAIT_COUNT BFW 0
+LCD_END_OF_FRAME_WAIT_COUNT EFW 0
+VPAC270_PIX_CLK_FALLING PCP 1
+FB_SYNC_HOR_HIGH_ACT_LOW HSP 0
+FB_SYNC_VERT_HIGH_ACT_LOW VSP 0
+VPAC270_LCD_DUAL SDS 0
+VPAC270_LCD_ACTIVE PAS 1
+VPAC270_BIAS_ACTIVE_LOW OEP 0
+*/
+#endif
+
+
+/*
+ * physical memory map
+ */
+
+#define VPAC270_FLASH_PHYS		PXA_CS0_PHYS    /* 0x00000000 */
+#define VPAC270_FLASH_SIZE		(0x02000000)
+
+#define VPAC270_ETH_PHYS		PXA_CS2_PHYS    /* 0x08000000 */
+//#define VPAC270_CPLD_PHYS       PXA_CS3_PHYS    /* 0x0c000000 */
+#define VPAC270_BCR_PHYS        0x0e000000
+
+/*
+ * virtual memory map
+ */
+
+#define VPAC270_FLASH           0x00000000
+//#define VPAC270_ETH_BASE		0xf4000000
+#define VPAC270_ETH_SIZE	8
+
+//#define VPAC270_CPLD_BASE       0xf0000000
+//#define VPAC270_CPLD_SIZE       0x04000000
+#define VPAC270_CF_OFFSET	    0x00000000
+#define VPAC270_BCR_OFFSET	    0x02000000
+#define VPAC270_IRDA_OFFSET	    0x02400000
+#define VPAC270_UPS_OFFSET	    0x02800000
+#define VPAC270_DCR_OFFSET	    0x03800000
+
+//#ifndef __ASSEMBLY__
+//#  define CPLD_REG(x)           (*((volatile unsigned short *)(VPAC270_CPLD_BASE + (x))))
+//#else
+//#  define CPLD_REG(x)           (VPAC270_CPLD_BASE + (x))
+//#endif
+
+
+//#define DM9000_BASE		        VPAC270_ETH_BASE
+//#define DM9000_MMIO             1
+//#define DM9000_ADDRFROMTAG      1
+
+#define VPAC270_CF0_STATUS      CPLD_REG(VPAC270_CF_OFFSET)
+#define VPAC270_BCR_CONTROL     CPLD_REG(VPAC270_BCR_OFFSET)
+#define VPAC270_DCR             CPLD_REG(VPAC270_DCR_OFFSET)
+
+/*
+ * interrupts
+ */
+/* Ethernet */
+#define GPIO_ETH_IRQ    114
+#define VPAC270_ETH_IRQ IRQ_GPIO(GPIO_ETH_IRQ)
+#define DM9000_IRQ      VPAC270_ETH_IRQ
+
+/* IDE */
+#define GPIO_IDE_IRQ	36
+#define VPAC270_IDE_IRQ IRQ_GPIO(GPIO_IDE_IRQ)
+
+/* Compact Flash/PCMCIA */
+#define GPIO_PCMCIA0_CD_IRQ     84
+#define VPAC270_PCMCIA0_CD_IRQ  IRQ_GPIO(GPIO_PCMCIA0_CD_IRQ)
+#define GPIO_PCMCIA1_CD_IRQ     17
+#define VPAC270_PCMCIA1_CD_IRQ  IRQ_GPIO(GPIO_PCMCIA1_CD_IRQ)
+#define VPAC270_PCMCIA_CD_EDGE  IRQT_BOTHEDGE
+#define GPIO_PCMCIA0_RDY_IRQ    35
+#define VPAC270_PCMCIA0_RDY_IRQ IRQ_GPIO(GPIO_PCMCIA0_RDY_IRQ)
+#define GPIO_PCMCIA1_RDY_IRQ    12
+#define VPAC270_PCMCIA1_RDY_IRQ IRQ_GPIO(GPIO_PCMCIA1_RDY_IRQ)
+#define VPAC270_PCMCIA_RDY_EDGE IRQT_FALLING
+#define GPIO_PCMCIA_POW_EN      107
+#define GPIO_PCMCIA_NPOE        48
+#define GPIO_PCMCIA_NPOE_AF     GPIO_ALT_FN_2_OUT
+#define GPIO_PCMCIA_NPIOR       50
+#define GPIO_PCMCIA_NPIOR_AF    GPIO_ALT_FN_2_OUT
+#define GPIO_PCMCIA_NPIOW       51
+#define GPIO_PCMCIA_NPIOW_AF    GPIO_ALT_FN_2_OUT
+#define GPIO_PCMCIA_NPCE1       85
+#define GPIO_PCMCIA_NPCE1_AF    GPIO_ALT_FN_1_OUT
+#define GPIO_PCMCIA_NPCE2       54
+#define GPIO_PCMCIA_NPCE2_AF    GPIO_ALT_FN_2_OUT
+#define GPIO_PCMCIA_NPREG       55
+#define GPIO_PCMCIA_NPREG_AF    GPIO_ALT_FN_2_OUT
+#define GPIO_PCMCIA_NPWAIT      56
+#define GPIO_PCMCIA_NPWAIT_AF   GPIO_ALT_FN_1_IN
+#define GPIO_PCMCIA_NPIOIS16    57
+#define GPIO_PCMCIA_NPIOIS16_AF GPIO_ALT_FN_1_IN
+#define GPIO_PCMCIA_PSKTSEL     104
+#define GPIO_PCMCIA_PSKTSEL_AF  GPIO_ALT_FN_1_OUT
+#define GPIO_PCMCIA0_RESET      11
+#define GPIO_PCMCIA1_RESET      16
+//#define GPIO_PCMCIA0_BVD1       83
+//#define GPIO_PCMCIA0_BVD2       82
+
+#define PCC0_DETECT (GPLR(GPIO_PCMCIA0_CD_IRQ) & GPIO_bit(GPIO_PCMCIA0_CD_IRQ))
+#define PCC0_READY (GPLR(GPIO_PCMCIA0_RDY_IRQ) & GPIO_bit(GPIO_PCMCIA0_RDY_IRQ))
+#define PCC1_DETECT (GPLR(GPIO_PCMCIA1_CD_IRQ) & GPIO_bit(GPIO_PCMCIA1_CD_IRQ))
+#define PCC1_READY (GPLR(GPIO_PCMCIA1_RDY_IRQ) & GPIO_bit(GPIO_PCMCIA1_RDY_IRQ))
+#define PCC_BVD1()  (GPLR(GPIO_PCMCIA0_BVD1) & GPIO_bit(GPIO_PCMCIA0_BVD1))
+#define PCC_BVD2()  (GPLR(GPIO_PCMCIA0_BVD2) & GPIO_bit(GPIO_PCMCIA0_BVD2))
+#define PCC_VS3V()  1       /* only 3.3V supported */
+#define PCC_VS5V()  0       /* only 3.3V supported */
+#define PCC_PWR_ON() (GPCR(GPIO_PCMCIA_POW_EN) |= GPIO_bit(GPIO_PCMCIA_POW_EN))
+#define PCC_PWR_OFF() (GPSR(GPIO_PCMCIA_POW_EN) |= GPIO_bit(GPIO_PCMCIA_POW_EN))
+
+/* MMC/SD */
+#define GPIO_MMC_CD_IRQ         53
+#define VPAC270_MMC_CD_IRQ      IRQ_GPIO(GPIO_MMC_CD_IRQ)
+#define GPIO_MMCCLK_AF          GPIO32_MMCCLK_MD
+#define GPIO_MMCDAT0_AF          GPIO92_MMCDAT0
+#define GPIO_MMCDAT1_AF          GPIO109_MMCDAT1
+#define GPIO_MMCDAT2_AF          GPIO110_MMCDAT2
+#define GPIO_MMCDAT3_AF          GPIO111_MMCDAT3
+#define GPIO_MMCCMD_AF          GPIO112_MMCCMD_MD
+#define GPIO_MMCCS0_AF          GPIO110_MMCCS0_MD
+
+/* TouchScreen and Sound */
+#define GPIO_TOUCH_IRQ          113
+#define VPAC270_TOUCH_IRQ       IRQ_GPIO(GPIO_TOUCH_IRQ)
+
+#define GPIO_AC97_RESET         95
+#define GPIO_AC97_RST_AF        GPIO_ALT_FN_1_OUT
+#define GPIO_AC97_SYSCLK        98
+#define GPIO_AC97_SYSCLK_AF     GPIO_ALT_FN_1_OUT
diff -urN linux-2.6.25/include/linux/usb_gadget.h linux-2.6.25-vpac1/include/linux/usb_gadget.h
--- linux-2.6.25/include/linux/usb_gadget.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.25-vpac1/include/linux/usb_gadget.h	2008-04-24 15:12:18.000000000 +0200
@@ -0,0 +1,902 @@
+/*
+ * <linux/usb_gadget.h>
+ *
+ * We call the USB code inside a Linux-based peripheral device a "gadget"
+ * driver, except for the hardware-specific bus glue.  One USB host can
+ * master many USB gadgets, but the gadgets are only slaved to one host.
+ *
+ *
+ * (C) Copyright 2002-2004 by David Brownell
+ * All Rights Reserved.
+ *
+ * This software is licensed under the GNU GPL version 2.
+ */
+
+#ifndef __LINUX_USB_GADGET_H
+#define __LINUX_USB_GADGET_H
+
+#ifdef __KERNEL__
+
+struct usb_ep;
+
+/**
+ * struct usb_request - describes one i/o request
+ * @buf: Buffer used for data.  Always provide this; some controllers
+ * 	only use PIO, or don't use DMA for some endpoints.
+ * @dma: DMA address corresponding to 'buf'.  If you don't set this
+ * 	field, and the usb controller needs one, it is responsible
+ * 	for mapping and unmapping the buffer.
+ * @length: Length of that data
+ * @no_interrupt: If true, hints that no completion irq is needed.
+ *	Helpful sometimes with deep request queues that are handled
+ *	directly by DMA controllers.
+ * @zero: If true, when writing data, makes the last packet be "short"
+ *     by adding a zero length packet as needed;
+ * @short_not_ok: When reading data, makes short packets be
+ *     treated as errors (queue stops advancing till cleanup).
+ * @complete: Function called when request completes, so this request and
+ *	its buffer may be re-used.
+ *	Reads terminate with a short packet, or when the buffer fills,
+ *	whichever comes first.  When writes terminate, some data bytes
+ *	will usually still be in flight (often in a hardware fifo).
+ *	Errors (for reads or writes) stop the queue from advancing
+ *	until the completion function returns, so that any transfers
+ *	invalidated by the error may first be dequeued.
+ * @context: For use by the completion callback
+ * @list: For use by the gadget driver.
+ * @status: Reports completion code, zero or a negative errno.
+ * 	Normally, faults block the transfer queue from advancing until
+ * 	the completion callback returns.
+ * 	Code "-ESHUTDOWN" indicates completion caused by device disconnect,
+ * 	or when the driver disabled the endpoint.
+ * @actual: Reports bytes transferred to/from the buffer.  For reads (OUT
+ * 	transfers) this may be less than the requested length.  If the
+ * 	short_not_ok flag is set, short reads are treated as errors
+ * 	even when status otherwise indicates successful completion.
+ * 	Note that for writes (IN transfers) some data bytes may still
+ * 	reside in a device-side FIFO when the request is reported as
+ *	complete.
+ *
+ * These are allocated/freed through the endpoint they're used with.  The
+ * hardware's driver can add extra per-request data to the memory it returns,
+ * which often avoids separate memory allocations (potential failures),
+ * later when the request is queued.
+ *
+ * Request flags affect request handling, such as whether a zero length
+ * packet is written (the "zero" flag), whether a short read should be
+ * treated as an error (blocking request queue advance, the "short_not_ok"
+ * flag), or hinting that an interrupt is not required (the "no_interrupt"
+ * flag, for use with deep request queues).
+ *
+ * Bulk endpoints can use any size buffers, and can also be used for interrupt
+ * transfers. interrupt-only endpoints can be much less functional.
+ */
+	// NOTE this is analagous to 'struct urb' on the host side,
+	// except that it's thinner and promotes more pre-allocation.
+
+struct usb_request {
+	void			*buf;
+	unsigned		length;
+	dma_addr_t		dma;
+
+	unsigned		no_interrupt:1;
+	unsigned		zero:1;
+	unsigned		short_not_ok:1;
+
+	void			(*complete)(struct usb_ep *ep,
+					struct usb_request *req);
+	void			*context;
+	struct list_head	list;
+
+	int			status;
+	unsigned		actual;
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* endpoint-specific parts of the api to the usb controller hardware.
+ * unlike the urb model, (de)multiplexing layers are not required.
+ * (so this api could slash overhead if used on the host side...)
+ *
+ * note that device side usb controllers commonly differ in how many
+ * endpoints they support, as well as their capabilities.
+ */
+struct usb_ep_ops {
+	int (*enable) (struct usb_ep *ep,
+		const struct usb_endpoint_descriptor *desc);
+	int (*disable) (struct usb_ep *ep);
+
+	struct usb_request *(*alloc_request) (struct usb_ep *ep,
+		gfp_t gfp_flags);
+	void (*free_request) (struct usb_ep *ep, struct usb_request *req);
+
+	void *(*alloc_buffer) (struct usb_ep *ep, unsigned bytes,
+		dma_addr_t *dma, gfp_t gfp_flags);
+	void (*free_buffer) (struct usb_ep *ep, void *buf, dma_addr_t dma,
+		unsigned bytes);
+	// NOTE:  on 2.6, drivers may also use dma_map() and
+	// dma_sync_single_*() to directly manage dma overhead. 
+
+	int (*queue) (struct usb_ep *ep, struct usb_request *req,
+		gfp_t gfp_flags);
+	int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
+
+	int (*set_halt) (struct usb_ep *ep, int value);
+	int (*fifo_status) (struct usb_ep *ep);
+	void (*fifo_flush) (struct usb_ep *ep);
+};
+
+/**
+ * struct usb_ep - device side representation of USB endpoint
+ * @name:identifier for the endpoint, such as "ep-a" or "ep9in-bulk"
+ * @ops: Function pointers used to access hardware-specific operations.
+ * @ep_list:the gadget's ep_list holds all of its endpoints
+ * @maxpacket:The maximum packet size used on this endpoint.  The initial
+ *	value can sometimes be reduced (hardware allowing), according to
+ *      the endpoint descriptor used to configure the endpoint.
+ * @driver_data:for use by the gadget driver.  all other fields are
+ * 	read-only to gadget drivers.
+ *
+ * the bus controller driver lists all the general purpose endpoints in
+ * gadget->ep_list.  the control endpoint (gadget->ep0) is not in that list,
+ * and is accessed only in response to a driver setup() callback.
+ */
+struct usb_ep {
+	void			*driver_data;
+
+	const char		*name;
+	const struct usb_ep_ops	*ops;
+	struct list_head	ep_list;
+	unsigned		maxpacket:16;
+};
+
+/*-------------------------------------------------------------------------*/
+
+/**
+ * usb_ep_enable - configure endpoint, making it usable
+ * @ep:the endpoint being configured.  may not be the endpoint named "ep0".
+ * 	drivers discover endpoints through the ep_list of a usb_gadget.
+ * @desc:descriptor for desired behavior.  caller guarantees this pointer
+ * 	remains valid until the endpoint is disabled; the data byte order
+ * 	is little-endian (usb-standard).
+ *
+ * when configurations are set, or when interface settings change, the driver
+ * will enable or disable the relevant endpoints.  while it is enabled, an
+ * endpoint may be used for i/o until the driver receives a disconnect() from
+ * the host or until the endpoint is disabled.
+ *
+ * the ep0 implementation (which calls this routine) must ensure that the
+ * hardware capabilities of each endpoint match the descriptor provided
+ * for it.  for example, an endpoint named "ep2in-bulk" would be usable
+ * for interrupt transfers as well as bulk, but it likely couldn't be used
+ * for iso transfers or for endpoint 14.  some endpoints are fully
+ * configurable, with more generic names like "ep-a".  (remember that for
+ * USB, "in" means "towards the USB master".)
+ *
+ * returns zero, or a negative error code.
+ */
+static inline int
+usb_ep_enable (struct usb_ep *ep, const struct usb_endpoint_descriptor *desc)
+{
+	return ep->ops->enable (ep, desc);
+}
+
+/**
+ * usb_ep_disable - endpoint is no longer usable
+ * @ep:the endpoint being unconfigured.  may not be the endpoint named "ep0".
+ *
+ * no other task may be using this endpoint when this is called.
+ * any pending and uncompleted requests will complete with status
+ * indicating disconnect (-ESHUTDOWN) before this call returns.
+ * gadget drivers must call usb_ep_enable() again before queueing
+ * requests to the endpoint.
+ *
+ * returns zero, or a negative error code.
+ */
+static inline int
+usb_ep_disable (struct usb_ep *ep)
+{
+	return ep->ops->disable (ep);
+}
+
+/**
+ * usb_ep_alloc_request - allocate a request object to use with this endpoint
+ * @ep:the endpoint to be used with with the request
+ * @gfp_flags:GFP_* flags to use
+ *
+ * Request objects must be allocated with this call, since they normally
+ * need controller-specific setup and may even need endpoint-specific
+ * resources such as allocation of DMA descriptors.
+ * Requests may be submitted with usb_ep_queue(), and receive a single
+ * completion callback.  Free requests with usb_ep_free_request(), when
+ * they are no longer needed.
+ *
+ * Returns the request, or null if one could not be allocated.
+ */
+static inline struct usb_request *
+usb_ep_alloc_request (struct usb_ep *ep, gfp_t gfp_flags)
+{
+	return ep->ops->alloc_request (ep, gfp_flags);
+}
+
+/**
+ * usb_ep_free_request - frees a request object
+ * @ep:the endpoint associated with the request
+ * @req:the request being freed
+ *
+ * Reverses the effect of usb_ep_alloc_request().
+ * Caller guarantees the request is not queued, and that it will
+ * no longer be requeued (or otherwise used).
+ */
+static inline void
+usb_ep_free_request (struct usb_ep *ep, struct usb_request *req)
+{
+	ep->ops->free_request (ep, req);
+}
+
+/**
+ * usb_ep_alloc_buffer - allocate an I/O buffer
+ * @ep:the endpoint associated with the buffer
+ * @len:length of the desired buffer
+ * @dma:pointer to the buffer's DMA address; must be valid
+ * @gfp_flags:GFP_* flags to use
+ *
+ * Returns a new buffer, or null if one could not be allocated.
+ * The buffer is suitably aligned for dma, if that endpoint uses DMA,
+ * and the caller won't have to care about dma-inconsistency
+ * or any hidden "bounce buffer" mechanism.  No additional per-request
+ * DMA mapping will be required for such buffers.
+ * Free it later with usb_ep_free_buffer().
+ *
+ * You don't need to use this call to allocate I/O buffers unless you
+ * want to make sure drivers don't incur costs for such "bounce buffer"
+ * copies or per-request DMA mappings.
+ */
+static inline void *
+usb_ep_alloc_buffer (struct usb_ep *ep, unsigned len, dma_addr_t *dma,
+	gfp_t gfp_flags)
+{
+	return ep->ops->alloc_buffer (ep, len, dma, gfp_flags);
+}
+
+/**
+ * usb_ep_free_buffer - frees an i/o buffer
+ * @ep:the endpoint associated with the buffer
+ * @buf:CPU view address of the buffer
+ * @dma:the buffer's DMA address
+ * @len:length of the buffer
+ *
+ * reverses the effect of usb_ep_alloc_buffer().
+ * caller guarantees the buffer will no longer be accessed
+ */
+static inline void
+usb_ep_free_buffer (struct usb_ep *ep, void *buf, dma_addr_t dma, unsigned len)
+{
+	ep->ops->free_buffer (ep, buf, dma, len);
+}
+
+/**
+ * usb_ep_queue - queues (submits) an I/O request to an endpoint.
+ * @ep:the endpoint associated with the request
+ * @req:the request being submitted
+ * @gfp_flags: GFP_* flags to use in case the lower level driver couldn't
+ * 	pre-allocate all necessary memory with the request.
+ *
+ * This tells the device controller to perform the specified request through
+ * that endpoint (reading or writing a buffer).  When the request completes,
+ * including being canceled by usb_ep_dequeue(), the request's completion
+ * routine is called to return the request to the driver.  Any endpoint
+ * (except control endpoints like ep0) may have more than one transfer
+ * request queued; they complete in FIFO order.  Once a gadget driver
+ * submits a request, that request may not be examined or modified until it
+ * is given back to that driver through the completion callback.
+ *
+ * Each request is turned into one or more packets.  The controller driver
+ * never merges adjacent requests into the same packet.  OUT transfers
+ * will sometimes use data that's already buffered in the hardware.
+ * Drivers can rely on the fact that the first byte of the request's buffer
+ * always corresponds to the first byte of some USB packet, for both
+ * IN and OUT transfers.
+ *
+ * Bulk endpoints can queue any amount of data; the transfer is packetized
+ * automatically.  The last packet will be short if the request doesn't fill it
+ * out completely.  Zero length packets (ZLPs) should be avoided in portable
+ * protocols since not all usb hardware can successfully handle zero length
+ * packets.  (ZLPs may be explicitly written, and may be implicitly written if
+ * the request 'zero' flag is set.)  Bulk endpoints may also be used
+ * for interrupt transfers; but the reverse is not true, and some endpoints
+ * won't support every interrupt transfer.  (Such as 768 byte packets.)
+ *
+ * Interrupt-only endpoints are less functional than bulk endpoints, for
+ * example by not supporting queueing or not handling buffers that are
+ * larger than the endpoint's maxpacket size.  They may also treat data
+ * toggle differently.
+ *
+ * Control endpoints ... after getting a setup() callback, the driver queues
+ * one response (even if it would be zero length).  That enables the
+ * status ack, after transfering data as specified in the response.  Setup
+ * functions may return negative error codes to generate protocol stalls.
+ * (Note that some USB device controllers disallow protocol stall responses
+ * in some cases.)  When control responses are deferred (the response is
+ * written after the setup callback returns), then usb_ep_set_halt() may be
+ * used on ep0 to trigger protocol stalls.
+ *
+ * For periodic endpoints, like interrupt or isochronous ones, the usb host
+ * arranges to poll once per interval, and the gadget driver usually will
+ * have queued some data to transfer at that time.
+ *
+ * Returns zero, or a negative error code.  Endpoints that are not enabled
+ * report errors; errors will also be
+ * reported when the usb peripheral is disconnected.
+ */
+static inline int
+usb_ep_queue (struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags)
+{
+	return ep->ops->queue (ep, req, gfp_flags);
+}
+
+/**
+ * usb_ep_dequeue - dequeues (cancels, unlinks) an I/O request from an endpoint
+ * @ep:the endpoint associated with the request
+ * @req:the request being canceled
+ *
+ * if the request is still active on the endpoint, it is dequeued and its
+ * completion routine is called (with status -ECONNRESET); else a negative
+ * error code is returned.
+ *
+ * note that some hardware can't clear out write fifos (to unlink the request
+ * at the head of the queue) except as part of disconnecting from usb.  such
+ * restrictions prevent drivers from supporting configuration changes,
+ * even to configuration zero (a "chapter 9" requirement).
+ */
+static inline int usb_ep_dequeue (struct usb_ep *ep, struct usb_request *req)
+{
+	return ep->ops->dequeue (ep, req);
+}
+
+/**
+ * usb_ep_set_halt - sets the endpoint halt feature.
+ * @ep: the non-isochronous endpoint being stalled
+ *
+ * Use this to stall an endpoint, perhaps as an error report.
+ * Except for control endpoints,
+ * the endpoint stays halted (will not stream any data) until the host
+ * clears this feature; drivers may need to empty the endpoint's request
+ * queue first, to make sure no inappropriate transfers happen.
+ *
+ * Note that while an endpoint CLEAR_FEATURE will be invisible to the
+ * gadget driver, a SET_INTERFACE will not be.  To reset endpoints for the
+ * current altsetting, see usb_ep_clear_halt().  When switching altsettings,
+ * it's simplest to use usb_ep_enable() or usb_ep_disable() for the endpoints.
+ *
+ * Returns zero, or a negative error code.  On success, this call sets
+ * underlying hardware state that blocks data transfers.
+ * Attempts to halt IN endpoints will fail (returning -EAGAIN) if any
+ * transfer requests are still queued, or if the controller hardware
+ * (usually a FIFO) still holds bytes that the host hasn't collected.
+ */
+static inline int
+usb_ep_set_halt (struct usb_ep *ep)
+{
+	return ep->ops->set_halt (ep, 1);
+}
+
+/**
+ * usb_ep_clear_halt - clears endpoint halt, and resets toggle
+ * @ep:the bulk or interrupt endpoint being reset
+ *
+ * Use this when responding to the standard usb "set interface" request,
+ * for endpoints that aren't reconfigured, after clearing any other state
+ * in the endpoint's i/o queue.
+ *
+ * Returns zero, or a negative error code.  On success, this call clears
+ * the underlying hardware state reflecting endpoint halt and data toggle.
+ * Note that some hardware can't support this request (like pxa2xx_udc),
+ * and accordingly can't correctly implement interface altsettings.
+ */
+static inline int
+usb_ep_clear_halt (struct usb_ep *ep)
+{
+	return ep->ops->set_halt (ep, 0);
+}
+
+/**
+ * usb_ep_fifo_status - returns number of bytes in fifo, or error
+ * @ep: the endpoint whose fifo status is being checked.
+ *
+ * FIFO endpoints may have "unclaimed data" in them in certain cases,
+ * such as after aborted transfers.  Hosts may not have collected all
+ * the IN data written by the gadget driver (and reported by a request
+ * completion).  The gadget driver may not have collected all the data
+ * written OUT to it by the host.  Drivers that need precise handling for
+ * fault reporting or recovery may need to use this call.
+ *
+ * This returns the number of such bytes in the fifo, or a negative
+ * errno if the endpoint doesn't use a FIFO or doesn't support such
+ * precise handling.
+ */
+static inline int
+usb_ep_fifo_status (struct usb_ep *ep)
+{
+	if (ep->ops->fifo_status)
+		return ep->ops->fifo_status (ep);
+	else
+		return -EOPNOTSUPP;
+}
+
+/**
+ * usb_ep_fifo_flush - flushes contents of a fifo
+ * @ep: the endpoint whose fifo is being flushed.
+ *
+ * This call may be used to flush the "unclaimed data" that may exist in
+ * an endpoint fifo after abnormal transaction terminations.  The call
+ * must never be used except when endpoint is not being used for any
+ * protocol translation.
+ */
+static inline void
+usb_ep_fifo_flush (struct usb_ep *ep)
+{
+	if (ep->ops->fifo_flush)
+		ep->ops->fifo_flush (ep);
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+struct usb_gadget;
+
+/**
+ * struct usb_endpoint_config - possible configurations of a given endpoint
+ * @config: the configuration number
+ * @interface: the interface number
+ * @altinterface: the altinterface number
+ *
+ * Used as an array to pass information about the possible configurations
+ * of a given endpoint to the bus controller.
+ */
+struct usb_endpoint_config {
+	u8	config;
+	u8	interface;
+	u8	altinterface;
+};
+
+/* the rest of the api to the controller hardware: device operations,
+ * which don't involve endpoints (or i/o).
+ */
+struct usb_gadget_ops {
+	struct usb_ep* (*ep_alloc)(struct usb_gadget *,
+				struct usb_endpoint_descriptor *,
+				struct usb_endpoint_config *, int);
+	int	(*get_frame)(struct usb_gadget *);
+	int	(*wakeup)(struct usb_gadget *);
+	int	(*set_selfpowered) (struct usb_gadget *, int is_selfpowered);
+	int	(*vbus_session) (struct usb_gadget *, int is_active);
+	int	(*vbus_draw) (struct usb_gadget *, unsigned mA);
+	int	(*pullup) (struct usb_gadget *, int is_on);
+	int	(*ioctl)(struct usb_gadget *,
+				unsigned code, unsigned long param);
+};
+
+/**
+ * struct usb_gadget - represents a usb slave device
+ * @ops: Function pointers used to access hardware-specific operations.
+ * @ep0: Endpoint zero, used when reading or writing responses to
+ * 	driver setup() requests
+ * @ep_list: List of other endpoints supported by the device.
+ * @speed: Speed of current connection to USB host.
+ * @is_dualspeed: True if the controller supports both high and full speed
+ *	operation.  If it does, the gadget driver must also support both.
+ * @is_otg: True if the USB device port uses a Mini-AB jack, so that the
+ *	gadget driver must provide a USB OTG descriptor.
+ * @is_a_peripheral: False unless is_otg, the "A" end of a USB cable
+ *	is in the Mini-AB jack, and HNP has been used to switch roles
+ *	so that the "A" device currently acts as A-Peripheral, not A-Host.
+ * @a_hnp_support: OTG device feature flag, indicating that the A-Host
+ *	supports HNP at this port.
+ * @a_alt_hnp_support: OTG device feature flag, indicating that the A-Host
+ *	only supports HNP on a different root port.
+ * @b_hnp_enable: OTG device feature flag, indicating that the A-Host
+ *	enabled HNP support.
+ * @name: Identifies the controller hardware type.  Used in diagnostics
+ * 	and sometimes configuration.
+ * @dev: Driver model state for this abstract device.
+ *
+ * Gadgets have a mostly-portable "gadget driver" implementing device
+ * functions, handling all usb configurations and interfaces.  Gadget
+ * drivers talk to hardware-specific code indirectly, through ops vectors.
+ * That insulates the gadget driver from hardware details, and packages
+ * the hardware endpoints through generic i/o queues.  The "usb_gadget"
+ * and "usb_ep" interfaces provide that insulation from the hardware.
+ *
+ * Except for the driver data, all fields in this structure are
+ * read-only to the gadget driver.  That driver data is part of the
+ * "driver model" infrastructure in 2.6 (and later) kernels, and for
+ * earlier systems is grouped in a similar structure that's not known
+ * to the rest of the kernel.
+ *
+ * Values of the three OTG device feature flags are updated before the
+ * setup() call corresponding to USB_REQ_SET_CONFIGURATION, and before
+ * driver suspend() calls.  They are valid only when is_otg, and when the
+ * device is acting as a B-Peripheral (so is_a_peripheral is false).
+ */
+struct usb_gadget {
+	/* readonly to gadget driver */
+	const struct usb_gadget_ops	*ops;
+	struct usb_ep			*ep0;
+	struct list_head		ep_list;	/* of usb_ep */
+	enum usb_device_speed		speed;
+	unsigned			is_dualspeed:1;
+	unsigned			is_otg:1;
+	unsigned			is_a_peripheral:1;
+	unsigned			b_hnp_enable:1;
+	unsigned			a_hnp_support:1;
+	unsigned			a_alt_hnp_support:1;
+	const char			*name;
+	struct device			dev;
+};
+
+static inline void set_gadget_data (struct usb_gadget *gadget, void *data)
+	{ dev_set_drvdata (&gadget->dev, data); }
+static inline void *get_gadget_data (struct usb_gadget *gadget)
+	{ return dev_get_drvdata (&gadget->dev); }
+
+/* iterates the non-control endpoints; 'tmp' is a struct usb_ep pointer */
+#define gadget_for_each_ep(tmp,gadget) \
+	list_for_each_entry(tmp, &(gadget)->ep_list, ep_list)
+
+
+/**
+ * usb_gadget_frame_number - returns the current frame number
+ * @gadget: controller that reports the frame number
+ *
+ * Returns the usb frame number, normally eleven bits from a SOF packet,
+ * or negative errno if this device doesn't support this capability.
+ */
+static inline int usb_gadget_frame_number (struct usb_gadget *gadget)
+{
+	return gadget->ops->get_frame (gadget);
+}
+
+/**
+ * usb_gadget_wakeup - tries to wake up the host connected to this gadget
+ * @gadget: controller used to wake up the host
+ *
+ * Returns zero on success, else negative error code if the hardware
+ * doesn't support such attempts, or its support has not been enabled
+ * by the usb host.  Drivers must return device descriptors that report
+ * their ability to support this, or hosts won't enable it.
+ *
+ * This may also try to use SRP to wake the host and start enumeration,
+ * even if OTG isn't otherwise in use.  OTG devices may also start
+ * remote wakeup even when hosts don't explicitly enable it.
+ */
+static inline int usb_gadget_wakeup (struct usb_gadget *gadget)
+{
+	if (!gadget->ops->wakeup)
+		return -EOPNOTSUPP;
+	return gadget->ops->wakeup (gadget);
+}
+
+/**
+ * usb_gadget_set_selfpowered - sets the device selfpowered feature.
+ * @gadget:the device being declared as self-powered
+ *
+ * this affects the device status reported by the hardware driver
+ * to reflect that it now has a local power supply.
+ *
+ * returns zero on success, else negative errno.
+ */
+static inline int
+usb_gadget_set_selfpowered (struct usb_gadget *gadget)
+{
+	if (!gadget->ops->set_selfpowered)
+		return -EOPNOTSUPP;
+	return gadget->ops->set_selfpowered (gadget, 1);
+}
+
+/**
+ * usb_gadget_clear_selfpowered - clear the device selfpowered feature.
+ * @gadget:the device being declared as bus-powered
+ *
+ * this affects the device status reported by the hardware driver.
+ * some hardware may not support bus-powered operation, in which
+ * case this feature's value can never change.
+ *
+ * returns zero on success, else negative errno.
+ */
+static inline int
+usb_gadget_clear_selfpowered (struct usb_gadget *gadget)
+{
+	if (!gadget->ops->set_selfpowered)
+		return -EOPNOTSUPP;
+	return gadget->ops->set_selfpowered (gadget, 0);
+}
+
+/**
+ * usb_gadget_vbus_connect - Notify controller that VBUS is powered
+ * @gadget:The device which now has VBUS power.
+ *
+ * This call is used by a driver for an external transceiver (or GPIO)
+ * that detects a VBUS power session starting.  Common responses include
+ * resuming the controller, activating the D+ (or D-) pullup to let the
+ * host detect that a USB device is attached, and starting to draw power
+ * (8mA or possibly more, especially after SET_CONFIGURATION).
+ *
+ * Returns zero on success, else negative errno.
+ */
+static inline int
+usb_gadget_vbus_connect(struct usb_gadget *gadget)
+{
+	if (!gadget->ops->vbus_session)
+		return -EOPNOTSUPP;
+	return gadget->ops->vbus_session (gadget, 1);
+}
+
+/**
+ * usb_gadget_vbus_draw - constrain controller's VBUS power usage
+ * @gadget:The device whose VBUS usage is being described
+ * @mA:How much current to draw, in milliAmperes.  This should be twice
+ *	the value listed in the configuration descriptor bMaxPower field.
+ *
+ * This call is used by gadget drivers during SET_CONFIGURATION calls,
+ * reporting how much power the device may consume.  For example, this
+ * could affect how quickly batteries are recharged.
+ *
+ * Returns zero on success, else negative errno.
+ */
+static inline int
+usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+{
+	if (!gadget->ops->vbus_draw)
+		return -EOPNOTSUPP;
+	return gadget->ops->vbus_draw (gadget, mA);
+}
+
+/**
+ * usb_gadget_vbus_disconnect - notify controller about VBUS session end
+ * @gadget:the device whose VBUS supply is being described
+ *
+ * This call is used by a driver for an external transceiver (or GPIO)
+ * that detects a VBUS power session ending.  Common responses include
+ * reversing everything done in usb_gadget_vbus_connect().
+ *
+ * Returns zero on success, else negative errno.
+ */
+static inline int
+usb_gadget_vbus_disconnect(struct usb_gadget *gadget)
+{
+	if (!gadget->ops->vbus_session)
+		return -EOPNOTSUPP;
+	return gadget->ops->vbus_session (gadget, 0);
+}
+
+/**
+ * usb_gadget_connect - software-controlled connect to USB host
+ * @gadget:the peripheral being connected
+ *
+ * Enables the D+ (or potentially D-) pullup.  The host will start
+ * enumerating this gadget when the pullup is active and a VBUS session
+ * is active (the link is powered).  This pullup is always enabled unless
+ * usb_gadget_disconnect() has been used to disable it.
+ *
+ * Returns zero on success, else negative errno.
+ */
+static inline int
+usb_gadget_connect (struct usb_gadget *gadget)
+{
+	if (!gadget->ops->pullup)
+		return -EOPNOTSUPP;
+	return gadget->ops->pullup (gadget, 1);
+}
+
+/**
+ * usb_gadget_disconnect - software-controlled disconnect from USB host
+ * @gadget:the peripheral being disconnected
+ *
+ * Disables the D+ (or potentially D-) pullup, which the host may see
+ * as a disconnect (when a VBUS session is active).  Not all systems
+ * support software pullup controls.
+ *
+ * This routine may be used during the gadget driver bind() call to prevent
+ * the peripheral from ever being visible to the USB host, unless later
+ * usb_gadget_connect() is called.  For example, user mode components may
+ * need to be activated before the system can talk to hosts.
+ *
+ * Returns zero on success, else negative errno.
+ */
+static inline int
+usb_gadget_disconnect (struct usb_gadget *gadget)
+{
+	if (!gadget->ops->pullup)
+		return -EOPNOTSUPP;
+	return gadget->ops->pullup (gadget, 0);
+}
+
+
+
+/*-------------------------------------------------------------------------*/
+
+/**
+ * struct usb_gadget_driver - driver for usb 'slave' devices
+ * @function: String describing the gadget's function
+ * @speed: Highest speed the driver handles.
+ * @bind: Invoked when the driver is bound to a gadget, usually
+ * 	after registering the driver.
+ * 	At that point, ep0 is fully initialized, and ep_list holds
+ * 	the currently-available endpoints.
+ * 	Called in a context that permits sleeping.
+ * @setup: Invoked for ep0 control requests that aren't handled by
+ * 	the hardware level driver. Most calls must be handled by
+ * 	the gadget driver, including descriptor and configuration
+ * 	management.  The 16 bit members of the setup data are in
+ * 	USB byte order. Called in_interrupt; this may not sleep.  Driver
+ *	queues a response to ep0, or returns negative to stall.
+ * @disconnect: Invoked after all transfers have been stopped,
+ * 	when the host is disconnected.  May be called in_interrupt; this
+ * 	may not sleep.  Some devices can't detect disconnect, so this might
+ *	not be called except as part of controller shutdown.
+ * @unbind: Invoked when the driver is unbound from a gadget,
+ * 	usually from rmmod (after a disconnect is reported).
+ * 	Called in a context that permits sleeping.
+ * @suspend: Invoked on USB suspend.  May be called in_interrupt.
+ * @resume: Invoked on USB resume.  May be called in_interrupt.
+ * @driver: Driver model state for this driver.
+ *
+ * Devices are disabled till a gadget driver successfully bind()s, which
+ * means the driver will handle setup() requests needed to enumerate (and
+ * meet "chapter 9" requirements) then do some useful work.
+ *
+ * If gadget->is_otg is true, the gadget driver must provide an OTG
+ * descriptor during enumeration, or else fail the bind() call.  In such
+ * cases, no USB traffic may flow until both bind() returns without
+ * having called usb_gadget_disconnect(), and the USB host stack has
+ * initialized.
+ *
+ * Drivers use hardware-specific knowledge to configure the usb hardware.
+ * endpoint addressing is only one of several hardware characteristics that
+ * are in descriptors the ep0 implementation returns from setup() calls.
+ *
+ * Except for ep0 implementation, most driver code shouldn't need change to
+ * run on top of different usb controllers.  It'll use endpoints set up by
+ * that ep0 implementation.
+ *
+ * The usb controller driver handles a few standard usb requests.  Those
+ * include set_address, and feature flags for devices, interfaces, and
+ * endpoints (the get_status, set_feature, and clear_feature requests).
+ *
+ * Accordingly, the driver's setup() callback must always implement all
+ * get_descriptor requests, returning at least a device descriptor and
+ * a configuration descriptor.  Drivers must make sure the endpoint
+ * descriptors match any hardware constraints. Some hardware also constrains
+ * other descriptors. (The pxa250 allows only configurations 1, 2, or 3).
+ *
+ * The driver's setup() callback must also implement set_configuration,
+ * and should also implement set_interface, get_configuration, and
+ * get_interface.  Setting a configuration (or interface) is where
+ * endpoints should be activated or (config 0) shut down.
+ *
+ * (Note that only the default control endpoint is supported.  Neither
+ * hosts nor devices generally support control traffic except to ep0.)
+ *
+ * Most devices will ignore USB suspend/resume operations, and so will
+ * not provide those callbacks.  However, some may need to change modes
+ * when the host is not longer directing those activities.  For example,
+ * local controls (buttons, dials, etc) may need to be re-enabled since
+ * the (remote) host can't do that any longer; or an error state might
+ * be cleared, to make the device behave identically whether or not
+ * power is maintained.
+ */
+struct usb_gadget_driver {
+	char			*function;
+	enum usb_device_speed	speed;
+	int			(*bind)(struct usb_gadget *);
+	void			(*unbind)(struct usb_gadget *);
+	int			(*setup)(struct usb_gadget *,
+					const struct usb_ctrlrequest *);
+	void			(*disconnect)(struct usb_gadget *);
+	void			(*suspend)(struct usb_gadget *);
+	void			(*resume)(struct usb_gadget *);
+
+	// FIXME support safe rmmod
+	struct device_driver	driver;
+};
+
+
+
+/*-------------------------------------------------------------------------*/
+
+/* driver modules register and unregister, as usual.
+ * these calls must be made in a context that can sleep.
+ *
+ * these will usually be implemented directly by the hardware-dependent
+ * usb bus interface driver, which will only support a single driver.
+ */
+
+/**
+ * usb_gadget_register_driver - register a gadget driver
+ * @driver:the driver being registered
+ *
+ * Call this in your gadget driver's module initialization function,
+ * to tell the underlying usb controller driver about your driver.
+ * The driver's bind() function will be called to bind it to a
+ * gadget before this registration call returns.  It's expected that
+ * the bind() functions will be in init sections.
+ * This function must be called in a context that can sleep.
+ */
+int usb_gadget_register_driver (struct usb_gadget_driver *driver);
+
+/**
+ * usb_gadget_unregister_driver - unregister a gadget driver
+ * @driver:the driver being unregistered
+ *
+ * Call this in your gadget driver's module cleanup function,
+ * to tell the underlying usb controller that your driver is
+ * going away.  If the controller is connected to a USB host,
+ * it will first disconnect().  The driver is also requested
+ * to unbind() and clean up any device state, before this procedure
+ * finally returns.  It's expected that the unbind() functions
+ * will in in exit sections, so may not be linked in some kernels.
+ * This function must be called in a context that can sleep.
+ */
+int usb_gadget_unregister_driver (struct usb_gadget_driver *driver);
+
+/*-------------------------------------------------------------------------*/
+
+/* utility to simplify dealing with string descriptors */
+
+/**
+ * struct usb_string - wraps a C string and its USB id
+ * @id:the (nonzero) ID for this string
+ * @s:the string, in UTF-8 encoding
+ *
+ * If you're using usb_gadget_get_string(), use this to wrap a string
+ * together with its ID.
+ */
+struct usb_string {
+	u8			id;
+	const char		*s;
+};
+
+/**
+ * struct usb_gadget_strings - a set of USB strings in a given language
+ * @language:identifies the strings' language (0x0409 for en-us)
+ * @strings:array of strings with their ids
+ *
+ * If you're using usb_gadget_get_string(), use this to wrap all the
+ * strings for a given language.
+ */
+struct usb_gadget_strings {
+	u16			language;	/* 0x0409 for en-us */
+	struct usb_string	*strings;
+};
+
+/* put descriptor for string with that id into buf (buflen >= 256) */
+int usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf);
+
+/*-------------------------------------------------------------------------*/
+
+/* utility to simplify managing config descriptors */
+
+/* write vector of descriptors into buffer */
+int usb_descriptor_fillbuf(void *, unsigned,
+		const struct usb_descriptor_header **);
+
+/* build config descriptor from single descriptor vector */
+int usb_gadget_config_buf(const struct usb_config_descriptor *config,
+	void *buf, unsigned buflen, const struct usb_descriptor_header **desc);
+
+/*-------------------------------------------------------------------------*/
+
+/* utility wrapping a simple endpoint selection policy */
+
+extern struct usb_ep *usb_ep_autoconfig (struct usb_gadget *,
+			struct usb_endpoint_descriptor *,
+			struct usb_endpoint_config *,
+			int numconfigs
+) __devinit;
+
+extern void usb_ep_autoconfig_reset (struct usb_gadget *) __devinit;
+
+#endif  /* __KERNEL__ */
+
+#endif	/* __LINUX_USB_GADGET_H */
diff -urN linux-2.6.25/Makefile linux-2.6.25-vpac1/Makefile
--- linux-2.6.25/Makefile	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/Makefile	2008-04-24 15:11:13.000000000 +0200
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 25
-EXTRAVERSION =
+EXTRAVERSION = -vpac1
 NAME = Funky Weasel is Jiggy wit it
 
 # *DOCUMENTATION*
@@ -190,8 +190,8 @@
 # Default value for CROSS_COMPILE is not to prefix executables
 # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
 export KBUILD_BUILDHOST := $(SUBARCH)
-ARCH		?= $(SUBARCH)
-CROSS_COMPILE	?=
+ARCH		?= arm
+CROSS_COMPILE	?= arm-linux-
 
 # Architecture as present in compile.h
 UTS_MACHINE 	:= $(ARCH)
diff -urN linux-2.6.25/sound/arm/pxa2xx-ac97.c linux-2.6.25-vpac1/sound/arm/pxa2xx-ac97.c
--- linux-2.6.25/sound/arm/pxa2xx-ac97.c	2008-04-17 04:49:44.000000000 +0200
+++ linux-2.6.25-vpac1/sound/arm/pxa2xx-ac97.c	2008-04-24 15:12:18.000000000 +0200
@@ -132,10 +132,12 @@
 #ifdef CONFIG_PXA27x
 		/* warm reset broken on Bulverde,
 		   so manually keep AC97 reset high */
-		pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH); 
+//		pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH); 
+		pxa_gpio_mode( 95 | GPIO_OUT | GPIO_DFLT_HIGH); 
 		udelay(10);
 		GCR |= GCR_WARM_RST;
-		pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+//		pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+		pxa_gpio_mode(GPIO_AC97_RESET | GPIO_AC97_RST_AF);
 		udelay(500);
 #else
 		GCR |= GCR_WARM_RST|GCR_PRIRDY_IEN|GCR_SECRDY_IEN;
@@ -147,6 +149,9 @@
 					 __FUNCTION__, gsr_bits);
 	}
 
+	pxa2xx_ac97_write(ac97, 0x6a, 0x0050);
+	pxa2xx_ac97_write(ac97, 0x6c, 0x0030);
+
 	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
 	GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
 }
@@ -334,7 +339,9 @@
 	pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
 #ifdef CONFIG_PXA27x
 	/* Use GPIO 113 as AC97 Reset on Bulverde */
-	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+//	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+        pxa_gpio_mode(GPIO_AC97_RESET | GPIO_AC97_RST_AF);
+	pxa_gpio_mode(GPIO_AC97_SYSCLK | GPIO_AC97_SYSCLK_AF);
 #endif
 	pxa_set_cken(CKEN_AC97, 1);