Index: /src/linux/rt2880/linux-2.6.23/kernel/module.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/kernel/module.c (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/kernel/module.c (revision 12433) @@ -1738,4 +1738,8 @@ layout_sections(mod, hdr, sechdrs, secstrings); +#ifdef __mips + module_relayout(hdr, sechdrs, secstrings, symindex, mod); +#endif + /* Do the allocs. */ ptr = module_alloc(mod->core_size); Index: /src/linux/rt2880/linux-2.6.23/include/asm-mips/module.h =================================================================== --- /src/linux/rt2880/linux-2.6.23/include/asm-mips/module.h (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/include/asm-mips/module.h (revision 12433) @@ -10,4 +10,7 @@ const struct exception_table_entry *dbe_start; const struct exception_table_entry *dbe_end; + + unsigned int core_plt_offset; + unsigned int init_plt_offset; }; @@ -66,4 +69,6 @@ /* Given an address, look for it in the exception tables. */ const struct exception_table_entry*search_module_dbetables(unsigned long addr); +int module_relayout(Elf32_Ehdr *hdr, Elf32_Shdr *sechdrs, + char *secstrings, unsigned symindex, struct module *me); #else /* Given an address, look for it in the exception tables. */ Index: /src/linux/rt2880/linux-2.6.23/include/asm-mips/string.h =================================================================== --- /src/linux/rt2880/linux-2.6.23/include/asm-mips/string.h (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/include/asm-mips/string.h (revision 12433) @@ -109,6 +109,7 @@ ".set\tnoreorder\n\t" ".set\tnoat\n" - "1:\tlbu\t%3,(%0)\n\t" - "beqz\t%2,2f\n\t" + "1:\tbeqz\t%2,2f\n\t" + "nop\n\t" + "lbu\t%3,(%0)\n\t" "lbu\t$1,(%1)\n\t" "subu\t%2,1\n\t" Index: /src/linux/rt2880/linux-2.6.23/include/linux/jhash.h =================================================================== --- /src/linux/rt2880/linux-2.6.23/include/linux/jhash.h (revision 11892) +++ /src/linux/rt2880/linux-2.6.23/include/linux/jhash.h (revision 12433) @@ -1,5 +1,2 @@ -#ifdef USE_JHASH2 -#include -#else #ifndef _LINUX_JHASH_H #define _LINUX_JHASH_H @@ -7,5 +4,5 @@ /* jhash.h: Jenkins hash support. * - * Copyright (C) 2006. Bob Jenkins (bob_jenkins@burtleburtle.net) + * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net) * * http://burtleburtle.net/bob/hash/ @@ -13,87 +10,72 @@ * These are the credits from Bob's sources: * - * lookup3.c, by Bob Jenkins, May 2006, Public Domain. + * lookup2.c, by Bob Jenkins, December 1996, Public Domain. + * hash(), hash2(), hash3, and mix() are externally useful functions. + * Routines to test the hash are included if SELF_TEST is defined. + * You can use this free for any purpose. It has no warranty. * - * These are functions for producing 32-bit hashes for hash table lookup. - * hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() - * are externally useful functions. Routines to test the hash are included - * if SELF_TEST is defined. You can use this free for any purpose. It's in - * the public domain. It has no warranty. - * - * Copyright (C) 2009 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu) + * Copyright (C) 2003 David S. Miller (davem@redhat.com) * * I've modified Bob's hash to be useful in the Linux kernel, and - * any bugs present are my fault. Jozsef + * any bugs present are surely my fault. -DaveM */ -#define __rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) - -/* __jhash_mix - mix 3 32-bit values reversibly. */ -#define __jhash_mix(a,b,c) \ +/* NOTE: Arguments are modified. */ +#define __jhash_mix(a, b, c) \ { \ - a -= c; a ^= __rot(c, 4); c += b; \ - b -= a; b ^= __rot(a, 6); a += c; \ - c -= b; c ^= __rot(b, 8); b += a; \ - a -= c; a ^= __rot(c,16); c += b; \ - b -= a; b ^= __rot(a,19); a += c; \ - c -= b; c ^= __rot(b, 4); b += a; \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<<8); \ + c -= a; c -= b; c ^= (b>>13); \ + a -= b; a -= c; a ^= (c>>12); \ + b -= c; b -= a; b ^= (a<<16); \ + c -= a; c -= b; c ^= (b>>5); \ + a -= b; a -= c; a ^= (c>>3); \ + b -= c; b -= a; b ^= (a<<10); \ + c -= a; c -= b; c ^= (b>>15); \ } -/* __jhash_final - final mixing of 3 32-bit values (a,b,c) into c */ -#define __jhash_final(a,b,c) \ -{ \ - c ^= b; c -= __rot(b,14); \ - a ^= c; a -= __rot(c,11); \ - b ^= a; b -= __rot(a,25); \ - c ^= b; c -= __rot(b,16); \ - a ^= c; a -= __rot(c,4); \ - b ^= a; b -= __rot(a,14); \ - c ^= b; c -= __rot(b,24); \ -} - -/* An arbitrary initial parameter */ -#define JHASH_INIT_PARAM 0xdeadbeef +/* The golden ration: an arbitrary value */ +#define JHASH_GOLDEN_RATIO 0x9e3779b9 /* The most generic version, hashes an arbitrary sequence * of bytes. No alignment or length assumptions are made about - * the input key. The result depends on endianness. + * the input key. */ static inline u32 jhash(const void *key, u32 length, u32 initval) { - u32 a,b,c; + u32 a, b, c, len; const u8 *k = key; - /* Set up the internal state */ - a = b = c = JHASH_INIT_PARAM + length + initval; + len = length; + a = b = JHASH_GOLDEN_RATIO; + c = initval; - /* all but the last block: affect some 32 bits of (a,b,c) */ - while (length > 12) { - a += (k[0] + ((u32)k[1]<<8) + ((u32)k[2]<<16) + ((u32)k[3]<<24)); - b += (k[4] + ((u32)k[5]<<8) + ((u32)k[6]<<16) + ((u32)k[7]<<24)); - c += (k[8] + ((u32)k[9]<<8) + ((u32)k[10]<<16) + ((u32)k[11]<<24)); - __jhash_mix(a, b, c); - length -= 12; + while (len >= 12) { + a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24)); + b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24)); + c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24)); + + __jhash_mix(a,b,c); + k += 12; + len -= 12; } - /* last block: affect all 32 bits of (c) */ - /* all the case statements fall through */ - switch (length) { - case 12: c += (u32)k[11]<<24; - case 11: c += (u32)k[10]<<16; - case 10: c += (u32)k[9]<<8; - case 9 : c += k[8]; - case 8 : b += (u32)k[7]<<24; - case 7 : b += (u32)k[6]<<16; - case 6 : b += (u32)k[5]<<8; + c += length; + switch (len) { + case 11: c += ((u32)k[10]<<24); + case 10: c += ((u32)k[9]<<16); + case 9 : c += ((u32)k[8]<<8); + case 8 : b += ((u32)k[7]<<24); + case 7 : b += ((u32)k[6]<<16); + case 6 : b += ((u32)k[5]<<8); case 5 : b += k[4]; - case 4 : a += (u32)k[3]<<24; - case 3 : a += (u32)k[2]<<16; - case 2 : a += (u32)k[1]<<8; + case 4 : a += ((u32)k[3]<<24); + case 3 : a += ((u32)k[2]<<16); + case 2 : a += ((u32)k[1]<<8); case 1 : a += k[0]; - __jhash_final(a, b, c); - case 0 : - break; - } + }; + + __jhash_mix(a,b,c); return c; @@ -105,43 +87,44 @@ static inline u32 jhash2(const u32 *k, u32 length, u32 initval) { - u32 a, b, c; + u32 a, b, c, len; - /* Set up the internal state */ - a = b = c = JHASH_INIT_PARAM + (length<<2) + initval; + a = b = JHASH_GOLDEN_RATIO; + c = initval; + len = length; - /* handle most of the key */ - while (length > 3) { + while (len >= 3) { a += k[0]; b += k[1]; c += k[2]; __jhash_mix(a, b, c); - length -= 3; - k += 3; + k += 3; len -= 3; } - /* handle the last 3 u32's */ - /* all the case statements fall through */ - switch (length) { - case 3: c += k[2]; - case 2: b += k[1]; - case 1: a += k[0]; - __jhash_final(a, b, c); - case 0: /* case 0: nothing left to add */ - break; - } + c += length * 4; + + switch (len) { + case 2 : b += k[1]; + case 1 : a += k[0]; + }; + + __jhash_mix(a,b,c); return c; } + /* A special ultra-optimized versions that knows they are hashing exactly * 3, 2 or 1 word(s). + * + * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally + * done at the end is not done here. */ static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval) { - a += JHASH_INIT_PARAM + initval; - b += JHASH_INIT_PARAM + initval; - c += JHASH_INIT_PARAM + initval; + a += JHASH_GOLDEN_RATIO; + b += JHASH_GOLDEN_RATIO; + c += initval; - __jhash_final(a, b, c); + __jhash_mix(a, b, c); return c; @@ -150,12 +133,11 @@ static inline u32 jhash_2words(u32 a, u32 b, u32 initval) { - return jhash_3words(0, a, b, initval); + return jhash_3words(a, b, 0, initval); } static inline u32 jhash_1word(u32 a, u32 initval) { - return jhash_3words(0, 0, a, initval); + return jhash_3words(a, 0, 0, initval); } #endif /* _LINUX_JHASH_H */ -#endif Index: /src/linux/rt2880/linux-2.6.23/.config =================================================================== --- /src/linux/rt2880/linux-2.6.23/.config (revision 11871) +++ /src/linux/rt2880/linux-2.6.23/.config (revision 12433) @@ -2,5 +2,5 @@ # Automatically generated make config: don't edit # Linux kernel version: 2.6.23.17 -# Mon Apr 6 12:18:07 2009 +# Fri Jul 3 16:08:30 2009 # CONFIG_MIPS=y @@ -9,8 +9,8 @@ # Machine selection # -CONFIG_RALINK_RT2880_MP=y -CONFIG_RALINK_RT2880=y +CONFIG_RALINK_RT3052_MP2=y +# CONFIG_RALINK_RT2880 is not set # CONFIG_RALINK_RT2883 is not set -# CONFIG_RALINK_RT3052 is not set +CONFIG_RALINK_RT3052=y # CONFIG_MACH_ALCHEMY is not set # CONFIG_BASLER_EXCITE is not set @@ -48,17 +48,13 @@ # CONFIG_TOSHIBA_RBTX4938 is not set # CONFIG_WR_PPMC is not set -CONFIG_RT2880_ASIC=y -CONFIG_FLASH_REMAP_NEED=y +CONFIG_RT3052_ASIC=y # CONFIG_RT2880_DRAM_8M is not set # CONFIG_RT2880_DRAM_16M is not set CONFIG_RT2880_DRAM_32M=y # CONFIG_RT2880_DRAM_64M is not set -# CONFIG_RT2880_FLASH_2M is not set -# CONFIG_RT2880_FLASH_4M is not set -CONFIG_RT2880_FLASH_8M=y -# CONFIG_RT2880_FLASH_16M is not set +# CONFIG_RT2880_FLASH_32M is not set CONFIG_RALINK_RAM_SIZE=32 CONFIG_MTD_PHYSMAP_START=0xBF000000 -CONFIG_MTD_PHYSMAP_LEN=0x800000 +CONFIG_MTD_PHYSMAP_LEN=0x1000000 CONFIG_MTD_PHYSMAP_BUSWIDTH=2 # CONFIG_RT2880_ROOTFS_IN_RAM is not set @@ -194,5 +190,6 @@ CONFIG_EMBEDDED=y # CONFIG_SYSCTL_SYSCALL is not set -# CONFIG_KALLSYMS is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y CONFIG_PRINTK=y @@ -241,6 +238,4 @@ # Bus options (PCI, PCMCIA, EISA, ISA, TC) # -CONFIG_HW_HAS_PCI=y -# CONFIG_PCI is not set # CONFIG_ARCH_SUPPORTS_MSI is not set CONFIG_MMU=y @@ -261,6 +256,9 @@ # Power management options # -# CONFIG_PM is not set +CONFIG_PM=y +# CONFIG_PM_LEGACY is not set +# CONFIG_PM_DEBUG is not set CONFIG_SUSPEND_UP_POSSIBLE=y +# CONFIG_SUSPEND is not set # @@ -555,5 +553,6 @@ # CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set -# CONFIG_RFKILL is not set +CONFIG_RFKILL=y +# CONFIG_RFKILL_INPUT is not set # CONFIG_NET_9P is not set @@ -597,5 +596,5 @@ CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set -CONFIG_MTD_CONCAT=y +# CONFIG_MTD_CONCAT is not set CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_REDBOOT_PARTS is not set @@ -638,6 +637,6 @@ # CONFIG_MTD_CFI_INTELEXT is not set CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_CFI_STAA=y -# CONFIG_MTD_CFI_SSTSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_SSTSTD=y CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_RAM is not set @@ -682,4 +681,5 @@ # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_CDROM_PKTCDVD is not set @@ -692,7 +692,38 @@ # # CONFIG_RAID_ATTRS is not set -# CONFIG_SCSI is not set -# CONFIG_SCSI_DMA is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +CONFIG_SCSI_TGT=y # 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=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CHR_DEV_SG=y +# 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 +CONFIG_SCSI_WAIT_SCAN=m + +# +# 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_LOWLEVEL is not set # CONFIG_ATA is not set # CONFIG_MD is not set @@ -731,9 +762,11 @@ CONFIG_RAETH=y CONFIG_RAETH_NAPI=y -CONFIG_RAETH_JUMBOFRAME=y -# CONFIG_RAETH_ROUTER is not set -# CONFIG_MAC_TO_MAC_MODE is not set -CONFIG_GIGAPHY=y -CONFIG_MAC_TO_GIGAPHY_MODE_ADDR=0x1F +# CONFIG_RAETH_QOS is not set +CONFIG_RT_3052_ESW=y +CONFIG_LAN_WAN_SUPPORT=y +CONFIG_WAN_AT_P4=y +# CONFIG_WAN_AT_P0 is not set +# CONFIG_ESW_DOUBLE_VLAN_TAG is not set +# CONFIG_RAETH_RT3052_P5 is not set CONFIG_NET_ETHERNET=y CONFIG_MII=y @@ -749,7 +782,9 @@ CONFIG_WLAN_80211=y # CONFIG_LIBERTAS is not set +# CONFIG_USB_ZD1201 is not set # CONFIG_HOSTAP is not set CONFIG_RT2860V2_AP=m -# CONFIG_RT2860V2_AP_2850 is not set +# CONFIG_RALINK_RT3050AP_1T1R is not set +CONFIG_RALINK_RT3052AP_2T2R=y CONFIG_RT2860V2_AP_LED=y CONFIG_RT2860V2_AP_WSC=y @@ -758,5 +793,5 @@ CONFIG_RT2860V2_AP_MBSS=y CONFIG_RT2860V2_AP_APCLI=y -CONFIG_RT2860V2_AP_IGMP_SNOOP=y +# CONFIG_RT2860V2_AP_IGMP_SNOOP is not set # CONFIG_RT2860V2_AP_NETIF_BLOCK is not set # CONFIG_RT2860V2_AP_DFS is not set @@ -768,5 +803,6 @@ # CONFIG_RT2860V2_AP_MEMORY_OPTIMIZATION is not set CONFIG_RT2860V2_STA=m -# CONFIG_RT2860V2_STA_2850 is not set +# CONFIG_RALINK_RT3050STA_1T1R is not set +CONFIG_RALINK_RT3052STA_2T2R=y CONFIG_RT2860V2_STA_LED=y CONFIG_RT2860V2_STA_WPA_SUPPLICANT=y @@ -776,4 +812,15 @@ CONFIG_RT2860V2_STA_DLS=y # CONFIG_RT2860V2_STA_MESH is not set + +# +# 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_MII is not set +# CONFIG_USB_USBNET is not set +CONFIG_USB_HSO=m # CONFIG_WAN is not set CONFIG_PPP=y @@ -838,7 +885,16 @@ # CONFIG_RALINK_PCM is not set # CONFIG_RALINK_I2S is not set -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_SERIAL_NONSTANDARD=y # CONFIG_MOXA is not set +# CONFIG_MOXA_SMARTIO is not set +CONFIG_N_HDLC=m +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set # @@ -871,4 +927,9 @@ # # CONFIG_SOFT_WATCHDOG is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set # CONFIG_HW_RANDOM is not set # CONFIG_RTC is not set @@ -913,9 +974,158 @@ # +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set +CONFIG_DUMMY_CONSOLE=y + +# # Sound # # CONFIG_SOUND is not set # CONFIG_HID_SUPPORT is not set -# CONFIG_USB_SUPPORT is not set +CONFIG_USB_SUPPORT=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +CONFIG_USB_DYNAMIC_MINORS=y +CONFIG_USB_SUSPEND=y +# CONFIG_USB_PERSIST is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +# 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=m + +# +# 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_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_KARMA is not set +CONFIG_USB_LIBUSUAL=y + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_MON is not set + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=y +# CONFIG_USB_SERIAL_CONSOLE is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_AIRPRIME is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_CP2101 is not set +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_FUNSOFT is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_HP4X is not set +# CONFIG_USB_SERIAL_SAFE is not set +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +CONFIG_USB_SERIAL_OPTION=m +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_DEBUG 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 + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set +CONFIG_DWC_OTG=y +CONFIG_DWC_OTG_HOST_ONLY=y +# CONFIG_DWC_OTG_DEVICE_ONLY is not set +# CONFIG_DWC_OTG_DEBUG is not set + +# +# USB Network Adapters +# # CONFIG_MMC is not set # CONFIG_NEW_LEDS is not set @@ -1018,5 +1228,10 @@ # CONFIG_NFSD is not set # CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1032,5 +1247,44 @@ # Native Language Support # -# CONFIG_NLS is not set +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# 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 is not set +# 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 # Index: /src/linux/rt2880/linux-2.6.23/net/ipv6/netfilter/nf_conntrack_reasm.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/net/ipv6/netfilter/nf_conntrack_reasm.c (revision 11891) +++ /src/linux/rt2880/linux-2.6.23/net/ipv6/netfilter/nf_conntrack_reasm.c (revision 12433) @@ -28,5 +28,5 @@ #include #include -#include +#include #include Index: /src/linux/rt2880/linux-2.6.23/net/ipv6/inet6_connection_sock.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/net/ipv6/inet6_connection_sock.c (revision 11891) +++ /src/linux/rt2880/linux-2.6.23/net/ipv6/inet6_connection_sock.c (revision 12433) @@ -1,3 +1,2 @@ -#define USE_JHASH2 /* * INET An implementation of the TCP/IP protocol suite for the LINUX @@ -18,5 +17,5 @@ #include #include -#include +#include #include Index: /src/linux/rt2880/linux-2.6.23/net/ipv6/reassembly.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/net/ipv6/reassembly.c (revision 11891) +++ /src/linux/rt2880/linux-2.6.23/net/ipv6/reassembly.c (revision 12433) @@ -1,3 +1,2 @@ -#define USE_JHASH2 1 /* * IPv6 fragment reassembly @@ -43,5 +42,5 @@ #include #include -#include +#include #include Index: /src/linux/rt2880/linux-2.6.23/.config_rt3052 =================================================================== --- /src/linux/rt2880/linux-2.6.23/.config_rt3052 (revision 11871) +++ /src/linux/rt2880/linux-2.6.23/.config_rt3052 (revision 12433) @@ -2,5 +2,5 @@ # Automatically generated make config: don't edit # Linux kernel version: 2.6.23.17 -# Mon Jan 5 14:47:41 2009 +# Tue May 19 13:55:15 2009 # CONFIG_MIPS=y @@ -415,4 +415,5 @@ CONFIG_IP_NF_TARGET_REJECT=y CONFIG_IP_NF_TARGET_IMQ=m +CONFIG_IP_NF_TARGET_ROUTE=y CONFIG_IP_NF_TARGET_LOG=y CONFIG_IP_NF_TARGET_ULOG=y @@ -559,39 +560,25 @@ # Ralink Common Flash Driver # -CONFIG_RALINK_FLASH_API=y +# CONFIG_RALINK_FLASH_API is not set # # 2MB Flash # -# CONFIG_FLASH_EN29LV160 is not set -# CONFIG_FLASH_MX29LV160 is not set -# CONFIG_FLASH_S29AL016X is not set -# CONFIG_FLASH_K8D3X16U is not set # # 4MB Flash # -CONFIG_FLASH_MX29LV320=y -# CONFIG_FLASH_EN29LV320 is not set -# CONFIG_FLASH_S29AL032X is not set -# CONFIG_FLASH_S29GL032N is not set -# CONFIG_FLASH_F49L320 is not set # # 8MB Flash # -# CONFIG_FLASH_MX29LV640 is not set -# CONFIG_FLASH_S29GL064N is not set -# CONFIG_FLASH_ST_M29W640 is not set # # 16MB Flash # -# CONFIG_FLASH_MX29LV128 is not set # # 32MB Flash # -# CONFIG_FLASH_S29GL256 is not set # @@ -657,4 +644,5 @@ # CONFIG_MTD_RALINK=y +# CONFIG_MTD_ESR6650 is not set # CONFIG_MTD_COMPLEX_MAPPINGS is not set # CONFIG_MTD_PHYSMAP is not set @@ -738,10 +726,6 @@ CONFIG_RAETH=y CONFIG_RAETH_NAPI=y -CONFIG_RAETH_CHECKSUM_OFFLOAD=y # CONFIG_RAETH_QOS is not set -# CONFIG_RAETH_ROUTER is not set -# CONFIG_MAC_TO_MAC_MODE is not set CONFIG_RT_3052_ESW=y -# CONFIG_GIGAPHY is not set CONFIG_LAN_WAN_SUPPORT=y # CONFIG_WAN_AT_P4 is not set @@ -1141,4 +1125,2 @@ CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y -CONFIG_IP_NF_TARGET_ROUTE=y -# CONFIG_MTD_ESR6650 is not set Index: /src/linux/rt2880/linux-2.6.23/fs/squashfs/LzmaDecode.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/fs/squashfs/LzmaDecode.c (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/fs/squashfs/LzmaDecode.c (revision 12433) @@ -46,5 +46,5 @@ } CRangeDecoder; -Byte RangeDecoderReadByte(CRangeDecoder *rd) +static inline Byte RangeDecoderReadByte(CRangeDecoder *rd) { if (rd->Buffer == rd->BufferLim) @@ -67,5 +67,5 @@ #define ReadByte (RangeDecoderReadByte(rd)) -void RangeDecoderInit(CRangeDecoder *rd, +static void RangeDecoderInit(CRangeDecoder *rd, #ifdef _LZMA_IN_CB ILzmaInCallback *inCallback @@ -94,5 +94,5 @@ #define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; } -UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits) +static inline UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits) { RC_INIT_VAR @@ -122,5 +122,5 @@ } -int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd) +static inline int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd) { UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob; @@ -160,5 +160,5 @@ #define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;) -int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) +static inline int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) { int mi = 1; @@ -182,5 +182,5 @@ } -int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) +static inline int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) { int mi = 1; @@ -207,5 +207,5 @@ } -Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd) +static inline Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd) { int symbol = 1; @@ -229,5 +229,5 @@ } -Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte) +static inline Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte) { int symbol = 1; @@ -287,5 +287,5 @@ #define kNumLenProbs (LenHigh + kLenNumHighSymbols) -int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState) +static inline int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState) { if(RangeDecoderBitDecode(p + LenChoice, rd) == 0) Index: /src/linux/rt2880/linux-2.6.23/fs/squashfs/LzmaDecode.h =================================================================== --- /src/linux/rt2880/linux-2.6.23/fs/squashfs/LzmaDecode.h (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/fs/squashfs/LzmaDecode.h (revision 12433) @@ -29,9 +29,9 @@ /* Use read function for output data */ -/* #define _LZMA_PROB32 */ +#define _LZMA_PROB32 /* It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case */ -/* #define _LZMA_LOC_OPT */ +#define _LZMA_LOC_OPT /* Enable local speed optimizations inside code */ Index: /src/linux/rt2880/linux-2.6.23/mm/page_alloc.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/mm/page_alloc.c (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/mm/page_alloc.c (revision 12433) @@ -1265,4 +1265,12 @@ /* + * Code in arch/mips/kernel/module.c wants physically + * contiguous memory only if there is plenty of free of them. + */ + if ((gfp_mask & (__GFP_THISNODE | __GFP_NORETRY | __GFP_NOWARN)) + == (__GFP_THISNODE | __GFP_NORETRY | __GFP_NOWARN)) + goto nopage; + + /* * GFP_THISNODE (meaning __GFP_THISNODE, __GFP_NORETRY and * __GFP_NOWARN set) should not cause reclaim since the subsystem @@ -1277,4 +1285,7 @@ for (z = zonelist->zones; *z; z++) wakeup_kswapd(*z, order); + + if (gfp_mask & 0x80000000) + goto nopage; /* Index: /src/linux/rt2880/linux-2.6.23/arch/mips/kernel/vmlinux.lds.S =================================================================== --- /src/linux/rt2880/linux-2.6.23/arch/mips/kernel/vmlinux.lds.S (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/arch/mips/kernel/vmlinux.lds.S (revision 12433) @@ -135,5 +135,6 @@ *(.bss) *(COMMON) - } + . = (ALIGN(_PAGE_SIZE) - .) < 8 ? ALIGN(_PAGE_SIZE) + 4 : . ; + } __bss_stop = .; Index: /src/linux/rt2880/linux-2.6.23/arch/mips/kernel/module.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/arch/mips/kernel/module.c (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/arch/mips/kernel/module.c (revision 12433) @@ -30,4 +30,5 @@ #include #include +#include #include /* MODULE_START */ @@ -43,4 +44,39 @@ static DEFINE_SPINLOCK(dbe_lock); +static void *alloc_phys(unsigned long size) +{ + unsigned order; + struct page *page; + struct page *p; + + size = PAGE_ALIGN(size); + order = get_order(size); + + page = alloc_pages( + GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN | __GFP_THISNODE, + order); + if (!page) + return 0; + + split_page(page, order); + + for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p) + __free_page(p); + + return page_address(page); +} + +static void free_phys(void *ptr, unsigned long size) +{ + struct page *page; + struct page *end; + + page = virt_to_page(ptr); + end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT); + + for (; page < end; ++page) + __free_pages(page, 0); +} + void *module_alloc(unsigned long size) { @@ -58,8 +94,39 @@ return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); #else + unsigned addr; + void *ptr; + + size = PAGE_ALIGN(size); if (size == 0) return NULL; - return vmalloc(size); + + ptr = alloc_phys(size); + if (ptr) + return ptr; + + /* try to allocate contiguos chunk of memory not spanning 256Mb + range, so all jump instructions can work */ + addr = VMALLOC_START; + while (addr < VMALLOC_END) { + unsigned end = ALIGN(addr + 1, 1u << 28); + + if (addr + size <= end) { + struct vm_struct *area + = __get_vm_area(size, VM_ALLOC, addr, end); + + if (area) + return __vmalloc_area( + area, GFP_KERNEL, PAGE_KERNEL); + } + addr = end; + } + return NULL; #endif +} + +static inline int is_phys(void *ptr) +{ + unsigned addr = (unsigned) ptr; + return addr && (addr < VMALLOC_START || addr > VMALLOC_END); } @@ -67,4 +134,14 @@ void module_free(struct module *mod, void *module_region) { + if (is_phys(module_region)) { + if (mod->module_init == module_region) + free_phys(module_region, mod->init_size); + else if (mod->module_core == module_region) + free_phys(module_region, mod->core_size); + else + BUG(); + return; + } + vfree(module_region); /* FIXME: If module_region == mod->init_region, trim exception @@ -78,4 +155,98 @@ } +/* Get the potential trampolines size required of the init and + non-init sections */ +static unsigned get_plt_size(const Elf32_Ehdr *hdr, + const Elf32_Shdr *sechdrs, + const char *secstrings, + unsigned symindex, + int is_init) +{ + unsigned long ret = 0; + unsigned i, j; + Elf_Sym *syms; + + /* Everything marked ALLOC (this includes the exported symbols) */ + for (i = 1; i < hdr->e_shnum; ++i) { + unsigned int info = sechdrs[i].sh_info; + + if (sechdrs[i].sh_type != SHT_REL + && sechdrs[i].sh_type != SHT_RELA) + continue; + + /* Not a valid relocation section? */ + if (info >= hdr->e_shnum) + continue; + + /* Don't bother with non-allocated sections */ + if (!(sechdrs[info].sh_flags & SHF_ALLOC)) + continue; + + /* If it's called *.init*, and we're not init, we're + not interested */ + if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0) + != is_init) + continue; + + syms = (Elf_Sym *) sechdrs[symindex].sh_addr; + if (sechdrs[i].sh_type == SHT_REL) { + Elf_Mips_Rel *rel = (void *) sechdrs[i].sh_addr; + unsigned size = sechdrs[i].sh_size / sizeof(*rel); + + for (j = 0; j < size; ++j) { + Elf_Sym *sym; + + if (ELF_MIPS_R_TYPE(rel[j]) != R_MIPS_26) + continue; + sym = syms + ELF_MIPS_R_SYM(rel[j]); + if (!is_init && sym->st_shndx != SHN_UNDEF) + continue; + + ret += sizeof(unsigned[4]); + } + } else { + Elf_Mips_Rela *rela = (void *) sechdrs[i].sh_addr; + unsigned size = sechdrs[i].sh_size / sizeof(*rela); + + for (j = 0; j < size; ++j) { + Elf_Sym *sym; + + if (ELF_MIPS_R_TYPE(rela[j]) != R_MIPS_26) + continue; + sym = syms + ELF_MIPS_R_SYM(rela[j]); + if (!is_init && sym->st_shndx != SHN_UNDEF) + continue; + + ret += sizeof(unsigned[4]); + } + } + + } + + return ret; +} + +int module_relayout(Elf32_Ehdr *hdr, + Elf32_Shdr *sechdrs, + char *secstrings, + unsigned symindex, + struct module *me) +{ + unsigned core_plt_size = get_plt_size( + hdr, sechdrs, secstrings, symindex, 0); + unsigned init_plt_size = get_plt_size( + hdr, sechdrs, secstrings, symindex, 1); + + if (core_plt_size > 0) + me->core_size = PAGE_ALIGN(me->core_size); + me->arch.core_plt_offset = me->core_size; + me->core_size = me->core_size + core_plt_size; + + me->arch.init_plt_offset = me->init_size; + me->init_size = me->init_size + init_plt_size; + + return 0; +} + static int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v) { @@ -94,4 +265,42 @@ *location = v; + return 0; +} + +static Elf_Addr add_plt_entry_to(unsigned *plt_offset, + void *start, unsigned size, Elf_Addr v) +{ + unsigned *tramp = start + *plt_offset; + if (*plt_offset == size) return 0; + + *plt_offset += sizeof(unsigned[4]); + + /* adjust carry for addiu */ + if (v & 0x00008000) + v += 0x10000; + + tramp[0] = 0x3c190000 | (v >> 16); /* lui t9, hi16 */ + tramp[1] = 0x27390000 | (v & 0xffff); /* addiu t9, t9, lo16 */ + tramp[2] = 0x03200008; /* jr t9 */ + tramp[3] = 0x00000000; /* nop */ + + return (Elf_Addr) tramp; +} + +static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v) +{ + if (location >= me->module_core + && location < me->module_core + me->core_size) { + return add_plt_entry_to(&me->arch.core_plt_offset, + me->module_core, me->core_size, v); + } else if (location > me->module_init + && location < me->module_init + me->init_size) { + return add_plt_entry_to(&me->arch.init_plt_offset, + me->module_init, me->init_size, v); + } else { + printk(KERN_ERR "module %s: " + "relocation to unknown segment %u\n", + me->name, v); + } return 0; } @@ -105,4 +314,7 @@ if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { + v = add_plt_entry(me, location, + v + ((*location & 0x03ffffff) << 2)); + if (v == 0) { printk(KERN_ERR "module %s: relocation overflow\n", @@ -110,4 +322,8 @@ return -ENOEXEC; } + *location = (*location & ~0x03ffffff) | + ((v >> 2) & 0x03ffffff); + return 0; + } *location = (*location & ~0x03ffffff) | @@ -125,8 +341,11 @@ if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { + v = add_plt_entry(me, location, v); + if (v == 0) { printk(KERN_ERR "module %s: relocation overflow\n", me->name); return -ENOEXEC; + } } @@ -400,4 +619,12 @@ spin_unlock_irq(&dbe_lock); } + + if (me->arch.core_plt_offset < me->core_size + && PAGE_ALIGN(me->arch.core_plt_offset) == me->arch.core_plt_offset + && is_phys(me->module_core)) { + free_phys(me->module_core + me->arch.core_plt_offset, + me->core_size - me->arch.core_plt_offset); + me->core_size = me->arch.core_plt_offset; + } return 0; } Index: /src/linux/rt2880/linux-2.6.23/arch/mips/kernel/scall32-o32.S =================================================================== --- /src/linux/rt2880/linux-2.6.23/arch/mips/kernel/scall32-o32.S (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/arch/mips/kernel/scall32-o32.S (revision 12433) @@ -647,5 +647,5 @@ sys sys_ppoll 5 sys sys_unshare 1 - sys sys_splice 4 + sys sys_splice 6 sys sys_sync_file_range 7 /* 4305 */ sys sys_tee 4 Index: /src/linux/rt2880/linux-2.6.23/arch/mips/Makefile =================================================================== --- /src/linux/rt2880/linux-2.6.23/arch/mips/Makefile (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/arch/mips/Makefile (revision 12433) @@ -84,5 +84,5 @@ cflags-y += -msoft-float LDFLAGS_vmlinux += -G 0 -static -n -nostdlib -MODFLAGS += -mlong-calls +MODFLAGS += -mno-long-calls cflags-y += -ffreestanding Index: /src/linux/rt2880/linux-2.6.23/arch/mips/rt2880/init.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/arch/mips/rt2880/init.c (revision 10843) +++ /src/linux/rt2880/linux-2.6.23/arch/mips/rt2880/init.c (revision 12433) @@ -351,4 +351,5 @@ prom_meminit(); prom_setup_printf(prom_get_ttysnum()); +// *(unsigned long *)(KSEG1ADDR(RALINK_USB_OTG_BASE+0xE00)) = 0x0; //Enable USB Port prom_printf("\nLINUX started...\n"); #if defined(CONFIG_RT2880_FPGA) || defined(CONFIG_RT3052_FPGA) || defined(CONFIG_RT2883_FPGA) Index: /src/linux/rt2880/linux-2.6.23/arch/mips/mm/c-r4k.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/arch/mips/mm/c-r4k.c (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/arch/mips/mm/c-r4k.c (revision 12433) @@ -929,5 +929,7 @@ c->dcache.waybit = __ffs(dcache_size/c->dcache.ways); +#ifdef CONFIG_CPU_HAS_PREFETCH c->options |= MIPS_CPU_PREFETCH; +#endif break; } Index: /src/linux/rt2880/linux-2.6.23/drivers/net/Makefile =================================================================== --- /src/linux/rt2880/linux-2.6.23/drivers/net/Makefile (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/drivers/net/Makefile (revision 12433) @@ -285,4 +285,5 @@ obj-$(CONFIG_USB_PEGASUS) += usb/ obj-$(CONFIG_USB_RTL8150) += usb/ +obj-$(CONFIG_USB_HSO) += usb/ obj-$(CONFIG_USB_USBNET) += usb/ obj-$(CONFIG_USB_ZD1201) += usb/ Index: /src/linux/rt2880/linux-2.6.23/drivers/net/usb/Kconfig =================================================================== --- /src/linux/rt2880/linux-2.6.23/drivers/net/usb/Kconfig (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/drivers/net/usb/Kconfig (revision 12433) @@ -160,4 +160,14 @@ what other networking devices you have in use. +config USB_HSO + tristate "Option USB High Speed Mobile Devices" + depends on USB && RFKILL + default n + help + Choose this option if you have an Option HSDPA/HSUPA card. + These cards support downlink speeds of 7.2Mbps or greater. + + To compile this driver as a module, choose M here: the + module will be called hso. config USB_NET_CDCETHER Index: /src/linux/rt2880/linux-2.6.23/drivers/net/usb/Makefile =================================================================== --- /src/linux/rt2880/linux-2.6.23/drivers/net/usb/Makefile (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/drivers/net/usb/Makefile (revision 12433) @@ -7,4 +7,5 @@ obj-$(CONFIG_USB_PEGASUS) += pegasus.o obj-$(CONFIG_USB_RTL8150) += rtl8150.o +obj-$(CONFIG_USB_HSO) += hso.o obj-$(CONFIG_USB_NET_AX8817X) += asix.o obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o @@ -22,2 +23,6 @@ EXTRA_CFLAGS += -DDEBUG endif + +ifeq ($(CONFIG_DWC_OTG_HOST_ONLY),y) +EXTRA_CFLAGS += -DDWC_HOST_ONLY +endif Index: /src/linux/rt2880/linux-2.6.23/drivers/usb/serial/Makefile =================================================================== --- /src/linux/rt2880/linux-2.6.23/drivers/usb/serial/Makefile (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/drivers/usb/serial/Makefile (revision 12433) @@ -40,5 +40,6 @@ obj-$(CONFIG_USB_SERIAL_NAVMAN) += navman.o obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o -obj-$(CONFIG_USB_SERIAL_OPTION) += option.o +obj-m += option.o +#obj-m += hso.o obj-$(CONFIG_USB_SERIAL_OTI6858) += oti6858.o obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o Index: /src/linux/rt2880/linux-2.6.23/drivers/usb/serial/option.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/drivers/usb/serial/option.c (revision 11829) +++ /src/linux/rt2880/linux-2.6.23/drivers/usb/serial/option.c (revision 12433) @@ -105,4 +105,10 @@ #define OPTION_PRODUCT_ETNA_KOI_MODEM 0x7100 #define OPTION_PRODUCT_ETNA_KOI_NETWORK 0x7111 + +#define QUALCOMM_OPTION_VENDOR_ID 0x1e0e +#define QUALCOMM_OPTION_PRODUCT_ICON_210 0x9000 + +//#define QUALCOMM2_OPTION_VENDOR_ID 0x0af0 +//#define QUALCOMM2_OPTION_PRODUCT_ICON_210 0x6971 #define HUAWEI_VENDOR_ID 0x12D1 @@ -336,4 +342,6 @@ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_EX) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) }, + { USB_DEVICE(QUALCOMM_OPTION_VENDOR_ID, QUALCOMM_OPTION_PRODUCT_ICON_210) }, +// { USB_DEVICE(QUALCOMM2_OPTION_VENDOR_ID, QUALCOMM2_OPTION_PRODUCT_ICON_210) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) }, Index: /src/linux/rt2880/linux-2.6.23/drivers/usb/serial/sierra.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/drivers/usb/serial/sierra.c (revision 12064) +++ /src/linux/rt2880/linux-2.6.23/drivers/usb/serial/sierra.c (revision 12433) @@ -778,8 +778,5 @@ portdata->dtr_state = 1; - if (port->tty) { - port->tty->low_latency = 1; - } - + spin_lock_init(&portdata->lock); Index: /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/Kconfig =================================================================== --- /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/Kconfig (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/Kconfig (revision 12433) @@ -1,11 +1,11 @@ config DWC_OTG - tristate "RALINK DWC_OTG support" + tristate "Ralink DWC_OTG support" ---help--- - This driver supports Ralink DWC_OTG + This driver supports Ralink DWC_OTG -config DWC_OTG_DEBUG - bool "enable debug mode" +choice + prompt "USB Operation Mode" depends on DWC_OTG - + default DWC_OTG_HOST_ONLY config DWC_OTG_HOST_ONLY @@ -17,2 +17,8 @@ depends on DWC_OTG +endchoice + + +config DWC_OTG_DEBUG + bool "Enable debug mode" + depends on DWC_OTG Index: /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_hcd_intr.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_hcd_intr.c (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_hcd_intr.c (revision 12433) @@ -1,12 +1,12 @@ /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_hcd_intr.c $ - * $Revision: 1.1 $ - * $Date: 2007-11-19 05:39:07 $ - * $Change: 553126 $ + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $ + * $Revision: 1.7 $ + * $Date: 2009-03-09 08:04:24 $ + * $Change: 1117667 $ * * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless * otherwise expressly agreed to in writing between Synopsys and you. - * + * * The Software IS NOT an item of Licensed Software or Licensed Product under * any End User Software License Agreement or Agreement for Licensed Product @@ -18,5 +18,5 @@ * Synopsys. If you do not agree with this notice, including the disclaimer * below, then you are not authorized to use the Software. - * + * * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -33,25 +33,27 @@ #ifndef DWC_DEVICE_ONLY +#include + #include "dwc_otg_driver.h" #include "dwc_otg_hcd.h" #include "dwc_otg_regs.h" -/** @file - * This file contains the implementation of the HCD Interrupt handlers. +/** @file + * This file contains the implementation of the HCD Interrupt handlers. */ /** This function handles interrupts for the HCD. */ -int32_t dwc_otg_hcd_handle_intr (dwc_otg_hcd_t *_dwc_otg_hcd) +int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t *dwc_otg_hcd) { int retval = 0; - dwc_otg_core_if_t *core_if = _dwc_otg_hcd->core_if; - gintsts_data_t gintsts; + dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; + gintsts_data_t gintsts; #ifdef DEBUG - dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; #endif /* Check if HOST Mode */ - if (dwc_otg_is_host_mode(core_if)) { + if (dwc_otg_is_host_mode(core_if)) { gintsts.d32 = dwc_otg_read_core_intr(core_if); if (!gintsts.d32) { @@ -61,42 +63,46 @@ #ifdef DEBUG /* Don't print debug message in the interrupt handler on SOF */ -# ifndef DEBUG_SOF +# ifndef DEBUG_SOF if (gintsts.d32 != DWC_SOF_INTR_MASK) -# endif - DWC_DEBUGPL (DBG_HCD, "\n"); +# endif + DWC_DEBUGPL(DBG_HCD, "\n"); #endif #ifdef DEBUG -# ifndef DEBUG_SOF +# ifndef DEBUG_SOF if (gintsts.d32 != DWC_SOF_INTR_MASK) -# endif +# endif DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x\n", gintsts.d32); #endif - - if (gintsts.b.sofintr) { - retval |= dwc_otg_hcd_handle_sof_intr (_dwc_otg_hcd); - } - if (gintsts.b.rxstsqlvl) { - retval |= dwc_otg_hcd_handle_rx_status_q_level_intr (_dwc_otg_hcd); - } - if (gintsts.b.nptxfempty) { - retval |= dwc_otg_hcd_handle_np_tx_fifo_empty_intr (_dwc_otg_hcd); - } - if (gintsts.b.i2cintr) { + if (gintsts.b.usbreset) { + DWC_PRINT("Usb Reset In Host Mode\n"); + } + + + if (gintsts.b.sofintr) { + retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd); + } + if (gintsts.b.rxstsqlvl) { + retval |= dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd); + } + if (gintsts.b.nptxfempty) { + retval |= dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd); + } + if (gintsts.b.i2cintr) { /** @todo Implement i2cintr handler. */ - } + } if (gintsts.b.portintr) { - retval |= dwc_otg_hcd_handle_port_intr (_dwc_otg_hcd); + retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd); } if (gintsts.b.hcintr) { - retval |= dwc_otg_hcd_handle_hc_intr (_dwc_otg_hcd); + retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd); } if (gintsts.b.ptxfempty) { - retval |= dwc_otg_hcd_handle_perio_tx_fifo_empty_intr (_dwc_otg_hcd); + retval |= dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd); } #ifdef DEBUG -# ifndef DEBUG_SOF +# ifndef DEBUG_SOF if (gintsts.d32 != DWC_SOF_INTR_MASK) -# endif +# endif { DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Finished Servicing Interrupts\n"); @@ -104,16 +110,18 @@ dwc_read_reg32(&global_regs->gintsts)); DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintmsk=0x%08x\n", - dwc_read_reg32(&global_regs->gintmsk)); + dwc_read_reg32(&global_regs->gintmsk)); } #endif #ifdef DEBUG -# ifndef DEBUG_SOF +# ifndef DEBUG_SOF if (gintsts.d32 != DWC_SOF_INTR_MASK) -# endif - DWC_DEBUGPL (DBG_HCD, "\n"); +# endif + DWC_DEBUGPL(DBG_HCD, "\n"); #endif } + + S3C2410X_CLEAR_EINTPEND(); return retval; @@ -126,5 +134,6 @@ * This function is for debug only. */ -static inline void track_missed_sofs(uint16_t _curr_frame_number) { +static inline void track_missed_sofs(uint16_t curr_frame_number) +{ static uint16_t frame_num_array[FRAME_NUM_ARRAY_SIZE]; static uint16_t last_frame_num_array[FRAME_NUM_ARRAY_SIZE]; @@ -132,8 +141,8 @@ static uint16_t last_frame_num = DWC_HFNUM_MAX_FRNUM; static int dumped_frame_num_array = 0; - + if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) { - if ((((last_frame_num + 1) & DWC_HFNUM_MAX_FRNUM) != _curr_frame_number)) { - frame_num_array[frame_num_idx] = _curr_frame_number; + if (((last_frame_num + 1) & DWC_HFNUM_MAX_FRNUM) != curr_frame_number) { + frame_num_array[frame_num_idx] = curr_frame_number; last_frame_num_array[frame_num_idx++] = last_frame_num; } @@ -148,7 +157,7 @@ dumped_frame_num_array = 1; } - last_frame_num = _curr_frame_number; -} -#endif + last_frame_num = curr_frame_number; +} +#endif /** @@ -158,51 +167,50 @@ * next (micro)frame. */ -int32_t dwc_otg_hcd_handle_sof_intr (dwc_otg_hcd_t *_hcd) +int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t *hcd) { hfnum_data_t hfnum; - struct list_head *qh_entry; - dwc_otg_qh_t *qh; + struct list_head *qh_entry; + dwc_otg_qh_t *qh; dwc_otg_transaction_type_e tr_type; gintsts_data_t gintsts = {.d32 = 0}; - hfnum.d32 = dwc_read_reg32(&_hcd->core_if->host_if->host_global_regs->hfnum); + hfnum.d32 = dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hfnum); #ifdef DEBUG_SOF DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n"); #endif - - _hcd->frame_number = hfnum.b.frnum; + hcd->frame_number = hfnum.b.frnum; #ifdef DEBUG - _hcd->frrem_accum += hfnum.b.frrem; - _hcd->frrem_samples++; + hcd->frrem_accum += hfnum.b.frrem; + hcd->frrem_samples++; #endif #ifdef DWC_TRACK_MISSED_SOFS - track_missed_sofs(_hcd->frame_number); -#endif + track_missed_sofs(hcd->frame_number); +#endif /* Determine whether any periodic QHs should be executed. */ - qh_entry = _hcd->periodic_sched_inactive.next; - while (qh_entry != &_hcd->periodic_sched_inactive) { + qh_entry = hcd->periodic_sched_inactive.next; + while (qh_entry != &hcd->periodic_sched_inactive) { qh = list_entry(qh_entry, dwc_otg_qh_t, qh_list_entry); qh_entry = qh_entry->next; - if (dwc_frame_num_le(qh->sched_frame, _hcd->frame_number)) { - /* + if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) { + /* * Move QH to the ready list to be executed next * (micro)frame. */ - list_move(&qh->qh_list_entry, &_hcd->periodic_sched_ready); - } - } - - tr_type = dwc_otg_hcd_select_transactions(_hcd); + list_move(&qh->qh_list_entry, &hcd->periodic_sched_ready); + } + } + + tr_type = dwc_otg_hcd_select_transactions(hcd); if (tr_type != DWC_OTG_TRANSACTION_NONE) { - dwc_otg_hcd_queue_transactions(_hcd, tr_type); + dwc_otg_hcd_queue_transactions(hcd, tr_type); } /* Clear interrupt */ gintsts.b.sofintr = 1; - dwc_write_reg32(&_hcd->core_if->core_global_regs->gintsts, gintsts.d32); + dwc_write_reg32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32); return 1; @@ -212,5 +220,5 @@ * least one packet in the Rx FIFO. The packets are moved from the FIFO to * memory if the DWC_otg controller is operating in Slave mode. */ -int32_t dwc_otg_hcd_handle_rx_status_q_level_intr (dwc_otg_hcd_t *_dwc_otg_hcd) +int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *dwc_otg_hcd) { host_grxsts_data_t grxsts; @@ -219,7 +227,7 @@ DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n"); - grxsts.d32 = dwc_read_reg32(&_dwc_otg_hcd->core_if->core_global_regs->grxstsp); - - hc = _dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum]; + grxsts.d32 = dwc_read_reg32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp); + + hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum]; /* Packet Status */ @@ -228,11 +236,11 @@ DWC_DEBUGPL(DBG_HCDV, " DPID = %d, hc.dpid = %d\n", grxsts.b.dpid, hc->data_pid_start); DWC_DEBUGPL(DBG_HCDV, " PStatus = %d\n", grxsts.b.pktsts); - + switch (grxsts.b.pktsts) { case DWC_GRXSTS_PKTSTS_IN: /* Read the data into the host buffer. */ if (grxsts.b.bcnt > 0) { - dwc_otg_read_packet(_dwc_otg_hcd->core_if, - hc->xfer_buff, + dwc_otg_read_packet(dwc_otg_hcd->core_if, + hc->xfer_buff, grxsts.b.bcnt); @@ -241,5 +249,5 @@ hc->xfer_buff += grxsts.b.bcnt; } - + case DWC_GRXSTS_PKTSTS_IN_XFER_COMP: case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR: @@ -248,8 +256,8 @@ break; default: - DWC_ERROR ("RX_STS_Q Interrupt: Unknown status %d\n", grxsts.b.pktsts); - break; - } - + DWC_ERROR("RX_STS_Q Interrupt: Unknown status %d\n", grxsts.b.pktsts); + break; + } + return 1; } @@ -259,8 +267,8 @@ * may be written to the non-periodic request queue for IN transfers. This * interrupt is enabled only in Slave mode. */ -int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr (dwc_otg_hcd_t *_dwc_otg_hcd) +int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *dwc_otg_hcd) { DWC_DEBUGPL(DBG_HCD, "--Non-Periodic TxFIFO Empty Interrupt--\n"); - dwc_otg_hcd_queue_transactions(_dwc_otg_hcd, + dwc_otg_hcd_queue_transactions(dwc_otg_hcd, DWC_OTG_TRANSACTION_NON_PERIODIC); return 1; @@ -271,8 +279,8 @@ * written to the periodic request queue for IN transfers. This interrupt is * enabled only in Slave mode. */ -int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr (dwc_otg_hcd_t *_dwc_otg_hcd) -{ - DWC_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n"); - dwc_otg_hcd_queue_transactions(_dwc_otg_hcd, +int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t *dwc_otg_hcd) +{ + DWC_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n"); + dwc_otg_hcd_queue_transactions(dwc_otg_hcd, DWC_OTG_TRANSACTION_PERIODIC); return 1; @@ -282,5 +290,5 @@ * determines which interrupt conditions have occurred and handles them * appropriately. */ -int32_t dwc_otg_hcd_handle_port_intr (dwc_otg_hcd_t *_dwc_otg_hcd) +int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t *dwc_otg_hcd) { int retval = 0; @@ -288,6 +296,6 @@ hprt0_data_t hprt0_modify; - hprt0.d32 = dwc_read_reg32(_dwc_otg_hcd->core_if->host_if->hprt0); - hprt0_modify.d32 = dwc_read_reg32(_dwc_otg_hcd->core_if->host_if->hprt0); + hprt0.d32 = dwc_read_reg32(dwc_otg_hcd->core_if->host_if->hprt0); + hprt0_modify.d32 = dwc_read_reg32(dwc_otg_hcd->core_if->host_if->hprt0); /* Clear appropriate bits in HPRT0 to clear the interrupt bit in @@ -295,19 +303,19 @@ hprt0_modify.b.prtena = 0; - hprt0_modify.b.prtconndet = 0; + hprt0_modify.b.prtconndet = 0; hprt0_modify.b.prtenchng = 0; - hprt0_modify.b.prtovrcurrchng = 0; - - /* Port Connect Detected + hprt0_modify.b.prtovrcurrchng = 0; + + /* Port Connect Detected * Set flag and clear if detected */ if (hprt0.b.prtconndet) { DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x " "Port Connect Detected--\n", hprt0.d32); - _dwc_otg_hcd->flags.b.port_connect_status_change = 1; - _dwc_otg_hcd->flags.b.port_connect_status = 1; + dwc_otg_hcd->flags.b.port_connect_status_change = 1; + dwc_otg_hcd->flags.b.port_connect_status = 1; hprt0_modify.b.prtconndet = 1; - /* B-Device has connected, Delete the connection timer. */ - del_timer( &_dwc_otg_hcd->conn_timer ); + /* B-Device has connected, Delete the connection timer. */ + del_timer( &dwc_otg_hcd->conn_timer ); /* The Hub driver asserts a reset when it sees port connect @@ -324,21 +332,19 @@ if (hprt0.b.prtena == 1) { int do_reset = 0; - dwc_otg_core_params_t *params = _dwc_otg_hcd->core_if->core_params; - dwc_otg_core_global_regs_t *global_regs = _dwc_otg_hcd->core_if->core_global_regs; - dwc_otg_host_if_t *host_if = _dwc_otg_hcd->core_if->host_if; + dwc_otg_core_params_t *params = dwc_otg_hcd->core_if->core_params; + dwc_otg_core_global_regs_t *global_regs = dwc_otg_hcd->core_if->core_global_regs; + dwc_otg_host_if_t *host_if = dwc_otg_hcd->core_if->host_if; /* Check if we need to adjust the PHY clock speed for * low power and adjust it */ - if (params->host_support_fs_ls_low_power) - { + if (params->host_support_fs_ls_low_power) { gusbcfg_data_t usbcfg; - usbcfg.d32 = dwc_read_reg32 (&global_regs->gusbcfg); - - if ((hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED) || - (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_FULL_SPEED)) - { - /* - * Low power + usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); + + if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED || + hprt0.b.prtspd == DWC_HPRT0_PRTSPD_FULL_SPEED) { + /* + * Low power */ hcfg_data_t hcfg; @@ -352,8 +358,7 @@ hcfg.d32 = dwc_read_reg32(&host_if->host_global_regs->hcfg); - if ((hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED) && - (params->host_ls_low_power_phy_clk == - DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)) - { + if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED && + params->host_ls_low_power_phy_clk == + DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ) { /* 6 MHZ */ DWC_DEBUGPL(DBG_CIL, "FS_PHY programming HCFG to 6 MHz (Low Power)\n"); @@ -364,6 +369,5 @@ do_reset = 1; } - } - else { + } else { /* 48 MHZ */ DWC_DEBUGPL(DBG_CIL, "FS_PHY programming HCFG to 48 MHz ()\n"); @@ -375,8 +379,7 @@ } } - } - else { - /* - * Not low power + } else { + /* + * Not low power */ if (usbcfg.b.phylpwrclksel == 1) { @@ -388,15 +391,14 @@ if (do_reset) { - tasklet_schedule(_dwc_otg_hcd->reset_tasklet); + tasklet_schedule(dwc_otg_hcd->reset_tasklet); } } - + if (!do_reset) { /* Port has been enabled set the reset change flag */ - _dwc_otg_hcd->flags.b.port_reset_change = 1; + dwc_otg_hcd->flags.b.port_reset_change = 1; } - } else { - _dwc_otg_hcd->flags.b.port_enable_change = 1; + dwc_otg_hcd->flags.b.port_enable_change = 1; } retval |= 1; @@ -407,15 +409,14 @@ DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x " "Port Overcurrent Changed--\n", hprt0.d32); - _dwc_otg_hcd->flags.b.port_over_current_change = 1; - hprt0_modify.b.prtovrcurrchng = 1; + dwc_otg_hcd->flags.b.port_over_current_change = 1; + hprt0_modify.b.prtovrcurrchng = 1; retval |= 1; } /* Clear Port Interrupts */ - dwc_write_reg32(_dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32); + dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32); return retval; } - /** This interrupt indicates that one or more host channels has a pending @@ -423,5 +424,5 @@ * interrupt. This function determines which conditions have occurred for each * host channel interrupt and handles them appropriately. */ -int32_t dwc_otg_hcd_handle_hc_intr (dwc_otg_hcd_t *_dwc_otg_hcd) +int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t *dwc_otg_hcd) { int i; @@ -432,9 +433,9 @@ * GINTSTS */ - haint.d32 = dwc_otg_read_host_all_channels_intr(_dwc_otg_hcd->core_if); - - for (i=0; i<_dwc_otg_hcd->core_if->core_params->host_channels; i++) { + haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if); + + for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) { if (haint.b2.chint & (1 << i)) { - retval |= dwc_otg_hcd_handle_hc_n_intr (_dwc_otg_hcd, i); + retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i); } } @@ -444,9 +445,9 @@ /* Macro used to clear one channel interrupt */ -#define clear_hc_int(_hc_regs_,_intr_) \ +#define clear_hc_int(_hc_regs_, _intr_) \ do { \ hcint_data_t hcint_clear = {.d32 = 0}; \ hcint_clear.b._intr_ = 1; \ - dwc_write_reg32(&((_hc_regs_)->hcint), hcint_clear.d32); \ + dwc_write_reg32(&(_hc_regs_)->hcint, hcint_clear.d32); \ } while (0) @@ -458,9 +459,9 @@ * because the channel structures are cleaned up when the channel is released. */ -#define disable_hc_int(_hc_regs_,_intr_) \ +#define disable_hc_int(_hc_regs_, _intr_) \ do { \ hcintmsk_data_t hcintmsk = {.d32 = 0}; \ hcintmsk.b._intr_ = 1; \ - dwc_modify_reg32(&((_hc_regs_)->hcintmsk), hcintmsk.d32, 0); \ + dwc_modify_reg32(&(_hc_regs_)->hcintmsk, hcintmsk.d32, 0); \ } while (0) @@ -469,34 +470,34 @@ * holds the reason for the halt. * - * For IN transfers where _halt_status is DWC_OTG_HC_XFER_COMPLETE, - * *_short_read is set to 1 upon return if less than the requested - * number of bytes were transferred. Otherwise, *_short_read is set to 0 upon - * return. _short_read may also be NULL on entry, in which case it remains + * For IN transfers where halt_status is DWC_OTG_HC_XFER_COMPLETE, + * *short_read is set to 1 upon return if less than the requested + * number of bytes were transferred. Otherwise, *short_read is set to 0 upon + * return. short_read may also be NULL on entry, in which case it remains * unchanged. */ -static uint32_t get_actual_xfer_length(dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - dwc_otg_qtd_t *_qtd, - dwc_otg_halt_status_e _halt_status, - int *_short_read) -{ - hctsiz_data_t hctsiz; - uint32_t length; - - if (_short_read != NULL) { - *_short_read = 0; - } - hctsiz.d32 = dwc_read_reg32(&_hc_regs->hctsiz); - - if (_halt_status == DWC_OTG_HC_XFER_COMPLETE) { - if (_hc->ep_is_in) { - length = _hc->xfer_len - hctsiz.b.xfersize; - if (_short_read != NULL) { - *_short_read = (hctsiz.b.xfersize != 0); +static uint32_t get_actual_xfer_length(dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + dwc_otg_qtd_t *qtd, + dwc_otg_halt_status_e halt_status, + int *short_read) +{ + hctsiz_data_t hctsiz; + uint32_t length; + + if (short_read != NULL) { + *short_read = 0; + } + hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); + + if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { + if (hc->ep_is_in) { + length = hc->xfer_len - hctsiz.b.xfersize; + if (short_read != NULL) { + *short_read = (hctsiz.b.xfersize != 0); } - } else if (_hc->qh->do_split) { - length = _qtd->ssplit_out_xfer_count; + } else if (hc->qh->do_split) { + length = qtd->ssplit_out_xfer_count; } else { - length = _hc->xfer_len; + length = hc->xfer_len; } } else { @@ -510,5 +511,5 @@ * bytes transferred via the AHB, not the USB). */ - length = (_hc->start_pkt_count - hctsiz.b.pktcnt) * _hc->max_packet; + length = (hc->start_pkt_count - hctsiz.b.pktcnt) * hc->max_packet; } @@ -520,28 +521,49 @@ * host channel. Updates the actual_length field of the URB based on the * number of bytes transferred via the host channel. Sets the URB status - * if the data transfer is finished. + * if the data transfer is finished. * * @return 1 if the data transfer specified by the URB is completely finished, * 0 otherwise. */ -static int update_urb_state_xfer_comp(dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - struct urb *_urb, - dwc_otg_qtd_t *_qtd) -{ - int xfer_done = 0; - int short_read = 0; - - _urb->actual_length += get_actual_xfer_length(_hc, _hc_regs, _qtd, - DWC_OTG_HC_XFER_COMPLETE, - &short_read); - - if (short_read || (_urb->actual_length == _urb->transfer_buffer_length)) { +static int update_urb_state_xfer_comp(dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + struct urb *urb, + dwc_otg_qtd_t *qtd) +{ + int xfer_done = 0; + int short_read = 0; + int overflow_read=0; + uint32_t len = 0; + int max_packet; + + len = get_actual_xfer_length(hc, hc_regs, qtd, + DWC_OTG_HC_XFER_COMPLETE, + &short_read); + + /* Data overflow case: by Steven */ + if (len > urb->transfer_buffer_length) { + len = urb->transfer_buffer_length; + overflow_read = 1; + } + + /* non DWORD-aligned buffer case handling. */ + if (((uint32_t)hc->xfer_buff & 0x3) && len && hc->qh->dw_align_buf && hc->ep_is_in) { + memcpy(urb->transfer_buffer + urb->actual_length, hc->qh->dw_align_buf, len); + } + urb->actual_length +=len; + + max_packet = usb_maxpacket(urb->dev, urb->pipe, !usb_pipein(urb->pipe)); + if((len) && usb_pipebulk(urb->pipe) && + (urb->transfer_flags & URB_ZERO_PACKET) && + (urb->actual_length == urb->transfer_buffer_length) && + (!(urb->transfer_buffer_length % max_packet))) { + } else if (short_read || urb->actual_length == urb->transfer_buffer_length) { xfer_done = 1; - if (short_read && (_urb->transfer_flags & URB_SHORT_NOT_OK)) { - _urb->status = -EREMOTEIO; - } - else { - _urb->status = 0; + if (short_read && (urb->transfer_flags & URB_SHORT_NOT_OK)) { + urb->status = -EREMOTEIO; + } else if (overflow_read) { + urb->status = -EOVERFLOW; + } else { + urb->status = 0; } } @@ -549,13 +571,13 @@ #ifdef DEBUG { - hctsiz_data_t hctsiz; - hctsiz.d32 = dwc_read_reg32(&_hc_regs->hctsiz); + hctsiz_data_t hctsiz; + hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n", - __func__, (_hc->ep_is_in ? "IN" : "OUT"), _hc->hc_num); - DWC_DEBUGPL(DBG_HCDV, " hc->xfer_len %d\n", _hc->xfer_len); + __func__, (hc->ep_is_in ? "IN" : "OUT"), hc->hc_num); + DWC_DEBUGPL(DBG_HCDV, " hc->xfer_len %d\n", hc->xfer_len); DWC_DEBUGPL(DBG_HCDV, " hctsiz.xfersize %d\n", hctsiz.b.xfersize); DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n", - _urb->transfer_buffer_length); - DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n", _urb->actual_length); + urb->transfer_buffer_length); + DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n", urb->actual_length); DWC_DEBUGPL(DBG_HCDV, " short_read %d, xfer_done %d\n", short_read, xfer_done); @@ -571,13 +593,13 @@ * control transfers. */ -static void save_data_toggle(dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - dwc_otg_qtd_t *_qtd) +static void save_data_toggle(dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + dwc_otg_qtd_t *qtd) { hctsiz_data_t hctsiz; - hctsiz.d32 = dwc_read_reg32(&_hc_regs->hctsiz); - - if (_hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) { - dwc_otg_qh_t *qh = _hc->qh; + hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); + + if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) { + dwc_otg_qh_t *qh = hc->qh; if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) { qh->data_toggle = DWC_OTG_HC_PID_DATA0; @@ -587,7 +609,7 @@ } else { if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) { - _qtd->data_toggle = DWC_OTG_HC_PID_DATA0; + qtd->data_toggle = DWC_OTG_HC_PID_DATA0; } else { - _qtd->data_toggle = DWC_OTG_HC_PID_DATA1; + qtd->data_toggle = DWC_OTG_HC_PID_DATA1; } } @@ -601,6 +623,6 @@ * schedule if no more QTDs are linked to the QH. */ -static void deactivate_qh(dwc_otg_hcd_t *_hcd, - dwc_otg_qh_t *_qh, +static void deactivate_qh(dwc_otg_hcd_t *hcd, + dwc_otg_qh_t *qh, int free_qtd) { @@ -608,25 +630,23 @@ dwc_otg_qtd_t *qtd; - DWC_DEBUGPL(DBG_HCDV, " %s(%p,%p,%d)\n", __func__, _hcd, _qh, free_qtd); - - qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); + DWC_DEBUGPL(DBG_HCDV, " %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd); + + qtd = list_entry(qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); if (qtd->complete_split) { continue_split = 1; - } - else if ((qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID) || - (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END)) - { + } else if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID || + qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END) { continue_split = 1; } if (free_qtd) { - dwc_otg_hcd_qtd_remove_and_free(qtd); + dwc_otg_hcd_qtd_remove_and_free(hcd, qtd); continue_split = 0; } - _qh->channel = NULL; - _qh->qtd_in_process = NULL; - dwc_otg_hcd_qh_deactivate(_hcd, _qh, continue_split); + qh->channel = NULL; + qh->qtd_in_process = NULL; + dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split); } @@ -641,25 +661,35 @@ */ static dwc_otg_halt_status_e -update_isoc_urb_state(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - dwc_otg_qtd_t *_qtd, - dwc_otg_halt_status_e _halt_status) -{ - struct urb *urb = _qtd->urb; - dwc_otg_halt_status_e ret_val = _halt_status; +update_isoc_urb_state(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + dwc_otg_qtd_t *qtd, + dwc_otg_halt_status_e halt_status) +{ + struct urb *urb = qtd->urb; + dwc_otg_halt_status_e ret_val = halt_status; struct usb_iso_packet_descriptor *frame_desc; - frame_desc = &urb->iso_frame_desc[_qtd->isoc_frame_index]; - switch (_halt_status) { + frame_desc = &urb->iso_frame_desc[qtd->isoc_frame_index]; + switch (halt_status) { case DWC_OTG_HC_XFER_COMPLETE: frame_desc->status = 0; frame_desc->actual_length = - get_actual_xfer_length(_hc, _hc_regs, _qtd, - _halt_status, NULL); + get_actual_xfer_length(hc, hc_regs, qtd, + halt_status, NULL); + + /* non DWORD-aligned buffer case handling. */ + if (frame_desc->actual_length && ((uint32_t)hc->xfer_buff & 0x3) && + hc->qh->dw_align_buf && hc->ep_is_in) { + memcpy(urb->transfer_buffer + frame_desc->offset + qtd->isoc_split_offset, + hc->qh->dw_align_buf, frame_desc->actual_length); + + } + break; case DWC_OTG_HC_XFER_FRAME_OVERRUN: + printk("DWC_OTG_HC_XFER_FRAME_OVERRUN: %d\n", halt_status); urb->error_count++; - if (_hc->ep_is_in) { + if (hc->ep_is_in) { frame_desc->status = -ENOSR; } else { @@ -669,4 +699,5 @@ break; case DWC_OTG_HC_XFER_BABBLE_ERR: + printk("DWC_OTG_HC_XFER_BABBLE_ERR: %d\n", halt_status); urb->error_count++; frame_desc->status = -EOVERFLOW; @@ -674,22 +705,33 @@ break; case DWC_OTG_HC_XFER_XACT_ERR: + printk("DWC_OTG_HC_XFER_XACT_ERR: %d\n", halt_status); urb->error_count++; frame_desc->status = -EPROTO; frame_desc->actual_length = - get_actual_xfer_length(_hc, _hc_regs, _qtd, - _halt_status, NULL); + get_actual_xfer_length(hc, hc_regs, qtd, + halt_status, NULL); + + /* non DWORD-aligned buffer case handling. */ + if (frame_desc->actual_length && ((uint32_t)hc->xfer_buff & 0x3) && + hc->qh->dw_align_buf && hc->ep_is_in) { + memcpy(urb->transfer_buffer + frame_desc->offset + qtd->isoc_split_offset, + hc->qh->dw_align_buf, frame_desc->actual_length); + + } + break; default: + DWC_ERROR("%s: Unhandled _halt_status (%d)\n", __func__, - _halt_status); + halt_status); BUG(); break; } - if (++_qtd->isoc_frame_index == urb->number_of_packets) { + if (++qtd->isoc_frame_index == urb->number_of_packets) { /* - * urb->status is not used for isoc transfers. + * urb->status is not used for isoc transfers. * The individual frame_desc statuses are used instead. */ - dwc_otg_hcd_complete_urb(_hcd, urb, 0); + dwc_otg_hcd_complete_urb(hcd, urb, 0); ret_val = DWC_OTG_HC_XFER_URB_COMPLETE; } else { @@ -704,15 +746,15 @@ * queue more transactions since at least one host channel is available. * - * @param _hcd The HCD state structure. - * @param _hc The host channel to release. - * @param _qtd The QTD associated with the host channel. This QTD may be freed + * @param hcd The HCD state structure. + * @param hc The host channel to release. + * @param qtd The QTD associated with the host channel. This QTD may be freed * if the transfer is complete or an error has occurred. - * @param _halt_status Reason the channel is being released. This status + * @param halt_status Reason the channel is being released. This status * determines the actions taken by this function. */ -static void release_channel(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - dwc_otg_qtd_t *_qtd, - dwc_otg_halt_status_e _halt_status) +static void release_channel(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + dwc_otg_qtd_t *qtd, + dwc_otg_halt_status_e halt_status) { dwc_otg_transaction_type_e tr_type; @@ -720,7 +762,7 @@ DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d\n", - __func__, _hc->hc_num, _halt_status); - - switch (_halt_status) { + __func__, hc->hc_num, halt_status); + + switch (halt_status) { case DWC_OTG_HC_XFER_URB_COMPLETE: free_qtd = 1; @@ -732,9 +774,9 @@ break; case DWC_OTG_HC_XFER_XACT_ERR: - if (_qtd->error_count >= 3) { + if (qtd->error_count >= 3) { DWC_DEBUGPL(DBG_HCDV, " Complete URB with transaction error\n"); free_qtd = 1; - _qtd->urb->status = -EPROTO; - dwc_otg_hcd_complete_urb(_hcd, _qtd->urb, -EPROTO); + qtd->urb->status = -EPROTO; + dwc_otg_hcd_complete_urb(hcd, qtd->urb, -EPROTO); } else { free_qtd = 0; @@ -749,5 +791,5 @@ goto cleanup; case DWC_OTG_HC_XFER_NO_HALT_STATUS: - DWC_ERROR("%s: No halt_status, channel %d\n", __func__, _hc->hc_num); + DWC_ERROR("%s: No halt_status, channel %d\n", __func__, hc->hc_num); free_qtd = 0; break; @@ -757,6 +799,5 @@ } - - deactivate_qh(_hcd, _hc->qh, free_qtd); + deactivate_qh(hcd, hc->qh, free_qtd); cleanup: @@ -766,11 +807,11 @@ * there's no need to clear the Channel Halted interrupt separately. */ - dwc_otg_hc_cleanup(_hcd->core_if, _hc); - list_add_tail(&_hc->hc_list_entry, &_hcd->free_hc_list); - - switch (_hc->ep_type) { + dwc_otg_hc_cleanup(hcd->core_if, hc); + list_add_tail(&hc->hc_list_entry, &hcd->free_hc_list); + + switch (hc->ep_type) { case DWC_OTG_EP_TYPE_CONTROL: case DWC_OTG_EP_TYPE_BULK: - _hcd->non_periodic_channels--; + hcd->non_periodic_channels--; break; @@ -785,7 +826,7 @@ /* Try to queue more transfers now that there's a free channel. */ - tr_type = dwc_otg_hcd_select_transactions(_hcd); + tr_type = dwc_otg_hcd_select_transactions(hcd); if (tr_type != DWC_OTG_TRANSACTION_NONE) { - dwc_otg_hcd_queue_transactions(_hcd, tr_type); + dwc_otg_hcd_queue_transactions(hcd, tr_type); } } @@ -801,24 +842,24 @@ * DMA mode. */ -static void halt_channel(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - dwc_otg_qtd_t *_qtd, - dwc_otg_halt_status_e _halt_status) -{ - if (_hcd->core_if->dma_enable) { - release_channel(_hcd, _hc, _qtd, _halt_status); +static void halt_channel(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + dwc_otg_qtd_t *qtd, + dwc_otg_halt_status_e halt_status) +{ + if (hcd->core_if->dma_enable) { + release_channel(hcd, hc, qtd, halt_status); return; } /* Slave mode processing... */ - dwc_otg_hc_halt(_hcd->core_if, _hc, _halt_status); - - if (_hc->halt_on_queue) { + dwc_otg_hc_halt(hcd->core_if, hc, halt_status); + + if (hc->halt_on_queue) { gintmsk_data_t gintmsk = {.d32 = 0}; dwc_otg_core_global_regs_t *global_regs; - global_regs = _hcd->core_if->core_global_regs; - - if (_hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || - _hc->ep_type == DWC_OTG_EP_TYPE_BULK) { + global_regs = hcd->core_if->core_global_regs; + + if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || + hc->ep_type == DWC_OTG_EP_TYPE_BULK) { /* * Make sure the Non-periodic Tx FIFO empty interrupt @@ -835,6 +876,6 @@ * processed. */ - list_move(&_hc->qh->qh_list_entry, - &_hcd->periodic_sched_assigned); + list_move(&hc->qh->qh_list_entry, + &hcd->periodic_sched_assigned); /* @@ -854,15 +895,15 @@ * specific handling is finished to release the host channel. */ -static void complete_non_periodic_xfer(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - dwc_otg_qtd_t *_qtd, - dwc_otg_halt_status_e _halt_status) +static void complete_non_periodic_xfer(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + dwc_otg_qtd_t *qtd, + dwc_otg_halt_status_e halt_status) { hcint_data_t hcint; - _qtd->error_count = 0; - - hcint.d32 = dwc_read_reg32(&_hc_regs->hcint); + qtd->error_count = 0; + + hcint.d32 = dwc_read_reg32(&hc_regs->hcint); if (hcint.b.nyet) { /* @@ -871,6 +912,6 @@ * beginning of the next transfer. */ - _hc->qh->ping_state = 1; - clear_hc_int(_hc_regs,nyet); + hc->qh->ping_state = 1; + clear_hc_int(hc_regs, nyet); } @@ -885,5 +926,5 @@ * Tx FIFO Empty interrupt if necessary. */ - if (_hc->ep_is_in) { + if (hc->ep_is_in) { /* * IN transfers in Slave mode require an explicit disable to @@ -891,5 +932,5 @@ * the channel.) */ - halt_channel(_hcd, _hc, _qtd, _halt_status); + halt_channel(hcd, hc, qtd, halt_status); } else { /* @@ -897,5 +938,5 @@ * transfers in Slave mode. */ - release_channel(_hcd, _hc, _qtd, _halt_status); + release_channel(hcd, hc, qtd, halt_status); } } @@ -906,20 +947,20 @@ * handling is finished to release the host channel. */ -static void complete_periodic_xfer(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - dwc_otg_qtd_t *_qtd, - dwc_otg_halt_status_e _halt_status) +static void complete_periodic_xfer(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + dwc_otg_qtd_t *qtd, + dwc_otg_halt_status_e halt_status) { hctsiz_data_t hctsiz; - _qtd->error_count = 0; - - hctsiz.d32 = dwc_read_reg32(&_hc_regs->hctsiz); - if (!_hc->ep_is_in || hctsiz.b.pktcnt == 0) { + qtd->error_count = 0; + + hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); + if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) { /* Core halts channel in these cases. */ - release_channel(_hcd, _hc, _qtd, _halt_status); + release_channel(hcd, hc, qtd, halt_status); } else { /* Flush any outstanding requests from the Tx queue. */ - halt_channel(_hcd, _hc, _qtd, _halt_status); + halt_channel(hcd, hc, qtd, halt_status); } } @@ -929,22 +970,22 @@ * called in either DMA mode or Slave mode. */ -static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - dwc_otg_qtd_t *_qtd) -{ - int urb_xfer_done; - dwc_otg_halt_status_e halt_status = DWC_OTG_HC_XFER_COMPLETE; - struct urb *urb = _qtd->urb; - int pipe_type = usb_pipetype(urb->pipe); +static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + dwc_otg_qtd_t *qtd) +{ + int urb_xfer_done; + dwc_otg_halt_status_e halt_status = DWC_OTG_HC_XFER_COMPLETE; + struct urb *urb = qtd->urb; + int pipe_type = usb_pipetype(urb->pipe); DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " - "Transfer Complete--\n", _hc->hc_num); - - /* + "Transfer Complete--\n", hc->hc_num); + + /* * Handle xfer complete on CSPLIT. */ - if (_hc->qh->do_split) { - _qtd->complete_split = 0; + if (hc->qh->do_split) { + qtd->complete_split = 0; } @@ -952,10 +993,10 @@ switch (pipe_type) { case PIPE_CONTROL: - switch (_qtd->control_phase) { + switch (qtd->control_phase) { case DWC_OTG_CONTROL_SETUP: if (urb->transfer_buffer_length > 0) { - _qtd->control_phase = DWC_OTG_CONTROL_DATA; + qtd->control_phase = DWC_OTG_CONTROL_DATA; } else { - _qtd->control_phase = DWC_OTG_CONTROL_STATUS; + qtd->control_phase = DWC_OTG_CONTROL_STATUS; } DWC_DEBUGPL(DBG_HCDV, " Control setup transaction done\n"); @@ -963,10 +1004,10 @@ break; case DWC_OTG_CONTROL_DATA: { - urb_xfer_done = update_urb_state_xfer_comp(_hc, _hc_regs, urb, _qtd); + urb_xfer_done = update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); if (urb_xfer_done) { - _qtd->control_phase = DWC_OTG_CONTROL_STATUS; + qtd->control_phase = DWC_OTG_CONTROL_STATUS; DWC_DEBUGPL(DBG_HCDV, " Control data transfer done\n"); } else { - save_data_toggle(_hc, _hc_regs, _qtd); + save_data_toggle(hc, hc_regs, qtd); } halt_status = DWC_OTG_HC_XFER_COMPLETE; @@ -978,27 +1019,27 @@ urb->status = 0; } - dwc_otg_hcd_complete_urb(_hcd, urb, urb->status); + dwc_otg_hcd_complete_urb(hcd, urb, urb->status); halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; break; } - complete_non_periodic_xfer(_hcd, _hc, _hc_regs, _qtd, halt_status); + complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); break; case PIPE_BULK: DWC_DEBUGPL(DBG_HCDV, " Bulk transfer complete\n"); - urb_xfer_done = update_urb_state_xfer_comp(_hc, _hc_regs, urb, _qtd); + urb_xfer_done = update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); if (urb_xfer_done) { - dwc_otg_hcd_complete_urb(_hcd, urb, urb->status); + dwc_otg_hcd_complete_urb(hcd, urb, urb->status); halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; } else { halt_status = DWC_OTG_HC_XFER_COMPLETE; } - - save_data_toggle(_hc, _hc_regs, _qtd); - complete_non_periodic_xfer(_hcd, _hc, _hc_regs, _qtd, halt_status); + + save_data_toggle(hc, hc_regs, qtd); + complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); break; case PIPE_INTERRUPT: DWC_DEBUGPL(DBG_HCDV, " Interrupt transfer complete\n"); - update_urb_state_xfer_comp(_hc, _hc_regs, urb, _qtd); + update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); /* @@ -1006,21 +1047,20 @@ * interrupt. */ - dwc_otg_hcd_complete_urb(_hcd, urb, urb->status); - save_data_toggle(_hc, _hc_regs, _qtd); - complete_periodic_xfer(_hcd, _hc, _hc_regs, _qtd, + dwc_otg_hcd_complete_urb(hcd, urb, urb->status); + save_data_toggle(hc, hc_regs, qtd); + complete_periodic_xfer(hcd, hc, hc_regs, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); break; case PIPE_ISOCHRONOUS: DWC_DEBUGPL(DBG_HCDV, " Isochronous transfer complete\n"); - if (_qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) - { - halt_status = update_isoc_urb_state(_hcd, _hc, _hc_regs, _qtd, + if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) { + halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd, DWC_OTG_HC_XFER_COMPLETE); } - complete_periodic_xfer(_hcd, _hc, _hc_regs, _qtd, halt_status); - break; - } - - disable_hc_int(_hc_regs,xfercompl); + complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); + break; + } + + disable_hc_int(hc_regs, xfercompl); return 1; @@ -1031,21 +1071,21 @@ * either DMA mode or Slave mode. */ -static int32_t handle_hc_stall_intr(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - dwc_otg_qtd_t *_qtd) -{ - struct urb *urb = _qtd->urb; +static int32_t handle_hc_stall_intr(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + dwc_otg_qtd_t *qtd) +{ + struct urb *urb = qtd->urb; int pipe_type = usb_pipetype(urb->pipe); DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " - "STALL Received--\n", _hc->hc_num); + "STALL Received--\n", hc->hc_num); if (pipe_type == PIPE_CONTROL) { - dwc_otg_hcd_complete_urb(_hcd, _qtd->urb, -EPIPE); + dwc_otg_hcd_complete_urb(hcd, urb, -EPIPE); } if (pipe_type == PIPE_BULK || pipe_type == PIPE_INTERRUPT) { - dwc_otg_hcd_complete_urb(_hcd, _qtd->urb, -EPIPE); + dwc_otg_hcd_complete_urb(hcd, urb, -EPIPE); /* * USB protocol requires resetting the data toggle for bulk @@ -1055,10 +1095,10 @@ * the data toggle now. */ - _hc->qh->data_toggle = 0; - } - - halt_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_STALL); - - disable_hc_int(_hc_regs,stall); + hc->qh->data_toggle = 0; + } + + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL); + + disable_hc_int(hc_regs, stall); return 1; @@ -1071,29 +1111,29 @@ * actually been transferred via the host channel. */ -static void update_urb_state_xfer_intr(dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - struct urb *_urb, - dwc_otg_qtd_t *_qtd, - dwc_otg_halt_status_e _halt_status) -{ - uint32_t bytes_transferred = get_actual_xfer_length(_hc, _hc_regs, _qtd, - _halt_status, NULL); - _urb->actual_length += bytes_transferred; +static void update_urb_state_xfer_intr(dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + struct urb *urb, + dwc_otg_qtd_t *qtd, + dwc_otg_halt_status_e halt_status) +{ + uint32_t bytes_transferred = get_actual_xfer_length(hc, hc_regs, qtd, + halt_status, NULL); + urb->actual_length += bytes_transferred; #ifdef DEBUG { - hctsiz_data_t hctsiz; - hctsiz.d32 = dwc_read_reg32(&_hc_regs->hctsiz); + hctsiz_data_t hctsiz; + hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n", - __func__, (_hc->ep_is_in ? "IN" : "OUT"), _hc->hc_num); - DWC_DEBUGPL(DBG_HCDV, " _hc->start_pkt_count %d\n", _hc->start_pkt_count); + __func__, (hc->ep_is_in ? "IN" : "OUT"), hc->hc_num); + DWC_DEBUGPL(DBG_HCDV, " hc->start_pkt_count %d\n", hc->start_pkt_count); DWC_DEBUGPL(DBG_HCDV, " hctsiz.pktcnt %d\n", hctsiz.b.pktcnt); - DWC_DEBUGPL(DBG_HCDV, " _hc->max_packet %d\n", _hc->max_packet); + DWC_DEBUGPL(DBG_HCDV, " hc->max_packet %d\n", hc->max_packet); DWC_DEBUGPL(DBG_HCDV, " bytes_transferred %d\n", bytes_transferred); - DWC_DEBUGPL(DBG_HCDV, " _urb->actual_length %d\n", _urb->actual_length); - DWC_DEBUGPL(DBG_HCDV, " _urb->transfer_buffer_length %d\n", - _urb->transfer_buffer_length); - } -#endif + DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n", urb->actual_length); + DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n", + urb->transfer_buffer_length); + } +#endif } @@ -1102,11 +1142,11 @@ * DMA mode or Slave mode. */ -static int32_t handle_hc_nak_intr(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - dwc_otg_qtd_t *_qtd) +static int32_t handle_hc_nak_intr(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + dwc_otg_qtd_t *qtd) { DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " - "NAK Received--\n", _hc->hc_num); + "NAK Received--\n", hc->hc_num); /* @@ -1114,17 +1154,17 @@ * interrupt. Re-start the SSPLIT transfer. */ - if (_hc->do_split) { - if (_hc->complete_split) { - _qtd->error_count = 0; - } - _qtd->complete_split = 0; - halt_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_NAK); + if (hc->do_split) { + if (hc->complete_split) { + qtd->error_count = 0; + } + qtd->complete_split = 0; + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); goto handle_nak_done; } - switch (usb_pipetype(_qtd->urb->pipe)) { + switch (usb_pipetype(qtd->urb->pipe)) { case PIPE_CONTROL: case PIPE_BULK: - if (_hcd->core_if->dma_enable && _hc->ep_is_in) { + if (hcd->core_if->dma_enable && hc->ep_is_in) { /* * NAK interrupts are enabled on bulk/control IN @@ -1133,5 +1173,5 @@ * occurs. The core will continue transferring data. */ - _qtd->error_count = 0; + qtd->error_count = 0; goto handle_nak_done; } @@ -1142,12 +1182,12 @@ * queued as request queue space is available. */ - _qtd->error_count = 0; - - if (!_hc->qh->ping_state) { - update_urb_state_xfer_intr(_hc, _hc_regs, _qtd->urb, - _qtd, DWC_OTG_HC_XFER_NAK); - save_data_toggle(_hc, _hc_regs, _qtd); - if (_qtd->urb->dev->speed == USB_SPEED_HIGH) { - _hc->qh->ping_state = 1; + qtd->error_count = 0; + + if (!hc->qh->ping_state) { + update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, + qtd, DWC_OTG_HC_XFER_NAK); + save_data_toggle(hc, hc_regs, qtd); + if (qtd->urb->dev->speed == USB_SPEED_HIGH) { + hc->qh->ping_state = 1; } } @@ -1156,11 +1196,11 @@ * Halt the channel so the transfer can be re-started from * the appropriate point or the PING protocol will - * start/continue. + * start/continue. */ - halt_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_NAK); + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); break; case PIPE_INTERRUPT: - _qtd->error_count = 0; - halt_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_NAK); + qtd->error_count = 0; + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); break; case PIPE_ISOCHRONOUS: @@ -1171,5 +1211,5 @@ handle_nak_done: - disable_hc_int(_hc_regs,nak); + disable_hc_int(hc_regs, nak); return 1; @@ -1181,36 +1221,36 @@ * either Slave mode or DMA mode, and during Start Split transactions. */ -static int32_t handle_hc_ack_intr(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - dwc_otg_qtd_t *_qtd) +static int32_t handle_hc_ack_intr(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + dwc_otg_qtd_t *qtd) { DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " - "ACK Received--\n", _hc->hc_num); - - if (_hc->do_split) { + "ACK Received--\n", hc->hc_num); + + if (hc->do_split) { /* * Handle ACK on SSPLIT. * ACK should not occur in CSPLIT. */ - if ((!_hc->ep_is_in) && (_hc->data_pid_start != DWC_OTG_HC_PID_SETUP)) { - _qtd->ssplit_out_xfer_count = _hc->xfer_len; - } - if (!(_hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !_hc->ep_is_in)) { + if (!hc->ep_is_in && hc->data_pid_start != DWC_OTG_HC_PID_SETUP) { + qtd->ssplit_out_xfer_count = hc->xfer_len; + } + if (!(hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)) { /* Don't need complete for isochronous out transfers. */ - _qtd->complete_split = 1; + qtd->complete_split = 1; } /* ISOC OUT */ - if ((_hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && !_hc->ep_is_in) { - switch (_hc->xact_pos) { + if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) { + switch (hc->xact_pos) { case DWC_HCSPLIT_XACTPOS_ALL: break; case DWC_HCSPLIT_XACTPOS_END: - _qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL; - _qtd->isoc_split_offset = 0; + qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL; + qtd->isoc_split_offset = 0; break; case DWC_HCSPLIT_XACTPOS_BEGIN: - case DWC_HCSPLIT_XACTPOS_MID: + case DWC_HCSPLIT_XACTPOS_MID: /* * For BEGIN or MID, calculate the length for @@ -1218,29 +1258,27 @@ * SSPLIT token, either MID or END. */ - do { + { struct usb_iso_packet_descriptor *frame_desc; - frame_desc = &_qtd->urb->iso_frame_desc[_qtd->isoc_frame_index]; - _qtd->isoc_split_offset += 188; - - if ((frame_desc->length - _qtd->isoc_split_offset) <= 188) { - _qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_END; + frame_desc = &qtd->urb->iso_frame_desc[qtd->isoc_frame_index]; + qtd->isoc_split_offset += 188; + + if ((frame_desc->length - qtd->isoc_split_offset) <= 188) { + qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_END; + } else { + qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_MID; } - else { - _qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_MID; - } - - } while(0); + + } break; } - } - else { - halt_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_ACK); + } else { + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK); } } else { - _qtd->error_count = 0; - - if (_hc->qh->ping_state) { - _hc->qh->ping_state = 0; + qtd->error_count = 0; + + if (hc->qh->ping_state) { + hc->qh->ping_state = 0; /* * Halt the channel so the transfer can be re-started @@ -1250,5 +1288,5 @@ * automatically executes the PING, then the transfer. */ - halt_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_ACK); + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK); } } @@ -1259,5 +1297,5 @@ */ - disable_hc_int(_hc_regs,ack); + disable_hc_int(hc_regs, ack); return 1; @@ -1271,11 +1309,11 @@ * called in either DMA mode or Slave mode. */ -static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - dwc_otg_qtd_t *_qtd) +static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + dwc_otg_qtd_t *qtd) { DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " - "NYET Received--\n", _hc->hc_num); + "NYET Received--\n", hc->hc_num); /* @@ -1283,11 +1321,11 @@ * re-do the CSPLIT immediately on non-periodic */ - if ((_hc->do_split) && (_hc->complete_split)) { - if ((_hc->ep_type == DWC_OTG_EP_TYPE_INTR) || - (_hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) { - int frnum = dwc_otg_hcd_get_frame_number(dwc_otg_hcd_to_hcd(_hcd)); + if (hc->do_split && hc->complete_split) { + if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { + int frnum = dwc_otg_hcd_get_frame_number(dwc_otg_hcd_to_hcd(hcd)); if (dwc_full_frame_num(frnum) != - dwc_full_frame_num(_hc->qh->sched_frame)) { + dwc_full_frame_num(hc->qh->sched_frame)) { /* * No longer in the same full speed frame. @@ -1301,8 +1339,8 @@ * occurs regularly in Slave mode. */ - _qtd->error_count++; -#endif - _qtd->complete_split = 0; - halt_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_XACT_ERR); + qtd->error_count++; +#endif + qtd->complete_split = 0; + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR); /** @todo add support for isoc release */ goto handle_nyet_done; @@ -1310,14 +1348,14 @@ } - halt_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_NYET); + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET); goto handle_nyet_done; } - _hc->qh->ping_state = 1; - _qtd->error_count = 0; - - update_urb_state_xfer_intr(_hc, _hc_regs, _qtd->urb, _qtd, + hc->qh->ping_state = 1; + qtd->error_count = 0; + + update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd, DWC_OTG_HC_XFER_NYET); - save_data_toggle(_hc, _hc_regs, _qtd); + save_data_toggle(hc, hc_regs, qtd); /* @@ -1325,8 +1363,8 @@ * protocol will start. */ - halt_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_NYET); + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET); handle_nyet_done: - disable_hc_int(_hc_regs,nyet); + disable_hc_int(hc_regs, nyet); return 1; } @@ -1336,21 +1374,21 @@ * either DMA mode or Slave mode. */ -static int32_t handle_hc_babble_intr(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - dwc_otg_qtd_t *_qtd) +static int32_t handle_hc_babble_intr(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + dwc_otg_qtd_t *qtd) { DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " - "Babble Error--\n", _hc->hc_num); - if (_hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { - dwc_otg_hcd_complete_urb(_hcd, _qtd->urb, -EOVERFLOW); - halt_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_BABBLE_ERR); + "Babble Error--\n", hc->hc_num); + if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { + dwc_otg_hcd_complete_urb(hcd, qtd->urb, -EOVERFLOW); + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_BABBLE_ERR); } else { dwc_otg_halt_status_e halt_status; - halt_status = update_isoc_urb_state(_hcd, _hc, _hc_regs, _qtd, + halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd, DWC_OTG_HC_XFER_BABBLE_ERR); - halt_channel(_hcd, _hc, _qtd, halt_status); - } - disable_hc_int(_hc_regs,bblerr); + halt_channel(hcd, hc, qtd, halt_status); + } + disable_hc_int(hc_regs, bblerr); return 1; } @@ -1360,32 +1398,32 @@ * DMA mode. */ -static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - dwc_otg_qtd_t *_qtd) -{ - hcchar_data_t hcchar; +static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + dwc_otg_qtd_t *qtd) +{ + hcchar_data_t hcchar; hcsplt_data_t hcsplt; - hctsiz_data_t hctsiz; + hctsiz_data_t hctsiz; uint32_t hcdma; - struct urb *urb = _qtd->urb; + struct urb *urb = qtd->urb; DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " - "AHB Error--\n", _hc->hc_num); - - hcchar.d32 = dwc_read_reg32(&_hc_regs->hcchar); - hcsplt.d32 = dwc_read_reg32(&_hc_regs->hcsplt); - hctsiz.d32 = dwc_read_reg32(&_hc_regs->hctsiz); - hcdma = dwc_read_reg32(&_hc_regs->hcdma); - - DWC_ERROR("AHB ERROR, Channel %d\n", _hc->hc_num); + "AHB Error--\n", hc->hc_num); + + hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); + hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); + hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); + hcdma = dwc_read_reg32(&hc_regs->hcdma); + + DWC_ERROR("AHB ERROR, Channel %d\n", hc->hc_num); DWC_ERROR(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32); DWC_ERROR(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma); - DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Enqueue\n"); + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Enqueue\n"); DWC_ERROR(" Device address: %d\n", usb_pipedevice(urb->pipe)); DWC_ERROR(" Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe), - (usb_pipein(urb->pipe) ? "IN" : "OUT")); + (usb_pipein(urb->pipe) ? "IN" : "OUT")); DWC_ERROR(" Endpoint type: %s\n", - ({char *pipetype; + ({char *pipetype; switch (usb_pipetype(urb->pipe)) { case PIPE_CONTROL: pipetype = "CONTROL"; break; @@ -1394,7 +1432,7 @@ case PIPE_ISOCHRONOUS: pipetype = "ISOCHRONOUS"; break; default: pipetype = "UNKNOWN"; break; - }; pipetype;})); + }; pipetype;})); DWC_ERROR(" Speed: %s\n", - ({char *speed; + ({char *speed; switch (urb->dev->speed) { case USB_SPEED_HIGH: speed = "HIGH"; break; @@ -1402,15 +1440,15 @@ case USB_SPEED_LOW: speed = "LOW"; break; default: speed = "UNKNOWN"; break; - }; speed;})); + }; speed;})); DWC_ERROR(" Max packet size: %d\n", - usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))); + usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))); DWC_ERROR(" Data buffer length: %d\n", urb->transfer_buffer_length); DWC_ERROR(" Transfer buffer: %p, Transfer DMA: %p\n", - urb->transfer_buffer, (void *)urb->transfer_dma); + urb->transfer_buffer, (void *)urb->transfer_dma); DWC_ERROR(" Setup buffer: %p, Setup DMA: %p\n", - urb->setup_packet, (void *)urb->setup_dma); + urb->setup_packet, (void *)urb->setup_dma); DWC_ERROR(" Interval: %d\n", urb->interval); - dwc_otg_hcd_complete_urb(_hcd, urb, -EIO); + dwc_otg_hcd_complete_urb(hcd, urb, -EIO); /* @@ -1418,7 +1456,7 @@ * write to the HCCHARn register in DMA mode to force the halt. */ - dwc_otg_hc_halt(_hcd->core_if, _hc, DWC_OTG_HC_XFER_AHB_ERR); - - disable_hc_int(_hc_regs,ahberr); + dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR); + + disable_hc_int(hc_regs, ahberr); return 1; } @@ -1428,22 +1466,22 @@ * called in either DMA mode or Slave mode. */ -static int32_t handle_hc_xacterr_intr(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - dwc_otg_qtd_t *_qtd) +static int32_t handle_hc_xacterr_intr(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + dwc_otg_qtd_t *qtd) { DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " - "Transaction Error--\n", _hc->hc_num); - - switch (usb_pipetype(_qtd->urb->pipe)) { + "Transaction Error--\n", hc->hc_num); + + switch (usb_pipetype(qtd->urb->pipe)) { case PIPE_CONTROL: case PIPE_BULK: - _qtd->error_count++; - if (!_hc->qh->ping_state) { - update_urb_state_xfer_intr(_hc, _hc_regs, _qtd->urb, - _qtd, DWC_OTG_HC_XFER_XACT_ERR); - save_data_toggle(_hc, _hc_regs, _qtd); - if (!_hc->ep_is_in && _qtd->urb->dev->speed == USB_SPEED_HIGH) { - _hc->qh->ping_state = 1; + qtd->error_count++; + if (!hc->qh->ping_state) { + update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, + qtd, DWC_OTG_HC_XFER_XACT_ERR); + save_data_toggle(hc, hc_regs, qtd); + if (!hc->ep_is_in && qtd->urb->dev->speed == USB_SPEED_HIGH) { + hc->qh->ping_state = 1; } } @@ -1453,26 +1491,25 @@ * the appropriate point or the PING protocol will start. */ - halt_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_XACT_ERR); + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR); break; case PIPE_INTERRUPT: - _qtd->error_count++; - if ((_hc->do_split) && (_hc->complete_split)) { - _qtd->complete_split = 0; - } - halt_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_XACT_ERR); + qtd->error_count++; + if (hc->do_split && hc->complete_split) { + qtd->complete_split = 0; + } + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR); break; case PIPE_ISOCHRONOUS: { dwc_otg_halt_status_e halt_status; - halt_status = update_isoc_urb_state(_hcd, _hc, _hc_regs, _qtd, + halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd, DWC_OTG_HC_XFER_XACT_ERR); - - halt_channel(_hcd, _hc, _qtd, halt_status); - } - break; - } - - - disable_hc_int(_hc_regs,xacterr); + + halt_channel(hcd, hc, qtd, halt_status); + } + break; + } + + disable_hc_int(hc_regs, xacterr); return 1; @@ -1483,31 +1520,31 @@ * in either DMA mode or Slave mode. */ -static int32_t handle_hc_frmovrun_intr(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - dwc_otg_qtd_t *_qtd) +static int32_t handle_hc_frmovrun_intr(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + dwc_otg_qtd_t *qtd) { DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " - "Frame Overrun--\n", _hc->hc_num); - - switch (usb_pipetype(_qtd->urb->pipe)) { + "Frame Overrun--\n", hc->hc_num); + + switch (usb_pipetype(qtd->urb->pipe)) { case PIPE_CONTROL: case PIPE_BULK: break; case PIPE_INTERRUPT: - halt_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN); + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN); break; case PIPE_ISOCHRONOUS: { dwc_otg_halt_status_e halt_status; - halt_status = update_isoc_urb_state(_hcd, _hc, _hc_regs, _qtd, + halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN); - - halt_channel(_hcd, _hc, _qtd, halt_status); - } - break; - } - - disable_hc_int(_hc_regs,frmovrun); + + halt_channel(hcd, hc, qtd, halt_status); + } + break; + } + + disable_hc_int(hc_regs, frmovrun); return 1; @@ -1518,20 +1555,20 @@ * called in either DMA mode or Slave mode. */ -static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - dwc_otg_qtd_t *_qtd) +static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + dwc_otg_qtd_t *qtd) { DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " - "Data Toggle Error--\n", _hc->hc_num); - - if (_hc->ep_is_in) { - _qtd->error_count = 0; + "Data Toggle Error--\n", hc->hc_num); + + if (hc->ep_is_in) { + qtd->error_count = 0; } else { DWC_ERROR("Data Toggle Error on OUT transfer," - "channel %d\n", _hc->hc_num); - } - - disable_hc_int(_hc_regs,datatglerr); + "channel %d\n", hc->hc_num); + } + + disable_hc_int(hc_regs, datatglerr); return 1; @@ -1545,8 +1582,8 @@ * @return 1 if halt status is ok, 0 otherwise. */ -static inline int halt_status_ok(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - dwc_otg_qtd_t *_qtd) +static inline int halt_status_ok(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + dwc_otg_qtd_t *qtd) { hcchar_data_t hcchar; @@ -1556,26 +1593,26 @@ hcsplt_data_t hcsplt; - if (_hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS) { + if (hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS) { /* * This code is here only as a check. This condition should * never happen. Ignore the halt if it does occur. */ - hcchar.d32 = dwc_read_reg32(&_hc_regs->hcchar); - hctsiz.d32 = dwc_read_reg32(&_hc_regs->hctsiz); - hcint.d32 = dwc_read_reg32(&_hc_regs->hcint); - hcintmsk.d32 = dwc_read_reg32(&_hc_regs->hcintmsk); - hcsplt.d32 = dwc_read_reg32(&_hc_regs->hcsplt); - DWC_WARN("%s: _hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS, " + hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); + hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); + hcint.d32 = dwc_read_reg32(&hc_regs->hcint); + hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk); + hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); + DWC_WARN("%s: hc->halt_status == DWC_OTG" "channel %d, hcchar 0x%08x, hctsiz 0x%08x, " "hcint 0x%08x, hcintmsk 0x%08x, " "hcsplt 0x%08x, qtd->complete_split %d\n", - __func__, _hc->hc_num, hcchar.d32, hctsiz.d32, + __func__, hc->hc_num, hcchar.d32, hctsiz.d32, hcint.d32, hcintmsk.d32, - hcsplt.d32, _qtd->complete_split); + hcsplt.d32, qtd->complete_split); DWC_WARN("%s: no halt status, channel %d, ignoring interrupt\n", - __func__, _hc->hc_num); + __func__, hc->hc_num); DWC_WARN("\n"); - clear_hc_int(_hc_regs,chhltd); + clear_hc_int(hc_regs, chhltd); return 0; } @@ -1586,12 +1623,12 @@ * channel again if it does occur. */ - hcchar.d32 = dwc_read_reg32(&_hc_regs->hcchar); + hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); if (hcchar.b.chdis) { DWC_WARN("%s: hcchar.chdis set unexpectedly, " "hcchar 0x%08x, trying to halt again\n", __func__, hcchar.d32); - clear_hc_int(_hc_regs,chhltd); - _hc->halt_pending = 0; - halt_channel(_hcd, _hc, _qtd, _hc->halt_status); + clear_hc_int(hc_regs, chhltd); + hc->halt_pending = 0; + halt_channel(hcd, hc, qtd, hc->halt_status); return 0; } @@ -1605,14 +1642,34 @@ * determines the reason the channel halted and proceeds accordingly. */ -static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - dwc_otg_qtd_t *_qtd) +static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + dwc_otg_qtd_t *qtd) { hcint_data_t hcint; hcintmsk_data_t hcintmsk; - - if (_hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE || - _hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR) { + int out_nak_enh = 0; + + /* For core with OUT NAK enhancement, the flow for high- + * speed CONTROL/BULK OUT is handled a little differently. + */ + if (hcd->core_if->snpsid >= 0x4F54271A) { + if (hc->speed == DWC_OTG_EP_SPEED_HIGH && !hc->ep_is_in && + (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || + hc->ep_type == DWC_OTG_EP_TYPE_BULK)) { + //20090415 NOT Show + //printk(KERN_DEBUG "OUT NAK enhancement enabled\n"); + out_nak_enh = 1; + } else { + //20090415 NOT Show + //printk(KERN_DEBUG "OUT NAK enhancement disabled, not HS Ctrl/Bulk OUT EP\n"); + } + } else { + //20090415 NOT Show + //printk(KERN_DEBUG "OUT NAK enhancement disabled, no core support\n"); + } + + if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE || + hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR) { /* * Just release the channel. A dequeue can happen on a @@ -1621,11 +1678,11 @@ * recover. */ - release_channel(_hcd, _hc, _qtd, _hc->halt_status); + release_channel(hcd, hc, qtd, hc->halt_status); return; } /* Read the HCINTn register to determine the cause for the halt. */ - hcint.d32 = dwc_read_reg32(&_hc_regs->hcint); - hcintmsk.d32 = dwc_read_reg32(&_hc_regs->hcintmsk); + hcint.d32 = dwc_read_reg32(&hc_regs->hcint); + hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk); if (hcint.b.xfercomp) { @@ -1636,11 +1693,20 @@ * for that behavior. Should fix this when hardware is fixed. */ - if ((_hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && (!_hc->ep_is_in)) { - handle_hc_ack_intr(_hcd, _hc, _hc_regs, _qtd); - } - handle_hc_xfercomp_intr(_hcd, _hc, _hc_regs, _qtd); + if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) { + handle_hc_ack_intr(hcd, hc, hc_regs, qtd); + } + handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd); } else if (hcint.b.stall) { - handle_hc_stall_intr(_hcd, _hc, _hc_regs, _qtd); + handle_hc_stall_intr(hcd, hc, hc_regs, qtd); } else if (hcint.b.xacterr) { + if (out_nak_enh) { + if (hcint.b.nyet || hcint.b.nak || hcint.b.ack) { + printk(KERN_DEBUG "XactErr with NYET/NAK/ACK\n"); + qtd->error_count = 0; + } else { + printk(KERN_DEBUG "XactErr without NYET/NAK/ACK\n"); + } + } + /* * Must handle xacterr before nak or ack. Could get a xacterr @@ -1648,53 +1714,57 @@ * that started with a PING. The xacterr takes precedence. */ - handle_hc_xacterr_intr(_hcd, _hc, _hc_regs, _qtd); - } else if (hcint.b.nyet) { - /* - * Must handle nyet before nak or ack. Could get a nyet at the - * same time as either of those on a BULK/CONTROL OUT that - * started with a PING. The nyet takes precedence. - */ - handle_hc_nyet_intr(_hcd, _hc, _hc_regs, _qtd); - } else if (hcint.b.bblerr) { - handle_hc_babble_intr(_hcd, _hc, _hc_regs, _qtd); - } else if (hcint.b.frmovrun) { - handle_hc_frmovrun_intr(_hcd, _hc, _hc_regs, _qtd); - } else if (hcint.b.nak && !hcintmsk.b.nak) { - /* - * If nak is not masked, it's because a non-split IN transfer - * is in an error state. In that case, the nak is handled by - * the nak interrupt handler, not here. Handle nak here for - * BULK/CONTROL OUT transfers, which halt on a NAK to allow - * rewinding the buffer pointer. - */ - handle_hc_nak_intr(_hcd, _hc, _hc_regs, _qtd); - } else if (hcint.b.ack && !hcintmsk.b.ack) { - /* - * If ack is not masked, it's because a non-split IN transfer - * is in an error state. In that case, the ack is handled by - * the ack interrupt handler, not here. Handle ack here for - * split transfers. Start splits halt on ACK. - */ - handle_hc_ack_intr(_hcd, _hc, _hc_regs, _qtd); + handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); + } else if (!out_nak_enh) { + if (hcint.b.nyet) { + /* + * Must handle nyet before nak or ack. Could get a nyet at the + * same time as either of those on a BULK/CONTROL OUT that + * started with a PING. The nyet takes precedence. + */ + handle_hc_nyet_intr(hcd, hc, hc_regs, qtd); + } else if (hcint.b.bblerr) { + handle_hc_babble_intr(hcd, hc, hc_regs, qtd); + } else if (hcint.b.frmovrun) { + handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd); + } else if (hcint.b.nak && !hcintmsk.b.nak) { + /* + * If nak is not masked, it's because a non-split IN transfer + * is in an error state. In that case, the nak is handled by + * the nak interrupt handler, not here. Handle nak here for + * BULK/CONTROL OUT transfers, which halt on a NAK to allow + * rewinding the buffer pointer. + */ + handle_hc_nak_intr(hcd, hc, hc_regs, qtd); + } else if (hcint.b.ack && !hcintmsk.b.ack) { + /* + * If ack is not masked, it's because a non-split IN transfer + * is in an error state. In that case, the ack is handled by + * the ack interrupt handler, not here. Handle ack here for + * split transfers. Start splits halt on ACK. + */ + handle_hc_ack_intr(hcd, hc, hc_regs, qtd); + } else { + if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { + /* + * A periodic transfer halted with no other channel + * interrupts set. Assume it was halted by the core + * because it could not be completed in its scheduled + * (micro)frame. + */ +#ifdef DEBUG + DWC_PRINT("%s: Halt channel %d (assume incomplete periodic transfer)\n", + __func__, hc->hc_num); +#endif + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE); + } else { + DWC_ERROR("%s: Channel %d, DMA Mode -- ChHltd set, but reason " + "for halting is unknown, hcint 0x%08x, intsts 0x%08x\n", + __func__, hc->hc_num, hcint.d32, + dwc_read_reg32(&hcd->core_if->core_global_regs->gintsts)); + } + } } else { - if (_hc->ep_type == DWC_OTG_EP_TYPE_INTR || - _hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { - /* - * A periodic transfer halted with no other channel - * interrupts set. Assume it was halted by the core - * because it could not be completed in its scheduled - * (micro)frame. - */ -#ifdef DEBUG - DWC_PRINT("%s: Halt channel %d (assume incomplete periodic transfer)\n", - __func__, _hc->hc_num); -#endif - halt_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE); - } else { - DWC_ERROR("%s: Channel %d, DMA Mode -- ChHltd set, but reason " - "for halting is unknown, hcint 0x%08x, intsts 0x%08x\n", - __func__, _hc->hc_num, hcint.d32, - dwc_read_reg32(&_hcd->core_if->core_global_regs->gintsts)); - } + printk(KERN_DEBUG "NYET/NAK/ACK/other in non-error case, 0x%08x\n", hcint.d32); } } @@ -1711,21 +1781,21 @@ * ahberr) are disabled in DMA mode. */ -static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - dwc_otg_hc_regs_t *_hc_regs, - dwc_otg_qtd_t *_qtd) +static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + dwc_otg_hc_regs_t *hc_regs, + dwc_otg_qtd_t *qtd) { DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " - "Channel Halted--\n", _hc->hc_num); - - if (_hcd->core_if->dma_enable) { - handle_hc_chhltd_intr_dma(_hcd, _hc, _hc_regs, _qtd); + "Channel Halted--\n", hc->hc_num); + + if (hcd->core_if->dma_enable) { + handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd); } else { #ifdef DEBUG - if (!halt_status_ok(_hcd, _hc, _hc_regs, _qtd)) { + if (!halt_status_ok(hcd, hc, hc_regs, qtd)) { return 1; } -#endif - release_channel(_hcd, _hc, _qtd, _hc->halt_status); +#endif + release_channel(hcd, hc, qtd, hc->halt_status); } @@ -1734,5 +1804,5 @@ /** Handles interrupt for a specific Host Channel */ -int32_t dwc_otg_hcd_handle_hc_n_intr (dwc_otg_hcd_t *_dwc_otg_hcd, uint32_t _num) +int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t *dwc_otg_hcd, uint32_t num) { int retval = 0; @@ -1742,9 +1812,9 @@ dwc_otg_hc_regs_t *hc_regs; dwc_otg_qtd_t *qtd; - - DWC_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", _num); - - hc = _dwc_otg_hcd->hc_ptr_array[_num]; - hc_regs = _dwc_otg_hcd->core_if->host_if->hc_regs[_num]; + + DWC_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", num); + + hc = dwc_otg_hcd->hc_ptr_array[num]; + hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num]; qtd = list_entry(hc->qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); @@ -1755,6 +1825,6 @@ hcint.d32 = hcint.d32 & hcintmsk.d32; - if (!_dwc_otg_hcd->core_if->dma_enable) { - if ((hcint.b.chhltd) && (hcint.d32 != 0x2)) { + if (!dwc_otg_hcd->core_if->dma_enable) { + if (hcint.b.chhltd && hcint.d32 != 0x2) { hcint.b.chhltd = 0; } @@ -1762,5 +1832,5 @@ if (hcint.b.xfercomp) { - retval |= handle_hc_xfercomp_intr(_dwc_otg_hcd, hc, hc_regs, qtd); + retval |= handle_hc_xfercomp_intr(dwc_otg_hcd, hc, hc_regs, qtd); /* * If NYET occurred at same time as Xfer Complete, the NYET is @@ -1771,32 +1841,32 @@ } if (hcint.b.chhltd) { - retval |= handle_hc_chhltd_intr(_dwc_otg_hcd, hc, hc_regs, qtd); + retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd); } if (hcint.b.ahberr) { - retval |= handle_hc_ahberr_intr(_dwc_otg_hcd, hc, hc_regs, qtd); + retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd); } if (hcint.b.stall) { - retval |= handle_hc_stall_intr(_dwc_otg_hcd, hc, hc_regs, qtd); + retval |= handle_hc_stall_intr(dwc_otg_hcd, hc, hc_regs, qtd); } if (hcint.b.nak) { - retval |= handle_hc_nak_intr(_dwc_otg_hcd, hc, hc_regs, qtd); + retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd); } if (hcint.b.ack) { - retval |= handle_hc_ack_intr(_dwc_otg_hcd, hc, hc_regs, qtd); + retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd); } if (hcint.b.nyet) { - retval |= handle_hc_nyet_intr(_dwc_otg_hcd, hc, hc_regs, qtd); + retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd); } if (hcint.b.xacterr) { - retval |= handle_hc_xacterr_intr(_dwc_otg_hcd, hc, hc_regs, qtd); + retval |= handle_hc_xacterr_intr(dwc_otg_hcd, hc, hc_regs, qtd); } if (hcint.b.bblerr) { - retval |= handle_hc_babble_intr(_dwc_otg_hcd, hc, hc_regs, qtd); + retval |= handle_hc_babble_intr(dwc_otg_hcd, hc, hc_regs, qtd); } if (hcint.b.frmovrun) { - retval |= handle_hc_frmovrun_intr(_dwc_otg_hcd, hc, hc_regs, qtd); + retval |= handle_hc_frmovrun_intr(dwc_otg_hcd, hc, hc_regs, qtd); } if (hcint.b.datatglerr) { - retval |= handle_hc_datatglerr_intr(_dwc_otg_hcd, hc, hc_regs, qtd); + retval |= handle_hc_datatglerr_intr(dwc_otg_hcd, hc, hc_regs, qtd); } Index: /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_driver.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_driver.c (revision 11800) +++ /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_driver.c (revision 12433) @@ -1,6 +1,6 @@ /* ========================================================================== * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_driver.c $ - * $Revision: 1.2 $ - * $Date: 2007-11-30 08:32:28 $ + * $Revision: 1.7 $ + * $Date: 2008-11-21 05:39:15 $ * $Change: 791271 $ * @@ -8,5 +8,5 @@ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless * otherwise expressly agreed to in writing between Synopsys and you. - * + * * The Software IS NOT an item of Licensed Software or Licensed Product under * any End User Software License Agreement or Agreement for Licensed Product @@ -18,5 +18,5 @@ * Synopsys. If you do not agree with this notice, including the disclaimer * below, then you are not authorized to use the Software. - * + * * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -38,5 +38,5 @@ * installed, the dwc_otg_driver_init function is called. When the module is * removed (using rmmod), the dwc_otg_driver_cleanup function is called. - * + * * This module also defines a data structure for the dwc_otg_driver, which is * used in conjunction with the standard ARM lm_device structure. These @@ -57,6 +57,16 @@ #include #include /* permission constants */ +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) +# include +#endif #include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +# include +#endif + //#include #include @@ -72,9 +82,8 @@ #include "dwc_otg_hcd.h" -#define DWC_DRIVER_VERSION "2.60a 22-NOV-2006" +#define DWC_DRIVER_VERSION "2.72a 24-JUN-2008" #define DWC_DRIVER_DESC "HS OTG USB Controller driver" static const char dwc_driver_name[] = "dwc_otg"; - /*-------------------------------------------------------------------------*/ @@ -85,4 +94,5 @@ .otg_cap = -1, .dma_enable = -1, + .dma_desc_enable = -1, .dma_burst_size = -1, .speed = -1, @@ -93,22 +103,23 @@ .dev_rx_fifo_size = -1, .dev_nperio_tx_fifo_size = -1, - .dev_perio_tx_fifo_size = - { /* dev_perio_tx_fifo_size_1 */ - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1 - }, /* 15 */ + .dev_perio_tx_fifo_size = { + /* dev_perio_tx_fifo_size_1 */ + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1 + /* 15 */ + }, .host_rx_fifo_size = -1, .host_nperio_tx_fifo_size = -1, @@ -126,25 +137,28 @@ .ts_dline = -1, .en_multiple_tx_fifo = -1, - .dev_tx_fifo_size = - { /* dev_tx_fifo_size */ - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1 - }, /* 15 */ + .dev_tx_fifo_size = { + /* dev_tx_fifo_size */ + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1 + /* 15 */ + }, .thr_ctl = -1, .tx_thr_length = -1, .rx_thr_length = -1, + .pti_enable = -1, + .mpi_enable = -1, }; @@ -154,6 +168,6 @@ static ssize_t version_show(struct device_driver *dev, char *buf) { - return snprintf(buf, sizeof(DWC_DRIVER_VERSION)+2,"%s\n", - DWC_DRIVER_VERSION); + return snprintf(buf, sizeof(DWC_DRIVER_VERSION)+2, "%s\n", + DWC_DRIVER_VERSION); } static DRIVER_ATTR(version, S_IRUGO, version_show, NULL); @@ -167,19 +181,19 @@ * This function shows the driver Debug Level. */ -static ssize_t dbg_level_show(struct device_driver *_drv, char *_buf) +static ssize_t dbg_level_show(struct device_driver *drv, char *buf) { - return sprintf(_buf, "0x%0x\n", g_dbg_lvl); + return sprintf(buf, "0x%0x\n", g_dbg_lvl); } + /** * This function stores the driver Debug Level. */ -static ssize_t dbg_level_store(struct device_driver *_drv, const char *_buf, - size_t _count) +static ssize_t dbg_level_store(struct device_driver *drv, const char *buf, + size_t count) { - g_dbg_lvl = simple_strtoul(_buf, NULL, 16); - return _count; + g_dbg_lvl = simple_strtoul(buf, NULL, 16); + return count; } static DRIVER_ATTR(debuglevel, S_IRUGO|S_IWUSR, dbg_level_show, dbg_level_store); - /** @@ -191,7 +205,7 @@ int i; int retval = 0; - + /* Checks if the parameter is outside of its valid range of values */ -#define DWC_OTG_PARAM_TEST(_param_,_low_,_high_) \ +#define DWC_OTG_PARAM_TEST(_param_, _low_, _high_) \ ((dwc_otg_module_params._param_ < (_low_)) || \ (dwc_otg_module_params._param_ > (_high_))) @@ -199,12 +213,12 @@ /* If the parameter has been set by the user, check that the parameter value is * within the value range of values. If not, report a module error. */ -#define DWC_OTG_PARAM_ERR(_param_,_low_,_high_,_string_) \ +#define DWC_OTG_PARAM_ERR(_param_, _low_, _high_, _string_) \ do { \ if (dwc_otg_module_params._param_ != -1) { \ - if (DWC_OTG_PARAM_TEST(_param_,(_low_),(_high_))) { \ + if (DWC_OTG_PARAM_TEST(_param_, (_low_), (_high_))) { \ DWC_ERROR("`%d' invalid for parameter `%s'\n", \ - dwc_otg_module_params._param_, _string_); \ + dwc_otg_module_params._param_, _string_); \ dwc_otg_module_params._param_ = dwc_param_##_param_##_default; \ - retval ++; \ + retval++; \ } \ } \ @@ -214,4 +228,5 @@ DWC_OTG_PARAM_ERR(otg_cap,0,2,"otg_cap"); DWC_OTG_PARAM_ERR(dma_enable,0,1,"dma_enable"); + DWC_OTG_PARAM_ERR(dma_desc_enable,0,1,"dma_desc_enable"); DWC_OTG_PARAM_ERR(speed,0,1,"speed"); DWC_OTG_PARAM_ERR(host_support_fs_ls_low_power,0,1,"host_support_fs_ls_low_power"); @@ -235,64 +250,63 @@ DWC_OTG_PARAM_ERR(ts_dline,0,1,"ts_dline"); - if (dwc_otg_module_params.dma_burst_size != -1) - { + if (dwc_otg_module_params.dma_burst_size != -1) { if (DWC_OTG_PARAM_TEST(dma_burst_size,1,1) && - DWC_OTG_PARAM_TEST(dma_burst_size,4,4) && - DWC_OTG_PARAM_TEST(dma_burst_size,8,8) && - DWC_OTG_PARAM_TEST(dma_burst_size,16,16) && - DWC_OTG_PARAM_TEST(dma_burst_size,32,32) && - DWC_OTG_PARAM_TEST(dma_burst_size,64,64) && - DWC_OTG_PARAM_TEST(dma_burst_size,128,128) && - DWC_OTG_PARAM_TEST(dma_burst_size,256,256)) - { - DWC_ERROR("`%d' invalid for parameter `dma_burst_size'\n", + DWC_OTG_PARAM_TEST(dma_burst_size,4,4) && + DWC_OTG_PARAM_TEST(dma_burst_size,8,8) && + DWC_OTG_PARAM_TEST(dma_burst_size,16,16) && + DWC_OTG_PARAM_TEST(dma_burst_size,32,32) && + DWC_OTG_PARAM_TEST(dma_burst_size,64,64) && + DWC_OTG_PARAM_TEST(dma_burst_size,128,128) && + DWC_OTG_PARAM_TEST(dma_burst_size,256,256)) { + DWC_ERROR("`%d' invalid for parameter `dma_burst_size'\n", dwc_otg_module_params.dma_burst_size); dwc_otg_module_params.dma_burst_size = 32; - retval ++; + retval++; } - } - - if (dwc_otg_module_params.phy_utmi_width != -1) - { - if (DWC_OTG_PARAM_TEST(phy_utmi_width,8,8) && - DWC_OTG_PARAM_TEST(phy_utmi_width,16,16)) + { - DWC_ERROR("`%d' invalid for parameter `phy_utmi_width'\n", + uint8_t brst_sz = 0; + while(dwc_otg_module_params.dma_burst_size > 1) { + brst_sz ++; + dwc_otg_module_params.dma_burst_size >>= 1; + } + dwc_otg_module_params.dma_burst_size = brst_sz; + } + } + + if (dwc_otg_module_params.phy_utmi_width != -1) { + if (DWC_OTG_PARAM_TEST(phy_utmi_width, 8, 8) && + DWC_OTG_PARAM_TEST(phy_utmi_width, 16, 16)) { + DWC_ERROR("`%d' invalid for parameter `phy_utmi_width'\n", dwc_otg_module_params.phy_utmi_width); dwc_otg_module_params.phy_utmi_width = 16; - retval ++; + retval++; } } - for (i=0; i<15; i++) - { + for (i = 0; i < 15; i++) { /** @todo should be like above */ - //DWC_OTG_PARAM_ERR(dev_perio_tx_fifo_size[i],4,768,"dev_perio_tx_fifo_size"); - if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] != -1) - { - if (DWC_OTG_PARAM_TEST(dev_perio_tx_fifo_size[i],4,768)) - { + //DWC_OTG_PARAM_ERR(dev_perio_tx_fifo_size[i], 4, 768, "dev_perio_tx_fifo_size"); + if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] != -1) { + if (DWC_OTG_PARAM_TEST(dev_perio_tx_fifo_size[i], 4, 768)) { DWC_ERROR("`%d' invalid for parameter `%s_%d'\n", dwc_otg_module_params.dev_perio_tx_fifo_size[i], "dev_perio_tx_fifo_size", i); dwc_otg_module_params.dev_perio_tx_fifo_size[i] = dwc_param_dev_perio_tx_fifo_size_default; - retval ++; + retval++; } } } - DWC_OTG_PARAM_ERR(en_multiple_tx_fifo,0,1,"en_multiple_tx_fifo"); - - for (i=0; i<15; i++) - { + DWC_OTG_PARAM_ERR(en_multiple_tx_fifo, 0, 1, "en_multiple_tx_fifo"); + + for (i = 0; i < 15; i++) { /** @todo should be like above */ - //DWC_OTG_PARAM_ERR(dev_tx_fifo_size[i],4,768,"dev_tx_fifo_size"); - if (dwc_otg_module_params.dev_tx_fifo_size[i] != -1) - { - if (DWC_OTG_PARAM_TEST(dev_tx_fifo_size[i],4,768)) - { + //DWC_OTG_PARAM_ERR(dev_tx_fifo_size[i], 4, 768, "dev_tx_fifo_size"); + if (dwc_otg_module_params.dev_tx_fifo_size[i] != -1) { + if (DWC_OTG_PARAM_TEST(dev_tx_fifo_size[i], 4, 768)) { DWC_ERROR("`%d' invalid for parameter `%s_%d'\n", dwc_otg_module_params.dev_tx_fifo_size[i], "dev_tx_fifo_size", i); dwc_otg_module_params.dev_tx_fifo_size[i] = dwc_param_dev_tx_fifo_size_default; - retval ++; + retval++; } } @@ -302,12 +316,12 @@ DWC_OTG_PARAM_ERR(tx_thr_length, 8, 128, "tx_thr_length"); DWC_OTG_PARAM_ERR(rx_thr_length, 8, 128, "rx_thr_length"); - - + + DWC_OTG_PARAM_ERR(pti_enable,0,1,"pti_enable"); + DWC_OTG_PARAM_ERR(mpi_enable,0,1,"mpi_enable"); + /* At this point, all module parameters that have been set by the user * are valid, and those that have not are left unset. Now set their * default values and/or check the parameters against the hardware * configurations of the OTG core. */ - - /* This sets the parameter to the default value if it has not been set by the @@ -324,14 +338,14 @@ /* This checks the macro agains the hardware configuration to see if it is - * valid. It is possible that the default value could be invalid. In this + * valid. It is possible that the default value could be invalid. In this * case, it will report a module error if the user touched the parameter. * Otherwise it will adjust the value without any error. */ -#define DWC_OTG_PARAM_CHECK_VALID(_param_,_str_,_is_valid_,_set_valid_) \ +#define DWC_OTG_PARAM_CHECK_VALID(_param_, _str_, _is_valid_, _set_valid_) \ ({ \ - int changed = DWC_OTG_PARAM_SET_DEFAULT(_param_); \ + int changed = DWC_OTG_PARAM_SET_DEFAULT(_param_); \ int error = 0; \ if (!(_is_valid_)) { \ if (changed) { \ - DWC_ERROR("`%d' invalid for parameter `%s'. Check HW configuration.\n", dwc_otg_module_params._param_,_str_); \ + DWC_ERROR("`%d' invalid for parameter `%s'. Check HW configuration.\n", dwc_otg_module_params._param_, _str_); \ error = 1; \ } \ @@ -342,41 +356,44 @@ /* OTG Cap */ - retval += DWC_OTG_PARAM_CHECK_VALID(otg_cap,"otg_cap", - ({ - int valid; - valid = 1; - switch (dwc_otg_module_params.otg_cap) { - case DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE: - if (core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) valid = 0; - break; - case DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE: - if ((core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) && - (core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) && - (core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE) && - (core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) - { - valid = 0; - } - break; - case DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE: - /* always valid */ - break; - } - valid; - }), - (((core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) || - (core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) || - (core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE) || - (core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) ? - DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE : - DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE)); - - retval += DWC_OTG_PARAM_CHECK_VALID(dma_enable,"dma_enable", - ((dwc_otg_module_params.dma_enable == 1) && (core_if->hwcfg2.b.architecture == 0)) ? 0 : 1, + retval += DWC_OTG_PARAM_CHECK_VALID(otg_cap, "otg_cap", + ({ + int valid; + valid = 1; + switch (dwc_otg_module_params.otg_cap) { + case DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE: + if (core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) + valid = 0; + break; + case DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE: + if ((core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) && + (core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) && + (core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE) && + (core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) { + valid = 0; + } + break; + case DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE: + /* always valid */ + break; + } + valid; + }), + (((core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) || + (core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) || + (core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE) || + (core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) ? + DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE : + DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE)); + + retval += DWC_OTG_PARAM_CHECK_VALID(dma_enable, "dma_enable", + ((dwc_otg_module_params.dma_enable == 1) && (core_if->hwcfg2.b.architecture == 0)) ? 0 : 1, 0); - retval += DWC_OTG_PARAM_CHECK_VALID(opt,"opt", - 1, + retval += DWC_OTG_PARAM_CHECK_VALID(dma_desc_enable, "dma_desc_enable", + ((dwc_otg_module_params.dma_desc_enable == 1) && + ((dwc_otg_module_params.dma_enable == 0) || (core_if->hwcfg4.b.desc_dma == 0))) ? 0 : 1, 0); + + retval += DWC_OTG_PARAM_CHECK_VALID(opt, "opt", 1, 0); DWC_OTG_PARAM_SET_DEFAULT(dma_burst_size); @@ -390,5 +407,4 @@ ((dwc_otg_module_params.enable_dynamic_fifo == 0) || (core_if->hwcfg2.b.dynamic_fifo == 1)), 0); - retval += DWC_OTG_PARAM_CHECK_VALID(data_fifo_size, @@ -412,5 +428,4 @@ dwc_read_reg32(&core_if->core_global_regs->grxfsiz)); - retval += DWC_OTG_PARAM_CHECK_VALID(host_nperio_tx_fifo_size, "host_nperio_tx_fifo_size", @@ -447,5 +462,5 @@ * internal testing only. * - * #define NO_FS_PHY_HW_CHECKS + * #define NO_FS_PHY_HW_CHECKS */ @@ -459,18 +474,15 @@ int valid = 0; if ((dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_UTMI) && - ((core_if->hwcfg2.b.hs_phy_type == 1) || - (core_if->hwcfg2.b.hs_phy_type == 3))) - { + ((core_if->hwcfg2.b.hs_phy_type == 1) || + (core_if->hwcfg2.b.hs_phy_type == 3))) { valid = 1; } else if ((dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_ULPI) && - ((core_if->hwcfg2.b.hs_phy_type == 2) || - (core_if->hwcfg2.b.hs_phy_type == 3))) - { + ((core_if->hwcfg2.b.hs_phy_type == 2) || + (core_if->hwcfg2.b.hs_phy_type == 3))) { valid = 1; } else if ((dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_FS) && - (core_if->hwcfg2.b.fs_phy_type == 1)) - { + (core_if->hwcfg2.b.fs_phy_type == 1)) { valid = 1; } @@ -479,6 +491,6 @@ ({ int set = DWC_PHY_TYPE_PARAM_FS; - if (core_if->hwcfg2.b.hs_phy_type) { - if ((core_if->hwcfg2.b.hs_phy_type == 3) || + if (core_if->hwcfg2.b.hs_phy_type) { + if ((core_if->hwcfg2.b.hs_phy_type == 3) || (core_if->hwcfg2.b.hs_phy_type == 1)) { set = DWC_PHY_TYPE_PARAM_UTMI; @@ -492,5 +504,5 @@ #endif - retval += DWC_OTG_PARAM_CHECK_VALID(speed,"speed", + retval += DWC_OTG_PARAM_CHECK_VALID(speed, "speed", (dwc_otg_module_params.speed == 0) && (dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_FS) ? 0 : 1, dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_FS ? 1 : 0); @@ -508,6 +520,5 @@ #ifdef NO_FS_PHY_HW_CHECKS - retval += DWC_OTG_PARAM_CHECK_VALID(i2c_enable, - "i2c_enable", 1, 0); + retval += DWC_OTG_PARAM_CHECK_VALID(i2c_enable, "i2c_enable", 1, 0); #else retval += DWC_OTG_PARAM_CHECK_VALID(i2c_enable, @@ -517,19 +528,15 @@ #endif - for (i=0; i<15; i++) - { + for (i = 0; i < 15; i++) { int changed = 1; int error = 0; - if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] == -1) - { + if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] == -1) { changed = 0; dwc_otg_module_params.dev_perio_tx_fifo_size[i] = dwc_param_dev_perio_tx_fifo_size_default; } - if (!(dwc_otg_module_params.dev_perio_tx_fifo_size[i] <= (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[i])))) - { - if (changed) - { - DWC_ERROR("`%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n", dwc_otg_module_params.dev_perio_tx_fifo_size[i],i); + if (!(dwc_otg_module_params.dev_perio_tx_fifo_size[i] <= (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[i])))) { + if (changed) { + DWC_ERROR("`%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n", dwc_otg_module_params.dev_perio_tx_fifo_size[i], i); error = 1; } @@ -539,26 +546,19 @@ } - - retval += DWC_OTG_PARAM_CHECK_VALID(en_multiple_tx_fifo,"en_multiple_tx_fifo", - ((dwc_otg_module_params.en_multiple_tx_fifo == 1) && (core_if->hwcfg4.b.ded_fifo_en == 0)) ? 0 : 1, + retval += DWC_OTG_PARAM_CHECK_VALID(en_multiple_tx_fifo, "en_multiple_tx_fifo", + ((dwc_otg_module_params.en_multiple_tx_fifo == 1) && (core_if->hwcfg4.b.ded_fifo_en == 0)) ? 0 : 1, 0); - - for (i=0; i<15; i++) - { - + for (i = 0; i < 15; i++) { int changed = 1; int error = 0; - if (dwc_otg_module_params.dev_tx_fifo_size[i] == -1) - { + if (dwc_otg_module_params.dev_tx_fifo_size[i] == -1) { changed = 0; dwc_otg_module_params.dev_tx_fifo_size[i] = dwc_param_dev_tx_fifo_size_default; } - if (!(dwc_otg_module_params.dev_tx_fifo_size[i] <= (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[i])))) - { - if (changed) - { - DWC_ERROR("%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n", dwc_otg_module_params.dev_tx_fifo_size[i],i); + if (!(dwc_otg_module_params.dev_tx_fifo_size[i] <= (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[i])))) { + if (changed) { + DWC_ERROR("%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n", dwc_otg_module_params.dev_tx_fifo_size[i], i); error = 1; } @@ -566,25 +566,37 @@ } retval += error; - - - } - - DWC_OTG_PARAM_SET_DEFAULT(thr_ctl); + } + + retval += DWC_OTG_PARAM_CHECK_VALID(thr_ctl, "thr_ctl", + ((dwc_otg_module_params.thr_ctl != 0) && ((dwc_otg_module_params.dma_enable == 0) || (core_if->hwcfg4.b.ded_fifo_en == 0))) ? 0 : 1, + 0); + DWC_OTG_PARAM_SET_DEFAULT(tx_thr_length); DWC_OTG_PARAM_SET_DEFAULT(rx_thr_length); - + + retval += DWC_OTG_PARAM_CHECK_VALID(pti_enable, "pti_enable", + ((dwc_otg_module_params.pti_enable == 0) || ((dwc_otg_module_params.pti_enable == 1) && (core_if->snpsid >= 0x4F54272A))) ? 1 : 0, + 0); + + retval += DWC_OTG_PARAM_CHECK_VALID(mpi_enable, "mpi_enable", + ((dwc_otg_module_params.mpi_enable == 0) || ((dwc_otg_module_params.mpi_enable == 1) && (core_if->hwcfg2.b.multi_proc_int == 1))) ? 1 : 0, + 0); return retval; } -/** +/** * This function is the top level interrupt handler for the Common * (Device and host modes) interrupts. */ -static irqreturn_t dwc_otg_common_irq(int _irq, void *_dev) +static irqreturn_t dwc_otg_common_irq(int irq, void *dev +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) + , struct pt_regs *r +#endif + ) { - dwc_otg_device_t *otg_dev = _dev; + dwc_otg_device_t *otg_dev = dev; int32_t retval = IRQ_NONE; - retval = dwc_otg_handle_common_intr( otg_dev->core_if ); + retval = dwc_otg_handle_common_intr(otg_dev->core_if); return IRQ_RETVAL(retval); } @@ -597,41 +609,40 @@ * of this device are freed. * - * @param[in] _lmdev + * @param[in] lmdev */ -static void dwc_otg_driver_remove(struct lm_device *_lmdev) +static void dwc_otg_driver_remove(struct lm_device *lmdev) { - dwc_otg_device_t *otg_dev = lm_get_drvdata(_lmdev); - DWC_DEBUGPL(DBG_ANY, "%s(%p)\n", __func__, _lmdev); - - if (otg_dev == NULL) - { + dwc_otg_device_t *otg_dev = lm_get_drvdata(lmdev); + DWC_DEBUGPL(DBG_ANY, "%s(%p)\n", __func__, lmdev); + + if (!otg_dev) { /* Memory allocation for the dwc_otg_device failed. */ + DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__); return; } /* - * Free the IRQ - */ - if (otg_dev->common_irq_installed) - { - free_irq( _lmdev->irq, otg_dev ); + * Free the IRQ + */ + if (otg_dev->common_irq_installed) { + free_irq(lmdev->irq, otg_dev); } #ifndef DWC_DEVICE_ONLY - if (otg_dev->hcd != NULL) - { - dwc_otg_hcd_remove( _lmdev ); + if (otg_dev->hcd) { + dwc_otg_hcd_remove(lmdev); + } else { + DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__); + return; } #endif #ifndef DWC_HOST_ONLY - if (otg_dev->pcd != NULL) - { - dwc_otg_pcd_remove( _lmdev ); + if (otg_dev->pcd) { + dwc_otg_pcd_remove(lmdev); } #endif - if (otg_dev->core_if != NULL) - { - dwc_otg_cil_remove( otg_dev->core_if ); + if (otg_dev->core_if) { + dwc_otg_cil_remove(otg_dev->core_if); } @@ -639,19 +650,18 @@ * Remove the device attributes */ - dwc_otg_attr_remove(_lmdev); + dwc_otg_attr_remove(lmdev); /* * Return the memory. */ - if (otg_dev->base != NULL) - { + if (otg_dev->base) { iounmap(otg_dev->base); } kfree(otg_dev); - + /* * Clear the drvdata pointer. */ - lm_set_drvdata( _lmdev, 0 ); + lm_set_drvdata(lmdev, 0); } @@ -665,24 +675,23 @@ * structure on subsequent calls to driver methods for this device. * - * @param[in] _lmdev lm_device definition + * @param[in] lmdev lm_device definition */ -static int dwc_otg_driver_probe(struct lm_device *_lmdev) +static int dwc_otg_driver_probe(struct lm_device *lmdev) { int retval = 0; + uint32_t snpsid; dwc_otg_device_t *dwc_otg_device; - int32_t snpsid; - - dev_dbg(&_lmdev->dev, "dwc_otg_driver_probe(%p)\n", _lmdev); - dev_dbg(&_lmdev->dev, "start=0x%08x\n", (unsigned)_lmdev->resource.start); + + dev_dbg(&lmdev->dev, "dwc_otg_driver_probe(%p)\n", lmdev); + dev_dbg(&lmdev->dev, "start=0x%08x\n", (unsigned)lmdev->resource.start); dwc_otg_device = kmalloc(sizeof(dwc_otg_device_t), GFP_KERNEL); - - if (dwc_otg_device == 0) - { - dev_err(&_lmdev->dev, "kmalloc of dwc_otg_device failed\n"); + + if (!dwc_otg_device) { + dev_err(&lmdev->dev, "kmalloc of dwc_otg_device failed\n"); retval = -ENOMEM; goto fail; } - + memset(dwc_otg_device, 0, sizeof(*dwc_otg_device)); dwc_otg_device->reg_offset = 0xFFFFFFFF; @@ -691,13 +700,12 @@ * Map the DWC_otg Core memory into virtual address space. */ - dwc_otg_device->base = ioremap(_lmdev->resource.start, SZ_256K); - - if (dwc_otg_device->base == NULL) - { - dev_err(&_lmdev->dev, "ioremap() failed\n"); + dwc_otg_device->base = ioremap(lmdev->resource.start, SZ_256K); + + if (!dwc_otg_device->base) { + dev_err(&lmdev->dev, "ioremap() failed\n"); retval = -ENOMEM; goto fail; } - dev_dbg(&_lmdev->dev, "base=0x%08x\n", (unsigned)dwc_otg_device->base); + dev_dbg(&lmdev->dev, "base=0x%08x\n", (unsigned)dwc_otg_device->base); /* @@ -707,33 +715,39 @@ */ snpsid = dwc_read_reg32((uint32_t *)((uint8_t *)dwc_otg_device->base + 0x40)); - - if ((snpsid & 0xFFFFF000) != 0x4F542000) - { - dev_err(&_lmdev->dev, "Bad value for SNPSID: 0x%08x\n", snpsid); + + if ((snpsid & 0xFFFFF000) != OTG_CORE_REV_2_00) { + dev_err(&lmdev->dev, "Bad value for SNPSID: 0x%08x\n", snpsid); retval = -EINVAL; goto fail; } + DWC_PRINT("Core Release: %x.%x%x%x\n", + (snpsid >> 12 & 0xF), + (snpsid >> 8 & 0xF), + (snpsid >> 4 & 0xF), + (snpsid & 0xF)); + /* * Initialize driver data to point to the global DWC_otg * Device structure. */ - lm_set_drvdata( _lmdev, dwc_otg_device ); - dev_dbg(&_lmdev->dev, "dwc_otg_device=0x%p\n", dwc_otg_device); + lm_set_drvdata(lmdev, dwc_otg_device); + dev_dbg(&lmdev->dev, "dwc_otg_device=0x%p\n", dwc_otg_device); + + dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->base, + &dwc_otg_module_params); - dwc_otg_device->core_if = dwc_otg_cil_init( dwc_otg_device->base, - &dwc_otg_module_params); - if (dwc_otg_device->core_if == 0) - { - dev_err(&_lmdev->dev, "CIL initialization failed!\n"); + dwc_otg_device->core_if->snpsid = snpsid; + + if (!dwc_otg_device->core_if) { + dev_err(&lmdev->dev, "CIL initialization failed!\n"); retval = -ENOMEM; goto fail; } - + /* * Validate parameter values. */ - if (check_parameters(dwc_otg_device->core_if) != 0) - { + if (check_parameters(dwc_otg_device->core_if)) { retval = -EINVAL; goto fail; @@ -742,6 +756,6 @@ /* * Create Device Attributes in sysfs - */ - dwc_otg_attr_create (_lmdev); + */ + dwc_otg_attr_create(lmdev); /* @@ -749,31 +763,26 @@ * handlers are installed. */ - dwc_otg_disable_global_interrupts( dwc_otg_device->core_if ); + dwc_otg_disable_global_interrupts(dwc_otg_device->core_if); + /* * Install the interrupt handler for the common interrupts before * enabling common interrupts in core_init below. */ - DWC_DEBUGPL( DBG_CIL, "registering (common) handler for irq%d\n", - _lmdev->irq); - retval = request_irq(_lmdev->irq, dwc_otg_common_irq,SA_SHIRQ, "dwc_otg", dwc_otg_device ); - if (retval != 0) - { - DWC_ERROR("request of irq%d failed\n", _lmdev->irq); + DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n", + lmdev->irq); + retval = request_irq(lmdev->irq, dwc_otg_common_irq, + SA_SHIRQ, "dwc_otg", dwc_otg_device); + if (retval) { + DWC_ERROR("request of irq%d failed\n", lmdev->irq); retval = -EBUSY; goto fail; - } - else - { + } else { dwc_otg_device->common_irq_installed = 1; } -#ifdef CONFIG_MACH_IPMATE - set_irq_type(_lmdev->irq, IRQT_LOW); -#endif - /* * Initialize the DWC_otg core. */ - dwc_otg_core_init( dwc_otg_device->core_if ); + dwc_otg_core_init(dwc_otg_device->core_if); #ifndef DWC_HOST_ONLY @@ -781,7 +790,6 @@ * Initialize the PCD */ - retval = dwc_otg_pcd_init( _lmdev ); - if (retval != 0) - { + retval = dwc_otg_pcd_init(lmdev); + if (retval != 0) { DWC_ERROR("dwc_otg_pcd_init failed\n"); dwc_otg_device->pcd = NULL; @@ -793,7 +801,6 @@ * Initialize the HCD */ - retval = dwc_otg_hcd_init(_lmdev); - if (retval != 0) - { + retval = dwc_otg_hcd_init(lmdev); + if (retval != 0) { DWC_ERROR("dwc_otg_hcd_init failed\n"); dwc_otg_device->hcd = NULL; @@ -806,14 +813,14 @@ * handlers are installed. */ - dwc_otg_enable_global_interrupts( dwc_otg_device->core_if ); + dwc_otg_enable_global_interrupts(dwc_otg_device->core_if); return 0; fail: - dwc_otg_driver_remove(_lmdev); + dwc_otg_driver_remove(lmdev); return retval; } -/** +/** * This structure defines the methods to be called by a bus driver * during the lifecycle of a device on that bus. Both drivers and @@ -826,14 +833,40 @@ * unregistered with the bus driver. */ -static struct lm_driver dwc_otg_driver = -{ - .drv = - { - . name = (char*)dwc_driver_name, - }, +static struct lm_driver dwc_otg_driver = { + .drv = { + .name = (char *)dwc_driver_name, + }, .probe = dwc_otg_driver_probe, .remove = dwc_otg_driver_remove, }; - +#define RALINK_PIO_BASE 0xA0300600 + +#define RALINK_PRGIO_ADDR RALINK_PIO_BASE // Programmable I/O + +#define RALINK_REG_PIOINT (RALINK_PRGIO_ADDR + 0) +#define RALINK_REG_PIOEDGE (RALINK_PRGIO_ADDR + 0x04) +#define RALINK_REG_PIORENA (RALINK_PRGIO_ADDR + 0x08) +#define RALINK_REG_PIOFENA (RALINK_PRGIO_ADDR + 0x0C) +#define RALINK_REG_PIODATA (RALINK_PRGIO_ADDR + 0x20) +#define RALINK_REG_PIODIR (RALINK_PRGIO_ADDR + 0x24) +#define RALINK_REG_PIOSET (RALINK_PRGIO_ADDR + 0x2C) +#define RALINK_REG_PIORESET (RALINK_PRGIO_ADDR + 0x30) + +void ralink_gpio_control(int gpio,int level) +{ + unsigned long piodir,piodata; + + piodir = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODIR)); + piodir |= (1L << gpio); + *(volatile u32 *)(RALINK_REG_PIODIR) = cpu_to_le32(piodir); + piodata = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODATA)); + + if(level) + piodata |= (1L << gpio); + else + piodata &= ~(1L << gpio); + + *(volatile u32 *)(RALINK_REG_PIODATA) = cpu_to_le32(piodata); +} /** @@ -847,13 +880,13 @@ * @return */ -static int __init dwc_otg_driver_init(void) +static int __init dwc_otg_driver_init(void) { int retval = 0; struct lm_device *lmdev; - + int error; + *(unsigned long *)(KSEG1ADDR(RALINK_USB_OTG_BASE+0xE00)) = 0x0; //Enable USB Port - + ralink_gpio_control(6,1); // turn on 5V lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL); - if (!lmdev) { @@ -871,11 +904,10 @@ printk(KERN_INFO "%s: version %s\n", dwc_driver_name, DWC_DRIVER_VERSION); retval = lm_driver_register(&dwc_otg_driver); - if (retval < 0) - { + if (retval < 0) { printk(KERN_ERR "%s retval=%d\n", __func__, retval); return retval; } - driver_create_file(&dwc_otg_driver.drv, &driver_attr_version); - driver_create_file(&dwc_otg_driver.drv, &driver_attr_debuglevel); + error = driver_create_file(&dwc_otg_driver.drv, &driver_attr_version); + error = driver_create_file(&dwc_otg_driver.drv, &driver_attr_debuglevel); return retval; @@ -883,5 +915,5 @@ module_init(dwc_otg_driver_init); -/** +/** * This function is called when the driver is removed from the kernel * with the rmmod command. The driver unregisters itself with its bus @@ -897,5 +929,5 @@ lm_driver_unregister(&dwc_otg_driver); - + ralink_gpio_control(6,0); // turn off 5V *(unsigned long *)(KSEG1ADDR(RALINK_USB_OTG_BASE+0xE00)) = 0xF; //Disable USB Port printk(KERN_INFO "%s module removed\n", dwc_driver_name); @@ -913,4 +945,8 @@ module_param_named(dma_enable, dwc_otg_module_params.dma_enable, int, 0444); MODULE_PARM_DESC(dma_enable, "DMA Mode 0=Slave 1=DMA enabled"); + +module_param_named(dma_desc_enable, dwc_otg_module_params.dma_desc_enable, int, 0444); +MODULE_PARM_DESC(dma_desc_enable, "DMA Desc Mode 0=Address DMA 1=DMA Descriptor enabled"); + module_param_named(dma_burst_size, dwc_otg_module_params.dma_burst_size, int, 0444); MODULE_PARM_DESC(dma_burst_size, "DMA Burst Size 1, 4, 8, 16, 32, 64, 128, 256"); @@ -1030,17 +1066,24 @@ module_param_named(rx_thr_length, dwc_otg_module_params.rx_thr_length, int, 0444); MODULE_PARM_DESC(rx_thr_length, "Rx Threshold length in 32 bit DWORDs"); + +module_param_named(pti_enable, dwc_otg_module_params.pti_enable, int, 0444); +MODULE_PARM_DESC(pti_enable, "Per Transfer Interrupt mode 0=disabled 1=enabled"); + +module_param_named(mpi_enable, dwc_otg_module_params.mpi_enable, int, 0444); +MODULE_PARM_DESC(mpi_enable, "Multiprocessor Interrupt mode 0=disabled 1=enabled"); + /** @page "Module Parameters" * * The following parameters may be specified when starting the module. * These parameters define how the DWC_otg controller should be - * configured. Parameter values are passed to the CIL initialization + * configured. Parameter values are passed to the CIL initialization * function dwc_otg_cil_init * * Example: modprobe dwc_otg speed=1 otg_cap=1 * - + - - + + @@ -1051,5 +1094,5 @@ - 2: No HNP/SRP capable - + @@ -1060,5 +1103,5 @@ - 1: DMA (default, if available) - + @@ -1066,5 +1109,5 @@ - Values: 1, 4, 8 16, 32, 64, 128, 256 (default 32) - + @@ -1075,5 +1118,5 @@ - 1: Full Speed - + @@ -1083,5 +1126,5 @@ - 1: Support low power mode - + @@ -1092,5 +1135,5 @@ - 1: 6 MHz - + @@ -1099,5 +1142,5 @@ - 1: Allow dynamic FIFO sizing (default) - + @@ -1108,5 +1151,5 @@ Note: The total FIFO memory depth in the FPGA configuration is 8192. - + @@ -1115,5 +1158,5 @@ - Values: 16 to 32768 (default 1064) - + @@ -1122,5 +1165,5 @@ - Values: 16 to 32768 (default 1024) - + @@ -1129,5 +1172,5 @@ - Values: 4 to 768 (default 256) - + @@ -1136,5 +1179,5 @@ - Values: 16 to 32768 (default 1024) - + @@ -1143,5 +1186,5 @@ - Values: 16 to 32768 (default 1024) - + @@ -1150,5 +1193,5 @@ - Values: 16 to 32768 (default 1024) - + @@ -1156,5 +1199,5 @@ - Values: 2047 to 65,535 (default 65,535) - + @@ -1162,5 +1205,5 @@ - Values: 15 to 511 (default 511) - + @@ -1170,5 +1213,5 @@ Note: The FPGA configuration supports a maximum of 12 host channels. - + @@ -1180,5 +1223,5 @@ addition to EP0. - + @@ -1189,5 +1232,5 @@ - 2: ULPI - + @@ -1198,5 +1241,5 @@ - Values: 8 or 16 bits (default 16) - + Index: /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_hcd.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_hcd.c (revision 11800) +++ /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_hcd.c (revision 12433) @@ -1,12 +1,12 @@ /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_hcd.c $ - * $Revision: 1.3 $ - * $Date: 2008-05-30 11:56:59 $ - * $Change: 762293 $ + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $ + * $Revision: 1.4 $ + * $Date: 2008-11-21 05:39:15 $ + * $Change: 1064940 $ * * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless * otherwise expressly agreed to in writing between Synopsys and you. - * + * * The Software IS NOT an item of Licensed Software or Licensed Product under * any End User Software License Agreement or Agreement for Licensed Product @@ -18,5 +18,5 @@ * Synopsys. If you do not agree with this notice, including the disclaimer * below, then you are not authorized to use the Software. - * + * * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -49,4 +49,6 @@ #include #include +#include + //#include #include @@ -57,5 +59,5 @@ #include "dwc_otg_regs.h" -static const char dwc_otg_hcd_name [] = "dwc_otg_hcd"; +static const char dwc_otg_hcd_name[] = "dwc_otg_hcd"; static const struct hc_driver dwc_otg_hc_driver = { @@ -69,5 +71,5 @@ .flags = HCD_MEMORY | HCD_USB2, - //.reset = + //.reset = .start = dwc_otg_hcd_start, //.suspend = @@ -83,9 +85,7 @@ .hub_status_data = dwc_otg_hcd_hub_status_data, .hub_control = dwc_otg_hcd_hub_control, - //.hub_suspend = + //.hub_suspend = //.hub_resume = }; - - /** @@ -93,12 +93,23 @@ * The dwc_otg_hcd_start() must be called in a process context. */ -static void hcd_start_func(struct work_struct *work) -{ - dwc_otg_hcd_t *priv = container_of(work, dwc_otg_hcd_t, start_work); - struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(priv); - DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, usb_hcd); - if (usb_hcd) { - dwc_otg_hcd_start(usb_hcd); - } +static void hcd_start_func( +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + void *_vp +#else + struct work_struct *_work +#endif + ) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + struct usb_hcd *usb_hcd = (struct usb_hcd *)_vp; +#else + struct delayed_work *dw = container_of(_work, struct delayed_work, work); + struct dwc_otg_hcd *otg_hcd = container_of(dw, struct dwc_otg_hcd, start_work); + struct usb_hcd *usb_hcd = container_of((void *)otg_hcd, struct usb_hcd, hcd_priv); +#endif + DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, usb_hcd); + if (usb_hcd) { + dwc_otg_hcd_start(usb_hcd); + } } @@ -107,63 +118,68 @@ * connected. * - * @param _p void pointer to the struct usb_hcd + * @param p void pointer to the struct usb_hcd */ -static int32_t dwc_otg_hcd_start_cb(void *_p) -{ - dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(_p); - dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; - hprt0_data_t hprt0; - - if (core_if->op_state == B_HOST) { - /* - * Reset the port. During a HNP mode switch the reset - * needs to occur within 1ms and have a duration of at - * least 50ms. - */ - hprt0.d32 = dwc_otg_read_hprt0 (core_if); - hprt0.b.prtrst = 1; - dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); - ((struct usb_hcd *)_p)->self.is_b_host = 1; - } else { - ((struct usb_hcd *)_p)->self.is_b_host = 0; - } - +static int32_t dwc_otg_hcd_start_cb(void *p) +{ + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(p); + dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; + hprt0_data_t hprt0; + + if (core_if->op_state == B_HOST) { + /* + * Reset the port. During a HNP mode switch the reset + * needs to occur within 1ms and have a duration of at + * least 50ms. + */ + hprt0.d32 = dwc_otg_read_hprt0(core_if); + hprt0.b.prtrst = 1; + dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); + ((struct usb_hcd *)p)->self.is_b_host = 1; + } else { + ((struct usb_hcd *)p)->self.is_b_host = 0; + } + /* Need to start the HCD in a non-interrupt context. */ - //INIT_WORK(&dwc_otg_hcd->start_work, hcd_start_func, _p); - INIT_WORK(&dwc_otg_hcd->start_work, hcd_start_func); - schedule_work(&dwc_otg_hcd->start_work); - - return 1; -} - +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + INIT_WORK(&dwc_otg_hcd->start_work, hcd_start_func, p); +// INIT_DELAYED_WORK(&dwc_otg_hcd->start_work, hcd_start_func, p); +#else +// INIT_WORK(&dwc_otg_hcd->start_work, hcd_start_func); + INIT_DELAYED_WORK(&dwc_otg_hcd->start_work, hcd_start_func); +#endif +// schedule_work(&dwc_otg_hcd->start_work); + queue_delayed_work(core_if->wq_otg, &dwc_otg_hcd->start_work, 50 * HZ / 1000); + + return 1; +} /** * HCD Callback function for stopping the HCD. * - * @param _p void pointer to the struct usb_hcd + * @param p void pointer to the struct usb_hcd */ -static int32_t dwc_otg_hcd_stop_cb( void *_p ) -{ - struct usb_hcd *usb_hcd = (struct usb_hcd *)_p; - DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, _p); - dwc_otg_hcd_stop( usb_hcd ); - return 1; -} - -static void del_xfer_timers(dwc_otg_hcd_t *_hcd) +static int32_t dwc_otg_hcd_stop_cb(void *p) +{ + struct usb_hcd *usb_hcd = (struct usb_hcd *)p; + DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p); + dwc_otg_hcd_stop(usb_hcd); + return 1; +} + +static void del_xfer_timers(dwc_otg_hcd_t *hcd) { #ifdef DEBUG int i; - int num_channels = _hcd->core_if->core_params->host_channels; + int num_channels = hcd->core_if->core_params->host_channels; for (i = 0; i < num_channels; i++) { - del_timer(&_hcd->core_if->hc_xfer_timer[i]); - } -#endif -} - -static void del_timers(dwc_otg_hcd_t *_hcd) -{ - del_xfer_timers(_hcd); - del_timer(&_hcd->conn_timer); + del_timer(&hcd->core_if->hc_xfer_timer[i]); + } +#endif +} + +static void del_timers(dwc_otg_hcd_t *hcd) +{ + del_xfer_timers(hcd); + del_timer(&hcd->conn_timer); } @@ -172,5 +188,5 @@ * -ETIMEDOUT and frees the QTD. */ -static void kill_urbs_in_qh_list(dwc_otg_hcd_t *_hcd, struct list_head *_qh_list) +static void kill_urbs_in_qh_list(dwc_otg_hcd_t *hcd, struct list_head *qh_list) { struct list_head *qh_item; @@ -179,5 +195,5 @@ dwc_otg_qtd_t *qtd; - list_for_each(qh_item, _qh_list) { + list_for_each(qh_item, qh_list) { qh = list_entry(qh_item, dwc_otg_qh_t, qh_list_entry); for (qtd_item = qh->qtd_list.next; @@ -186,8 +202,8 @@ qtd = list_entry(qtd_item, dwc_otg_qtd_t, qtd_list_entry); if (qtd->urb != NULL) { - dwc_otg_hcd_complete_urb(_hcd, qtd->urb, + dwc_otg_hcd_complete_urb(hcd, qtd->urb, -ETIMEDOUT); } - dwc_otg_hcd_qtd_remove_and_free(qtd); + dwc_otg_hcd_qtd_remove_and_free(hcd, qtd); } } @@ -200,12 +216,12 @@ * detected or when the HCD is being stopped. */ -static void kill_all_urbs(dwc_otg_hcd_t *_hcd) -{ - kill_urbs_in_qh_list(_hcd, &_hcd->non_periodic_sched_inactive); - kill_urbs_in_qh_list(_hcd, &_hcd->non_periodic_sched_active); - kill_urbs_in_qh_list(_hcd, &_hcd->periodic_sched_inactive); - kill_urbs_in_qh_list(_hcd, &_hcd->periodic_sched_ready); - kill_urbs_in_qh_list(_hcd, &_hcd->periodic_sched_assigned); - kill_urbs_in_qh_list(_hcd, &_hcd->periodic_sched_queued); +static void kill_all_urbs(dwc_otg_hcd_t *hcd) +{ + kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive); + kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active); + kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive); + kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready); + kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned); + kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued); } @@ -213,30 +229,30 @@ * HCD Callback function for disconnect of the HCD. * - * @param _p void pointer to the struct usb_hcd + * @param p void pointer to the struct usb_hcd */ -static int32_t dwc_otg_hcd_disconnect_cb( void *_p ) +static int32_t dwc_otg_hcd_disconnect_cb(void *p) { gintsts_data_t intr; - dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd (_p); - - //DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, _p); - - /* - * Set status flags for the hub driver. - */ - dwc_otg_hcd->flags.b.port_connect_status_change = 1; + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(p); + + //DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p); + + /* + * Set status flags for the hub driver. + */ + dwc_otg_hcd->flags.b.port_connect_status_change = 1; dwc_otg_hcd->flags.b.port_connect_status = 0; - /* - * Shutdown any transfers in process by clearing the Tx FIFO Empty - * interrupt mask and status bits and disabling subsequent host - * channel interrupts. - */ - intr.d32 = 0; - intr.b.nptxfempty = 1; - intr.b.ptxfempty = 1; + /* + * Shutdown any transfers in process by clearing the Tx FIFO Empty + * interrupt mask and status bits and disabling subsequent host + * channel interrupts. + */ + intr.d32 = 0; + intr.b.nptxfempty = 1; + intr.b.ptxfempty = 1; intr.b.hcintr = 1; - dwc_modify_reg32 (&dwc_otg_hcd->core_if->core_global_regs->gintmsk, intr.d32, 0); - dwc_modify_reg32 (&dwc_otg_hcd->core_if->core_global_regs->gintsts, intr.d32, 0); + dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, intr.d32, 0); + dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintsts, intr.d32, 0); del_timers(dwc_otg_hcd); @@ -248,14 +264,14 @@ */ if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) { - if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) { - hprt0_data_t hprt0 = { .d32=0 }; - DWC_PRINT("Disconnect: PortPower off\n"); - hprt0.b.prtpwr = 0; - dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0.d32); - } - - dwc_otg_disable_host_interrupts( dwc_otg_hcd->core_if ); - } - + if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) { + hprt0_data_t hprt0 = { .d32=0 }; + DWC_PRINT("Disconnect: PortPower off\n"); + hprt0.b.prtpwr = 0; + dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0.d32); + } + + dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if); + } + /* Respond with an error status to all URBs in the schedule. */ kill_all_urbs(dwc_otg_hcd); @@ -306,8 +322,8 @@ } - /* A disconnect will end the session so the B-Device is no - * longer a B-host. */ - ((struct usb_hcd *)_p)->self.is_b_host = 0; - return 1; + /* A disconnect will end the session so the B-Device is no + * longer a B-host. */ + ((struct usb_hcd *)p)->self.is_b_host = 0; + return 1; } @@ -316,9 +332,9 @@ * message if the device does not connect within 10 seconds. */ -void dwc_otg_hcd_connect_timeout( unsigned long _ptr ) -{ - DWC_DEBUGPL(DBG_HCDV, "%s(%x)\n", __func__, (int)_ptr); - DWC_PRINT( "Connect Timeout\n"); - DWC_ERROR( "Device Not Connected/Responding\n" ); +void dwc_otg_hcd_connect_timeout(unsigned long ptr) +{ + DWC_DEBUGPL(DBG_HCDV, "%s(%x)\n", __func__, (int)ptr); + DWC_PRINT("Connect Timeout\n"); + DWC_ERROR("Device Not Connected/Responding\n"); } @@ -329,11 +345,11 @@ * timer expires. */ -static void dwc_otg_hcd_start_connect_timer( dwc_otg_hcd_t *_hcd) -{ - init_timer( &_hcd->conn_timer ); - _hcd->conn_timer.function = dwc_otg_hcd_connect_timeout; - _hcd->conn_timer.data = (unsigned long)0; - _hcd->conn_timer.expires = jiffies + (HZ*10); - add_timer( &_hcd->conn_timer ); +static void dwc_otg_hcd_start_connect_timer(dwc_otg_hcd_t *hcd) +{ + init_timer(&hcd->conn_timer); + hcd->conn_timer.function = dwc_otg_hcd_connect_timeout; + hcd->conn_timer.data = 0; + hcd->conn_timer.expires = jiffies + (HZ * 10); + add_timer(&hcd->conn_timer); } @@ -341,12 +357,12 @@ * HCD Callback function for disconnect of the HCD. * - * @param _p void pointer to the struct usb_hcd + * @param p void pointer to the struct usb_hcd */ -static int32_t dwc_otg_hcd_session_start_cb( void *_p ) -{ - dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd (_p); - DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, _p); - dwc_otg_hcd_start_connect_timer( dwc_otg_hcd ); - return 1; +static int32_t dwc_otg_hcd_session_start_cb(void *p) +{ + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(p); + DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p); + dwc_otg_hcd_start_connect_timer(dwc_otg_hcd); + return 1; } @@ -355,18 +371,17 @@ */ static dwc_otg_cil_callbacks_t hcd_cil_callbacks = { - .start = dwc_otg_hcd_start_cb, - .stop = dwc_otg_hcd_stop_cb, - .disconnect = dwc_otg_hcd_disconnect_cb, - .session_start = dwc_otg_hcd_session_start_cb, - .p = 0, + .start = dwc_otg_hcd_start_cb, + .stop = dwc_otg_hcd_stop_cb, + .disconnect = dwc_otg_hcd_disconnect_cb, + .session_start = dwc_otg_hcd_session_start_cb, + .p = 0, }; - /** * Reset tasklet function */ -static void reset_tasklet_func (unsigned long data) -{ - dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t*)data; +static void reset_tasklet_func(unsigned long data) +{ + dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *)data; dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; hprt0_data_t hprt0; @@ -374,17 +389,15 @@ DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n"); - hprt0.d32 = dwc_otg_read_hprt0 (core_if); + hprt0.d32 = dwc_otg_read_hprt0(core_if); hprt0.b.prtrst = 1; dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); - mdelay (60); + mdelay(60); hprt0.b.prtrst = 0; dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); - dwc_otg_hcd->flags.b.port_reset_change = 1; - - return; -} - -static struct tasklet_struct reset_tasklet = { + dwc_otg_hcd->flags.b.port_reset_change = 1; +} + +static struct tasklet_struct reset_tasklet = { .next = NULL, .state = 0, @@ -400,9 +413,9 @@ * a negative error on failure. */ -int dwc_otg_hcd_init(struct lm_device *_lmdev) +int dwc_otg_hcd_init(struct lm_device *lmdev) { struct usb_hcd *hcd = NULL; dwc_otg_hcd_t *dwc_otg_hcd = NULL; - dwc_otg_device_t *otg_dev = lm_get_drvdata(_lmdev); + dwc_otg_device_t *otg_dev = lm_get_drvdata(lmdev); int num_channels; @@ -414,28 +427,36 @@ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT\n"); -#if 1 //kaiker .these code must execute before usb_create_hcd +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) + /* 2.6.20+ requires dev.dma_mask to be set prior to calling usb_create_hcd() */ + /* Set device flags indicating whether the HCD supports DMA. */ if (otg_dev->core_if->dma_enable) { DWC_PRINT("Using DMA mode\n"); - _lmdev->dev.dma_mask = (void *)~0; - _lmdev->dev.coherent_dma_mask = ~0; + lmdev->dev.dma_mask = (void *)~0; + lmdev->dev.coherent_dma_mask = ~0; + + if (otg_dev->core_if->dma_desc_enable) { + DWC_PRINT("Device using Descriptor DMA mode\n"); + } else { + DWC_PRINT("Device using Buffer DMA mode\n"); + } } else { DWC_PRINT("Using Slave mode\n"); - _lmdev->dev.dma_mask = (void *)0; - _lmdev->dev.coherent_dma_mask = 0; - } -#endif - + lmdev->dev.dma_mask = (void *)0; + lmdev->dev.coherent_dma_mask = 0; + } +#endif /* * Allocate memory for the base HCD plus the DWC OTG HCD. * Initialize the base HCD. */ - hcd = usb_create_hcd(&dwc_otg_hc_driver, &_lmdev->dev, _lmdev->dev.bus_id); - if (hcd == NULL) { + hcd = usb_create_hcd(&dwc_otg_hc_driver, &lmdev->dev, lmdev->dev.bus_id); + if (!hcd) { retval = -ENOMEM; goto error1; } + hcd->regs = otg_dev->base; - hcd->self.otg_port = 1; + hcd->self.otg_port = 1; /* Initialize the DWC OTG HCD. */ @@ -444,6 +465,9 @@ otg_dev->hcd = dwc_otg_hcd; - /* Register the HCD CIL Callbacks */ - dwc_otg_cil_register_hcd_callbacks(otg_dev->core_if, + /* */ + spin_lock_init(&dwc_otg_hcd->lock); + + /* Register the HCD CIL Callbacks */ + dwc_otg_cil_register_hcd_callbacks(otg_dev->core_if, &hcd_cil_callbacks, hcd); @@ -464,4 +488,5 @@ INIT_LIST_HEAD(&dwc_otg_hcd->free_hc_list); num_channels = dwc_otg_hcd->core_if->core_params->host_channels; + memset(dwc_otg_hcd->hc_ptr_array, 0, sizeof(dwc_otg_hcd->hc_ptr_array)); for (i = 0; i < num_channels; i++) { channel = kmalloc(sizeof(dwc_hc_t), GFP_KERNEL); @@ -476,26 +501,31 @@ #ifdef DEBUG init_timer(&dwc_otg_hcd->core_if->hc_xfer_timer[i]); -#endif - +#endif DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i, channel); } - - /* Initialize the Connection timeout timer. */ - init_timer( &dwc_otg_hcd->conn_timer ); + + /* Initialize the Connection timeout timer. */ + init_timer(&dwc_otg_hcd->conn_timer); /* Initialize reset tasklet. */ reset_tasklet.data = (unsigned long) dwc_otg_hcd; dwc_otg_hcd->reset_tasklet = &reset_tasklet; -#if 0 // mask by kaiker .these code must execute before usb_create_hcd - + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) /* Set device flags indicating whether the HCD supports DMA. */ if (otg_dev->core_if->dma_enable) { DWC_PRINT("Using DMA mode\n"); - _lmdev->dev.dma_mask = (void *)~0; - _lmdev->dev.coherent_dma_mask = ~0; + lmdev->dev.dma_mask = (void *)~0; + lmdev->dev.coherent_dma_mask = ~0; + + if (otg_dev->core_if->dma_desc_enable){ + DWC_PRINT("Device using Descriptor DMA mode\n"); + } else { + DWC_PRINT("Device using Buffer DMA mode\n"); + } } else { DWC_PRINT("Using Slave mode\n"); - _lmdev->dev.dma_mask = (void *)0; - _lmdev->dev.coherent_dma_mask = 0; + lmdev->dev.dma_mask = (void *)0; + lmdev->dev.coherent_dma_mask = 0; } #endif @@ -505,5 +535,5 @@ * IRQ line, and calls dwc_otg_hcd_start method. */ - retval = usb_add_hcd(hcd, _lmdev->irq, SA_SHIRQ); + retval = usb_add_hcd(hcd, lmdev->irq, SA_SHIRQ); if (retval < 0) { goto error2; @@ -518,5 +548,5 @@ if (otg_dev->core_if->dma_enable) { dwc_otg_hcd->status_buf = - dma_alloc_coherent(&_lmdev->dev, + dma_alloc_coherent(&lmdev->dev, DWC_OTG_HCD_STATUS_BUF_SIZE, &dwc_otg_hcd->status_buf_dma, @@ -526,5 +556,5 @@ GFP_KERNEL); } - if (dwc_otg_hcd->status_buf == NULL) { + if (!dwc_otg_hcd->status_buf) { retval = -ENOMEM; DWC_ERROR("%s: status_buf allocation failed\n", __func__); @@ -532,7 +562,9 @@ } - DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Initialized HCD, bus=%s, usbbus=%d\n", - _lmdev->dev.bus_id, hcd->self.busnum); - + dwc_otg_hcd->otg_dev = otg_dev; + + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Initialized HCD, bus=%s, usbbus=%d\n", + lmdev->dev.bus_id, hcd->self.busnum); + return 0; @@ -548,5 +580,5 @@ * dwc_otg_hcd has already been released by dwc_otg_hcd_free() */ - lm_set_drvdata( _lmdev, otg_dev); + lm_set_drvdata( lmdev, otg_dev); error1: @@ -558,23 +590,39 @@ * Frees memory and resources associated with the HCD and deregisters the bus. */ -void dwc_otg_hcd_remove(struct lm_device *_lmdev) -{ - dwc_otg_device_t *otg_dev = lm_get_drvdata(_lmdev); - dwc_otg_hcd_t *dwc_otg_hcd = otg_dev->hcd; - struct usb_hcd *hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd); +void dwc_otg_hcd_remove(struct lm_device *lmdev) +{ + dwc_otg_device_t *otg_dev = lm_get_drvdata(lmdev); + dwc_otg_hcd_t *dwc_otg_hcd; + struct usb_hcd *hcd; DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD REMOVE\n"); + if (!otg_dev) { + DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__); + return; + } + + dwc_otg_hcd = otg_dev->hcd; + + if (!dwc_otg_hcd) { + DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__); + return; + } + + hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd); + + if (!hcd) { + DWC_DEBUGPL(DBG_ANY, "%s: dwc_otg_hcd_to_hcd(dwc_otg_hcd) NULL!\n", __func__); + return; + } + /* Turn off all interrupts */ - dwc_write_reg32 (&dwc_otg_hcd->core_if->core_global_regs->gintmsk, 0); - dwc_modify_reg32 (&dwc_otg_hcd->core_if->core_global_regs->gahbcfg, 1, 0); + dwc_write_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, 0); + dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gahbcfg, 1, 0); usb_remove_hcd(hcd); dwc_otg_hcd_free(hcd); usb_put_hcd(hcd); - - return; -} - +} /* ========================================================================= @@ -585,5 +633,5 @@ * Initializes dynamic portions of the DWC_otg HCD state. */ -static void hcd_reinit(dwc_otg_hcd_t *_hcd) +static void hcd_reinit(dwc_otg_hcd_t *hcd) { struct list_head *item; @@ -592,9 +640,9 @@ dwc_hc_t *channel; - _hcd->flags.d32 = 0; - - _hcd->non_periodic_qh_ptr = &_hcd->non_periodic_sched_active; - _hcd->non_periodic_channels = 0; - _hcd->periodic_channels = 0; + hcd->flags.d32 = 0; + + hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active; + hcd->non_periodic_channels = 0; + hcd->periodic_channels = 0; /* @@ -602,18 +650,18 @@ * states. */ - item = _hcd->free_hc_list.next; - while (item != &_hcd->free_hc_list) { + item = hcd->free_hc_list.next; + while (item != &hcd->free_hc_list) { list_del(item); - item = _hcd->free_hc_list.next; - } - num_channels = _hcd->core_if->core_params->host_channels; + item = hcd->free_hc_list.next; + } + num_channels = hcd->core_if->core_params->host_channels; for (i = 0; i < num_channels; i++) { - channel = _hcd->hc_ptr_array[i]; - list_add_tail(&channel->hc_list_entry, &_hcd->free_hc_list); - dwc_otg_hc_cleanup(_hcd->core_if, channel); + channel = hcd->hc_ptr_array[i]; + list_add_tail(&channel->hc_list_entry, &hcd->free_hc_list); + dwc_otg_hc_cleanup(hcd->core_if, channel); } /* Initialize the DWC core for host mode operation. */ - dwc_otg_core_host_init(_hcd->core_if); + dwc_otg_core_host_init(hcd->core_if); } @@ -621,34 +669,41 @@ * mode operation. Activates the root port. Returns 0 on success and a negative * error code on failure. */ -extern int register_root_hub(struct usb_hcd *hcd); -int dwc_otg_hcd_start(struct usb_hcd *_hcd) -{ - dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd (_hcd); - dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; - +int dwc_otg_hcd_start(struct usb_hcd *hcd) +{ + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); + dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; + struct usb_bus *bus; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) struct usb_device *udev; - struct usb_bus *bus; - int retval; +#endif DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n"); - bus = hcd_to_bus(_hcd); + bus = hcd_to_bus(hcd); /* Initialize the bus state. If the core is in Device Mode * HALT the USB bus and return. */ - if (dwc_otg_is_device_mode (core_if)) { - _hcd->state = HC_STATE_HALT; + if (dwc_otg_is_device_mode(core_if)) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + hcd->state = HC_STATE_HALT; +#else + hcd->state = HC_STATE_RUNNING; +#endif return 0; } - _hcd->state = HC_STATE_RUNNING; + hcd->state = HC_STATE_RUNNING; /* Initialize and connect root hub if one is not already attached */ if (bus->root_hub) { DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Has Root Hub\n"); - /* Inform the HUB driver to resume. */ - usb_hcd_resume_root_hub(_hcd); - } + /* Inform the HUB driver to resume. */ + usb_hcd_resume_root_hub(hcd); + } else { + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Does Not Have Root Hub\n"); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) udev = usb_alloc_dev(NULL, bus, 0); udev->speed = USB_SPEED_HIGH; @@ -657,8 +712,9 @@ return -ENODEV; } - if ((retval = register_root_hub(_hcd)) != 0) { + if ((retval = usb_hcd_register_root_hub(udev, hcd)) != 0) { DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Error registering %d\n", retval); - return -ENODEV; - } + return -ENODEV; + } +#endif } @@ -668,10 +724,10 @@ } -static void qh_list_free(dwc_otg_hcd_t *_hcd, struct list_head *_qh_list) +static void qh_list_free(dwc_otg_hcd_t *hcd, struct list_head *qh_list) { struct list_head *item; dwc_otg_qh_t *qh; - if (_qh_list->next == NULL) { + if (!qh_list->next) { /* The list hasn't been initialized yet. */ return; @@ -679,9 +735,9 @@ /* Ensure there are no QTDs or URBs left. */ - kill_urbs_in_qh_list(_hcd, _qh_list); - - for (item = _qh_list->next; item != _qh_list; item = _qh_list->next) { + kill_urbs_in_qh_list(hcd, qh_list); + + for (item = qh_list->next; item != qh_list; item = qh_list->next) { qh = list_entry(item, dwc_otg_qh_t, qh_list_entry); - dwc_otg_hcd_qh_remove_and_free(_hcd, qh); + dwc_otg_hcd_qh_remove_and_free(hcd, qh); } } @@ -691,7 +747,7 @@ * stopped. */ -void dwc_otg_hcd_stop(struct usb_hcd *_hcd) -{ - dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd (_hcd); +void dwc_otg_hcd_stop(struct usb_hcd *hcd) +{ + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); hprt0_data_t hprt0 = { .d32=0 }; @@ -699,5 +755,5 @@ /* Turn off all host-specific interrupts. */ - dwc_otg_disable_host_interrupts( dwc_otg_hcd->core_if ); + dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if); /* @@ -711,13 +767,10 @@ hprt0.b.prtpwr = 0; dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0.d32); - - return; -} - +} /** Returns the current frame number. */ -int dwc_otg_hcd_get_frame_number(struct usb_hcd *_hcd) -{ - dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(_hcd); +int dwc_otg_hcd_get_frame_number(struct usb_hcd *hcd) +{ + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); hfnum_data_t hfnum; @@ -727,5 +780,5 @@ #ifdef DEBUG_SOF DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n", hfnum.b.frnum); -#endif +#endif return hfnum.b.frnum; } @@ -735,7 +788,7 @@ * in the struct usb_hcd field. */ -void dwc_otg_hcd_free(struct usb_hcd *_hcd) -{ - dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(_hcd); +void dwc_otg_hcd_free(struct usb_hcd *hcd) +{ + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); int i; @@ -763,5 +816,5 @@ if (dwc_otg_hcd->core_if->dma_enable) { if (dwc_otg_hcd->status_buf_dma) { - dma_free_coherent(_hcd->self.controller, + dma_free_coherent(hcd->self.controller, DWC_OTG_HCD_STATUS_BUF_SIZE, dwc_otg_hcd->status_buf, @@ -771,53 +824,50 @@ kfree(dwc_otg_hcd->status_buf); } - - return; -} - +} #ifdef DEBUG -static void dump_urb_info(struct urb *_urb, char* _fn_name) -{ - DWC_PRINT("%s, urb %p\n", _fn_name, _urb); - DWC_PRINT(" Device address: %d\n", usb_pipedevice(_urb->pipe)); - DWC_PRINT(" Endpoint: %d, %s\n", usb_pipeendpoint(_urb->pipe), - (usb_pipein(_urb->pipe) ? "IN" : "OUT")); +static void dump_urb_info(struct urb *urb, char* fn_name) +{ + DWC_PRINT("%s, urb %p\n", fn_name, urb); + DWC_PRINT(" Device address: %d\n", usb_pipedevice(urb->pipe)); + DWC_PRINT(" Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe), + (usb_pipein(urb->pipe) ? "IN" : "OUT")); DWC_PRINT(" Endpoint type: %s\n", ({char *pipetype; - switch (usb_pipetype(_urb->pipe)) { - case PIPE_CONTROL: pipetype = "CONTROL"; break; - case PIPE_BULK: pipetype = "BULK"; break; - case PIPE_INTERRUPT: pipetype = "INTERRUPT"; break; - case PIPE_ISOCHRONOUS: pipetype = "ISOCHRONOUS"; break; - default: pipetype = "UNKNOWN"; break; - }; pipetype;})); + switch (usb_pipetype(urb->pipe)) { + case PIPE_CONTROL: pipetype = "CONTROL"; break; + case PIPE_BULK: pipetype = "BULK"; break; + case PIPE_INTERRUPT: pipetype = "INTERRUPT"; break; + case PIPE_ISOCHRONOUS: pipetype = "ISOCHRONOUS"; break; + default: pipetype = "UNKNOWN"; break; + }; pipetype;})); DWC_PRINT(" Speed: %s\n", ({char *speed; - switch (_urb->dev->speed) { - case USB_SPEED_HIGH: speed = "HIGH"; break; - case USB_SPEED_FULL: speed = "FULL"; break; - case USB_SPEED_LOW: speed = "LOW"; break; - default: speed = "UNKNOWN"; break; - }; speed;})); + switch (urb->dev->speed) { + case USB_SPEED_HIGH: speed = "HIGH"; break; + case USB_SPEED_FULL: speed = "FULL"; break; + case USB_SPEED_LOW: speed = "LOW"; break; + default: speed = "UNKNOWN"; break; + }; speed;})); DWC_PRINT(" Max packet size: %d\n", - usb_maxpacket(_urb->dev, _urb->pipe, usb_pipeout(_urb->pipe))); - DWC_PRINT(" Data buffer length: %d\n", _urb->transfer_buffer_length); + usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))); + DWC_PRINT(" Data buffer length: %d\n", urb->transfer_buffer_length); DWC_PRINT(" Transfer buffer: %p, Transfer DMA: %p\n", - _urb->transfer_buffer, (void *)_urb->transfer_dma); + urb->transfer_buffer, (void *)urb->transfer_dma); DWC_PRINT(" Setup buffer: %p, Setup DMA: %p\n", - _urb->setup_packet, (void *)_urb->setup_dma); - DWC_PRINT(" Interval: %d\n", _urb->interval); - if (usb_pipetype(_urb->pipe) == PIPE_ISOCHRONOUS) { + urb->setup_packet, (void *)urb->setup_dma); + DWC_PRINT(" Interval: %d\n", urb->interval); + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { int i; - for (i = 0; i < _urb->number_of_packets; i++) { + for (i = 0; i < urb->number_of_packets; i++) { DWC_PRINT(" ISO Desc %d:\n", i); DWC_PRINT(" offset: %d, length %d\n", - _urb->iso_frame_desc[i].offset, - _urb->iso_frame_desc[i].length); - } - } -} - -static void dump_channel_info(dwc_otg_hcd_t *_hcd, + urb->iso_frame_desc[i].offset, + urb->iso_frame_desc[i].length); + } + } +} + +static void dump_channel_info(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) { @@ -826,5 +876,5 @@ struct list_head *item; dwc_otg_qh_t *qh_item; - int num_channels = _hcd->core_if->core_params->host_channels; + int num_channels = hcd->core_if->core_params->host_channels; int i; @@ -835,5 +885,5 @@ uint32_t hcdma; - hc_regs = _hcd->core_if->host_if->hc_regs[hc->hc_num]; + hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num]; hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); @@ -855,10 +905,10 @@ DWC_PRINT(" qh: %p\n", hc->qh); DWC_PRINT(" NP inactive sched:\n"); - list_for_each(item, &_hcd->non_periodic_sched_inactive) { + list_for_each(item, &hcd->non_periodic_sched_inactive) { qh_item = list_entry(item, dwc_otg_qh_t, qh_list_entry); DWC_PRINT(" %p\n", qh_item); } DWC_PRINT(" NP active sched:\n"); - list_for_each(item, &_hcd->non_periodic_sched_active) { + list_for_each(item, &hcd->non_periodic_sched_active) { qh_item = list_entry(item, dwc_otg_qh_t, qh_list_entry); DWC_PRINT(" %p\n", qh_item); @@ -866,5 +916,5 @@ DWC_PRINT(" Channels: \n"); for (i = 0; i < num_channels; i++) { - dwc_hc_t *hc = _hcd->hc_ptr_array[i]; + dwc_hc_t *hc = hcd->hc_ptr_array[i]; DWC_PRINT(" %2d: %p\n", i, hc); } @@ -876,18 +926,23 @@ * (URB). mem_flags indicates the type of memory allocation to use while * processing this URB. */ -int dwc_otg_hcd_urb_enqueue(struct usb_hcd *_hcd, - struct usb_host_endpoint *_ep, - struct urb *_urb, - gfp_t _mem_flags) +int dwc_otg_hcd_urb_enqueue(struct usb_hcd *hcd, + struct usb_host_endpoint *ep, + struct urb *urb, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + int mem_flags +#else + gfp_t mem_flags +#endif + ) { int retval = 0; - dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd (_hcd); + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); dwc_otg_qtd_t *qtd; - + #ifdef DEBUG if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { - dump_urb_info(_urb, "dwc_otg_hcd_urb_enqueue"); - } -#endif + dump_urb_info(urb, "dwc_otg_hcd_urb_enqueue"); + } +#endif if (!dwc_otg_hcd->flags.b.port_connect_status) { /* No longer connected. */ @@ -895,5 +950,5 @@ } - qtd = dwc_otg_hcd_qtd_create (_urb); + qtd = dwc_otg_hcd_qtd_create(urb); if (qtd == NULL) { DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n"); @@ -901,5 +956,5 @@ } - retval = dwc_otg_hcd_qtd_add (qtd, dwc_otg_hcd); + retval = dwc_otg_hcd_qtd_add(qtd, dwc_otg_hcd); if (retval < 0) { DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. " @@ -913,6 +968,9 @@ /** Aborts/cancels a USB transfer request. Always returns 0 to indicate * success. */ -int dwc_otg_hcd_urb_dequeue(struct usb_hcd *_hcd, - struct urb *_urb) +int dwc_otg_hcd_urb_dequeue(struct usb_hcd *hcd, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + struct usb_host_endpoint *ep, +#endif + struct urb *urb) { unsigned long flags; @@ -920,23 +978,25 @@ dwc_otg_qtd_t *urb_qtd; dwc_otg_qh_t *qh; - struct usb_host_endpoint *_ep = dwc_urb_to_endpoint(_urb); - +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) + struct usb_host_endpoint *ep = dwc_urb_to_endpoint(urb); +#endif DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n"); - local_irq_save(flags); - - dwc_otg_hcd = hcd_to_dwc_otg_hcd(_hcd); - urb_qtd = (dwc_otg_qtd_t *)_urb->hcpriv; - qh = (dwc_otg_qh_t *)_ep->hcpriv; + dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); + + SPIN_LOCK_IRQSAVE(&dwc_otg_hcd->lock, flags); + + urb_qtd = (dwc_otg_qtd_t *)urb->hcpriv; + qh = (dwc_otg_qh_t *)ep->hcpriv; #ifdef DEBUG if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { - dump_urb_info(_urb, "dwc_otg_hcd_urb_dequeue"); + dump_urb_info(urb, "dwc_otg_hcd_urb_dequeue"); if (urb_qtd == qh->qtd_in_process) { dump_channel_info(dwc_otg_hcd, qh); } } -#endif +#endif if (urb_qtd == qh->qtd_in_process) { @@ -960,5 +1020,5 @@ * schedule if it has any remaining QTDs. */ - dwc_otg_hcd_qtd_remove_and_free(urb_qtd); + dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd, urb_qtd); if (urb_qtd == qh->qtd_in_process) { dwc_otg_hcd_qh_deactivate(dwc_otg_hcd, qh, 0); @@ -969,34 +1029,67 @@ } - local_irq_restore(flags); - - _urb->hcpriv = NULL; + SPIN_UNLOCK_IRQRESTORE(&dwc_otg_hcd->lock, flags); + + urb->hcpriv = NULL; /* Higher layer software sets URB status. */ - usb_hcd_giveback_urb(_hcd, _urb); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) + usb_hcd_giveback_urb(hcd, urb); +#else + usb_hcd_giveback_urb(hcd, urb, NULL); +#endif if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { DWC_PRINT("Called usb_hcd_giveback_urb()\n"); - DWC_PRINT(" urb->status = %d\n", _urb->status); + DWC_PRINT(" urb->status = %d\n", urb->status); } return 0; } - /** Frees resources in the DWC_otg controller related to a given endpoint. Also * clears state in the HCD related to the endpoint. Any URBs for the endpoint * must already be dequeued. */ -void dwc_otg_hcd_endpoint_disable(struct usb_hcd *_hcd, - struct usb_host_endpoint *_ep) - -{ +void dwc_otg_hcd_endpoint_disable(struct usb_hcd *hcd, + struct usb_host_endpoint *ep) +{ + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); dwc_otg_qh_t *qh; - dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(_hcd); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) + unsigned long flags; + int retry = 0; +#endif DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, " - "endpoint=%d\n", _ep->desc.bEndpointAddress, - dwc_ep_addr_to_endpoint(_ep->desc.bEndpointAddress)); - - qh = (dwc_otg_qh_t *)(_ep->hcpriv); + "endpoint=%d\n", ep->desc.bEndpointAddress, + dwc_ep_addr_to_endpoint(ep->desc.bEndpointAddress)); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) +rescan: + SPIN_LOCK_IRQSAVE(&dwc_otg_hcd->lock, flags); + qh = (dwc_otg_qh_t *)(ep->hcpriv); + if (!qh) + goto done; + + /** Check that the QTD list is really empty */ + if (!list_empty(&qh->qtd_list)) { + if (retry++ < 250) { + SPIN_UNLOCK_IRQRESTORE(&dwc_otg_hcd->lock, flags); + schedule_timeout_uninterruptible(1); + goto rescan; + } + + DWC_WARN("DWC OTG HCD EP DISABLE:" + " QTD List for this endpoint is not empty\n"); + } + + dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd, qh); + ep->hcpriv = NULL; +done: + SPIN_UNLOCK_IRQRESTORE(&dwc_otg_hcd->lock, flags); + +#else // LINUX_VERSION_CODE + + qh = (dwc_otg_qh_t *)(ep->hcpriv); if (qh != NULL) { #ifdef DEBUG @@ -1007,10 +1100,8 @@ } #endif - dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd, qh); - _ep->hcpriv = NULL; - } - - return; + ep->hcpriv = NULL; + } +#endif // LINUX_VERSION_CODE } @@ -1020,7 +1111,11 @@ * * This function is called by the USB core when an interrupt occurs */ -irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *_hcd) -{ - dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd (_hcd); +irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) + , struct pt_regs *regs +#endif + ) +{ + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); return IRQ_RETVAL(dwc_otg_hcd_handle_intr(dwc_otg_hcd)); } @@ -1030,18 +1125,17 @@ * is the status change indicator for the single root port. Returns 1 if either * change indicator is 1, otherwise returns 0. */ -int dwc_otg_hcd_hub_status_data(struct usb_hcd *_hcd, - char *_buf) -{ - dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd (_hcd); - - _buf[0] = 0; - _buf[0] |= (dwc_otg_hcd->flags.b.port_connect_status_change || +int dwc_otg_hcd_hub_status_data(struct usb_hcd *hcd, char *buf) +{ + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); + + buf[0] = 0; + buf[0] |= (dwc_otg_hcd->flags.b.port_connect_status_change || dwc_otg_hcd->flags.b.port_reset_change || dwc_otg_hcd->flags.b.port_enable_change || dwc_otg_hcd->flags.b.port_suspend_change || dwc_otg_hcd->flags.b.port_over_current_change) << 1; - + #ifdef DEBUG - if (_buf[0]) { + if (buf[0]) { DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:" " Root port status changed\n"); @@ -1058,5 +1152,5 @@ } #endif - return (_buf[0] != 0); + return (buf[0] != 0); } @@ -1573,16 +1667,16 @@ #endif /* DWC_HS_ELECT_TST */ -/** Handles hub class-specific requests.*/ -int dwc_otg_hcd_hub_control(struct usb_hcd *_hcd, - u16 _typeReq, - u16 _wValue, - u16 _wIndex, - char *_buf, - u16 _wLength) +/** Handles hub class-specific requests. */ +int dwc_otg_hcd_hub_control(struct usb_hcd *hcd, + u16 typeReq, + u16 wValue, + u16 wIndex, + char *buf, + u16 wLength) { int retval = 0; - dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd (_hcd); - dwc_otg_core_if_t *core_if = hcd_to_dwc_otg_hcd (_hcd)->core_if; + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); + dwc_otg_core_if_t *core_if = hcd_to_dwc_otg_hcd(hcd)->core_if; struct usb_hub_descriptor *desc; hprt0_data_t hprt0 = {.d32 = 0}; @@ -1590,9 +1684,9 @@ uint32_t port_status; - switch (_typeReq) { + switch (typeReq) { case ClearHubFeature: - DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "ClearHubFeature 0x%x\n", _wValue); - switch (_wValue) { + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "ClearHubFeature 0x%x\n", wValue); + switch (wValue) { case C_HUB_LOCAL_POWER: case C_HUB_OVER_CURRENT: @@ -1601,41 +1695,41 @@ default: retval = -EINVAL; - DWC_ERROR ("DWC OTG HCD - " - "ClearHubFeature request %xh unknown\n", _wValue); + DWC_ERROR("DWC OTG HCD - " + "ClearHubFeature request %xh unknown\n", wValue); } break; case ClearPortFeature: - if (!_wIndex || _wIndex > 1) + if (!wIndex || wIndex > 1) goto error; - switch (_wValue) { + switch (wValue) { case USB_PORT_FEAT_ENABLE: - DWC_DEBUGPL (DBG_ANY, "DWC OTG HCD HUB CONTROL - " - "ClearPortFeature USB_PORT_FEAT_ENABLE\n"); - hprt0.d32 = dwc_otg_read_hprt0 (core_if); + DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - " + "ClearPortFeature USB_PORT_FEAT_ENABLE\n"); + hprt0.d32 = dwc_otg_read_hprt0(core_if); hprt0.b.prtena = 1; dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); break; case USB_PORT_FEAT_SUSPEND: - DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "ClearPortFeature USB_PORT_FEAT_SUSPEND\n"); - hprt0.d32 = dwc_otg_read_hprt0 (core_if); + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "ClearPortFeature USB_PORT_FEAT_SUSPEND\n"); + hprt0.d32 = dwc_otg_read_hprt0(core_if); hprt0.b.prtres = 1; dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); /* Clear Resume bit */ - mdelay (100); + mdelay(100); hprt0.b.prtres = 0; dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); break; case USB_PORT_FEAT_POWER: - DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "ClearPortFeature USB_PORT_FEAT_POWER\n"); - hprt0.d32 = dwc_otg_read_hprt0 (core_if); + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "ClearPortFeature USB_PORT_FEAT_POWER\n"); + hprt0.d32 = dwc_otg_read_hprt0(core_if); hprt0.b.prtpwr = 0; dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); break; case USB_PORT_FEAT_INDICATOR: - DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "ClearPortFeature USB_PORT_FEAT_INDICATOR\n"); + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "ClearPortFeature USB_PORT_FEAT_INDICATOR\n"); /* Port inidicator not supported */ break; @@ -1643,6 +1737,6 @@ /* Clears drivers internal connect status change * flag */ - DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n"); + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n"); dwc_otg_hcd->flags.b.port_connect_status_change = 0; break; @@ -1650,6 +1744,6 @@ /* Clears the driver's internal Port Reset Change * flag */ - DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "ClearPortFeature USB_PORT_FEAT_C_RESET\n"); + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "ClearPortFeature USB_PORT_FEAT_C_RESET\n"); dwc_otg_hcd->flags.b.port_reset_change = 0; break; @@ -1657,6 +1751,6 @@ /* Clears the driver's internal Port * Enable/Disable Change flag */ - DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n"); + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n"); dwc_otg_hcd->flags.b.port_enable_change = 0; break; @@ -1665,24 +1759,24 @@ * Change flag, which is set when resume signaling on * the host port is complete */ - DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n"); + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n"); dwc_otg_hcd->flags.b.port_suspend_change = 0; break; case USB_PORT_FEAT_C_OVER_CURRENT: - DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n"); + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n"); dwc_otg_hcd->flags.b.port_over_current_change = 0; break; default: retval = -EINVAL; - DWC_ERROR ("DWC OTG HCD - " - "ClearPortFeature request %xh " - "unknown or unsupported\n", _wValue); + DWC_ERROR("DWC OTG HCD - " + "ClearPortFeature request %xh " + "unknown or unsupported\n", wValue); } break; case GetHubDescriptor: - DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "GetHubDescriptor\n"); - desc = (struct usb_hub_descriptor *)_buf; + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "GetHubDescriptor\n"); + desc = (struct usb_hub_descriptor *)buf; desc->bDescLength = 9; desc->bDescriptorType = 0x29; @@ -1695,13 +1789,13 @@ break; case GetHubStatus: - DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "GetHubStatus\n"); - memset (_buf, 0, 4); + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "GetHubStatus\n"); + memset(buf, 0, 4); break; case GetPortStatus: - DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "GetPortStatus\n"); - - if (!_wIndex || _wIndex > 1) + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "GetPortStatus\n"); + + if (!wIndex || wIndex > 1) goto error; @@ -1733,5 +1827,5 @@ * is in device mode. */ - *((__le32 *) _buf) = cpu_to_le32(port_status); + *((__le32 *) buf) = cpu_to_le32(port_status); break; } @@ -1740,5 +1834,5 @@ DWC_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32); - if (hprt0.b.prtconnsts) + if (hprt0.b.prtconnsts) port_status |= (1 << USB_PORT_FEAT_CONNECTION); @@ -1768,14 +1862,14 @@ /* USB_PORT_FEAT_INDICATOR unsupported always 0 */ - *((__le32 *) _buf) = cpu_to_le32(port_status); + *((__le32 *) buf) = cpu_to_le32(port_status); break; case SetHubFeature: - DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "SetHubFeature\n"); + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "SetHubFeature\n"); /* No HUB features supported */ break; case SetPortFeature: - if (_wValue != USB_PORT_FEAT_TEST && (!_wIndex || _wIndex > 1)) + if (wValue != USB_PORT_FEAT_TEST && (!wIndex || wIndex > 1)) goto error; @@ -1791,54 +1885,54 @@ } - switch (_wValue) { + switch (wValue) { case USB_PORT_FEAT_SUSPEND: - DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "SetPortFeature - USB_PORT_FEAT_SUSPEND\n"); - if (_hcd->self.otg_port == _wIndex && - _hcd->self.b_hnp_enable) { - gotgctl_data_t gotgctl = {.d32=0}; - gotgctl.b.hstsethnpen = 1; - dwc_modify_reg32( &core_if->core_global_regs->gotgctl, - 0, gotgctl.d32); - core_if->op_state = A_SUSPEND; - } - hprt0.d32 = dwc_otg_read_hprt0 (core_if); - hprt0.b.prtsusp = 1; + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "SetPortFeature - USB_PORT_FEAT_SUSPEND\n"); + if (hcd->self.otg_port == wIndex && + hcd->self.b_hnp_enable) { + gotgctl_data_t gotgctl = {.d32=0}; + gotgctl.b.hstsethnpen = 1; + dwc_modify_reg32(&core_if->core_global_regs->gotgctl, + 0, gotgctl.d32); + core_if->op_state = A_SUSPEND; + } + hprt0.d32 = dwc_otg_read_hprt0(core_if); + hprt0.b.prtsusp = 1; dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); - //DWC_PRINT( "SUSPEND: HPRT0=%0x\n", hprt0.d32); - /* Suspend the Phy Clock */ - { - pcgcctl_data_t pcgcctl = {.d32=0}; - pcgcctl.b.stoppclk = 1; - dwc_write_reg32(core_if->pcgcctl, pcgcctl.d32); - } - - /* For HNP the bus must be suspended for at least 200ms.*/ - if (_hcd->self.b_hnp_enable) { - mdelay(200); - //DWC_PRINT( "SUSPEND: wait complete! (%d)\n", _hcd->state); - } + //DWC_PRINT("SUSPEND: HPRT0=%0x\n", hprt0.d32); + /* Suspend the Phy Clock */ + { + pcgcctl_data_t pcgcctl = {.d32=0}; + pcgcctl.b.stoppclk = 1; + dwc_write_reg32(core_if->pcgcctl, pcgcctl.d32); + } + + /* For HNP the bus must be suspended for at least 200ms. */ + if (hcd->self.b_hnp_enable) { + mdelay(200); + //DWC_PRINT("SUSPEND: wait complete! (%d)\n", _hcd->state); + } break; case USB_PORT_FEAT_POWER: - DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "SetPortFeature - USB_PORT_FEAT_POWER\n"); - hprt0.d32 = dwc_otg_read_hprt0 (core_if); + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "SetPortFeature - USB_PORT_FEAT_POWER\n"); + hprt0.d32 = dwc_otg_read_hprt0(core_if); hprt0.b.prtpwr = 1; dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); break; case USB_PORT_FEAT_RESET: - DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "SetPortFeature - USB_PORT_FEAT_RESET\n"); - hprt0.d32 = dwc_otg_read_hprt0 (core_if); - /* When B-Host the Port reset bit is set in - * the Start HCD Callback function, so that - * the reset is started within 1ms of the HNP - * success interrupt. */ - if (!_hcd->self.is_b_host) { - hprt0.b.prtrst = 1; - dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); - } + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "SetPortFeature - USB_PORT_FEAT_RESET\n"); + hprt0.d32 = dwc_otg_read_hprt0(core_if); + /* When B-Host the Port reset bit is set in + * the Start HCD Callback function, so that + * the reset is started within 1ms of the HNP + * success interrupt. */ + if (!hcd->self.is_b_host) { + hprt0.b.prtrst = 1; + dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); + } /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */ - MDELAY (60); + MDELAY(60); hprt0.b.prtrst = 0; dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); @@ -1851,10 +1945,10 @@ gintmsk_data_t gintmsk; - t = (_wIndex >> 8); /* MSB wIndex USB */ - DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "SetPortFeature - USB_PORT_FEAT_TEST %d\n", t); + t = (wIndex >> 8); /* MSB wIndex USB */ + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "SetPortFeature - USB_PORT_FEAT_TEST %d\n", t); warn("USB_PORT_FEAT_TEST %d\n", t); if (t < 6) { - hprt0.d32 = dwc_otg_read_hprt0 (core_if); + hprt0.d32 = dwc_otg_read_hprt0(core_if); hprt0.b.prttstctl = t; dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); @@ -1881,5 +1975,5 @@ /* Drive suspend on the root port */ - hprt0.d32 = dwc_otg_read_hprt0 (core_if); + hprt0.d32 = dwc_otg_read_hprt0(core_if); hprt0.b.prtsusp = 1; hprt0.b.prtres = 0; @@ -1890,5 +1984,5 @@ /* Drive resume on the root port */ - hprt0.d32 = dwc_otg_read_hprt0 (core_if); + hprt0.d32 = dwc_otg_read_hprt0(core_if); hprt0.b.prtsusp = 0; hprt0.b.prtres = 1; @@ -1952,13 +2046,13 @@ case USB_PORT_FEAT_INDICATOR: - DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "SetPortFeature - USB_PORT_FEAT_INDICATOR\n"); + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "SetPortFeature - USB_PORT_FEAT_INDICATOR\n"); /* Not supported */ break; default: retval = -EINVAL; - DWC_ERROR ("DWC OTG HCD - " - "SetPortFeature request %xh " - "unknown or unsupported\n", _wValue); + DWC_ERROR("DWC OTG HCD - " + "SetPortFeature request %xh " + "unknown or unsupported\n", wValue); break; } @@ -1967,7 +2061,7 @@ error: retval = -EINVAL; - DWC_WARN ("DWC OTG HCD - " - "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n", - _typeReq, _wIndex, _wValue); + DWC_WARN("DWC OTG HCD - " + "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n", + typeReq, wIndex, wValue); break; } @@ -1975,5 +2069,4 @@ return retval; } - /** @@ -1982,9 +2075,9 @@ * the free list. * - * @param _hcd The HCD state structure. - * @param _qh Transactions from the first QTD for this QH are selected and + * @param hcd The HCD state structure. + * @param qh Transactions from the first QTD for this QH are selected and * assigned to a free host channel. */ -static void assign_and_init_hc(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh) +static void assign_and_init_hc(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) { dwc_hc_t *hc; @@ -1992,15 +2085,15 @@ struct urb *urb; - DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p)\n", __func__, _hcd, _qh); - - hc = list_entry(_hcd->free_hc_list.next, dwc_hc_t, hc_list_entry); + DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p)\n", __func__, hcd, qh); + + hc = list_entry(hcd->free_hc_list.next, dwc_hc_t, hc_list_entry); /* Remove the host channel from the free list. */ list_del_init(&hc->hc_list_entry); - qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); + qtd = list_entry(qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); urb = qtd->urb; - _qh->channel = hc; - _qh->qtd_in_process = qtd; + qh->channel = hc; + qh->qtd_in_process = qtd; /* @@ -2019,5 +2112,5 @@ } - hc->max_packet = dwc_max_packet(_qh->maxp); + hc->max_packet = dwc_max_packet(qh->maxp); hc->xfer_started = 0; @@ -2034,10 +2127,10 @@ * fields in the HCTSIZn register. */ - hc->do_ping = _qh->ping_state; + hc->do_ping = qh->ping_state; hc->ep_is_in = (usb_pipein(urb->pipe) != 0); - hc->data_pid_start = _qh->data_toggle; + hc->data_pid_start = qh->data_toggle; hc->multi_count = 1; - if (_hcd->core_if->dma_enable) { + if (hcd->core_if->dma_enable) { hc->xfer_buff = (uint8_t *)urb->transfer_dma + urb->actual_length; } else { @@ -2051,5 +2144,5 @@ */ hc->do_split = 0; - if (_qh->do_split) { + if (qh->do_split) { hc->do_split = 1; hc->xact_pos = qtd->isoc_split_pos; @@ -2068,5 +2161,5 @@ hc->ep_is_in = 0; hc->data_pid_start = DWC_OTG_HC_PID_SETUP; - if (_hcd->core_if->dma_enable) { + if (hcd->core_if->dma_enable) { hc->xfer_buff = (uint8_t *)urb->setup_dma; } else { @@ -2095,8 +2188,8 @@ hc->data_pid_start = DWC_OTG_HC_PID_DATA1; hc->xfer_len = 0; - if (_hcd->core_if->dma_enable) { - hc->xfer_buff = (uint8_t *)_hcd->status_buf_dma; + if (hcd->core_if->dma_enable) { + hc->xfer_buff = (uint8_t *)hcd->status_buf_dma; } else { - hc->xfer_buff = (uint8_t *)_hcd->status_buf; + hc->xfer_buff = (uint8_t *)hcd->status_buf; } break; @@ -2114,5 +2207,5 @@ frame_desc = &urb->iso_frame_desc[qtd->isoc_frame_index]; hc->ep_type = DWC_OTG_EP_TYPE_ISOC; - if (_hcd->core_if->dma_enable) { + if (hcd->core_if->dma_enable) { hc->xfer_buff = (uint8_t *)urb->transfer_dma; } else { @@ -2140,9 +2233,9 @@ * reflect the actual transfer length. */ - hc->multi_count = dwc_hb_mult(_qh->maxp); - } - - dwc_otg_hc_init(_hcd->core_if, hc); - hc->qh = _qh; + hc->multi_count = dwc_hb_mult(qh->maxp); + } + + dwc_otg_hc_init(hcd->core_if, hc); + hc->qh = qh; } @@ -2152,9 +2245,9 @@ * handler functions. * - * @param _hcd The HCD state structure. + * @param hcd The HCD state structure. * * @return The types of new transactions that were assigned to host channels. */ -dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t *_hcd) +dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t *hcd) { struct list_head *qh_ptr; @@ -2168,10 +2261,10 @@ /* Process entries in the periodic ready list. */ - qh_ptr = _hcd->periodic_sched_ready.next; - while (qh_ptr != &_hcd->periodic_sched_ready && - !list_empty(&_hcd->free_hc_list)) { + qh_ptr = hcd->periodic_sched_ready.next; + while (qh_ptr != &hcd->periodic_sched_ready && + !list_empty(&hcd->free_hc_list)) { qh = list_entry(qh_ptr, dwc_otg_qh_t, qh_list_entry); - assign_and_init_hc(_hcd, qh); + assign_and_init_hc(hcd, qh); /* @@ -2180,5 +2273,5 @@ */ qh_ptr = qh_ptr->next; - list_move(&qh->qh_list_entry, &_hcd->periodic_sched_assigned); + list_move(&qh->qh_list_entry, &hcd->periodic_sched_assigned); ret_val = DWC_OTG_TRANSACTION_PERIODIC; @@ -2190,13 +2283,13 @@ * reserved for periodic transfers. */ - qh_ptr = _hcd->non_periodic_sched_inactive.next; - num_channels = _hcd->core_if->core_params->host_channels; - while (qh_ptr != &_hcd->non_periodic_sched_inactive && - (_hcd->non_periodic_channels < - num_channels - _hcd->periodic_channels) && - !list_empty(&_hcd->free_hc_list)) { + qh_ptr = hcd->non_periodic_sched_inactive.next; + num_channels = hcd->core_if->core_params->host_channels; + while (qh_ptr != &hcd->non_periodic_sched_inactive && + (hcd->non_periodic_channels < + num_channels - hcd->periodic_channels) && + !list_empty(&hcd->free_hc_list)) { qh = list_entry(qh_ptr, dwc_otg_qh_t, qh_list_entry); - assign_and_init_hc(_hcd, qh); + assign_and_init_hc(hcd, qh); /* @@ -2205,5 +2298,5 @@ */ qh_ptr = qh_ptr->next; - list_move(&qh->qh_list_entry, &_hcd->non_periodic_sched_active); + list_move(&qh->qh_list_entry, &hcd->non_periodic_sched_active); if (ret_val == DWC_OTG_TRANSACTION_NONE) { @@ -2213,5 +2306,5 @@ } - _hcd->non_periodic_channels++; + hcd->non_periodic_channels++; } @@ -2226,8 +2319,8 @@ * is available in the appropriate Tx FIFO. * - * @param _hcd The HCD state structure. - * @param _hc Host channel descriptor associated with either a periodic or + * @param hcd The HCD state structure. + * @param hc Host channel descriptor associated with either a periodic or * non-periodic transfer. - * @param _fifo_dwords_avail Number of DWORDs available in the periodic Tx + * @param fifo_dwords_avail Number of DWORDs available in the periodic Tx * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic * transfers. @@ -2237,45 +2330,45 @@ * transfer, -1 if there is insufficient space in the Tx FIFO. */ -static int queue_transaction(dwc_otg_hcd_t *_hcd, - dwc_hc_t *_hc, - uint16_t _fifo_dwords_avail) +static int queue_transaction(dwc_otg_hcd_t *hcd, + dwc_hc_t *hc, + uint16_t fifo_dwords_avail) { int retval; - if (_hcd->core_if->dma_enable) { - if (!_hc->xfer_started) { - dwc_otg_hc_start_transfer(_hcd->core_if, _hc); - _hc->qh->ping_state = 0; + if (hcd->core_if->dma_enable) { + if (!hc->xfer_started) { + dwc_otg_hc_start_transfer(hcd->core_if, hc); + hc->qh->ping_state = 0; } retval = 0; - } else if (_hc->halt_pending) { + } else if (hc->halt_pending) { /* Don't queue a request if the channel has been halted. */ retval = 0; - } else if (_hc->halt_on_queue) { - dwc_otg_hc_halt(_hcd->core_if, _hc, _hc->halt_status); + } else if (hc->halt_on_queue) { + dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status); retval = 0; - } else if (_hc->do_ping) { - if (!_hc->xfer_started) { - dwc_otg_hc_start_transfer(_hcd->core_if, _hc); + } else if (hc->do_ping) { + if (!hc->xfer_started) { + dwc_otg_hc_start_transfer(hcd->core_if, hc); } retval = 0; - } else if (!_hc->ep_is_in || - _hc->data_pid_start == DWC_OTG_HC_PID_SETUP) { - if ((_fifo_dwords_avail * 4) >= _hc->max_packet) { - if (!_hc->xfer_started) { - dwc_otg_hc_start_transfer(_hcd->core_if, _hc); + } else if (!hc->ep_is_in || + hc->data_pid_start == DWC_OTG_HC_PID_SETUP) { + if ((fifo_dwords_avail * 4) >= hc->max_packet) { + if (!hc->xfer_started) { + dwc_otg_hc_start_transfer(hcd->core_if, hc); retval = 1; } else { - retval = dwc_otg_hc_continue_transfer(_hcd->core_if, _hc); + retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc); } } else { retval = -1; } - } else { - if (!_hc->xfer_started) { - dwc_otg_hc_start_transfer(_hcd->core_if, _hc); + } else { + if (!hc->xfer_started) { + dwc_otg_hc_start_transfer(hcd->core_if, hc); retval = 1; } else { - retval = dwc_otg_hc_continue_transfer(_hcd->core_if, _hc); + retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc); } } @@ -2291,5 +2384,5 @@ * FIFO Empty interrupt is disabled. */ -static void process_non_periodic_channels(dwc_otg_hcd_t *_hcd) +static void process_non_periodic_channels(dwc_otg_hcd_t *hcd) { gnptxsts_data_t tx_status; @@ -2301,8 +2394,8 @@ int more_to_do = 0; - dwc_otg_core_global_regs_t *global_regs = _hcd->core_if->core_global_regs; + dwc_otg_core_global_regs_t *global_regs = hcd->core_if->core_global_regs; DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n"); -#ifdef DEBUG +#ifdef DEBUG tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts); DWC_DEBUGPL(DBG_HCDV, " NP Tx Req Queue Space Avail (before queue): %d\n", @@ -2315,8 +2408,8 @@ * entry. */ - if (_hcd->non_periodic_qh_ptr == &_hcd->non_periodic_sched_active) { - _hcd->non_periodic_qh_ptr = _hcd->non_periodic_qh_ptr->next; - } - orig_qh_ptr = _hcd->non_periodic_qh_ptr; + if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) { + hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; + } + orig_qh_ptr = hcd->non_periodic_qh_ptr; /* @@ -2326,11 +2419,11 @@ do { tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts); - if (!_hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) { + if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) { no_queue_space = 1; break; } - qh = list_entry(_hcd->non_periodic_qh_ptr, dwc_otg_qh_t, qh_list_entry); - status = queue_transaction(_hcd, qh->channel, tx_status.b.nptxfspcavail); + qh = list_entry(hcd->non_periodic_qh_ptr, dwc_otg_qh_t, qh_list_entry); + status = queue_transaction(hcd, qh->channel, tx_status.b.nptxfspcavail); if (status > 0) { @@ -2342,16 +2435,16 @@ /* Advance to next QH, skipping start-of-list entry. */ - _hcd->non_periodic_qh_ptr = _hcd->non_periodic_qh_ptr->next; - if (_hcd->non_periodic_qh_ptr == &_hcd->non_periodic_sched_active) { - _hcd->non_periodic_qh_ptr = _hcd->non_periodic_qh_ptr->next; - } - - } while (_hcd->non_periodic_qh_ptr != orig_qh_ptr); - - if (!_hcd->core_if->dma_enable) { + hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; + if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) { + hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; + } + + } while (hcd->non_periodic_qh_ptr != orig_qh_ptr); + + if (!hcd->core_if->dma_enable) { gintmsk_data_t intr_mask = {.d32 = 0}; intr_mask.b.nptxfempty = 1; -#ifdef DEBUG +#ifdef DEBUG tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts); DWC_DEBUGPL(DBG_HCDV, " NP Tx Req Queue Space Avail (after queue): %d\n", @@ -2389,5 +2482,5 @@ * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled. */ -static void process_periodic_channels(dwc_otg_hcd_t *_hcd) +static void process_periodic_channels(dwc_otg_hcd_t *hcd) { hptxsts_data_t tx_status; @@ -2399,8 +2492,8 @@ dwc_otg_host_global_regs_t *host_regs; - host_regs = _hcd->core_if->host_if->host_global_regs; + host_regs = hcd->core_if->host_if->host_global_regs; DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n"); -#ifdef DEBUG +#ifdef DEBUG tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts); DWC_DEBUGPL(DBG_HCDV, " P Tx Req Queue Space Avail (before queue): %d\n", @@ -2410,6 +2503,6 @@ #endif - qh_ptr = _hcd->periodic_sched_assigned.next; - while (qh_ptr != &_hcd->periodic_sched_assigned) { + qh_ptr = hcd->periodic_sched_assigned.next; + while (qh_ptr != &hcd->periodic_sched_assigned) { tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts); if (tx_status.b.ptxqspcavail == 0) { @@ -2425,11 +2518,11 @@ * the middle of multiple high-bandwidth packets getting queued. */ - if ((!_hcd->core_if->dma_enable) && - (qh->channel->multi_count > 1)) + if (!hcd->core_if->dma_enable && + qh->channel->multi_count > 1) { - _hcd->core_if->queuing_high_bandwidth = 1; - } - - status = queue_transaction(_hcd, qh->channel, tx_status.b.ptxfspcavail); + hcd->core_if->queuing_high_bandwidth = 1; + } + + status = queue_transaction(hcd, qh->channel, tx_status.b.ptxfspcavail); if (status < 0) { no_fifo_space = 1; @@ -2444,7 +2537,6 @@ * high-bandwidth transfers. */ - if (_hcd->core_if->dma_enable || - (status == 0 || - qh->channel->requests == qh->channel->multi_count)) { + if (hcd->core_if->dma_enable || status == 0 || + qh->channel->requests == qh->channel->multi_count) { qh_ptr = qh_ptr->next; /* @@ -2452,18 +2544,18 @@ * the periodic queued schedule. */ - list_move(&qh->qh_list_entry, &_hcd->periodic_sched_queued); + list_move(&qh->qh_list_entry, &hcd->periodic_sched_queued); /* done queuing high bandwidth */ - _hcd->core_if->queuing_high_bandwidth = 0; - } - } - - if (!_hcd->core_if->dma_enable) { + hcd->core_if->queuing_high_bandwidth = 0; + } + } + + if (!hcd->core_if->dma_enable) { dwc_otg_core_global_regs_t *global_regs; gintmsk_data_t intr_mask = {.d32 = 0}; - global_regs = _hcd->core_if->core_global_regs; + global_regs = hcd->core_if->core_global_regs; intr_mask.b.ptxfempty = 1; -#ifdef DEBUG +#ifdef DEBUG tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts); DWC_DEBUGPL(DBG_HCDV, " P Tx Req Queue Space Avail (after queue): %d\n", @@ -2472,5 +2564,5 @@ tx_status.b.ptxfspcavail); #endif - if (!(list_empty(&_hcd->periodic_sched_assigned)) || + if (!list_empty(&hcd->periodic_sched_assigned) || no_queue_space || no_fifo_space) { /* @@ -2492,5 +2584,5 @@ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, 0); } - } + } } @@ -2500,10 +2592,10 @@ * from HCD interrupt handler functions. * - * @param _hcd The HCD state structure. - * @param _tr_type The type(s) of transactions to queue (non-periodic, + * @param hcd The HCD state structure. + * @param tr_type The type(s) of transactions to queue (non-periodic, * periodic, or both). */ -void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t *_hcd, - dwc_otg_transaction_type_e _tr_type) +void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t *hcd, + dwc_otg_transaction_type_e tr_type) { #ifdef DEBUG_SOF @@ -2511,16 +2603,16 @@ #endif /* Process host channels associated with periodic transfers. */ - if ((_tr_type == DWC_OTG_TRANSACTION_PERIODIC || - _tr_type == DWC_OTG_TRANSACTION_ALL) && - !list_empty(&_hcd->periodic_sched_assigned)) { - - process_periodic_channels(_hcd); + if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC || + tr_type == DWC_OTG_TRANSACTION_ALL) && + !list_empty(&hcd->periodic_sched_assigned)) { + + process_periodic_channels(hcd); } /* Process host channels associated with non-periodic transfers. */ - if ((_tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC || - _tr_type == DWC_OTG_TRANSACTION_ALL)) { - if (!list_empty(&_hcd->non_periodic_sched_active)) { - process_non_periodic_channels(_hcd); + if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC || + tr_type == DWC_OTG_TRANSACTION_ALL) { + if (!list_empty(&hcd->non_periodic_sched_active)) { + process_non_periodic_channels(hcd); } else { /* @@ -2530,5 +2622,5 @@ gintmsk_data_t gintmsk = {.d32 = 0}; gintmsk.b.nptxfempty = 1; - dwc_modify_reg32(&_hcd->core_if->core_global_regs->gintmsk, + dwc_modify_reg32(&hcd->core_if->core_global_regs->gintmsk, gintmsk.d32, 0); } @@ -2540,17 +2632,17 @@ * required cleanup of the URB is performed. */ -void dwc_otg_hcd_complete_urb(dwc_otg_hcd_t *_hcd, struct urb *_urb, int _status) +void dwc_otg_hcd_complete_urb(dwc_otg_hcd_t *hcd, struct urb *urb, int status) { #ifdef DEBUG if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { DWC_PRINT("%s: urb %p, device %d, ep %d %s, status=%d\n", - __func__, _urb, usb_pipedevice(_urb->pipe), - usb_pipeendpoint(_urb->pipe), - usb_pipein(_urb->pipe) ? "IN" : "OUT", _status); - if (usb_pipetype(_urb->pipe) == PIPE_ISOCHRONOUS) { + __func__, urb, usb_pipedevice(urb->pipe), + usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe) ? "IN" : "OUT", status); + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { int i; - for (i = 0; i < _urb->number_of_packets; i++) { + for (i = 0; i < urb->number_of_packets; i++) { DWC_PRINT(" ISO Desc %d status: %d\n", - i, _urb->iso_frame_desc[i].status); + i, urb->iso_frame_desc[i].status); } } @@ -2558,7 +2650,11 @@ #endif - _urb->status = _status; - _urb->hcpriv = NULL; - usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(_hcd), _urb); + urb->status = status; + urb->hcpriv = NULL; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) + usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb); +#else + usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, NULL); +#endif } @@ -2566,21 +2662,21 @@ * Returns the Queue Head for an URB. */ -dwc_otg_qh_t *dwc_urb_to_qh(struct urb *_urb) -{ - struct usb_host_endpoint *ep = dwc_urb_to_endpoint(_urb); +dwc_otg_qh_t *dwc_urb_to_qh(struct urb *urb) +{ + struct usb_host_endpoint *ep = dwc_urb_to_endpoint(urb); return (dwc_otg_qh_t *)ep->hcpriv; } #ifdef DEBUG -void dwc_print_setup_data (uint8_t *setup) +void dwc_print_setup_data(uint8_t *setup) { int i; if (CHK_DEBUG_LEVEL(DBG_HCD)){ DWC_PRINT("Setup Data = MSB "); - for (i=7; i>=0; i--) DWC_PRINT ("%02x ", setup[i]); + for (i = 7; i >= 0; i--) DWC_PRINT("%02x ", setup[i]); DWC_PRINT("\n"); - DWC_PRINT(" bmRequestType Tranfer = %s\n", (setup[0]&0x80) ? "Device-to-Host" : "Host-to-Device"); + DWC_PRINT(" bmRequestType Tranfer = %s\n", (setup[0] & 0x80) ? "Device-to-Host" : "Host-to-Device"); DWC_PRINT(" bmRequestType Type = "); - switch ((setup[0]&0x60) >> 5) { + switch ((setup[0] & 0x60) >> 5) { case 0: DWC_PRINT("Standard\n"); break; case 1: DWC_PRINT("Class\n"); break; @@ -2589,5 +2685,5 @@ } DWC_PRINT(" bmRequestType Recipient = "); - switch (setup[0]&0x1f) { + switch (setup[0] & 0x1f) { case 0: DWC_PRINT("Device\n"); break; case 1: DWC_PRINT("Interface\n"); break; @@ -2604,66 +2700,66 @@ #endif -void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t *_hcd) { -#ifdef DEBUG +void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t *hcd) { +#if defined(DEBUG) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) DWC_PRINT("Frame remaining at SOF:\n"); DWC_PRINT(" samples %u, accum %llu, avg %llu\n", - _hcd->frrem_samples, _hcd->frrem_accum, - (_hcd->frrem_samples > 0) ? - _hcd->frrem_accum/_hcd->frrem_samples : 0); + hcd->frrem_samples, hcd->frrem_accum, + (hcd->frrem_samples > 0) ? + hcd->frrem_accum/hcd->frrem_samples : 0); DWC_PRINT("\n"); DWC_PRINT("Frame remaining at start_transfer (uframe 7):\n"); DWC_PRINT(" samples %u, accum %llu, avg %llu\n", - _hcd->core_if->hfnum_7_samples, _hcd->core_if->hfnum_7_frrem_accum, - (_hcd->core_if->hfnum_7_samples > 0) ? - _hcd->core_if->hfnum_7_frrem_accum/_hcd->core_if->hfnum_7_samples : 0); + hcd->core_if->hfnum_7_samples, hcd->core_if->hfnum_7_frrem_accum, + (hcd->core_if->hfnum_7_samples > 0) ? + hcd->core_if->hfnum_7_frrem_accum/hcd->core_if->hfnum_7_samples : 0); DWC_PRINT("Frame remaining at start_transfer (uframe 0):\n"); DWC_PRINT(" samples %u, accum %llu, avg %llu\n", - _hcd->core_if->hfnum_0_samples, _hcd->core_if->hfnum_0_frrem_accum, - (_hcd->core_if->hfnum_0_samples > 0) ? - _hcd->core_if->hfnum_0_frrem_accum/_hcd->core_if->hfnum_0_samples : 0); + hcd->core_if->hfnum_0_samples, hcd->core_if->hfnum_0_frrem_accum, + (hcd->core_if->hfnum_0_samples > 0) ? + hcd->core_if->hfnum_0_frrem_accum/hcd->core_if->hfnum_0_samples : 0); DWC_PRINT("Frame remaining at start_transfer (uframe 1-6):\n"); DWC_PRINT(" samples %u, accum %llu, avg %llu\n", - _hcd->core_if->hfnum_other_samples, _hcd->core_if->hfnum_other_frrem_accum, - (_hcd->core_if->hfnum_other_samples > 0) ? - _hcd->core_if->hfnum_other_frrem_accum/_hcd->core_if->hfnum_other_samples : 0); + hcd->core_if->hfnum_other_samples, hcd->core_if->hfnum_other_frrem_accum, + (hcd->core_if->hfnum_other_samples > 0) ? + hcd->core_if->hfnum_other_frrem_accum/hcd->core_if->hfnum_other_samples : 0); DWC_PRINT("\n"); DWC_PRINT("Frame remaining at sample point A (uframe 7):\n"); DWC_PRINT(" samples %u, accum %llu, avg %llu\n", - _hcd->hfnum_7_samples_a, _hcd->hfnum_7_frrem_accum_a, - (_hcd->hfnum_7_samples_a > 0) ? - _hcd->hfnum_7_frrem_accum_a/_hcd->hfnum_7_samples_a : 0); + hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a, + (hcd->hfnum_7_samples_a > 0) ? + hcd->hfnum_7_frrem_accum_a/hcd->hfnum_7_samples_a : 0); DWC_PRINT("Frame remaining at sample point A (uframe 0):\n"); DWC_PRINT(" samples %u, accum %llu, avg %llu\n", - _hcd->hfnum_0_samples_a, _hcd->hfnum_0_frrem_accum_a, - (_hcd->hfnum_0_samples_a > 0) ? - _hcd->hfnum_0_frrem_accum_a/_hcd->hfnum_0_samples_a : 0); + hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a, + (hcd->hfnum_0_samples_a > 0) ? + hcd->hfnum_0_frrem_accum_a/hcd->hfnum_0_samples_a : 0); DWC_PRINT("Frame remaining at sample point A (uframe 1-6):\n"); DWC_PRINT(" samples %u, accum %llu, avg %llu\n", - _hcd->hfnum_other_samples_a, _hcd->hfnum_other_frrem_accum_a, - (_hcd->hfnum_other_samples_a > 0) ? - _hcd->hfnum_other_frrem_accum_a/_hcd->hfnum_other_samples_a : 0); + hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a, + (hcd->hfnum_other_samples_a > 0) ? + hcd->hfnum_other_frrem_accum_a/hcd->hfnum_other_samples_a : 0); DWC_PRINT("\n"); DWC_PRINT("Frame remaining at sample point B (uframe 7):\n"); DWC_PRINT(" samples %u, accum %llu, avg %llu\n", - _hcd->hfnum_7_samples_b, _hcd->hfnum_7_frrem_accum_b, - (_hcd->hfnum_7_samples_b > 0) ? - _hcd->hfnum_7_frrem_accum_b/_hcd->hfnum_7_samples_b : 0); + hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b, + (hcd->hfnum_7_samples_b > 0) ? + hcd->hfnum_7_frrem_accum_b/hcd->hfnum_7_samples_b : 0); DWC_PRINT("Frame remaining at sample point B (uframe 0):\n"); DWC_PRINT(" samples %u, accum %llu, avg %llu\n", - _hcd->hfnum_0_samples_b, _hcd->hfnum_0_frrem_accum_b, - (_hcd->hfnum_0_samples_b > 0) ? - _hcd->hfnum_0_frrem_accum_b/_hcd->hfnum_0_samples_b : 0); + hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b, + (hcd->hfnum_0_samples_b > 0) ? + hcd->hfnum_0_frrem_accum_b/hcd->hfnum_0_samples_b : 0); DWC_PRINT("Frame remaining at sample point B (uframe 1-6):\n"); DWC_PRINT(" samples %u, accum %llu, avg %llu\n", - _hcd->hfnum_other_samples_b, _hcd->hfnum_other_frrem_accum_b, - (_hcd->hfnum_other_samples_b > 0) ? - _hcd->hfnum_other_frrem_accum_b/_hcd->hfnum_other_samples_b : 0); -#endif -} - -void dwc_otg_hcd_dump_state(dwc_otg_hcd_t *_hcd) + hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b, + (hcd->hfnum_other_samples_b > 0) ? + hcd->hfnum_other_frrem_accum_b/hcd->hfnum_other_samples_b : 0); +#endif +} + +void dwc_otg_hcd_dump_state(dwc_otg_hcd_t *hcd) { #ifdef DEBUG @@ -2673,5 +2769,5 @@ hptxsts_data_t p_tx_status; - num_channels = _hcd->core_if->core_params->host_channels; + num_channels = hcd->core_if->core_params->host_channels; DWC_PRINT("\n"); DWC_PRINT("************************************************************\n"); @@ -2679,5 +2775,5 @@ DWC_PRINT(" Num channels: %d\n", num_channels); for (i = 0; i < num_channels; i++) { - dwc_hc_t *hc = _hcd->hc_ptr_array[i]; + dwc_hc_t *hc = hcd->hc_ptr_array[i]; DWC_PRINT(" Channel %d:\n", i); DWC_PRINT(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n", @@ -2708,9 +2804,9 @@ hcint_data_t hcint; hcintmsk_data_t hcintmsk; - hfnum.d32 = dwc_read_reg32(&_hcd->core_if->host_if->host_global_regs->hfnum); - hcchar.d32 = dwc_read_reg32(&_hcd->core_if->host_if->hc_regs[i]->hcchar); - hctsiz.d32 = dwc_read_reg32(&_hcd->core_if->host_if->hc_regs[i]->hctsiz); - hcint.d32 = dwc_read_reg32(&_hcd->core_if->host_if->hc_regs[i]->hcint); - hcintmsk.d32 = dwc_read_reg32(&_hcd->core_if->host_if->hc_regs[i]->hcintmsk); + hfnum.d32 = dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hfnum); + hcchar.d32 = dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]->hcchar); + hctsiz.d32 = dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]->hctsiz); + hcint.d32 = dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]->hcint); + hcintmsk.d32 = dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]->hcintmsk); DWC_PRINT(" hfnum: 0x%08x\n", hfnum.d32); DWC_PRINT(" hcchar: 0x%08x\n", hcchar.d32); @@ -2719,5 +2815,5 @@ DWC_PRINT(" hcintmsk: 0x%08x\n", hcintmsk.d32); } - if (hc->xfer_started && (hc->qh != NULL) && (hc->qh->qtd_in_process != NULL)) { + if (hc->xfer_started && hc->qh && hc->qh->qtd_in_process) { dwc_otg_qtd_t *qtd; struct urb *urb; @@ -2726,5 +2822,5 @@ DWC_PRINT(" URB Info:\n"); DWC_PRINT(" qtd: %p, urb: %p\n", qtd, urb); - if (urb != NULL) { + if (urb) { DWC_PRINT(" Dev: %d, EP: %d %s\n", usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe), @@ -2739,16 +2835,16 @@ } } - DWC_PRINT(" non_periodic_channels: %d\n", _hcd->non_periodic_channels); - DWC_PRINT(" periodic_channels: %d\n", _hcd->periodic_channels); - DWC_PRINT(" periodic_usecs: %d\n", _hcd->periodic_usecs); - np_tx_status.d32 = dwc_read_reg32(&_hcd->core_if->core_global_regs->gnptxsts); + DWC_PRINT(" non_periodic_channels: %d\n", hcd->non_periodic_channels); + DWC_PRINT(" periodic_channels: %d\n", hcd->periodic_channels); + DWC_PRINT(" periodic_usecs: %d\n", hcd->periodic_usecs); + np_tx_status.d32 = dwc_read_reg32(&hcd->core_if->core_global_regs->gnptxsts); DWC_PRINT(" NP Tx Req Queue Space Avail: %d\n", np_tx_status.b.nptxqspcavail); DWC_PRINT(" NP Tx FIFO Space Avail: %d\n", np_tx_status.b.nptxfspcavail); - p_tx_status.d32 = dwc_read_reg32(&_hcd->core_if->host_if->host_global_regs->hptxsts); + p_tx_status.d32 = dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hptxsts); DWC_PRINT(" P Tx Req Queue Space Avail: %d\n", p_tx_status.b.ptxqspcavail); DWC_PRINT(" P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail); - dwc_otg_hcd_dump_frrem(_hcd); - dwc_otg_dump_global_registers(_hcd->core_if); - dwc_otg_dump_host_registers(_hcd->core_if); + dwc_otg_hcd_dump_frrem(hcd); + dwc_otg_dump_global_registers(hcd->core_if); + dwc_otg_dump_host_registers(hcd->core_if); DWC_PRINT("************************************************************\n"); DWC_PRINT("\n"); Index: /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_driver.h =================================================================== --- /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_driver.h (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_driver.h (revision 12433) @@ -1,7 +1,7 @@ /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_driver.h $ - * $Revision: 1.1 $ - * $Date: 2007-11-19 05:39:07 $ - * $Change: 791271 $ + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $ + * $Revision: 1.2 $ + * $Date: 2008-11-21 05:39:15 $ + * $Change: 1064918 $ * * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, @@ -32,5 +32,5 @@ * ========================================================================== */ -#if !defined(__DWC_OTG_DRIVER_H__) +#ifndef __DWC_OTG_DRIVER_H__ #define __DWC_OTG_DRIVER_H__ @@ -48,22 +48,21 @@ * manage a single DWC_otg controller. */ -typedef struct dwc_otg_device -{ - /** Base address returned from ioremap() */ - void *base; +typedef struct dwc_otg_device { + /** Base address returned from ioremap() */ + void *base; struct lm_device *lmdev; - /** Pointer to the core interface structure. */ - dwc_otg_core_if_t *core_if; + /** Pointer to the core interface structure. */ + dwc_otg_core_if_t *core_if; - /** Register offset for Diagnostic API.*/ - uint32_t reg_offset; - - /** Pointer to the PCD structure. */ - struct dwc_otg_pcd *pcd; + /** Register offset for Diagnostic API. */ + uint32_t reg_offset; - /** Pointer to the HCD structure. */ - struct dwc_otg_hcd *hcd; + /** Pointer to the PCD structure. */ + struct dwc_otg_pcd *pcd; + + /** Pointer to the HCD structure. */ + struct dwc_otg_hcd *hcd; /** Flag to indicate whether the common IRQ handler is installed. */ Index: /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_pcd_intr.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_pcd_intr.c (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_pcd_intr.c (revision 12433) @@ -1,7 +1,7 @@ /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_pcd_intr.c $ - * $Revision: 1.1 $ - * $Date: 2007-11-19 05:39:07 $ - * $Change: 791271 $ + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $ + * $Revision: 1.2 $ + * $Date: 2008-11-21 05:39:15 $ + * $Change: 1115682 $ * * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, @@ -34,4 +34,6 @@ #include #include +#include + #include "dwc_otg_driver.h" #include "dwc_otg_pcd.h" @@ -41,9 +43,4 @@ /* request functions defined in "dwc_otg_pcd.c" */ -extern void request_done( dwc_otg_pcd_ep_t *_ep, dwc_otg_pcd_request_t *_req, - int _status); -extern void request_nuke( dwc_otg_pcd_ep_t *_ep ); -extern void dwc_otg_pcd_update_otg( dwc_otg_pcd_t *_pcd, - const unsigned _reset ); /** @file @@ -62,11 +59,10 @@ * This function prints the ep0 state for debug purposes. */ -static inline void print_ep0_state( dwc_otg_pcd_t *_pcd ) +static inline void print_ep0_state(dwc_otg_pcd_t *pcd) { #ifdef DEBUG char str[40]; - switch (_pcd->ep0state) - { + switch (pcd->ep0state) { case EP0_DISCONNECT: strcpy(str, "EP0_DISCONNECT"); @@ -81,6 +77,9 @@ strcpy(str, "EP0_OUT_DATA_PHASE"); break; - case EP0_STATUS: - strcpy(str,"EP0_STATUS"); + case EP0_IN_STATUS_PHASE: + strcpy(str,"EP0_IN_STATUS_PHASE"); + break; + case EP0_OUT_STATUS_PHASE: + strcpy(str,"EP0_OUT_STATUS_PHASE"); break; case EP0_STALL: @@ -91,5 +90,5 @@ } - DWC_DEBUGPL(DBG_ANY, "%s(%d)\n", str, _pcd->ep0state); + DWC_DEBUGPL(DBG_ANY, "%s(%d)\n", str, pcd->ep0state); #endif } @@ -98,18 +97,16 @@ * This function returns pointer to in ep struct with number ep_num */ -static inline dwc_otg_pcd_ep_t* get_in_ep( dwc_otg_pcd_t *_pcd, uint32_t ep_num) +static inline dwc_otg_pcd_ep_t* get_in_ep(dwc_otg_pcd_t *pcd, uint32_t ep_num) { int i; - int num_in_eps = GET_CORE_IF(_pcd)->dev_if->num_in_eps; - if(ep_num == 0) - { - return &_pcd->ep0; - } - else - { + int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps; + if(ep_num == 0) { + return &pcd->ep0; + } + else { for(i = 0; i < num_in_eps; ++i) { - if(_pcd->in_ep[i].dwc_ep.num == ep_num) - return &_pcd->in_ep[i]; + if(pcd->in_ep[i].dwc_ep.num == ep_num) + return &pcd->in_ep[i]; } return 0; @@ -119,18 +116,16 @@ * This function returns pointer to out ep struct with number ep_num */ -static inline dwc_otg_pcd_ep_t* get_out_ep( dwc_otg_pcd_t *_pcd, uint32_t ep_num) +static inline dwc_otg_pcd_ep_t* get_out_ep(dwc_otg_pcd_t *pcd, uint32_t ep_num) { int i; - int num_out_eps = GET_CORE_IF(_pcd)->dev_if->num_out_eps; - if(ep_num == 0) - { - return &_pcd->ep0; - } - else - { + int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps; + if(ep_num == 0) { + return &pcd->ep0; + } + else { for(i = 0; i < num_out_eps; ++i) { - if(_pcd->out_ep[i].dwc_ep.num == ep_num) - return &_pcd->out_ep[i]; + if(pcd->out_ep[i].dwc_ep.num == ep_num) + return &pcd->out_ep[i]; } return 0; @@ -141,11 +136,11 @@ * value of the control request. */ -static dwc_otg_pcd_ep_t *get_ep_by_addr (dwc_otg_pcd_t *_pcd, u16 _wIndex) +static dwc_otg_pcd_ep_t *get_ep_by_addr (dwc_otg_pcd_t *pcd, u16 wIndex) { dwc_otg_pcd_ep_t *ep; - if ((_wIndex & USB_ENDPOINT_NUMBER_MASK) == 0) - return &_pcd->ep0; - list_for_each_entry( ep, &_pcd->gadget.ep_list, ep.ep_list) + if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0) + return &pcd->ep0; + list_for_each_entry(ep, &pcd->gadget.ep_list, ep.ep_list) { u8 bEndpointAddress; @@ -153,8 +148,8 @@ if (!ep->desc) continue; + bEndpointAddress = ep->desc->bEndpointAddress; - if ((_wIndex ^ bEndpointAddress) & USB_DIR_IN) - continue; - if ((_wIndex & 0x0f) == (bEndpointAddress & 0x0f)) + if((wIndex & (USB_DIR_IN | USB_ENDPOINT_NUMBER_MASK)) + == (bEndpointAddress & (USB_DIR_IN | USB_ENDPOINT_NUMBER_MASK))) return ep; } @@ -166,26 +161,37 @@ * empty the next request is started. */ -void start_next_request( dwc_otg_pcd_ep_t *_ep ) +void start_next_request(dwc_otg_pcd_ep_t *ep) { dwc_otg_pcd_request_t *req = 0; - - if (!list_empty(&_ep->queue)) - { - req = list_entry(_ep->queue.next, + uint32_t max_transfer = GET_CORE_IF(ep->pcd)->core_params->max_transfer_size; + + if (!list_empty(&ep->queue)) { + req = list_entry(ep->queue.next, dwc_otg_pcd_request_t, queue); /* Setup and start the Transfer */ - _ep->dwc_ep.start_xfer_buff = req->req.buf; - _ep->dwc_ep.xfer_buff = req->req.buf; - _ep->dwc_ep.xfer_len = req->req.length; - _ep->dwc_ep.xfer_count = 0; - _ep->dwc_ep.dma_addr = req->req.dma; - _ep->dwc_ep.sent_zlp = 0; - _ep->dwc_ep.total_len = _ep->dwc_ep.xfer_len; + ep->dwc_ep.dma_addr = req->req.dma; + ep->dwc_ep.start_xfer_buff = req->req.buf; + ep->dwc_ep.xfer_buff = req->req.buf; + ep->dwc_ep.sent_zlp = 0; + ep->dwc_ep.total_len = req->req.length; + ep->dwc_ep.xfer_len = 0; + ep->dwc_ep.xfer_count = 0; + + if(max_transfer > MAX_TRANSFER_SIZE) { + ep->dwc_ep.maxxfer = max_transfer - (max_transfer % ep->dwc_ep.maxpacket); + } else { + ep->dwc_ep.maxxfer = max_transfer; + } + + if(req->req.zero) { + if((ep->dwc_ep.total_len % ep->dwc_ep.maxpacket == 0) + && (ep->dwc_ep.total_len != 0)) { + ep->dwc_ep.sent_zlp = 1; + } - //DWC_ERROR(" -> starting transfer (start_next_req) %s %s\n", - //_ep->ep.name, _ep->dwc_ep.is_in?"IN":"OUT"); + } - dwc_otg_ep_start_transfer( GET_CORE_IF(_ep->pcd), &_ep->dwc_ep ); + dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep); } } @@ -195,11 +201,11 @@ * Interrupt is disabled. */ -int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t *_pcd) -{ - dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd); +int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t *pcd) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); gintsts_data_t gintsts; - //DWC_DEBUGPL(DBG_PCD, "SOF\n"); + DWC_DEBUGPL(DBG_PCD, "SOF\n"); /* Clear interrupt */ @@ -229,7 +235,7 @@ * to the destination buffer */ -int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t *_pcd) -{ - dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd); +int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t *pcd) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; gintmsk_data_t gintmask = {.d32=0}; @@ -244,8 +250,8 @@ /* Disable the Rx Status Queue Level interrupt */ gintmask.b.rxstsqlvl= 1; - dwc_modify_reg32( &global_regs->gintmsk, gintmask.d32, 0); + dwc_modify_reg32(&global_regs->gintmsk, gintmask.d32, 0); /* Get the Status from the top of the FIFO */ - status.d32 = dwc_read_reg32( &global_regs->grxstsp ); + status.d32 = dwc_read_reg32(&global_regs->grxstsp); DWC_DEBUGPL(DBG_PCD, "EP:%d BCnt:%d DPID:%s " @@ -255,9 +261,7 @@ status.b.pktsts, status.b.fn, status.b.fn); /* Get pointer to EP structure */ - ep = get_out_ep(_pcd, status.b.epnum); -// ep = &_pcd->out_ep[ status.b.epnum - 1]; - - switch (status.b.pktsts) - { + ep = get_out_ep(pcd, status.b.epnum); + + switch (status.b.pktsts) { case DWC_DSTS_GOUT_NAK: DWC_DEBUGPL(DBG_PCDV, "Global OUT NAK\n"); @@ -265,10 +269,9 @@ case DWC_STS_DATA_UPDT: DWC_DEBUGPL(DBG_PCDV, "OUT Data Packet\n"); - if (status.b.bcnt && ep->dwc_ep.xfer_buff) - { + if (status.b.bcnt && ep->dwc_ep.xfer_buff) { /** @todo NGS Check for buffer overflow? */ - dwc_otg_read_packet( core_if, - ep->dwc_ep.xfer_buff, - status.b.bcnt); + dwc_otg_read_packet(core_if, + ep->dwc_ep.xfer_buff, + status.b.bcnt); ep->dwc_ep.xfer_count += status.b.bcnt; ep->dwc_ep.xfer_buff += status.b.bcnt; @@ -284,13 +287,13 @@ break; case DWC_DSTS_SETUP_UPDT: - dwc_otg_read_setup_packet( core_if, _pcd->setup_pkt->d32); + dwc_otg_read_setup_packet(core_if, pcd->setup_pkt->d32); #ifdef DEBUG_EP0 DWC_DEBUGPL(DBG_PCD, - "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n", - _pcd->setup_pkt->req.bRequestType, - _pcd->setup_pkt->req.bRequest, - _pcd->setup_pkt->req.wValue, - _pcd->setup_pkt->req.wIndex, - _pcd->setup_pkt->req.wLength); + "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n", + pcd->setup_pkt->req.bRequestType, + pcd->setup_pkt->req.bRequest, + pcd->setup_pkt->req.wValue, + pcd->setup_pkt->req.wIndex, + pcd->setup_pkt->req.wLength); #endif ep->dwc_ep.xfer_count += status.b.bcnt; @@ -298,10 +301,10 @@ default: DWC_DEBUGPL(DBG_PCDV, "Invalid Packet Status (0x%0x)\n", - status.b.pktsts); + status.b.pktsts); break; } /* Enable the Rx Status Queue Level interrupt */ - dwc_modify_reg32( &global_regs->gintmsk, 0, gintmask.d32); + dwc_modify_reg32(&global_regs->gintmsk, 0, gintmask.d32); /* Clear interrupt */ gintsts.d32 = 0; @@ -321,12 +324,12 @@ * are 8 EP Numbers in each of the other possible DTKNQ Registers. * - * @param _core_if Programming view of DWC_otg controller. - * - */ -static inline int get_ep_of_last_in_token(dwc_otg_core_if_t *_core_if) + * @param core_if Programming view of DWC_otg controller. + * + */ +static inline int get_ep_of_last_in_token(dwc_otg_core_if_t *core_if) { dwc_otg_device_global_regs_t *dev_global_regs = - _core_if->dev_if->dev_global_regs; - const uint32_t TOKEN_Q_DEPTH = _core_if->hwcfg2.b.dev_token_q_depth; + core_if->dev_if->dev_global_regs; + const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth; /* Number of Token Queue Registers */ const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8; @@ -346,70 +349,58 @@ in_tkn_epnums[ i ] = dwc_read_reg32(addr); DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i+1, - in_tkn_epnums[i]); - if (addr == &dev_global_regs->dvbusdis) - { + in_tkn_epnums[i]); + if (addr == &dev_global_regs->dvbusdis) { addr = &dev_global_regs->dtknqr3_dthrctl; } - else - { + else { ++addr; } - } - - /* Copy the DTKNQR1 data to the bit field. */ - dtknqr1.d32 = in_tkn_epnums[0]; - /* Get the EP numbers */ - in_tkn_epnums[0] = dtknqr1.b.epnums0_5; - ndx = dtknqr1.b.intknwptr - 1; - - //DWC_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx); - if (ndx == -1) - { - /** @todo Find a simpler way to calculate the max - * queue position.*/ - int cnt = TOKEN_Q_DEPTH; - if (TOKEN_Q_DEPTH <= 6) - { - cnt = TOKEN_Q_DEPTH - 1; - } - else if (TOKEN_Q_DEPTH <= 14) - { - cnt = TOKEN_Q_DEPTH - 7; - } - else if (TOKEN_Q_DEPTH <= 22) - { - cnt = TOKEN_Q_DEPTH - 15; - } - else - { - cnt = TOKEN_Q_DEPTH - 23; - } - epnum = (in_tkn_epnums[ DTKNQ_REG_CNT - 1 ] >> (cnt * 4)) & 0xF; + } + + /* Copy the DTKNQR1 data to the bit field. */ + dtknqr1.d32 = in_tkn_epnums[0]; + /* Get the EP numbers */ + in_tkn_epnums[0] = dtknqr1.b.epnums0_5; + ndx = dtknqr1.b.intknwptr - 1; + + //DWC_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx); + if (ndx == -1) { + /** @todo Find a simpler way to calculate the max + * queue position.*/ + int cnt = TOKEN_Q_DEPTH; + if (TOKEN_Q_DEPTH <= 6) { + cnt = TOKEN_Q_DEPTH - 1; + } + else if (TOKEN_Q_DEPTH <= 14) { + cnt = TOKEN_Q_DEPTH - 7; } - else - { - if (ndx <= 5) - { - epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF; - } - else if (ndx <= 13 ) - { - ndx -= 6; - epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF; - } - else if (ndx <= 21 ) - { - ndx -= 14; - epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF; - } - else if (ndx <= 29 ) - { - ndx -= 22; - epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF; - } - } - //DWC_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum); - return epnum; + else if (TOKEN_Q_DEPTH <= 22) { + cnt = TOKEN_Q_DEPTH - 15; + } + else { + cnt = TOKEN_Q_DEPTH - 23; + } + epnum = (in_tkn_epnums[ DTKNQ_REG_CNT - 1 ] >> (cnt * 4)) & 0xF; + } + else { + if (ndx <= 5) { + epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF; + } + else if (ndx <= 13) { + ndx -= 6; + epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF; + } + else if (ndx <= 21) { + ndx -= 14; + epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF; + } + else if (ndx <= 29) { + ndx -= 22; + epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF; + } + } + //DWC_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum); + return epnum; } @@ -419,7 +410,7 @@ * the non-periodic Tx FIFO. */ -int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t *_pcd) -{ - dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd); +int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t *pcd) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; @@ -435,18 +426,11 @@ /* Get the epnum from the IN Token Learning Queue. */ epnum = get_ep_of_last_in_token(core_if); - ep = get_in_ep(_pcd, epnum); -/* - if(epnum != 0) - ep = &_pcd->in_ep[epnum-1]; - else - ep = &_pcd->ep0; -*/ - DWC_DEBUGPL(DBG_PCD, "NP TxFifo Empty: %s(%d) \n", ep->ep.name, epnum ); - + ep = get_in_ep(pcd, epnum); + + DWC_DEBUGPL(DBG_PCD, "NP TxFifo Empty: %s(%d) \n", ep->ep.name, epnum); ep_regs = core_if->dev_if->in_ep_regs[epnum]; len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; - if (len > ep->dwc_ep.maxpacket) - { + if (len > ep->dwc_ep.maxpacket) { len = ep->dwc_ep.maxpacket; } @@ -456,17 +440,15 @@ /* While there is space in the queue and space in the FIFO and * More data to tranfer, Write packets to the Tx FIFO */ - txstatus.d32 = dwc_read_reg32( &global_regs->gnptxsts ); + txstatus.d32 = dwc_read_reg32(&global_regs->gnptxsts); DWC_DEBUGPL(DBG_PCDV, "b4 GNPTXSTS=0x%08x\n",txstatus.d32); while (txstatus.b.nptxqspcavail > 0 && - txstatus.b.nptxfspcavail > dwords && - ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len) - { + txstatus.b.nptxfspcavail > dwords && + ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len) { /* Write the FIFO */ - dwc_otg_ep_write_packet( core_if, &ep->dwc_ep, 0 ); + dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0); len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; - if (len > ep->dwc_ep.maxpacket) - { + if (len > ep->dwc_ep.maxpacket) { len = ep->dwc_ep.maxpacket; } @@ -478,5 +460,5 @@ DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", - dwc_read_reg32( &global_regs->gnptxsts)); + dwc_read_reg32(&global_regs->gnptxsts)); /* Clear interrupt */ @@ -493,7 +475,7 @@ * apropriate Tx FIFO. */ -static int32_t write_empty_tx_fifo(dwc_otg_pcd_t *_pcd, uint32_t epnum) -{ - dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd); +static int32_t write_empty_tx_fifo(dwc_otg_pcd_t *pcd, uint32_t epnum) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); dwc_otg_dev_if_t* dev_if = core_if->dev_if; dwc_otg_dev_in_ep_regs_t *ep_regs; @@ -503,12 +485,7 @@ int dwords; - ep = get_in_ep(_pcd, epnum); -/* - if(epnum != 0) - ep = &_pcd->in_ep[epnum-1]; - else - ep = &_pcd->ep0; -*/ - DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %s(%d) \n", ep->ep.name, epnum ); + ep = get_in_ep(pcd, epnum); + + DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %s(%d) \n", ep->ep.name, epnum); ep_regs = core_if->dev_if->in_ep_regs[epnum]; @@ -516,6 +493,5 @@ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; - if (len > ep->dwc_ep.maxpacket) - { + if (len > ep->dwc_ep.maxpacket) { len = ep->dwc_ep.maxpacket; } @@ -525,17 +501,15 @@ /* While there is space in the queue and space in the FIFO and * More data to tranfer, Write packets to the Tx FIFO */ - txstatus.d32 = dwc_read_reg32( &dev_if->in_ep_regs[epnum]->dtxfsts); + txstatus.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dtxfsts); DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n",epnum,txstatus.d32); while (txstatus.b.txfspcavail > dwords && - ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len && - ep->dwc_ep.xfer_len != 0) - { + ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len && + ep->dwc_ep.xfer_len != 0) { /* Write the FIFO */ - dwc_otg_ep_write_packet( core_if, &ep->dwc_ep, 0); + dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0); len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; - if (len > ep->dwc_ep.maxpacket) - { + if (len > ep->dwc_ep.maxpacket) { len = ep->dwc_ep.maxpacket; } @@ -553,9 +527,9 @@ /** - * This function is called when the Device is disconnected. It stops + * This function is called when the Device is disconnected. It stops * any active requests and informs the Gadget driver of the * disconnect. */ -void dwc_otg_pcd_stop(dwc_otg_pcd_t *_pcd) +void dwc_otg_pcd_stop(dwc_otg_pcd_t *pcd) { int i, num_in_eps, num_out_eps; @@ -564,51 +538,49 @@ gintmsk_data_t intr_mask = {.d32 = 0}; - num_in_eps = GET_CORE_IF(_pcd)->dev_if->num_in_eps; - num_out_eps = GET_CORE_IF(_pcd)->dev_if->num_out_eps; - - DWC_DEBUGPL(DBG_PCDV, "%s() \n", __func__ ); + num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps; + num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps; + + DWC_DEBUGPL(DBG_PCDV, "%s() \n", __func__); /* don't disconnect drivers more than once */ - if (_pcd->ep0state == EP0_DISCONNECT) - { - DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__ ); + if (pcd->ep0state == EP0_DISCONNECT) { + DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__); return; } - _pcd->ep0state = EP0_DISCONNECT; + pcd->ep0state = EP0_DISCONNECT; /* Reset the OTG state. */ - dwc_otg_pcd_update_otg( _pcd, 1); + dwc_otg_pcd_update_otg(pcd, 1); /* Disable the NP Tx Fifo Empty Interrupt. */ intr_mask.b.nptxfempty = 1; - dwc_modify_reg32(&GET_CORE_IF(_pcd)->core_global_regs->gintmsk, + dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, intr_mask.d32, 0); /* Flush the FIFOs */ /**@todo NGS Flush Periodic FIFOs */ - dwc_otg_flush_tx_fifo( GET_CORE_IF(_pcd), 0); - dwc_otg_flush_rx_fifo( GET_CORE_IF(_pcd) ); + dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), 0x10); + dwc_otg_flush_rx_fifo(GET_CORE_IF(pcd)); /* prevent new request submissions, kill any outstanding requests */ - ep = &_pcd->ep0; - request_nuke(ep); + ep = &pcd->ep0; + dwc_otg_request_nuke(ep); /* prevent new request submissions, kill any outstanding requests */ for (i = 0; i < num_in_eps; i++) { - dwc_otg_pcd_ep_t *ep = &_pcd->in_ep[i]; - request_nuke(ep); + dwc_otg_pcd_ep_t *ep = &pcd->in_ep[i]; + dwc_otg_request_nuke(ep); } /* prevent new request submissions, kill any outstanding requests */ for (i = 0; i < num_out_eps; i++) { - dwc_otg_pcd_ep_t *ep = &_pcd->out_ep[i]; - request_nuke(ep); + dwc_otg_pcd_ep_t *ep = &pcd->out_ep[i]; + dwc_otg_request_nuke(ep); } /* report disconnect; the driver is already quiesced */ - if (_pcd->driver && _pcd->driver->disconnect) - { - SPIN_UNLOCK(&_pcd->lock); - _pcd->driver->disconnect(&_pcd->gadget); - SPIN_LOCK(&_pcd->lock); + if (pcd->driver && pcd->driver->disconnect) { + SPIN_UNLOCK(&pcd->lock); + pcd->driver->disconnect(&pcd->gadget); + SPIN_LOCK(&pcd->lock); } } @@ -617,5 +589,5 @@ * This interrupt indicates that ... */ -int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t *_pcd) +int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t *pcd) { gintmsk_data_t intr_mask = { .d32 = 0}; @@ -624,11 +596,11 @@ DWC_PRINT("INTERRUPT Handler not implemented for %s\n", "i2cintr"); intr_mask.b.i2cintr = 1; - dwc_modify_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintmsk, - intr_mask.d32, 0 ); + dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, + intr_mask.d32, 0); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.i2cintr = 1; - dwc_write_reg32 (&GET_CORE_IF(_pcd)->core_global_regs->gintsts, + dwc_write_reg32 (&GET_CORE_IF(pcd)->core_global_regs->gintsts, gintsts.d32); return 1; @@ -639,5 +611,5 @@ * This interrupt indicates that ... */ -int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t *_pcd) +int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t *pcd) { gintsts_data_t gintsts; @@ -648,6 +620,6 @@ gintsts.d32 = 0; gintsts.b.erlysuspend = 1; - dwc_write_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintsts, - gintsts.d32); + dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, + gintsts.d32); return 1; } @@ -667,11 +639,13 @@ * store any setup packets received * - * @param _core_if Programming view of DWC_otg controller. - * @param _pcd Programming view of the PCD. - */ -static inline void ep0_out_start( dwc_otg_core_if_t *_core_if, dwc_otg_pcd_t *_pcd ) -{ - dwc_otg_dev_if_t *dev_if = _core_if->dev_if; + * @param core_if Programming view of DWC_otg controller. + * @param pcd Programming view of the PCD. + */ +static inline void ep0_out_start(dwc_otg_core_if_t *core_if, dwc_otg_pcd_t *pcd) +{ + dwc_otg_dev_if_t *dev_if = core_if->dev_if; deptsiz0_data_t doeptsize0 = { .d32 = 0}; + dwc_otg_dma_desc_t* dma_desc; + depctl_data_t doepctl = { .d32 = 0 }; #ifdef VERBOSE @@ -684,28 +658,47 @@ doeptsize0.b.xfersize = 8*3; - dwc_write_reg32( &dev_if->out_ep_regs[0]->doeptsiz, - doeptsize0.d32 ); - - if (_core_if->dma_enable) - { - depctl_data_t doepctl = { .d32 = 0 }; - /** @todo dma needs to handle multiple setup packets (up to 3) */ - dwc_write_reg32(&dev_if->out_ep_regs[0]->doepdma, - _pcd->setup_pkt_dma_handle); - // EP enable - doepctl.d32 = dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl); - doepctl.b.epena = 1; - - doepctl.d32 = 0x80008000; - dwc_write_reg32(&dev_if->out_ep_regs[0]->doepctl, - doepctl.d32); - } + + if (core_if->dma_enable) { + if (!core_if->dma_desc_enable) { + /** put here as for Hermes mode deptisz register should not be written */ + dwc_write_reg32(&dev_if->out_ep_regs[0]->doeptsiz, + doeptsize0.d32); + + /** @todo dma needs to handle multiple setup packets (up to 3) */ + dwc_write_reg32(&dev_if->out_ep_regs[0]->doepdma, + pcd->setup_pkt_dma_handle); + } else { + dev_if->setup_desc_index = (dev_if->setup_desc_index + 1) & 1; + dma_desc = dev_if->setup_desc_addr[dev_if->setup_desc_index]; + + /** DMA Descriptor Setup */ + dma_desc->status.b.bs = BS_HOST_BUSY; + dma_desc->status.b.l = 1; + dma_desc->status.b.ioc = 1; + dma_desc->status.b.bytes = pcd->ep0.dwc_ep.maxpacket; + dma_desc->buf = pcd->setup_pkt_dma_handle; + dma_desc->status.b.bs = BS_HOST_READY; + + /** DOEPDMA0 Register write */ + dwc_write_reg32(&dev_if->out_ep_regs[0]->doepdma, dev_if->dma_setup_desc_addr[dev_if->setup_desc_index]); + } + + } else { + /** put here as for Hermes mode deptisz register should not be written */ + dwc_write_reg32(&dev_if->out_ep_regs[0]->doeptsiz, + doeptsize0.d32); + } + + /** DOEPCTL0 Register write */ + doepctl.b.epena = 1; + doepctl.b.cnak = 1; + dwc_write_reg32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); + #ifdef VERBOSE - DWC_DEBUGPL(DBG_PCDV,"doepctl0=%0x\n", - dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl)); - DWC_DEBUGPL(DBG_PCDV,"diepctl0=%0x\n", - dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl)); + DWC_DEBUGPL(DBG_PCDV,"doepctl0=%0x\n", + dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl)); + DWC_DEBUGPL(DBG_PCDV,"diepctl0=%0x\n", + dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl)); #endif - } @@ -734,12 +727,14 @@ * the control 0 OUT endpoint is done, for receiving SETUP packets. */ -int32_t dwc_otg_pcd_handle_usb_reset_intr( dwc_otg_pcd_t * _pcd) -{ - dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd); +int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); dwc_otg_dev_if_t *dev_if = core_if->dev_if; depctl_data_t doepctl = { .d32 = 0}; + daint_data_t daintmsk = { .d32 = 0}; doepmsk_data_t doepmsk = { .d32 = 0}; diepmsk_data_t diepmsk = { .d32 = 0}; + dcfg_data_t dcfg = { .d32=0 }; grstctl_t resetctl = { .d32=0 }; @@ -749,12 +744,24 @@ DWC_PRINT("USB RESET\n"); +#ifdef DWC_EN_ISOC + for(i = 1;i < 16; ++i) + { + dwc_otg_pcd_ep_t *ep; + dwc_ep_t *dwc_ep; + ep = get_in_ep(pcd,i); + if(ep != 0){ + dwc_ep = &ep->dwc_ep; + dwc_ep->next_frame = 0xffffffff; + } + } +#endif /* DWC_EN_ISOC */ /* reset the HNP settings */ - dwc_otg_pcd_update_otg( _pcd, 1); + dwc_otg_pcd_update_otg(pcd, 1); /* Clear the Remote Wakeup Signalling */ dctl.b.rmtwkupsig = 1; - dwc_modify_reg32( &core_if->dev_if->dev_global_regs->dctl, - dctl.d32, 0 ); + dwc_modify_reg32(&core_if->dev_if->dev_global_regs->dctl, + dctl.d32, 0); /* Set NAK for all OUT EPs */ @@ -762,37 +769,96 @@ for (i=0; i <= dev_if->num_out_eps; i++) { - dwc_write_reg32( &dev_if->out_ep_regs[i]->doepctl, - doepctl.d32 ); + dwc_write_reg32(&dev_if->out_ep_regs[i]->doepctl, + doepctl.d32); } /* Flush the NP Tx FIFO */ - dwc_otg_flush_tx_fifo( core_if, 0 ); + dwc_otg_flush_tx_fifo(core_if, 0x10); /* Flush the Learning Queue */ resetctl.b.intknqflsh = 1; - dwc_write_reg32( &core_if->core_global_regs->grstctl, resetctl.d32); - - daintmsk.b.inep0 = 1; - daintmsk.b.outep0 = 1; - dwc_write_reg32( &dev_if->dev_global_regs->daintmsk, daintmsk.d32 ); - - doepmsk.b.setup = 1; - doepmsk.b.xfercompl = 1; - doepmsk.b.ahberr = 1; - doepmsk.b.epdisabled = 1; - dwc_write_reg32( &dev_if->dev_global_regs->doepmsk, doepmsk.d32 ); - - diepmsk.b.xfercompl = 1; - diepmsk.b.timeout = 1; - diepmsk.b.epdisabled = 1; - diepmsk.b.ahberr = 1; - diepmsk.b.intknepmis = 1; - dwc_write_reg32( &dev_if->dev_global_regs->diepmsk, diepmsk.d32 ); + dwc_write_reg32(&core_if->core_global_regs->grstctl, resetctl.d32); + + if(core_if->multiproc_int_enable) { + daintmsk.b.inep0 = 1; + daintmsk.b.outep0 = 1; + dwc_write_reg32(&dev_if->dev_global_regs->deachintmsk, daintmsk.d32); + + doepmsk.b.setup = 1; + doepmsk.b.xfercompl = 1; + doepmsk.b.ahberr = 1; + doepmsk.b.epdisabled = 1; + + if(core_if->dma_desc_enable) { + doepmsk.b.stsphsercvd = 1; + doepmsk.b.bna = 1; + } +/* + doepmsk.b.babble = 1; + doepmsk.b.nyet = 1; + + if(core_if->dma_enable) { + doepmsk.b.nak = 1; + } +*/ + dwc_write_reg32(&dev_if->dev_global_regs->doepeachintmsk[0], doepmsk.d32); + + diepmsk.b.xfercompl = 1; + diepmsk.b.timeout = 1; + diepmsk.b.epdisabled = 1; + diepmsk.b.ahberr = 1; + diepmsk.b.intknepmis = 1; + + if(core_if->dma_desc_enable) { + diepmsk.b.bna = 1; + } +/* + if(core_if->dma_enable) { + diepmsk.b.nak = 1; + } +*/ + dwc_write_reg32(&dev_if->dev_global_regs->diepeachintmsk[0], diepmsk.d32); + } else{ + daintmsk.b.inep0 = 1; + daintmsk.b.outep0 = 1; + dwc_write_reg32(&dev_if->dev_global_regs->daintmsk, daintmsk.d32); + + doepmsk.b.setup = 1; + doepmsk.b.xfercompl = 1; + doepmsk.b.ahberr = 1; + doepmsk.b.epdisabled = 1; + + if(core_if->dma_desc_enable) { + doepmsk.b.stsphsercvd = 1; + doepmsk.b.bna = 1; + } +/* + doepmsk.b.babble = 1; + doepmsk.b.nyet = 1; + doepmsk.b.nak = 1; +*/ + dwc_write_reg32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32); + + diepmsk.b.xfercompl = 1; + diepmsk.b.timeout = 1; + diepmsk.b.epdisabled = 1; + diepmsk.b.ahberr = 1; + diepmsk.b.intknepmis = 1; + + if(core_if->dma_desc_enable) { + diepmsk.b.bna = 1; + } + +// diepmsk.b.nak = 1; + + dwc_write_reg32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32); + } + /* Reset Device Address */ - dcfg.d32 = dwc_read_reg32( &dev_if->dev_global_regs->dcfg); + dcfg.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dcfg); dcfg.b.devaddr = 0; - dwc_write_reg32( &dev_if->dev_global_regs->dcfg, dcfg.d32); + dwc_write_reg32(&dev_if->dev_global_regs->dcfg, dcfg.d32); /* setup EP0 to receive SETUP packets */ - ep0_out_start( core_if, _pcd ); + ep0_out_start(core_if, pcd); /* Clear interrupt */ @@ -808,14 +874,13 @@ * to USB speed constant. * - * @param _core_if Programming view of DWC_otg controller. - */ -static int get_device_speed( dwc_otg_core_if_t *_core_if ) + * @param core_if Programming view of DWC_otg controller. + */ +static int get_device_speed(dwc_otg_core_if_t *core_if) { dsts_data_t dsts; enum usb_device_speed speed = USB_SPEED_UNKNOWN; - dsts.d32 = dwc_read_reg32(&_core_if->dev_if->dev_global_regs->dsts); - - switch (dsts.b.enumspd) - { + dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); + + switch (dsts.b.enumspd) { case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: speed = USB_SPEED_HIGH; @@ -839,93 +904,74 @@ * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate. */ -int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t *_pcd) -{ - dwc_otg_pcd_ep_t *ep0 = &_pcd->ep0; +int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t *pcd) +{ + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; gintsts_data_t gintsts; gusbcfg_data_t gusbcfg; dwc_otg_core_global_regs_t *global_regs = - GET_CORE_IF(_pcd)->core_global_regs; - uint32_t gsnpsid = global_regs->gsnpsid; + GET_CORE_IF(pcd)->core_global_regs; uint8_t utmi16b, utmi8b; DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n"); - if(gsnpsid >= (uint32_t)0x4f54260a) - { - utmi16b = 5; + if (GET_CORE_IF(pcd)->snpsid >= 0x4F54260A) { + utmi16b = 6; utmi8b = 9; - } - else - { + } else { utmi16b = 4; utmi8b = 8; } - dwc_otg_ep0_activate( GET_CORE_IF(_pcd), &ep0->dwc_ep ); + dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep); #ifdef DEBUG_EP0 - print_ep0_state(_pcd); + print_ep0_state(pcd); #endif - if (_pcd->ep0state == EP0_DISCONNECT) - { - _pcd->ep0state = EP0_IDLE; + if (pcd->ep0state == EP0_DISCONNECT) { + pcd->ep0state = EP0_IDLE; } - else if (_pcd->ep0state == EP0_STALL) - { - _pcd->ep0state = EP0_IDLE; - } - - _pcd->ep0state = EP0_IDLE; + else if (pcd->ep0state == EP0_STALL) { + pcd->ep0state = EP0_IDLE; + } + + pcd->ep0state = EP0_IDLE; ep0->stopped = 0; - _pcd->gadget.speed = get_device_speed(GET_CORE_IF(_pcd)); + pcd->gadget.speed = get_device_speed(GET_CORE_IF(pcd)); /* Set USB turnaround time based on device speed and PHY interface. */ gusbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); - if (_pcd->gadget.speed == USB_SPEED_HIGH) - { - if (GET_CORE_IF(_pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_ULPI) - { + if (pcd->gadget.speed == USB_SPEED_HIGH) { + if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_ULPI) { /* ULPI interface */ gusbcfg.b.usbtrdtim = 9; } - if (GET_CORE_IF(_pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_UTMI) - { -///// + if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_UTMI) { /* UTMI+ interface */ - if (GET_CORE_IF(_pcd)->hwcfg4.b.utmi_phy_data_width == 0) - { + if (GET_CORE_IF(pcd)->hwcfg4.b.utmi_phy_data_width == 0) { gusbcfg.b.usbtrdtim = utmi8b; } - else if (GET_CORE_IF(_pcd)->hwcfg4.b.utmi_phy_data_width == 1) - { + else if (GET_CORE_IF(pcd)->hwcfg4.b.utmi_phy_data_width == 1) { gusbcfg.b.usbtrdtim = utmi16b; } - else if (GET_CORE_IF(_pcd)->core_params->phy_utmi_width == 8) - { + else if (GET_CORE_IF(pcd)->core_params->phy_utmi_width == 8) { gusbcfg.b.usbtrdtim = utmi8b; } - else - { + else { gusbcfg.b.usbtrdtim = utmi16b; } } - if (GET_CORE_IF(_pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) - { + if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) { /* UTMI+ OR ULPI interface */ - if (gusbcfg.b.ulpi_utmi_sel == 1) - { + if (gusbcfg.b.ulpi_utmi_sel == 1) { /* ULPI interface */ gusbcfg.b.usbtrdtim = 9; } - else - { + else { /* UTMI+ interface */ - if (GET_CORE_IF(_pcd)->core_params->phy_utmi_width == 16) - { + if (GET_CORE_IF(pcd)->core_params->phy_utmi_width == 16) { gusbcfg.b.usbtrdtim = utmi16b; } - else - { + else { gusbcfg.b.usbtrdtim = utmi8b; } @@ -933,6 +979,5 @@ } } - else - { + else { /* Full or low speed */ gusbcfg.b.usbtrdtim = 9; @@ -943,6 +988,6 @@ gintsts.d32 = 0; gintsts.b.enumdone = 1; - dwc_write_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintsts, - gintsts.d32 ); + dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, + gintsts.d32); return 1; } @@ -953,5 +998,5 @@ * read all the data from the Rx FIFO. */ -int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t *_pcd ) +int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t *pcd) { gintmsk_data_t intr_mask = { .d32 = 0}; @@ -962,12 +1007,13 @@ intr_mask.b.isooutdrop = 1; - dwc_modify_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintmsk, - intr_mask.d32, 0 ); + dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, + intr_mask.d32, 0); /* Clear interrupt */ + gintsts.d32 = 0; gintsts.b.isooutdrop = 1; - dwc_write_reg32 (&GET_CORE_IF(_pcd)->core_global_regs->gintsts, - gintsts.d32); + dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, + gintsts.d32); return 1; @@ -979,20 +1025,18 @@ * the next frame, load the packets into the EP periodic Tx FIFO. */ -int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t *_pcd ) +int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t *pcd) { gintmsk_data_t intr_mask = { .d32 = 0}; gintsts_data_t gintsts; - DWC_PRINT("INTERRUPT Handler not implemented for %s\n", - "EOP"); + DWC_PRINT("INTERRUPT Handler not implemented for %s\n", "EOP"); intr_mask.b.eopframe = 1; - dwc_modify_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintmsk, - intr_mask.d32, 0 ); + dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, + intr_mask.d32, 0); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.eopframe = 1; - dwc_write_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintsts, - gintsts.d32); + dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, gintsts.d32); return 1; @@ -1008,13 +1052,13 @@ * Queue. */ -int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_core_if_t *_core_if) +int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_core_if_t *core_if) { gintsts_data_t gintsts; - DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _core_if); + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.epmismatch = 1; - dwc_write_reg32 (&_core_if->core_global_regs->gintsts, gintsts.d32); + dwc_write_reg32 (&core_if->core_global_regs->gintsts, gintsts.d32); return 1; @@ -1024,16 +1068,16 @@ * This funcion stalls EP0. */ -static inline void ep0_do_stall( dwc_otg_pcd_t *_pcd, const int err_val ) -{ - dwc_otg_pcd_ep_t *ep0 = &_pcd->ep0; - struct usb_ctrlrequest *ctrl = &_pcd->setup_pkt->req; +static inline void ep0_do_stall(dwc_otg_pcd_t *pcd, const int err_val) +{ + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; + struct usb_ctrlrequest *ctrl = &pcd->setup_pkt->req; DWC_WARN("req %02x.%02x protocol STALL; err %d\n", ctrl->bRequestType, ctrl->bRequest, err_val); ep0->dwc_ep.is_in = 1; - dwc_otg_ep_set_stall( _pcd->otg_dev->core_if, &ep0->dwc_ep ); - _pcd->ep0.stopped = 1; - _pcd->ep0state = EP0_IDLE; - ep0_out_start( GET_CORE_IF(_pcd), _pcd ); + dwc_otg_ep_set_stall(pcd->otg_dev->core_if, &ep0->dwc_ep); + pcd->ep0.stopped = 1; + pcd->ep0state = EP0_IDLE; + ep0_out_start(GET_CORE_IF(pcd), pcd); } @@ -1041,16 +1085,14 @@ * This functions delegates the setup command to the gadget driver. */ -static inline void do_gadget_setup( dwc_otg_pcd_t *_pcd, - struct usb_ctrlrequest * _ctrl) +static inline void do_gadget_setup(dwc_otg_pcd_t *pcd, + struct usb_ctrlrequest * ctrl) { int ret = 0; - if (_pcd->driver && _pcd->driver->setup) - { - SPIN_UNLOCK(&_pcd->lock); - ret = _pcd->driver->setup(&_pcd->gadget, _ctrl); - SPIN_LOCK(&_pcd->lock); - if (ret < 0) - { - ep0_do_stall( _pcd, ret ); + if (pcd->driver && pcd->driver->setup) { + SPIN_UNLOCK(&pcd->lock); + ret = pcd->driver->setup(&pcd->gadget, ctrl); + SPIN_LOCK(&pcd->lock); + if (ret < 0) { + ep0_do_stall(pcd, ret); } @@ -1067,7 +1109,6 @@ */ - if (ret == 256 + 999) - { - _pcd->request_config = 1; + if (ret == 256 + 999) { + pcd->request_config = 1; } } @@ -1078,13 +1119,12 @@ * of a 2 stage control transfer. */ -static inline void do_setup_in_status_phase( dwc_otg_pcd_t *_pcd) -{ - dwc_otg_pcd_ep_t *ep0 = &_pcd->ep0; - if (_pcd->ep0state == EP0_STALL) - { +static inline void do_setup_in_status_phase(dwc_otg_pcd_t *pcd) +{ + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; + if (pcd->ep0state == EP0_STALL) { return; } - _pcd->ep0state = EP0_STATUS; + pcd->ep0state = EP0_IN_STATUS_PHASE; /* Prepare for more SETUP Packets */ @@ -1093,11 +1133,9 @@ ep0->dwc_ep.xfer_count = 0; ep0->dwc_ep.is_in = 1; - ep0->dwc_ep.dma_addr = _pcd->setup_pkt_dma_handle; - - dwc_otg_ep0_start_transfer( GET_CORE_IF(_pcd), &ep0->dwc_ep ); + ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle; + dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep); /* Prepare for more SETUP Packets */ - ep0_out_start( GET_CORE_IF(_pcd), _pcd ); - +// if(GET_CORE_IF(pcd)->dma_enable == 0) ep0_out_start(GET_CORE_IF(pcd), pcd); } @@ -1106,28 +1144,24 @@ * of a 2 stage control transfer. */ -static inline void do_setup_out_status_phase( dwc_otg_pcd_t *_pcd) -{ - dwc_otg_pcd_ep_t *ep0 = &_pcd->ep0; - if (_pcd->ep0state == EP0_STALL) - { +static inline void do_setup_out_status_phase(dwc_otg_pcd_t *pcd) +{ + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; + if (pcd->ep0state == EP0_STALL) { DWC_DEBUGPL(DBG_PCD, "EP0 STALLED\n"); return; } - _pcd->ep0state = EP0_STATUS; - - /* Prepare for more SETUP Packets */ - //ep0_out_start( GET_CORE_IF(_pcd), _pcd ); - + pcd->ep0state = EP0_OUT_STATUS_PHASE; + DWC_DEBUGPL(DBG_PCD, "EP0 OUT ZLP\n"); ep0->dwc_ep.xfer_len = 0; ep0->dwc_ep.xfer_count = 0; ep0->dwc_ep.is_in = 0; - //ep0->dwc_ep.dma_addr = 0xffffffff; - ep0->dwc_ep.dma_addr = _pcd->setup_pkt_dma_handle; - dwc_otg_ep0_start_transfer( GET_CORE_IF(_pcd), &ep0->dwc_ep ); + ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle; + dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep); /* Prepare for more SETUP Packets */ - ep0_out_start( GET_CORE_IF(_pcd), _pcd ); - + if(GET_CORE_IF(pcd)->dma_enable == 0) { + ep0_out_start(GET_CORE_IF(pcd), pcd); + } } @@ -1136,14 +1170,13 @@ * transfer. */ -static inline void pcd_clear_halt( dwc_otg_pcd_t *_pcd, dwc_otg_pcd_ep_t *_ep ) -{ - if(_ep->dwc_ep.stall_clear_flag == 0) - dwc_otg_ep_clear_stall( GET_CORE_IF(_pcd), &_ep->dwc_ep ); +static inline void pcd_clear_halt(dwc_otg_pcd_t *pcd, dwc_otg_pcd_ep_t *ep) +{ + if(ep->dwc_ep.stall_clear_flag == 0) + dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep); /* Reactive the EP */ - dwc_otg_ep_activate( GET_CORE_IF(_pcd), &_ep->dwc_ep ); - if (_ep->stopped) - { - _ep->stopped = 0; + dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep); + if (ep->stopped) { + ep->stopped = 0; /* If there is a request in the EP queue start it */ @@ -1158,24 +1191,9 @@ * ever uses more than one endpoint at once */ - if (GET_CORE_IF(_pcd)->dma_enable) - { - _ep->queue_sof = 1; - tasklet_schedule (_pcd->start_xfer_tasklet); - } - else - { -#if 0 - _ep->queue_sof = 1; - DWC_ERROR("tasklet schedule\n"); - tasklet_schedule (_pcd->start_xfer_tasklet); - if (GET_CORE_IF(_pcd)->core_params->opt) - { - start_next_request( _ep ); - } -#endif - } + ep->queue_sof = 1; + tasklet_schedule (pcd->start_xfer_tasklet); } /* Start Control Status Phase */ - do_setup_in_status_phase( _pcd ); + do_setup_in_status_phase(pcd); } @@ -1191,8 +1209,8 @@ * */ -static void do_test_mode( unsigned long _data ) +static void do_test_mode(unsigned long data) { dctl_data_t dctl; - dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *)_data; + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *)data; dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); int test_mode = pcd->test_mode; @@ -1202,6 +1220,5 @@ dctl.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dctl); - switch (test_mode) - { + switch (test_mode) { case 1: // TEST_J dctl.b.tstctl = 1; @@ -1224,18 +1241,62 @@ break; } - dwc_write_reg32(&core_if->dev_if->dev_global_regs->dctl, - dctl.d32); -} - - + dwc_write_reg32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); +} + +/** + * This function process the GET_STATUS Setup Commands. + */ +static inline void do_get_status(dwc_otg_pcd_t *pcd) +{ + struct usb_ctrlrequest ctrl = pcd->setup_pkt->req; + dwc_otg_pcd_ep_t *ep; + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; + uint16_t *status = pcd->status_buf; + +#ifdef DEBUG_EP0 + DWC_DEBUGPL(DBG_PCD, + "GET_STATUS %02x.%02x v%04x i%04x l%04x\n", + ctrl.bRequestType, ctrl.bRequest, + ctrl.wValue, ctrl.wIndex, ctrl.wLength); +#endif + + switch (ctrl.bRequestType & USB_RECIP_MASK) { + case USB_RECIP_DEVICE: + *status = 0x1; /* Self powered */ + *status |= pcd->remote_wakeup_enable << 1; + break; + + case USB_RECIP_INTERFACE: + *status = 0; + break; + + case USB_RECIP_ENDPOINT: + ep = get_ep_by_addr(pcd, ctrl.wIndex); + if (ep == 0 || ctrl.wLength > 2) { + ep0_do_stall(pcd, -EOPNOTSUPP); + return; + } + /** @todo check for EP stall */ + *status = ep->stopped; + break; + } + pcd->ep0_pending = 1; + ep0->dwc_ep.start_xfer_buff = (uint8_t *)status; + ep0->dwc_ep.xfer_buff = (uint8_t *)status; + ep0->dwc_ep.dma_addr = pcd->status_buf_dma_handle; + ep0->dwc_ep.xfer_len = 2; + ep0->dwc_ep.xfer_count = 0; + ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len; + dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep); +} /** * This function process the SET_FEATURE Setup Commands. */ -static inline void do_set_feature( dwc_otg_pcd_t *_pcd ) -{ - dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd); +static inline void do_set_feature(dwc_otg_pcd_t *pcd) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; - struct usb_ctrlrequest ctrl = _pcd->setup_pkt->req; + struct usb_ctrlrequest ctrl = pcd->setup_pkt->req; dwc_otg_pcd_ep_t *ep = 0; int32_t otg_cap_param = core_if->core_params->otg_cap; @@ -1243,16 +1304,14 @@ DWC_DEBUGPL(DBG_PCD, "SET_FEATURE:%02x.%02x v%04x i%04x l%04x\n", - ctrl.bRequestType, ctrl.bRequest, - ctrl.wValue, ctrl.wIndex, ctrl.wLength); + ctrl.bRequestType, ctrl.bRequest, + ctrl.wValue, ctrl.wIndex, ctrl.wLength); DWC_DEBUGPL(DBG_PCD,"otg_cap=%d\n", otg_cap_param); - switch (ctrl.bRequestType & USB_RECIP_MASK) - { + switch (ctrl.bRequestType & USB_RECIP_MASK) { case USB_RECIP_DEVICE: - switch (ctrl.wValue) - { + switch (ctrl.wValue) { case USB_DEVICE_REMOTE_WAKEUP: - _pcd->remote_wakeup_enable = 1; + pcd->remote_wakeup_enable = 1; break; @@ -1265,11 +1324,11 @@ * tasklet struct was put into the PCD * struct! */ - _pcd->test_mode_tasklet.next = 0; - _pcd->test_mode_tasklet.state = 0; - atomic_set( &_pcd->test_mode_tasklet.count, 0); - _pcd->test_mode_tasklet.func = do_test_mode; - _pcd->test_mode_tasklet.data = (unsigned long)_pcd; - _pcd->test_mode = ctrl.wIndex >> 8; - tasklet_schedule(&_pcd->test_mode_tasklet); + pcd->test_mode_tasklet.next = 0; + pcd->test_mode_tasklet.state = 0; + atomic_set(&pcd->test_mode_tasklet.count, 0); + pcd->test_mode_tasklet.func = do_test_mode; + pcd->test_mode_tasklet.data = (unsigned long)pcd; + pcd->test_mode = ctrl.wIndex >> 8; + tasklet_schedule(&pcd->test_mode_tasklet); break; @@ -1278,8 +1337,7 @@ /* dev may initiate HNP */ - if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) - { - _pcd->b_hnp_enable = 1; - dwc_otg_pcd_update_otg( _pcd, 0 ); + if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { + pcd->b_hnp_enable = 1; + dwc_otg_pcd_update_otg(pcd, 0); DWC_DEBUGPL(DBG_PCD, "Request B HNP\n"); /**@todo Is the gotgctl.devhnpen cleared @@ -1287,9 +1345,8 @@ gotgctl.b.devhnpen = 1; gotgctl.b.hnpreq = 1; - dwc_write_reg32( &global_regs->gotgctl, gotgctl.d32 ); - } - else - { - ep0_do_stall( _pcd, -EOPNOTSUPP); + dwc_write_reg32(&global_regs->gotgctl, gotgctl.d32); + } + else { + ep0_do_stall(pcd, -EOPNOTSUPP); } break; @@ -1298,12 +1355,10 @@ /* RH port supports HNP */ DWC_DEBUGPL(DBG_PCDV, "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n"); - if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) - { - _pcd->a_hnp_support = 1; - dwc_otg_pcd_update_otg( _pcd, 0 ); + if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { + pcd->a_hnp_support = 1; + dwc_otg_pcd_update_otg(pcd, 0); } - else - { - ep0_do_stall( _pcd, -EOPNOTSUPP); + else { + ep0_do_stall(pcd, -EOPNOTSUPP); } break; @@ -1312,35 +1367,31 @@ /* other RH port does */ DWC_DEBUGPL(DBG_PCDV, "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n"); - if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) - { - _pcd->a_alt_hnp_support = 1; - dwc_otg_pcd_update_otg( _pcd, 0 ); + if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { + pcd->a_alt_hnp_support = 1; + dwc_otg_pcd_update_otg(pcd, 0); } - else - { - ep0_do_stall( _pcd, -EOPNOTSUPP); + else { + ep0_do_stall(pcd, -EOPNOTSUPP); } break; } - do_setup_in_status_phase( _pcd ); + do_setup_in_status_phase(pcd); break; case USB_RECIP_INTERFACE: - do_gadget_setup(_pcd, &ctrl ); + do_gadget_setup(pcd, &ctrl); break; case USB_RECIP_ENDPOINT: - if (ctrl.wValue == USB_ENDPOINT_HALT) - { - ep = get_ep_by_addr(_pcd, ctrl.wIndex); - if (ep == 0) - { - ep0_do_stall(_pcd, -EOPNOTSUPP); + if (ctrl.wValue == USB_ENDPOINT_HALT) { + ep = get_ep_by_addr(pcd, ctrl.wIndex); + if (ep == 0) { + ep0_do_stall(pcd, -EOPNOTSUPP); return; } ep->stopped = 1; - dwc_otg_ep_set_stall( core_if, &ep->dwc_ep ); - } - do_setup_in_status_phase( _pcd ); + dwc_otg_ep_set_stall(core_if, &ep->dwc_ep); + } + do_setup_in_status_phase(pcd); break; } @@ -1350,10 +1401,9 @@ * This function process the CLEAR_FEATURE Setup Commands. */ -static inline void do_clear_feature( dwc_otg_pcd_t *_pcd ) -{ - struct usb_ctrlrequest ctrl = _pcd->setup_pkt->req; +static inline void do_clear_feature(dwc_otg_pcd_t *pcd) +{ + struct usb_ctrlrequest ctrl = pcd->setup_pkt->req; dwc_otg_pcd_ep_t *ep = 0; - - + DWC_DEBUGPL(DBG_PCD, "CLEAR_FEATURE:%02x.%02x v%04x i%04x l%04x\n", @@ -1361,11 +1411,9 @@ ctrl.wValue, ctrl.wIndex, ctrl.wLength); - switch (ctrl.bRequestType & USB_RECIP_MASK) - { + switch (ctrl.bRequestType & USB_RECIP_MASK) { case USB_RECIP_DEVICE: - switch (ctrl.wValue) - { + switch (ctrl.wValue) { case USB_DEVICE_REMOTE_WAKEUP: - _pcd->remote_wakeup_enable = 0; + pcd->remote_wakeup_enable = 0; break; @@ -1374,18 +1422,37 @@ break; } - do_setup_in_status_phase( _pcd ); + do_setup_in_status_phase(pcd); break; case USB_RECIP_ENDPOINT: - ep = get_ep_by_addr(_pcd, ctrl.wIndex); - if (ep == 0) - { - ep0_do_stall(_pcd, -EOPNOTSUPP); + ep = get_ep_by_addr(pcd, ctrl.wIndex); + if (ep == 0) { + ep0_do_stall(pcd, -EOPNOTSUPP); return; } - pcd_clear_halt(_pcd, ep ); - - break; + pcd_clear_halt(pcd, ep); + + break; + } +} + +/** + * This function process the SET_ADDRESS Setup Commands. + */ +static inline void do_set_address(dwc_otg_pcd_t *pcd) +{ + dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; + struct usb_ctrlrequest ctrl = pcd->setup_pkt->req; + + if (ctrl.bRequestType == USB_RECIP_DEVICE) { + dcfg_data_t dcfg = {.d32=0}; + +#ifdef DEBUG_EP0 +// DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue); +#endif + dcfg.b.devaddr = ctrl.wValue; + dwc_modify_reg32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32); + do_setup_in_status_phase(pcd); } } @@ -1441,12 +1508,10 @@ * pcd_setup processes the gadget SETUP commands. */ -static inline void pcd_setup( dwc_otg_pcd_t *_pcd ) -{ - dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd); +static inline void pcd_setup(dwc_otg_pcd_t *pcd) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); dwc_otg_dev_if_t *dev_if = core_if->dev_if; - struct usb_ctrlrequest ctrl = _pcd->setup_pkt->req; - dwc_otg_pcd_ep_t *ep; - dwc_otg_pcd_ep_t *ep0 = &_pcd->ep0; - uint16_t *status = _pcd->status_buf; + struct usb_ctrlrequest ctrl = pcd->setup_pkt->req; + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; deptsiz0_data_t doeptsize0 = { .d32 = 0}; @@ -1454,35 +1519,37 @@ #ifdef DEBUG_EP0 DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n", - ctrl.bRequestType, ctrl.bRequest, - ctrl.wValue, ctrl.wIndex, ctrl.wLength); + ctrl.bRequestType, ctrl.bRequest, + ctrl.wValue, ctrl.wIndex, ctrl.wLength); #endif - doeptsize0.d32 = dwc_read_reg32( &dev_if->out_ep_regs[0]->doeptsiz ); + doeptsize0.d32 = dwc_read_reg32(&dev_if->out_ep_regs[0]->doeptsiz); /** @todo handle > 1 setup packet , assert error for now */ - if (core_if->dma_enable && (doeptsize0.b.supcnt < 2)) - { + + if (core_if->dma_enable && core_if->dma_desc_enable == 0 && (doeptsize0.b.supcnt < 2)) { DWC_ERROR ("\n\n----------- CANNOT handle > 1 setup packet in DMA mode\n\n"); } /* Clean up the request queue */ - request_nuke( ep0 ); + dwc_otg_request_nuke(ep0); ep0->stopped = 0; - if (ctrl.bRequestType & USB_DIR_IN) - { + if (ctrl.bRequestType & USB_DIR_IN) { ep0->dwc_ep.is_in = 1; - _pcd->ep0state = EP0_IN_DATA_PHASE; + pcd->ep0state = EP0_IN_DATA_PHASE; } - else - { + else { ep0->dwc_ep.is_in = 0; - _pcd->ep0state = EP0_OUT_DATA_PHASE; - } - - if ((ctrl.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD) - { + pcd->ep0state = EP0_OUT_DATA_PHASE; + } + + if(ctrl.wLength == 0) { + ep0->dwc_ep.is_in = 1; + pcd->ep0state = EP0_IN_STATUS_PHASE; + } + + if ((ctrl.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD) { /* handle non-standard (class/vendor) requests in the gadget driver */ - do_gadget_setup(_pcd, &ctrl ); + do_gadget_setup(pcd, &ctrl); return; } @@ -1490,84 +1557,37 @@ /** @todo NGS: Handle bad setup packet? */ - switch (ctrl.bRequest) - { +/////////////////////////////////////////// +//// --- Standard Request handling --- //// + + switch (ctrl.bRequest) { case USB_REQ_GET_STATUS: -#ifdef DEBUG_EP0 - DWC_DEBUGPL(DBG_PCD, - "GET_STATUS %02x.%02x v%04x i%04x l%04x\n", - ctrl.bRequestType, ctrl.bRequest, - ctrl.wValue, ctrl.wIndex, ctrl.wLength); -#endif - - switch (ctrl.bRequestType & USB_RECIP_MASK) - { - case USB_RECIP_DEVICE: - *status = 0x1; /* Self powered */ - *status |= _pcd->remote_wakeup_enable << 1; - break; - - case USB_RECIP_INTERFACE: - *status = 0; - break; - - case USB_RECIP_ENDPOINT: - ep = get_ep_by_addr(_pcd, ctrl.wIndex); - if ( ep == 0 || ctrl.wLength > 2) - { - ep0_do_stall(_pcd, -EOPNOTSUPP); - return; - } - /** @todo check for EP stall */ - *status = ep->stopped; - break; - } - _pcd->ep0_pending = 1; - - ep0->dwc_ep.start_xfer_buff = (uint8_t *)status; - ep0->dwc_ep.xfer_buff = (uint8_t *)status; - ep0->dwc_ep.dma_addr = _pcd->status_buf_dma_handle; - ep0->dwc_ep.xfer_len = 2; - ep0->dwc_ep.xfer_count = 0; - ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len; - dwc_otg_ep0_start_transfer( GET_CORE_IF(_pcd), &ep0->dwc_ep ); + do_get_status(pcd); break; case USB_REQ_CLEAR_FEATURE: - do_clear_feature( _pcd ); + do_clear_feature(pcd); break; case USB_REQ_SET_FEATURE: - do_set_feature( _pcd ); + do_set_feature(pcd); break; case USB_REQ_SET_ADDRESS: - if (ctrl.bRequestType == USB_RECIP_DEVICE) - { - dcfg_data_t dcfg = {.d32=0}; - -#ifdef DEBUG_EP0 - DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue); -#endif - dcfg.b.devaddr = ctrl.wValue; - dwc_modify_reg32( &dev_if->dev_global_regs->dcfg, - 0, dcfg.d32); - do_setup_in_status_phase( _pcd ); - return; - } + do_set_address(pcd); break; case USB_REQ_SET_INTERFACE: case USB_REQ_SET_CONFIGURATION: - _pcd->request_config = 1; /* Configuration changed */ - do_gadget_setup(_pcd, &ctrl ); - break; +// _pcd->request_config = 1; /* Configuration changed */ + do_gadget_setup(pcd, &ctrl); + break; case USB_REQ_SYNCH_FRAME: - do_gadget_setup(_pcd, &ctrl ); - break; + do_gadget_setup(pcd, &ctrl); + break; default: - /* Call the Gadget Driver's setup functions */ - do_gadget_setup(_pcd, &ctrl ); + /* Call the Gadget Driver's setup functions */ + do_gadget_setup(pcd, &ctrl); break; } @@ -1577,25 +1597,24 @@ * This function completes the ep0 control transfer. */ -static int32_t ep0_complete_request( dwc_otg_pcd_ep_t *_ep ) -{ - dwc_otg_core_if_t *core_if = GET_CORE_IF(_ep->pcd); +static int32_t ep0_complete_request(dwc_otg_pcd_ep_t *ep) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); dwc_otg_dev_if_t *dev_if = core_if->dev_if; dwc_otg_dev_in_ep_regs_t *in_ep_regs = - dev_if->in_ep_regs[_ep->dwc_ep.num]; + dev_if->in_ep_regs[ep->dwc_ep.num]; #ifdef DEBUG_EP0 dwc_otg_dev_out_ep_regs_t *out_ep_regs = - dev_if->out_ep_regs[_ep->dwc_ep.num]; + dev_if->out_ep_regs[ep->dwc_ep.num]; #endif deptsiz0_data_t deptsiz; + desc_sts_data_t desc_sts; dwc_otg_pcd_request_t *req; int is_last = 0; - dwc_otg_pcd_t *pcd = _ep->pcd; + dwc_otg_pcd_t *pcd = ep->pcd; //DWC_DEBUGPL(DBG_PCDV, "%s() %s\n", __func__, _ep->ep.name); - if (pcd->ep0_pending && list_empty(&_ep->queue)) - { - if (_ep->dwc_ep.is_in) - { + if (pcd->ep0_pending && list_empty(&ep->queue)) { + if (ep->dwc_ep.is_in) { #ifdef DEBUG_EP0 DWC_DEBUGPL(DBG_PCDV, "Do setup OUT status phase\n"); @@ -1603,6 +1622,5 @@ do_setup_out_status_phase(pcd); } - else - { + else { #ifdef DEBUG_EP0 DWC_DEBUGPL(DBG_PCDV, "Do setup IN status phase\n"); @@ -1611,76 +1629,66 @@ } pcd->ep0_pending = 0; - pcd->ep0state = EP0_STATUS; return 1; } - if (list_empty(&_ep->queue)) - { + if (list_empty(&ep->queue)) { return 0; } - req = list_entry(_ep->queue.next, dwc_otg_pcd_request_t, queue); - - - if (pcd->ep0state == EP0_STATUS) - { + req = list_entry(ep->queue.next, dwc_otg_pcd_request_t, queue); + + + if (pcd->ep0state == EP0_OUT_STATUS_PHASE || pcd->ep0state == EP0_IN_STATUS_PHASE) { is_last = 1; } - else if (req->req.zero) - { - req->req.actual = _ep->dwc_ep.xfer_count; - //do_setup_in_status_phase (pcd); - req->req.zero = 0; - _ep->dwc_ep.xfer_len = 0; - _ep->dwc_ep.xfer_count = 0; - _ep->dwc_ep.sent_zlp = 1; - dwc_otg_ep0_start_transfer( GET_CORE_IF(pcd), &_ep->dwc_ep ); - return 1; - } - else if (_ep->dwc_ep.is_in) - { - deptsiz.d32 = dwc_read_reg32( &in_ep_regs->dieptsiz); + else if (ep->dwc_ep.is_in) { + deptsiz.d32 = dwc_read_reg32(&in_ep_regs->dieptsiz); + if(core_if->dma_desc_enable != 0) + desc_sts.d32 = readl(dev_if->in_desc_addr); #ifdef DEBUG_EP0 DWC_DEBUGPL(DBG_PCDV, "%s len=%d xfersize=%d pktcnt=%d\n", - _ep->ep.name, _ep->dwc_ep.xfer_len, - deptsiz.b.xfersize, deptsiz.b.pktcnt); + ep->ep.name, ep->dwc_ep.xfer_len, + deptsiz.b.xfersize, deptsiz.b.pktcnt); #endif - if (deptsiz.b.xfersize == 0) - { - req->req.actual = _ep->dwc_ep.xfer_count; + + if (((core_if->dma_desc_enable == 0) && (deptsiz.b.xfersize == 0)) || + ((core_if->dma_desc_enable != 0) && (desc_sts.b.bytes == 0))) { + req->req.actual = ep->dwc_ep.xfer_count; /* Is a Zero Len Packet needed? */ - //if (req->req.zero) { + if (req->req.zero) { #ifdef DEBUG_EP0 - DWC_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n"); + DWC_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n"); #endif + req->req.zero = 0; + } do_setup_out_status_phase(pcd); } } - else - { + else { /* ep0-OUT */ #ifdef DEBUG_EP0 - deptsiz.d32 = dwc_read_reg32( &out_ep_regs->doeptsiz); + deptsiz.d32 = dwc_read_reg32(&out_ep_regs->doeptsiz); DWC_DEBUGPL(DBG_PCDV, "%s len=%d xsize=%d pktcnt=%d\n", - _ep->ep.name, _ep->dwc_ep.xfer_len, - deptsiz.b.xfersize, - deptsiz.b.pktcnt); + ep->ep.name, ep->dwc_ep.xfer_len, + deptsiz.b.xfersize, + deptsiz.b.pktcnt); #endif - req->req.actual = _ep->dwc_ep.xfer_count; - + req->req.actual = ep->dwc_ep.xfer_count; /* Is a Zero Len Packet needed? */ - //if (req->req.zero) { + if (req->req.zero) { #ifdef DEBUG_EP0 - DWC_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n"); + DWC_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n"); #endif - do_setup_in_status_phase(pcd); + req->req.zero = 0; + } + if(core_if->dma_desc_enable == 0) + do_setup_in_status_phase(pcd); } /* Complete the request */ - if (is_last) - { - request_done(_ep, req, 0); - _ep->dwc_ep.start_xfer_buff = 0; - _ep->dwc_ep.xfer_buff = 0; - _ep->dwc_ep.xfer_len = 0; + if (is_last) { + dwc_otg_request_done(ep, req, 0); + ep->dwc_ep.start_xfer_buff = 0; + ep->dwc_ep.xfer_buff = 0; + ep->dwc_ep.xfer_len = 0; return 1; } @@ -1692,92 +1700,795 @@ * additional requests for the EP in the queue they will be started. */ -static void complete_ep( dwc_otg_pcd_ep_t *_ep ) -{ - dwc_otg_core_if_t *core_if = GET_CORE_IF(_ep->pcd); +static void complete_ep(dwc_otg_pcd_ep_t *ep) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); dwc_otg_dev_if_t *dev_if = core_if->dev_if; dwc_otg_dev_in_ep_regs_t *in_ep_regs = - dev_if->in_ep_regs[_ep->dwc_ep.num]; + dev_if->in_ep_regs[ep->dwc_ep.num]; deptsiz_data_t deptsiz; + desc_sts_data_t desc_sts; dwc_otg_pcd_request_t *req = 0; + dwc_otg_dma_desc_t* dma_desc; + uint32_t byte_count = 0; int is_last = 0; - - DWC_DEBUGPL(DBG_PCDV,"%s() %s-%s\n", __func__, _ep->ep.name, - (_ep->dwc_ep.is_in?"IN":"OUT")); + int i; + + DWC_DEBUGPL(DBG_PCDV,"%s() %s-%s\n", __func__, ep->ep.name, + (ep->dwc_ep.is_in?"IN":"OUT")); /* Get any pending requests */ - if (!list_empty(&_ep->queue)) - { - req = list_entry(_ep->queue.next, dwc_otg_pcd_request_t, - queue); - } - DWC_DEBUGPL(DBG_PCD, "Requests %d\n",_ep->pcd->request_pending); - - if (_ep->dwc_ep.is_in) - { - deptsiz.d32 = dwc_read_reg32( &in_ep_regs->dieptsiz); - - if (core_if->dma_enable) - { - if (deptsiz.b.xfersize == 0) - _ep->dwc_ep.xfer_count = _ep->dwc_ep.xfer_len; - } - - DWC_DEBUGPL(DBG_PCDV, "%s len=%d xfersize=%d pktcnt=%d\n", - _ep->ep.name, _ep->dwc_ep.xfer_len, + if (!list_empty(&ep->queue)) { + req = list_entry(ep->queue.next, dwc_otg_pcd_request_t, + queue); + if (!req) { + printk("complete_ep 0x%p, req = NULL!\n", ep); + return; + } + } + else { + printk("complete_ep 0x%p, ep->queue empty!\n", ep); + return; + } + DWC_DEBUGPL(DBG_PCD, "Requests %d\n", ep->pcd->request_pending); + + if (ep->dwc_ep.is_in) { + deptsiz.d32 = dwc_read_reg32(&in_ep_regs->dieptsiz); + + if (core_if->dma_enable) { + if(core_if->dma_desc_enable == 0) { + if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0) { + byte_count = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; + + ep->dwc_ep.xfer_buff += byte_count; + ep->dwc_ep.dma_addr += byte_count; + ep->dwc_ep.xfer_count += byte_count; + + DWC_DEBUGPL(DBG_PCDV, "%s len=%d xfersize=%d pktcnt=%d\n", + ep->ep.name, ep->dwc_ep.xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt); - - if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0 && - _ep->dwc_ep.xfer_count == _ep->dwc_ep.xfer_len) - { - is_last = 1; - } - else - { - DWC_WARN("Incomplete transfer (%s-%s [siz=%d pkt=%d])\n", - _ep->ep.name, (_ep->dwc_ep.is_in?"IN":"OUT"), - deptsiz.b.xfersize, deptsiz.b.pktcnt); - } - } - else - { + + + if(ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { + dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep); + } else if(ep->dwc_ep.sent_zlp) { + /* + * This fragment of code should initiate 0 + * length trasfer in case if it is queued + * a trasfer with size divisible to EPs max + * packet size and with usb_request zero field + * is set, which means that after data is transfered, + * it is also should be transfered + * a 0 length packet at the end. For Slave and + * Buffer DMA modes in this case SW has + * to initiate 2 transfers one with transfer size, + * and the second with 0 size. For Desriptor + * DMA mode SW is able to initiate a transfer, + * which will handle all the packets including + * the last 0 legth. + */ + ep->dwc_ep.sent_zlp = 0; + dwc_otg_ep_start_zl_transfer(core_if, &ep->dwc_ep); + } else { + is_last = 1; + } + } else { + DWC_WARN("Incomplete transfer (%s-%s [siz=%d pkt=%d])\n", + ep->ep.name, (ep->dwc_ep.is_in?"IN":"OUT"), + deptsiz.b.xfersize, deptsiz.b.pktcnt); + } + } else { + dma_desc = ep->dwc_ep.desc_addr; + byte_count = 0; + ep->dwc_ep.sent_zlp = 0; + + for(i = 0; i < ep->dwc_ep.desc_cnt; ++i) { + desc_sts.d32 = readl(dma_desc); + byte_count += desc_sts.b.bytes; + dma_desc++; + } + + if(byte_count == 0) { + ep->dwc_ep.xfer_count = ep->dwc_ep.total_len; + is_last = 1; + } else { + DWC_WARN("Incomplete transfer\n"); + } + } + } else { + if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0) { + /* Check if the whole transfer was completed, + * if no, setup transfer for next portion of data + */ + DWC_DEBUGPL(DBG_PCDV, "%s len=%d xfersize=%d pktcnt=%d\n", + ep->ep.name, ep->dwc_ep.xfer_len, + deptsiz.b.xfersize, deptsiz.b.pktcnt); + if(ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { + dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep); + } else if(ep->dwc_ep.sent_zlp) { + /* + * This fragment of code should initiate 0 + * length trasfer in case if it is queued + * a trasfer with size divisible to EPs max + * packet size and with usb_request zero field + * is set, which means that after data is transfered, + * it is also should be transfered + * a 0 length packet at the end. For Slave and + * Buffer DMA modes in this case SW has + * to initiate 2 transfers one with transfer size, + * and the second with 0 size. For Desriptor + * DMA mode SW is able to initiate a transfer, + * which will handle all the packets including + * the last 0 legth. + */ + ep->dwc_ep.sent_zlp = 0; + dwc_otg_ep_start_zl_transfer(core_if, &ep->dwc_ep); + } else { + is_last = 1; + } + } + else { + DWC_WARN("Incomplete transfer (%s-%s [siz=%d pkt=%d])\n", + ep->ep.name, (ep->dwc_ep.is_in?"IN":"OUT"), + deptsiz.b.xfersize, deptsiz.b.pktcnt); + } + } + } else { dwc_otg_dev_out_ep_regs_t *out_ep_regs = - dev_if->out_ep_regs[_ep->dwc_ep.num]; - deptsiz.d32 = 0; - deptsiz.d32 = dwc_read_reg32( &out_ep_regs->doeptsiz); + dev_if->out_ep_regs[ep->dwc_ep.num]; + desc_sts.d32 = 0; + if(core_if->dma_enable) { + if(core_if->dma_desc_enable) { + dma_desc = ep->dwc_ep.desc_addr; + byte_count = 0; + ep->dwc_ep.sent_zlp = 0; + for(i = 0; i < ep->dwc_ep.desc_cnt; ++i) { + desc_sts.d32 = readl(dma_desc); + byte_count += desc_sts.b.bytes; + dma_desc++; + } + + ep->dwc_ep.xfer_count = ep->dwc_ep.total_len + - byte_count + ((4 - (ep->dwc_ep.total_len & 0x3)) & 0x3); + is_last = 1; + } else { + deptsiz.d32 = 0; + deptsiz.d32 = dwc_read_reg32(&out_ep_regs->doeptsiz); + + byte_count = (ep->dwc_ep.xfer_len - + ep->dwc_ep.xfer_count - deptsiz.b.xfersize); + ep->dwc_ep.xfer_buff += byte_count; + ep->dwc_ep.dma_addr += byte_count; + ep->dwc_ep.xfer_count += byte_count; + + /* Check if the whole transfer was completed, + * if no, setup transfer for next portion of data + */ + if(ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { + dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep); + } + else if(ep->dwc_ep.sent_zlp) { + /* + * This fragment of code should initiate 0 + * length trasfer in case if it is queued + * a trasfer with size divisible to EPs max + * packet size and with usb_request zero field + * is set, which means that after data is transfered, + * it is also should be transfered + * a 0 length packet at the end. For Slave and + * Buffer DMA modes in this case SW has + * to initiate 2 transfers one with transfer size, + * and the second with 0 size. For Desriptor + * DMA mode SW is able to initiate a transfer, + * which will handle all the packets including + * the last 0 legth. + */ + ep->dwc_ep.sent_zlp = 0; + dwc_otg_ep_start_zl_transfer(core_if, &ep->dwc_ep); + } else { + is_last = 1; + } + } + } else { + /* Check if the whole transfer was completed, + * if no, setup transfer for next portion of data + */ + if(ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { + dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep); + } + else if(ep->dwc_ep.sent_zlp) { + /* + * This fragment of code should initiate 0 + * length trasfer in case if it is queued + * a trasfer with size divisible to EPs max + * packet size and with usb_request zero field + * is set, which means that after data is transfered, + * it is also should be transfered + * a 0 length packet at the end. For Slave and + * Buffer DMA modes in this case SW has + * to initiate 2 transfers one with transfer size, + * and the second with 0 size. For Desriptor + * DMA mode SW is able to initiate a transfer, + * which will handle all the packets including + * the last 0 legth. + */ + ep->dwc_ep.sent_zlp = 0; + dwc_otg_ep_start_zl_transfer(core_if, &ep->dwc_ep); + } else { + is_last = 1; + } + } #ifdef DEBUG DWC_DEBUGPL(DBG_PCDV, "addr %p, %s len=%d cnt=%d xsize=%d pktcnt=%d\n", - &out_ep_regs->doeptsiz, _ep->ep.name, _ep->dwc_ep.xfer_len, - _ep->dwc_ep.xfer_count, - deptsiz.b.xfersize, - deptsiz.b.pktcnt); + &out_ep_regs->doeptsiz, ep->ep.name, ep->dwc_ep.xfer_len, + ep->dwc_ep.xfer_count, + deptsiz.b.xfersize, + deptsiz.b.pktcnt); #endif - is_last = 1; } /* Complete the request */ - if (is_last) + if (is_last) { + req->req.actual = ep->dwc_ep.xfer_count; + + dwc_otg_request_done(ep, req, 0); + + ep->dwc_ep.start_xfer_buff = 0; + ep->dwc_ep.xfer_buff = 0; + ep->dwc_ep.xfer_len = 0; + + /* If there is a request in the queue start it.*/ + start_next_request(ep); + } +} + + +#ifdef DWC_EN_ISOC + +/** + * This function BNA interrupt for Isochronous EPs + * + */ +static void dwc_otg_pcd_handle_iso_bna(dwc_otg_pcd_ep_t *ep) +{ + dwc_ep_t *dwc_ep = &ep->dwc_ep; + volatile uint32_t *addr; + depctl_data_t depctl = {.d32 = 0}; + dwc_otg_pcd_t *pcd = ep->pcd; + dwc_otg_dma_desc_t *dma_desc; + int i; + + dma_desc = dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * (dwc_ep->proc_buf_num); + + if(dwc_ep->is_in) { + desc_sts_data_t sts = {.d32 = 0}; + for(i = 0;i < dwc_ep->desc_cnt; ++i, ++dma_desc) + { + sts.d32 = readl(&dma_desc->status); + sts.b_iso_in.bs = BS_HOST_READY; + writel(sts.d32,&dma_desc->status); + } + } + else { + desc_sts_data_t sts = {.d32 = 0}; + for(i = 0;i < dwc_ep->desc_cnt; ++i, ++dma_desc) + { + sts.d32 = readl(&dma_desc->status); + sts.b_iso_out.bs = BS_HOST_READY; + writel(sts.d32,&dma_desc->status); + } + } + + if(dwc_ep->is_in == 0){ + addr = &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]->doepctl; + } + else{ + addr = &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl; + } + depctl.b.epena = 1; + dwc_modify_reg32(addr,depctl.d32,depctl.d32); +} + +/** + * This function sets latest iso packet information(non-PTI mode) + * + * @param core_if Programming view of DWC_otg controller. + * @param ep The EP to start the transfer on. + * + */ +void set_current_pkt_info(dwc_otg_core_if_t *core_if, dwc_ep_t *ep) +{ + deptsiz_data_t deptsiz = { .d32 = 0 }; + dma_addr_t dma_addr; + uint32_t offset; + + if(ep->proc_buf_num) + dma_addr = ep->dma_addr1; + else + dma_addr = ep->dma_addr0; + + + if(ep->is_in) { + deptsiz.d32 = dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz); + offset = ep->data_per_frame; + } else { + deptsiz.d32 = dwc_read_reg32(&core_if->dev_if->out_ep_regs[ep->num]->doeptsiz); + offset = ep->data_per_frame + (0x4 & (0x4 - (ep->data_per_frame & 0x3))); + } + + if(!deptsiz.b.xfersize) { + ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame; + ep->pkt_info[ep->cur_pkt].offset = ep->cur_pkt_dma_addr - dma_addr; + ep->pkt_info[ep->cur_pkt].status = 0; + } else { + ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame; + ep->pkt_info[ep->cur_pkt].offset = ep->cur_pkt_dma_addr - dma_addr; + ep->pkt_info[ep->cur_pkt].status = -ENODATA; + } + ep->cur_pkt_addr += offset; + ep->cur_pkt_dma_addr += offset; + ep->cur_pkt++; +} + +/** + * This function sets latest iso packet information(DDMA mode) + * + * @param core_if Programming view of DWC_otg controller. + * @param dwc_ep The EP to start the transfer on. + * + */ +static void set_ddma_iso_pkts_info(dwc_otg_core_if_t *core_if, dwc_ep_t *dwc_ep) +{ + dwc_otg_dma_desc_t* dma_desc; + desc_sts_data_t sts = {.d32 = 0}; + iso_pkt_info_t *iso_packet; + uint32_t data_per_desc; + uint32_t offset; + int i, j; + + iso_packet = dwc_ep->pkt_info; + + /** Reinit closed DMA Descriptors*/ + /** ISO OUT EP */ + if(dwc_ep->is_in == 0) { + dma_desc = dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * dwc_ep->proc_buf_num; + offset = 0; + + for(i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; i+= dwc_ep->pkt_per_frm) + { + for(j = 0; j < dwc_ep->pkt_per_frm; ++j) + { + data_per_desc = ((j + 1) * dwc_ep->maxpacket > dwc_ep->data_per_frame) ? + dwc_ep->data_per_frame - j * dwc_ep->maxpacket : dwc_ep->maxpacket; + data_per_desc += (data_per_desc % 4) ? (4 - data_per_desc % 4):0; + + sts.d32 = readl(&dma_desc->status); + + /* Write status in iso_packet_decsriptor */ + iso_packet->status = sts.b_iso_out.rxsts + (sts.b_iso_out.bs^BS_DMA_DONE); + if(iso_packet->status) { + iso_packet->status = -ENODATA; + } + + /* Received data length */ + if(!sts.b_iso_out.rxbytes){ + iso_packet->length = data_per_desc - sts.b_iso_out.rxbytes; + } else { + iso_packet->length = data_per_desc - sts.b_iso_out.rxbytes + + (4 - dwc_ep->data_per_frame % 4); + } + + iso_packet->offset = offset; + + offset += data_per_desc; + dma_desc ++; + iso_packet ++; + } + } + + for(j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) + { + data_per_desc = ((j + 1) * dwc_ep->maxpacket > dwc_ep->data_per_frame) ? + dwc_ep->data_per_frame - j * dwc_ep->maxpacket : dwc_ep->maxpacket; + data_per_desc += (data_per_desc % 4) ? (4 - data_per_desc % 4):0; + + sts.d32 = readl(&dma_desc->status); + + /* Write status in iso_packet_decsriptor */ + iso_packet->status = sts.b_iso_out.rxsts + (sts.b_iso_out.bs^BS_DMA_DONE); + if(iso_packet->status) { + iso_packet->status = -ENODATA; + } + + /* Received data length */ + iso_packet->length = dwc_ep->data_per_frame - sts.b_iso_out.rxbytes; + + iso_packet->offset = offset; + + offset += data_per_desc; + iso_packet++; + dma_desc++; + } + + sts.d32 = readl(&dma_desc->status); + + /* Write status in iso_packet_decsriptor */ + iso_packet->status = sts.b_iso_out.rxsts + (sts.b_iso_out.bs^BS_DMA_DONE); + if(iso_packet->status) { + iso_packet->status = -ENODATA; + } + /* Received data length */ + if(!sts.b_iso_out.rxbytes){ + iso_packet->length = dwc_ep->data_per_frame - sts.b_iso_out.rxbytes; + } else { + iso_packet->length = dwc_ep->data_per_frame - sts.b_iso_out.rxbytes + + (4 - dwc_ep->data_per_frame % 4); + } + + iso_packet->offset = offset; + } + else /** ISO IN EP */ { - - if (core_if->dma_enable) + dma_desc = dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * dwc_ep->proc_buf_num; + + for(i = 0; i < dwc_ep->desc_cnt - 1; i++) { - req->req.actual = _ep->dwc_ep.xfer_len - deptsiz.b.xfersize; - } - else + sts.d32 = readl(&dma_desc->status); + + /* Write status in iso packet descriptor */ + iso_packet->status = sts.b_iso_in.txsts + (sts.b_iso_in.bs^BS_DMA_DONE); + if(iso_packet->status != 0) { + iso_packet->status = -ENODATA; + + } + /* Bytes has been transfered */ + iso_packet->length = dwc_ep->data_per_frame - sts.b_iso_in.txbytes; + + dma_desc ++; + iso_packet++; + } + + sts.d32 = readl(&dma_desc->status); + while(sts.b_iso_in.bs == BS_DMA_BUSY) { + sts.d32 = readl(&dma_desc->status); + } + + /* Write status in iso packet descriptor ??? do be done with ERROR codes*/ + iso_packet->status = sts.b_iso_in.txsts + (sts.b_iso_in.bs^BS_DMA_DONE); + if(iso_packet->status != 0) { + iso_packet->status = -ENODATA; + } + + /* Bytes has been transfered */ + iso_packet->length = dwc_ep->data_per_frame - sts.b_iso_in.txbytes; + } +} + +/** + * This function reinitialize DMA Descriptors for Isochronous transfer + * + * @param core_if Programming view of DWC_otg controller. + * @param dwc_ep The EP to start the transfer on. + * + */ +static void reinit_ddma_iso_xfer(dwc_otg_core_if_t *core_if, dwc_ep_t *dwc_ep) +{ + int i, j; + dwc_otg_dma_desc_t* dma_desc; + dma_addr_t dma_ad; + volatile uint32_t *addr; + desc_sts_data_t sts = { .d32 =0 }; + uint32_t data_per_desc; + + if(dwc_ep->is_in == 0) { + addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl; + } + else { + addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl; + } + + + if(dwc_ep->proc_buf_num == 0) { + /** Buffer 0 descriptors setup */ + dma_ad = dwc_ep->dma_addr0; + } + else { + /** Buffer 1 descriptors setup */ + dma_ad = dwc_ep->dma_addr1; + } + + + /** Reinit closed DMA Descriptors*/ + /** ISO OUT EP */ + if(dwc_ep->is_in == 0) { + dma_desc = dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * dwc_ep->proc_buf_num; + + sts.b_iso_out.bs = BS_HOST_READY; + sts.b_iso_out.rxsts = 0; + sts.b_iso_out.l = 0; + sts.b_iso_out.sp = 0; + sts.b_iso_out.ioc = 0; + sts.b_iso_out.pid = 0; + sts.b_iso_out.framenum = 0; + + for(i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; i+= dwc_ep->pkt_per_frm) { - req->req.actual = _ep->dwc_ep.xfer_count; - } - - request_done(_ep, req, 0); - - _ep->dwc_ep.start_xfer_buff = 0; - _ep->dwc_ep.xfer_buff = 0; - _ep->dwc_ep.xfer_len = 0; - - /* If there is a request in the queue start it.*/ - start_next_request( _ep ); - } -} + for(j = 0; j < dwc_ep->pkt_per_frm; ++j) + { + data_per_desc = ((j + 1) * dwc_ep->maxpacket > dwc_ep->data_per_frame) ? + dwc_ep->data_per_frame - j * dwc_ep->maxpacket : dwc_ep->maxpacket; + data_per_desc += (data_per_desc % 4) ? (4 - data_per_desc % 4):0; + sts.b_iso_out.rxbytes = data_per_desc; + writel((uint32_t)dma_ad, &dma_desc->buf); + writel(sts.d32, &dma_desc->status); + + (uint32_t)dma_ad += data_per_desc; + dma_desc ++; + } + } + + for(j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) + { + + data_per_desc = ((j + 1) * dwc_ep->maxpacket > dwc_ep->data_per_frame) ? + dwc_ep->data_per_frame - j * dwc_ep->maxpacket : dwc_ep->maxpacket; + data_per_desc += (data_per_desc % 4) ? (4 - data_per_desc % 4):0; + sts.b_iso_out.rxbytes = data_per_desc; + + writel((uint32_t)dma_ad, &dma_desc->buf); + writel(sts.d32, &dma_desc->status); + + dma_desc++; + (uint32_t)dma_ad += data_per_desc; + } + + sts.b_iso_out.ioc = 1; + sts.b_iso_out.l = dwc_ep->proc_buf_num; + + data_per_desc = ((j + 1) * dwc_ep->maxpacket > dwc_ep->data_per_frame) ? + dwc_ep->data_per_frame - j * dwc_ep->maxpacket : dwc_ep->maxpacket; + data_per_desc += (data_per_desc % 4) ? (4 - data_per_desc % 4):0; + sts.b_iso_out.rxbytes = data_per_desc; + + writel((uint32_t)dma_ad, &dma_desc->buf); + writel(sts.d32, &dma_desc->status); + } + else /** ISO IN EP */ + { + dma_desc = dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * dwc_ep->proc_buf_num; + + sts.b_iso_in.bs = BS_HOST_READY; + sts.b_iso_in.txsts = 0; + sts.b_iso_in.sp = 0; + sts.b_iso_in.ioc = 0; + sts.b_iso_in.pid = dwc_ep->pkt_per_frm; + sts.b_iso_in.framenum = dwc_ep->next_frame; + sts.b_iso_in.txbytes = dwc_ep->data_per_frame; + sts.b_iso_in.l = 0; + + for(i = 0; i < dwc_ep->desc_cnt - 1; i++) + { + writel((uint32_t)dma_ad, &dma_desc->buf); + writel(sts.d32, &dma_desc->status); + + sts.b_iso_in.framenum += dwc_ep->bInterval; + (uint32_t)dma_ad += dwc_ep->data_per_frame; + dma_desc ++; + } + + sts.b_iso_in.ioc = 1; + sts.b_iso_in.l = dwc_ep->proc_buf_num; + + writel((uint32_t)dma_ad, &dma_desc->buf); + writel(sts.d32, &dma_desc->status); + + dwc_ep->next_frame = sts.b_iso_in.framenum + dwc_ep->bInterval * 1; + } + dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1; +} + + +/** + * This function is to handle Iso EP transfer complete interrupt + * in case Iso out packet was dropped + * + * @param core_if Programming view of DWC_otg controller. + * @param dwc_ep The EP for wihich transfer complete was asserted + * + */ +static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t *core_if, dwc_ep_t *dwc_ep) +{ + uint32_t dma_addr; + uint32_t drp_pkt; + uint32_t drp_pkt_cnt; + deptsiz_data_t deptsiz = { .d32 = 0 }; + depctl_data_t depctl = { .d32 = 0 }; + int i; + + deptsiz.d32 = dwc_read_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz); + + drp_pkt = dwc_ep->pkt_cnt - deptsiz.b.pktcnt; + drp_pkt_cnt = dwc_ep->pkt_per_frm - (drp_pkt % dwc_ep->pkt_per_frm); + + /* Setting dropped packets status */ + for(i = 0; i < drp_pkt_cnt; ++i) { + dwc_ep->pkt_info[drp_pkt].status = -ENODATA; + drp_pkt ++; + deptsiz.b.pktcnt--; + } + + + if(deptsiz.b.pktcnt > 0) { + deptsiz.b.xfersize = dwc_ep->xfer_len - (dwc_ep->pkt_cnt - deptsiz.b.pktcnt) * dwc_ep->maxpacket; + } else { + deptsiz.b.xfersize = 0; + deptsiz.b.pktcnt = 0; + } + + dwc_write_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz, deptsiz.d32); + + if(deptsiz.b.pktcnt > 0) { + if(dwc_ep->proc_buf_num) { + dma_addr = dwc_ep->dma_addr1 + dwc_ep->xfer_len - deptsiz.b.xfersize; + } else { + dma_addr = dwc_ep->dma_addr0 + dwc_ep->xfer_len - deptsiz.b.xfersize;; + } + + dwc_write_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepdma, dma_addr); + + /** Re-enable endpoint, clear nak */ + depctl.d32 = 0; + depctl.b.epena = 1; + depctl.b.cnak = 1; + + dwc_modify_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl, + depctl.d32,depctl.d32); + return 0; + } else { + return 1; + } +} + +/** + * This function sets iso packets information(PTI mode) + * + * @param core_if Programming view of DWC_otg controller. + * @param ep The EP to start the transfer on. + * + */ +static uint32_t set_iso_pkts_info(dwc_otg_core_if_t *core_if, dwc_ep_t *ep) +{ + int i, j; + dma_addr_t dma_ad; + iso_pkt_info_t *packet_info = ep->pkt_info; + uint32_t offset; + uint32_t frame_data; + deptsiz_data_t deptsiz; + + if(ep->proc_buf_num == 0) { + /** Buffer 0 descriptors setup */ + dma_ad = ep->dma_addr0; + } + else { + /** Buffer 1 descriptors setup */ + dma_ad = ep->dma_addr1; + } + + + if(ep->is_in) { + deptsiz.d32 = dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz); + } else { + deptsiz.d32 = dwc_read_reg32(&core_if->dev_if->out_ep_regs[ep->num]->doeptsiz); + } + + if(!deptsiz.b.xfersize) { + offset = 0; + for(i = 0; i < ep->pkt_cnt; i += ep->pkt_per_frm) + { + frame_data = ep->data_per_frame; + for(j = 0; j < ep->pkt_per_frm; ++j) { + + /* Packet status - is not set as initially + * it is set to 0 and if packet was sent + successfully, status field will remain 0*/ + + + /* Bytes has been transfered */ + packet_info->length = (ep->maxpacket < frame_data) ? + ep->maxpacket : frame_data; + + /* Received packet offset */ + packet_info->offset = offset; + offset += packet_info->length; + frame_data -= packet_info->length; + + packet_info ++; + } + } + return 1; + } else { + /* This is a workaround for in case of Transfer Complete with + * PktDrpSts interrupts merging - in this case Transfer complete + * interrupt for Isoc Out Endpoint is asserted without PktDrpSts + * set and with DOEPTSIZ register non zero. Investigations showed, + * that this happens when Out packet is dropped, but because of + * interrupts merging during first interrupt handling PktDrpSts + * bit is cleared and for next merged interrupts it is not reset. + * In this case SW hadles the interrupt as if PktDrpSts bit is set. + */ + if(ep->is_in) { + return 1; + } else { + return handle_iso_out_pkt_dropped(core_if, ep); + } + } +} + +/** + * This function is to handle Iso EP transfer complete interrupt + * + * @param ep The EP for which transfer complete was asserted + * + */ +static void complete_iso_ep(dwc_otg_pcd_ep_t *ep) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); + dwc_ep_t *dwc_ep = &ep->dwc_ep; + uint8_t is_last = 0; + + if(core_if->dma_enable) { + if(core_if->dma_desc_enable) { + set_ddma_iso_pkts_info(core_if, dwc_ep); + reinit_ddma_iso_xfer(core_if, dwc_ep); + is_last = 1; + } else { + if(core_if->pti_enh_enable) { + if(set_iso_pkts_info(core_if, dwc_ep)) { + dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1; + dwc_otg_iso_ep_start_buf_transfer(core_if, dwc_ep); + is_last = 1; + } + } else { + set_current_pkt_info(core_if, dwc_ep); + if(dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { + is_last = 1; + dwc_ep->cur_pkt = 0; + dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1; + if(dwc_ep->proc_buf_num) { + dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff1; + dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr1; + } else { + dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff0; + dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr0; + } + + } + dwc_otg_iso_ep_start_frm_transfer(core_if, dwc_ep); + } + } + } else { + set_current_pkt_info(core_if, dwc_ep); + if(dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { + is_last = 1; + dwc_ep->cur_pkt = 0; + dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1; + if(dwc_ep->proc_buf_num) { + dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff1; + dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr1; + } else { + dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff0; + dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr0; + } + + } + dwc_otg_iso_ep_start_frm_transfer(core_if, dwc_ep); + } + if(is_last) + dwc_otg_iso_buffer_done(ep, ep->iso_req); +} + +#endif //DWC_EN_ISOC + /** @@ -1787,23 +2498,25 @@ * ep0state. */ -static void handle_ep0( dwc_otg_pcd_t *_pcd ) -{ - dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd); - dwc_otg_pcd_ep_t *ep0 = &_pcd->ep0; - +static void handle_ep0(dwc_otg_pcd_t *pcd) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; + desc_sts_data_t desc_sts; + deptsiz0_data_t deptsiz; + uint32_t byte_count; + #ifdef DEBUG_EP0 DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__); - print_ep0_state(_pcd); + print_ep0_state(pcd); #endif - - switch (_pcd->ep0state) - { + + switch (pcd->ep0state) { case EP0_DISCONNECT: break; case EP0_IDLE: - _pcd->request_config = 0; - - pcd_setup( _pcd ); + pcd->request_config = 0; + + pcd_setup(pcd); break; @@ -1811,9 +2524,9 @@ #ifdef DEBUG_EP0 DWC_DEBUGPL(DBG_PCD, "DATA_IN EP%d-%s: type=%d, mps=%d\n", - ep0->dwc_ep.num, (ep0->dwc_ep.is_in ?"IN":"OUT"), - ep0->dwc_ep.type, ep0->dwc_ep.maxpacket ); + ep0->dwc_ep.num, (ep0->dwc_ep.is_in ?"IN":"OUT"), + ep0->dwc_ep.type, ep0->dwc_ep.maxpacket); #endif - if (core_if->dma_enable) - { + + if (core_if->dma_enable != 0) { /* * For EP0 we can only program 1 packet at a time so we @@ -1823,14 +2536,27 @@ * can complete. */ - dwc_otg_ep_write_packet (core_if, &ep0->dwc_ep, 1); - } - if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) - { - dwc_otg_ep0_continue_transfer ( GET_CORE_IF(_pcd), &ep0->dwc_ep ); + if(core_if->dma_desc_enable == 0) { + deptsiz.d32 = dwc_read_reg32(&core_if->dev_if->in_ep_regs[0]->dieptsiz); + byte_count = ep0->dwc_ep.xfer_len - deptsiz.b.xfersize; + } + else { + desc_sts.d32 = readl(core_if->dev_if->in_desc_addr); + byte_count = ep0->dwc_ep.xfer_len - desc_sts.b.bytes; + } + ep0->dwc_ep.xfer_count += byte_count; + ep0->dwc_ep.xfer_buff += byte_count; + ep0->dwc_ep.dma_addr += byte_count; + } + if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) { + dwc_otg_ep0_continue_transfer (GET_CORE_IF(pcd), &ep0->dwc_ep); DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); } - else - { - ep0_complete_request( ep0 ); + else if(ep0->dwc_ep.sent_zlp) { + dwc_otg_ep0_continue_transfer (GET_CORE_IF(pcd), &ep0->dwc_ep); + ep0->dwc_ep.sent_zlp = 0; + DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); + } + else { + ep0_complete_request(ep0); DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); } @@ -1839,55 +2565,48 @@ #ifdef DEBUG_EP0 DWC_DEBUGPL(DBG_PCD, "DATA_OUT EP%d-%s: type=%d, mps=%d\n", - ep0->dwc_ep.num, (ep0->dwc_ep.is_in ?"IN":"OUT"), - ep0->dwc_ep.type, ep0->dwc_ep.maxpacket ); + ep0->dwc_ep.num, (ep0->dwc_ep.is_in ?"IN":"OUT"), + ep0->dwc_ep.type, ep0->dwc_ep.maxpacket); #endif - ep0_complete_request( ep0 ); + if (core_if->dma_enable != 0) { + if(core_if->dma_desc_enable == 0) { + deptsiz.d32 = dwc_read_reg32(&core_if->dev_if->out_ep_regs[0]->doeptsiz); + byte_count = ep0->dwc_ep.maxpacket - deptsiz.b.xfersize; + } + else { + desc_sts.d32 = readl(core_if->dev_if->out_desc_addr); + byte_count = ep0->dwc_ep.maxpacket - desc_sts.b.bytes; + } + ep0->dwc_ep.xfer_count += byte_count; + ep0->dwc_ep.xfer_buff += byte_count; + ep0->dwc_ep.dma_addr += byte_count; + } + if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) { + dwc_otg_ep0_continue_transfer (GET_CORE_IF(pcd), &ep0->dwc_ep); + DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); + } + else if(ep0->dwc_ep.sent_zlp) { + dwc_otg_ep0_continue_transfer (GET_CORE_IF(pcd), &ep0->dwc_ep); + ep0->dwc_ep.sent_zlp = 0; + DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); + } + else { + ep0_complete_request(ep0); + DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); + } break; - case EP0_STATUS: + case EP0_IN_STATUS_PHASE: + case EP0_OUT_STATUS_PHASE: DWC_DEBUGPL(DBG_PCD, "CASE: EP0_STATUS\n"); - ep0_complete_request( ep0 ); - _pcd->ep0state = EP0_IDLE; - ep0->stopped = 1; - ep0->dwc_ep.is_in = 0; /* OUT for next SETUP */ + ep0_complete_request(ep0); + pcd->ep0state = EP0_IDLE; + ep0->stopped = 1; + ep0->dwc_ep.is_in = 0; /* OUT for next SETUP */ /* Prepare for more SETUP Packets */ - if (core_if->dma_enable) - { - ep0_out_start( core_if, _pcd ); - } - - if (!GET_CORE_IF(_pcd)->dma_enable) - { - int i; - - depctl_data_t diepctl; - diepctl.d32 = dwc_read_reg32( &core_if->dev_if->in_ep_regs[0]->diepctl); - - if (_pcd->ep0.queue_sof) - { - _pcd->ep0.queue_sof = 0; - start_next_request (&_pcd->ep0); - } - - diepctl.d32 = dwc_read_reg32( &core_if->dev_if->in_ep_regs[0]->diepctl); - - if (_pcd->ep0.queue_sof) - { - _pcd->ep0.queue_sof = 0; - start_next_request (&_pcd->ep0); - } - for (i=0; i < core_if->dev_if->num_in_eps; i++) - { - diepctl.d32 = dwc_read_reg32( &core_if->dev_if->in_ep_regs[i+1]->diepctl); - - if (_pcd->in_ep[i].queue_sof) - { - _pcd->in_ep[i].queue_sof = 0; - start_next_request (&_pcd->in_ep[i]); - } - } - } + if(core_if->dma_enable) { + ep0_out_start(core_if, pcd); + } break; @@ -1897,62 +2616,63 @@ } #ifdef DEBUG_EP0 - print_ep0_state(_pcd); + print_ep0_state(pcd); #endif } + /** * Restart transfer */ -static void restart_transfer( dwc_otg_pcd_t *_pcd, const uint32_t _epnum) -{ - dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd); - dwc_otg_dev_if_t *dev_if = core_if->dev_if; +static void restart_transfer(dwc_otg_pcd_t *pcd, const uint32_t epnum) +{ + dwc_otg_core_if_t *core_if; + dwc_otg_dev_if_t *dev_if; deptsiz_data_t dieptsiz = {.d32=0}; - //depctl_data_t diepctl = {.d32=0}; dwc_otg_pcd_ep_t *ep; - dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[_epnum]->dieptsiz); - - ep = get_in_ep(_pcd, _epnum); -/* - if(_epnum != 0) - ep = &_pcd->in_ep[ _epnum - 1]; - else - ep = &_pcd->ep0; -*/ + ep = get_in_ep(pcd, epnum); + +#ifdef DWC_EN_ISOC + if(ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { + return; + } +#endif /* DWC_EN_ISOC */ + + core_if = GET_CORE_IF(pcd); + dev_if = core_if->dev_if; + + dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dieptsiz); + DWC_DEBUGPL(DBG_PCD,"xfer_buff=%p xfer_count=%0x xfer_len=%0x" - " stopped=%d\n", ep->dwc_ep.xfer_buff, - ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len , - ep->stopped); + " stopped=%d\n", ep->dwc_ep.xfer_buff, + ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len , + ep->stopped); /* * If xfersize is 0 and pktcnt in not 0, resend the last packet. */ - if ( dieptsiz.b.pktcnt && dieptsiz.b.xfersize == 0 && - ep->dwc_ep.start_xfer_buff != 0) - { - if ( ep->dwc_ep.xfer_len <= ep->dwc_ep.maxpacket ) - { + if (dieptsiz.b.pktcnt && dieptsiz.b.xfersize == 0 && + ep->dwc_ep.start_xfer_buff != 0) { + if (ep->dwc_ep.total_len <= ep->dwc_ep.maxpacket) { ep->dwc_ep.xfer_count = 0; ep->dwc_ep.xfer_buff = ep->dwc_ep.start_xfer_buff; + ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count; } - else - { + else { ep->dwc_ep.xfer_count -= ep->dwc_ep.maxpacket; /* convert packet size to dwords. */ ep->dwc_ep.xfer_buff -= ep->dwc_ep.maxpacket; + ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count; } ep->stopped = 0; DWC_DEBUGPL(DBG_PCD,"xfer_buff=%p xfer_count=%0x " - "xfer_len=%0x stopped=%d\n", - ep->dwc_ep.xfer_buff, - ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len , - ep->stopped - ); - if (_epnum == 0) - { + "xfer_len=%0x stopped=%d\n", + ep->dwc_ep.xfer_buff, + ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len , + ep->stopped + ); + if (epnum == 0) { dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep); } - else - { + else { dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep); } @@ -1964,8 +2684,8 @@ * handle the IN EP disable interrupt. */ -static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t *_pcd, - const uint32_t _epnum) -{ - dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd); +static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t *pcd, + const uint32_t epnum) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); dwc_otg_dev_if_t *dev_if = core_if->dev_if; deptsiz_data_t dieptsiz = {.d32=0}; @@ -1974,50 +2694,39 @@ dwc_ep_t *dwc_ep; - ep = get_in_ep(_pcd, _epnum); + ep = get_in_ep(pcd, epnum); dwc_ep = &ep->dwc_ep; -/* - if(_epnum != 0) - { - ep = &_pcd->in_ep[ _epnum - 1]; - dwc_ep = &_pcd->in_ep[ _epnum - 1].dwc_ep; - } - else - { - ep = &_pcd->ep0; - dwc_ep = &_pcd->ep0.dwc_ep; - } -*/ - DWC_DEBUGPL(DBG_PCD,"diepctl%d=%0x\n", _epnum, - dwc_read_reg32(&dev_if->in_ep_regs[_epnum]->diepctl)); - dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[_epnum]->dieptsiz); + + if(dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { + dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num); + return; + } + + DWC_DEBUGPL(DBG_PCD,"diepctl%d=%0x\n", epnum, + dwc_read_reg32(&dev_if->in_ep_regs[epnum]->diepctl)); + dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dieptsiz); DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n", - dieptsiz.b.pktcnt, - dieptsiz.b.xfersize ); - - if (ep->stopped) - { + dieptsiz.b.pktcnt, + dieptsiz.b.xfersize); + + if (ep->stopped) { /* Flush the Tx FIFO */ - /** @todo NGS: This is not the correct FIFO */ - dwc_otg_flush_tx_fifo( core_if, 0 ); + dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num); /* Clear the Global IN NP NAK */ dctl.d32 = 0; dctl.b.cgnpinnak = 1; dwc_modify_reg32(&dev_if->dev_global_regs->dctl, - dctl.d32, 0); + dctl.d32, 0); /* Restart the transaction */ if (dieptsiz.b.pktcnt != 0 || - dieptsiz.b.xfersize != 0) - { - restart_transfer( _pcd, _epnum ); + dieptsiz.b.xfersize != 0) { + restart_transfer(pcd, epnum); } } - else - { + else { /* Restart the transaction */ if (dieptsiz.b.pktcnt != 0 || - dieptsiz.b.xfersize != 0) - { - restart_transfer( _pcd, _epnum ); + dieptsiz.b.xfersize != 0) { + restart_transfer(pcd, epnum); } DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n"); @@ -2028,13 +2737,13 @@ * Handler for the IN EP timeout handshake interrupt. */ -static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t *_pcd, - const uint32_t _epnum) -{ - dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd); +static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t *pcd, + const uint32_t epnum) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); dwc_otg_dev_if_t *dev_if = core_if->dev_if; #ifdef DEBUG deptsiz_data_t dieptsiz = {.d32=0}; - uint32_t epnum = 0; + uint32_t num = 0; #endif dctl_data_t dctl = {.d32=0}; @@ -2043,17 +2752,10 @@ gintmsk_data_t intr_mask = {.d32 = 0}; - ep = get_in_ep(_pcd, _epnum); -/* - if(_epnum != 0) - ep = &_pcd->in_ep[ _epnum - 1]; - else - ep = &_pcd->ep0; -*/ + ep = get_in_ep(pcd, epnum); /* Disable the NP Tx Fifo Empty Interrrupt */ - if (!core_if->dma_enable) - { + if (!core_if->dma_enable) { intr_mask.b.nptxfempty = 1; - dwc_modify_reg32( &core_if->core_global_regs->gintmsk, intr_mask.d32, 0); + dwc_modify_reg32(&core_if->core_global_regs->gintmsk, intr_mask.d32, 0); } /** @todo NGS Check EP type. @@ -2064,5 +2766,5 @@ /* Enable the Global IN NAK Effective Interrupt */ intr_mask.b.ginnakeff = 1; - dwc_modify_reg32( &core_if->core_global_regs->gintmsk, + dwc_modify_reg32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32); @@ -2075,8 +2777,8 @@ #ifdef DEBUG - dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dieptsiz); + dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[num]->dieptsiz); DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n", - dieptsiz.b.pktcnt, - dieptsiz.b.xfersize ); + dieptsiz.b.pktcnt, + dieptsiz.b.xfersize); #endif @@ -2088,5 +2790,5 @@ diepctl.d32 = 0; diepctl.b.snak = 1; - dwc_modify_reg32(&dev_if->in_ep_regs[epnum]->diepctl, diepctl.d32, diepctl.d32); + dwc_modify_reg32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32, diepctl.d32); ep->disabling = 1; ep->stopped = 1; @@ -2094,4 +2796,103 @@ } +/** + * Handler for the IN EP NAK interrupt. + */ +static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t *pcd, + const uint32_t epnum) +{ + /** @todo implement ISR */ + dwc_otg_core_if_t* core_if; + diepmsk_data_t intr_mask = { .d32 = 0}; + + DWC_PRINT("INTERRUPT Handler not implemented for %s\n", "IN EP NAK"); + core_if = GET_CORE_IF(pcd); + intr_mask.b.nak = 1; + + if(core_if->multiproc_int_enable) { + dwc_modify_reg32(&core_if->dev_if->dev_global_regs->diepeachintmsk[epnum], + intr_mask.d32, 0); + } else { + dwc_modify_reg32(&core_if->dev_if->dev_global_regs->diepmsk, + intr_mask.d32, 0); + } + + return 1; +} + +/** + * Handler for the OUT EP Babble interrupt. + */ +static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t *pcd, + const uint32_t epnum) +{ + /** @todo implement ISR */ + dwc_otg_core_if_t* core_if; + doepmsk_data_t intr_mask = { .d32 = 0}; + + DWC_PRINT("INTERRUPT Handler not implemented for %s\n", "OUT EP Babble"); + core_if = GET_CORE_IF(pcd); + intr_mask.b.babble = 1; + + if(core_if->multiproc_int_enable) { + dwc_modify_reg32(&core_if->dev_if->dev_global_regs->doepeachintmsk[epnum], + intr_mask.d32, 0); + } else { + dwc_modify_reg32(&core_if->dev_if->dev_global_regs->doepmsk, + intr_mask.d32, 0); + } + + return 1; +} + +/** + * Handler for the OUT EP NAK interrupt. + */ +static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t *pcd, + const uint32_t epnum) +{ + /** @todo implement ISR */ + dwc_otg_core_if_t* core_if; + doepmsk_data_t intr_mask = { .d32 = 0}; + + DWC_PRINT("INTERRUPT Handler not implemented for %s\n", "OUT EP NAK"); + core_if = GET_CORE_IF(pcd); + intr_mask.b.nak = 1; + + if(core_if->multiproc_int_enable) { + dwc_modify_reg32(&core_if->dev_if->dev_global_regs->doepeachintmsk[epnum], + intr_mask.d32, 0); + } else { + dwc_modify_reg32(&core_if->dev_if->dev_global_regs->doepmsk, + intr_mask.d32, 0); + } + + return 1; +} + +/** + * Handler for the OUT EP NYET interrupt. + */ +static inline int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t *pcd, + const uint32_t epnum) +{ + /** @todo implement ISR */ + dwc_otg_core_if_t* core_if; + doepmsk_data_t intr_mask = { .d32 = 0}; + + DWC_PRINT("INTERRUPT Handler not implemented for %s\n", "OUT EP NYET"); + core_if = GET_CORE_IF(pcd); + intr_mask.b.nyet = 1; + + if(core_if->multiproc_int_enable) { + dwc_modify_reg32(&core_if->dev_if->dev_global_regs->doepeachintmsk[epnum], + intr_mask.d32, 0); + } else { + dwc_modify_reg32(&core_if->dev_if->dev_global_regs->doepmsk, + intr_mask.d32, 0); + } + + return 1; +} /** @@ -2111,5 +2912,5 @@ * Mismatch Interrupt) */ -static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t *_pcd) +static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t *pcd) { #define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \ @@ -2121,61 +2922,56 @@ } while (0) - dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd); + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); dwc_otg_dev_if_t *dev_if = core_if->dev_if; diepint_data_t diepint = {.d32=0}; - depctl_data_t diepctl = {.d32=0}; + dctl_data_t dctl = {.d32=0}; + depctl_data_t depctl = {.d32=0}; uint32_t ep_intr; uint32_t epnum = 0; dwc_otg_pcd_ep_t *ep; dwc_ep_t *dwc_ep; - uint32_t _empty_msk, _diepctl; gintmsk_data_t intr_mask = {.d32 = 0}; - DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd); + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, pcd); /* Read in the device interrupt bits */ - ep_intr = dwc_otg_read_dev_all_in_ep_intr( core_if ); + ep_intr = dwc_otg_read_dev_all_in_ep_intr(core_if); /* Service the Device IN interrupts for each endpoint */ - while( ep_intr ) - { - if (ep_intr&0x1) - { - - + while(ep_intr) { + if (ep_intr&0x1) { + uint32_t empty_msk; /* Get EP pointer */ - ep = get_in_ep(_pcd, epnum); + ep = get_in_ep(pcd, epnum); dwc_ep = &ep->dwc_ep; - _diepctl = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->diepctl); - _empty_msk = dwc_read_reg32(&dev_if->dev_global_regs->dtknqr4_fifoemptymsk); - - DWC_DEBUGPL(DBG_PCDV, "IN EP INTERRUPT - %d\nepmty_msk - %8x diepctl - %8x\n",epnum, _empty_msk, _diepctl); + depctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->diepctl); + empty_msk = dwc_read_reg32(&dev_if->dev_global_regs->dtknqr4_fifoemptymsk); + + DWC_DEBUGPL(DBG_PCDV, + "IN EP INTERRUPT - %d\nepmty_msk - %8x diepctl - %8x\n", + epnum, + empty_msk, + depctl.d32); DWC_DEBUGPL(DBG_PCD, - "EP%d-%s: type=%d, mps=%d\n", - dwc_ep->num, (dwc_ep->is_in ?"IN":"OUT"), - dwc_ep->type, dwc_ep->maxpacket ); - - diepint.d32 = dwc_otg_read_dev_in_ep_intr( core_if, dwc_ep ); - + "EP%d-%s: type=%d, mps=%d\n", + dwc_ep->num, (dwc_ep->is_in ?"IN":"OUT"), + dwc_ep->type, dwc_ep->maxpacket); + + diepint.d32 = dwc_otg_read_dev_in_ep_intr(core_if, dwc_ep); + DWC_DEBUGPL(DBG_PCDV, "EP %d Interrupt Register - 0x%x\n", epnum, diepint.d32); /* Transfer complete */ - if ( diepint.b.xfercompl ) - { - - DWC_DEBUGPL(DBG_PCD,"EP%d IN Xfer Complete\n", epnum); - + if (diepint.b.xfercompl) { /* Disable the NP Tx FIFO Empty * Interrrupt */ - if(core_if->en_multiple_tx_fifo == 0) - { + if(core_if->en_multiple_tx_fifo == 0) { intr_mask.b.nptxfempty = 1; - dwc_modify_reg32( &core_if->core_global_regs->gintmsk, intr_mask.d32, 0); + dwc_modify_reg32(&core_if->core_global_regs->gintmsk, intr_mask.d32, 0); } - else - { + else { /* Disable the Tx FIFO Empty Interrupt for this EP */ uint32_t fifoemptymsk = 0x1 << dwc_ep->num; @@ -2185,20 +2981,24 @@ /* Clear the bit in DIEPINTn for this interrupt */ CLEAR_IN_EP_INTR(core_if,epnum,xfercompl); - + /* Complete the transfer */ - if (epnum == 0) - { - handle_ep0( _pcd ); + if (epnum == 0) { + handle_ep0(pcd); } - else - { - complete_ep( ep ); +#ifdef DWC_EN_ISOC + else if(dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { + if(!ep->stopped) + complete_iso_ep(ep); } +#endif //DWC_EN_ISOC + else { + + complete_ep(ep); + } } /* Endpoint disable */ - if ( diepint.b.epdisabled ) - { + if (diepint.b.epdisabled) { DWC_DEBUGPL(DBG_ANY,"EP%d IN disabled\n", epnum); - handle_in_ep_disable_intr( _pcd, epnum ); + handle_in_ep_disable_intr(pcd, epnum); /* Clear the bit in DIEPINTn for this interrupt */ @@ -2206,6 +3006,5 @@ } /* AHB Error */ - if ( diepint.b.ahberr ) - { + if (diepint.b.ahberr) { DWC_DEBUGPL(DBG_ANY,"EP%d IN AHB Error\n", epnum); /* Clear the bit in DIEPINTn for this interrupt */ @@ -2213,42 +3012,55 @@ } /* TimeOUT Handshake (non-ISOC IN EPs) */ - if ( diepint.b.timeout ) - { + if (diepint.b.timeout) { DWC_DEBUGPL(DBG_ANY,"EP%d IN Time-out\n", epnum); - handle_in_ep_timeout_intr( _pcd, epnum ); + handle_in_ep_timeout_intr(pcd, epnum); CLEAR_IN_EP_INTR(core_if,epnum,timeout); } /** IN Token received with TxF Empty */ - if (diepint.b.intktxfemp) - { + if (diepint.b.intktxfemp) { DWC_DEBUGPL(DBG_ANY,"EP%d IN TKN TxFifo Empty\n", epnum); - if (!ep->stopped && epnum != 0) - { + if (!ep->stopped && epnum != 0) { + diepmsk_data_t diepmsk = { .d32 = 0}; diepmsk.b.intktxfemp = 1; - dwc_modify_reg32( &dev_if->dev_global_regs->diepmsk, diepmsk.d32, 0 ); + + if(core_if->multiproc_int_enable) { + dwc_modify_reg32(&dev_if->dev_global_regs->diepeachintmsk[epnum], + diepmsk.d32, 0); + } else { + dwc_modify_reg32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32, 0); + } start_next_request(ep); + } + else if(core_if->dma_desc_enable && epnum == 0 && + pcd->ep0state == EP0_OUT_STATUS_PHASE) { + // EP0 IN set STALL + depctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->diepctl); + + /* set the disable and stall bits */ + if (depctl.b.epena) { + depctl.b.epdis = 1; + } + depctl.b.stall = 1; + dwc_write_reg32(&dev_if->in_ep_regs[epnum]->diepctl, depctl.d32); } CLEAR_IN_EP_INTR(core_if,epnum,intktxfemp); } /** IN Token Received with EP mismatch */ - if (diepint.b.intknepmis) - { + if (diepint.b.intknepmis) { DWC_DEBUGPL(DBG_ANY,"EP%d IN TKN EP Mismatch\n", epnum); CLEAR_IN_EP_INTR(core_if,epnum,intknepmis); } /** IN Endpoint NAK Effective */ - if (diepint.b.inepnakeff) - { + if (diepint.b.inepnakeff) { DWC_DEBUGPL(DBG_ANY,"EP%d IN EP NAK Effective\n", epnum); /* Periodic EP */ - if (ep->disabling) - { - diepctl.d32 = 0; - diepctl.b.snak = 1; - diepctl.b.epdis = 1; - dwc_modify_reg32(&dev_if->in_ep_regs[epnum]->diepctl, diepctl.d32, diepctl.d32); + if (ep->disabling) { + depctl.d32 = 0; + depctl.b.snak = 1; + depctl.b.epdis = 1; + dwc_modify_reg32(&dev_if->in_ep_regs[epnum]->diepctl, depctl.d32, depctl.d32); } CLEAR_IN_EP_INTR(core_if,epnum,inepnakeff); @@ -2257,11 +3069,48 @@ /** IN EP Tx FIFO Empty Intr */ - if (diepint.b.emptyintr) - { + if (diepint.b.emptyintr) { DWC_DEBUGPL(DBG_ANY,"EP%d Tx FIFO Empty Intr \n", epnum); - write_empty_tx_fifo(_pcd, epnum); + write_empty_tx_fifo(pcd, epnum); CLEAR_IN_EP_INTR(core_if,epnum,emptyintr); + } + + /** IN EP BNA Intr */ + if (diepint.b.bna) { + CLEAR_IN_EP_INTR(core_if,epnum,bna); + if(core_if->dma_desc_enable) { +#ifdef DWC_EN_ISOC + if(dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { + /* + * This checking is performed to prevent first "false" BNA + * handling occuring right after reconnect + */ + if(dwc_ep->next_frame != 0xffffffff) + dwc_otg_pcd_handle_iso_bna(ep); + } + else +#endif //DWC_EN_ISOC + { + dctl.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dctl); + + /* If Global Continue on BNA is disabled - disable EP */ + if(!dctl.b.gcontbna) { + depctl.d32 = 0; + depctl.b.snak = 1; + depctl.b.epdis = 1; + dwc_modify_reg32(&dev_if->in_ep_regs[epnum]->diepctl, depctl.d32, depctl.d32); + } else { + start_next_request(ep); + } + } + } + } + /* NAK Interrutp */ + if (diepint.b.nak) { + DWC_DEBUGPL(DBG_ANY,"EP%d IN NAK Interrupt\n", epnum); + handle_in_ep_nak_intr(pcd, epnum); + + CLEAR_IN_EP_INTR(core_if,epnum,nak); } } @@ -2287,5 +3136,5 @@ * Command Processing) */ -static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t *_pcd) +static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t *pcd) { #define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \ @@ -2297,8 +3146,12 @@ } while (0) - dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd); + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); + dwc_otg_dev_if_t *dev_if = core_if->dev_if; uint32_t ep_intr; doepint_data_t doepint = {.d32=0}; + dctl_data_t dctl = {.d32=0}; + depctl_data_t doepctl = {.d32=0}; uint32_t epnum = 0; + dwc_otg_pcd_ep_t *ep; dwc_ep_t *dwc_ep; @@ -2306,49 +3159,62 @@ /* Read in the device interrupt bits */ - ep_intr = dwc_otg_read_dev_all_out_ep_intr( core_if ); - - while( ep_intr ) - { - if (ep_intr&0x1) - { + ep_intr = dwc_otg_read_dev_all_out_ep_intr(core_if); + + while(ep_intr) { + if (ep_intr&0x1) { /* Get EP pointer */ - dwc_ep = &((get_out_ep(_pcd, epnum))->dwc_ep); -// dwc_ep = &_pcd->out_ep[ epnum - 1].dwc_ep; + ep = get_out_ep(pcd, epnum); + dwc_ep = &ep->dwc_ep; + #ifdef VERBOSE DWC_DEBUGPL(DBG_PCDV, - "EP%d-%s: type=%d, mps=%d\n", - dwc_ep->num, (dwc_ep->is_in ?"IN":"OUT"), - dwc_ep->type, dwc_ep->maxpacket ); + "EP%d-%s: type=%d, mps=%d\n", + dwc_ep->num, (dwc_ep->is_in ?"IN":"OUT"), + dwc_ep->type, dwc_ep->maxpacket); #endif doepint.d32 = dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep); + + /* Transfer complete */ + if (doepint.b.xfercompl) { - /* Transfer complete */ - if ( doepint.b.xfercompl ) - { - DWC_DEBUGPL(DBG_PCD,"EP%d OUT Xfer Complete\n", - epnum); - /* Clear the bit in DOEPINTn for this interrupt */ - CLEAR_OUT_EP_INTR(core_if,epnum,xfercompl); - - if (epnum == 0) - { - handle_ep0( _pcd ); - } - else - { - complete_ep( get_out_ep(_pcd, epnum) ); -// complete_ep( &_pcd->out_ep[ epnum - 1] ); + if (epnum == 0) { + /* Clear the bit in DOEPINTn for this interrupt */ + CLEAR_OUT_EP_INTR(core_if,epnum,xfercompl); + if(core_if->dma_desc_enable == 0 || pcd->ep0state != EP0_IDLE) + handle_ep0(pcd); +#ifdef DWC_EN_ISOC + } else if(dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { + if (doepint.b.pktdrpsts == 0) { + /* Clear the bit in DOEPINTn for this interrupt */ + CLEAR_OUT_EP_INTR(core_if,epnum,xfercompl); + complete_iso_ep(ep); + } else { + + doepint_data_t doepint = {.d32=0}; + doepint.b.xfercompl = 1; + doepint.b.pktdrpsts = 1; + dwc_write_reg32(&core_if->dev_if->out_ep_regs[epnum]->doepint, + doepint.d32); + if(handle_iso_out_pkt_dropped(core_if,dwc_ep)) { + complete_iso_ep(ep); + } + } +#endif //DWC_EN_ISOC + } else { + /* Clear the bit in DOEPINTn for this interrupt */ + CLEAR_OUT_EP_INTR(core_if,epnum,xfercompl); + complete_ep(ep); } - } + + } + /* Endpoint disable */ - if ( doepint.b.epdisabled ) - { - DWC_DEBUGPL(DBG_PCD,"EP%d OUT disabled\n", epnum); + if (doepint.b.epdisabled) { + /* Clear the bit in DOEPINTn for this interrupt */ CLEAR_OUT_EP_INTR(core_if,epnum,epdisabled); } /* AHB Error */ - if ( doepint.b.ahberr ) - { + if (doepint.b.ahberr) { DWC_DEBUGPL(DBG_PCD,"EP%d OUT AHB Error\n", epnum); DWC_DEBUGPL(DBG_PCD,"EP DMA REG %d \n", core_if->dev_if->out_ep_regs[epnum]->doepdma); @@ -2356,14 +3222,73 @@ } /* Setup Phase Done (contorl EPs) */ - if ( doepint.b.setup ) - { + if (doepint.b.setup) { #ifdef DEBUG_EP0 DWC_DEBUGPL(DBG_PCD,"EP%d SETUP Done\n", epnum); #endif - handle_ep0( _pcd ); CLEAR_OUT_EP_INTR(core_if,epnum,setup); - } - } + + handle_ep0(pcd); + } + + /** OUT EP BNA Intr */ + if (doepint.b.bna) { + CLEAR_OUT_EP_INTR(core_if,epnum,bna); + if(core_if->dma_desc_enable) { +#ifdef DWC_EN_ISOC + if(dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { + /* + * This checking is performed to prevent first "false" BNA + * handling occuring right after reconnect + */ + if(dwc_ep->next_frame != 0xffffffff) + dwc_otg_pcd_handle_iso_bna(ep); + } + else +#endif //DWC_EN_ISOC + { + dctl.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dctl); + + /* If Global Continue on BNA is disabled - disable EP*/ + if(!dctl.b.gcontbna) { + doepctl.d32 = 0; + doepctl.b.snak = 1; + doepctl.b.epdis = 1; + dwc_modify_reg32(&dev_if->out_ep_regs[epnum]->doepctl, doepctl.d32, doepctl.d32); + } else { + start_next_request(ep); + } + } + } + } + if (doepint.b.stsphsercvd) { + CLEAR_OUT_EP_INTR(core_if,epnum,stsphsercvd); + if(core_if->dma_desc_enable) { + do_setup_in_status_phase(pcd); + } + } + /* Babble Interrutp */ + if (doepint.b.babble) { + DWC_DEBUGPL(DBG_ANY,"EP%d OUT Babble\n", epnum); + handle_out_ep_babble_intr(pcd, epnum); + + CLEAR_OUT_EP_INTR(core_if,epnum,babble); + } + /* NAK Interrutp */ + if (doepint.b.nak) { + DWC_DEBUGPL(DBG_ANY,"EP%d OUT NAK\n", epnum); + handle_out_ep_nak_intr(pcd, epnum); + + CLEAR_OUT_EP_INTR(core_if,epnum,nak); + } + /* NYET Interrutp */ + if (doepint.b.nyet) { + DWC_DEBUGPL(DBG_ANY,"EP%d OUT NYET\n", epnum); + handle_out_ep_nyet_intr(pcd, epnum); + + CLEAR_OUT_EP_INTR(core_if,epnum,nyet); + } + } + epnum++; ep_intr >>=1; @@ -2374,4 +3299,5 @@ #undef CLEAR_OUT_EP_INTR } + /** @@ -2387,20 +3313,66 @@ * Flush FIFO */ -int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t *_pcd) -{ - gintmsk_data_t intr_mask = { .d32 = 0}; - gintsts_data_t gintsts; - DWC_PRINT("INTERRUPT Handler not implemented for %s\n", - "IN ISOC Incomplete"); - - intr_mask.b.incomplisoin = 1; - dwc_modify_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintmsk, - intr_mask.d32, 0 ); +int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t *pcd) +{ + gintsts_data_t gintsts; + + +#ifdef DWC_EN_ISOC + dwc_otg_dev_if_t *dev_if; + deptsiz_data_t deptsiz = { .d32 = 0}; + depctl_data_t depctl = { .d32 = 0}; + dsts_data_t dsts = { .d32 = 0}; + dwc_ep_t *dwc_ep; + int i; + + dev_if = GET_CORE_IF(pcd)->dev_if; + + for(i = 1; i <= dev_if->num_in_eps; ++i) { + dwc_ep = &pcd->in_ep[i].dwc_ep; + if(dwc_ep->active && + dwc_ep->type == USB_ENDPOINT_XFER_ISOC) + { + deptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[i]->dieptsiz); + depctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl); + + if(depctl.b.epdis && deptsiz.d32) { + set_current_pkt_info(GET_CORE_IF(pcd), dwc_ep); + if(dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { + dwc_ep->cur_pkt = 0; + dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1; + + if(dwc_ep->proc_buf_num) { + dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff1; + dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr1; + } else { + dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff0; + dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr0; + } + + } + + dsts.d32 = dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if->dev_global_regs->dsts); + dwc_ep->next_frame = dsts.b.soffn; + + dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF(pcd), dwc_ep); + } + } + } + +#else + gintmsk_data_t intr_mask = { .d32 = 0}; + DWC_PRINT("INTERRUPT Handler not implemented for %s\n", + "IN ISOC Incomplete"); + + intr_mask.b.incomplisoin = 1; + dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, + intr_mask.d32, 0); +#endif //DWC_EN_ISOC /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.incomplisoin = 1; - dwc_write_reg32 (&GET_CORE_IF(_pcd)->core_global_regs->gintsts, - gintsts.d32); + dwc_write_reg32 (&GET_CORE_IF(pcd)->core_global_regs->gintsts, + gintsts.d32); return 1; @@ -2422,21 +3394,68 @@ * re-enable EP. */ -int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t *_pcd) -{ - /** @todo implement ISR */ - gintmsk_data_t intr_mask = { .d32 = 0}; +int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t *pcd) +{ + /* @todo implement ISR */ gintsts_data_t gintsts; - DWC_PRINT("INTERRUPT Handler not implemented for %s\n", - "OUT ISOC Incomplete"); - - intr_mask.b.incomplisoout = 1; - dwc_modify_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintmsk, - intr_mask.d32, 0 ); + +#ifdef DWC_EN_ISOC + dwc_otg_dev_if_t *dev_if; + deptsiz_data_t deptsiz = { .d32 = 0}; + depctl_data_t depctl = { .d32 = 0}; + dsts_data_t dsts = { .d32 = 0}; + dwc_ep_t *dwc_ep; + int i; + + dev_if = GET_CORE_IF(pcd)->dev_if; + + for(i = 1; i <= dev_if->num_out_eps; ++i) { + dwc_ep = &pcd->in_ep[i].dwc_ep; + if(pcd->out_ep[i].dwc_ep.active && + pcd->out_ep[i].dwc_ep.type == USB_ENDPOINT_XFER_ISOC) + { + deptsiz.d32 = dwc_read_reg32(&dev_if->out_ep_regs[i]->doeptsiz); + depctl.d32 = dwc_read_reg32(&dev_if->out_ep_regs[i]->doepctl); + + if(depctl.b.epdis && deptsiz.d32) { + set_current_pkt_info(GET_CORE_IF(pcd), &pcd->out_ep[i].dwc_ep); + if(dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { + dwc_ep->cur_pkt = 0; + dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1; + + if(dwc_ep->proc_buf_num) { + dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff1; + dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr1; + } else { + dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff0; + dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr0; + } + + } + + dsts.d32 = dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if->dev_global_regs->dsts); + dwc_ep->next_frame = dsts.b.soffn; + + dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF(pcd), dwc_ep); + } + } + } +#else + /** @todo implement ISR */ + gintmsk_data_t intr_mask = { .d32 = 0}; + + DWC_PRINT("INTERRUPT Handler not implemented for %s\n", + "OUT ISOC Incomplete"); + + intr_mask.b.incomplisoout = 1; + dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, + intr_mask.d32, 0); + +#endif // DWC_EN_ISOC /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.incomplisoout = 1; - dwc_write_reg32 (&GET_CORE_IF(_pcd)->core_global_regs->gintsts, - gintsts.d32); + dwc_write_reg32 (&GET_CORE_IF(pcd)->core_global_regs->gintsts, + gintsts.d32); return 1; @@ -2447,7 +3466,7 @@ * */ -int32_t dwc_otg_pcd_handle_in_nak_effective( dwc_otg_pcd_t *_pcd ) -{ - dwc_otg_dev_if_t *dev_if = GET_CORE_IF(_pcd)->dev_if; +int32_t dwc_otg_pcd_handle_in_nak_effective(dwc_otg_pcd_t *pcd) +{ + dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; depctl_data_t diepctl = { .d32 = 0}; depctl_data_t diepctl_rd = { .d32 = 0}; @@ -2465,13 +3484,12 @@ { diepctl_rd.d32 = dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl); - if (diepctl_rd.b.epena) - { - dwc_write_reg32( &dev_if->in_ep_regs[i]->diepctl, - diepctl.d32 ); + if (diepctl_rd.b.epena) { + dwc_write_reg32(&dev_if->in_ep_regs[i]->diepctl, + diepctl.d32); } } /* Disable the Global IN NAK Effective Interrupt */ intr_mask.b.ginnakeff = 1; - dwc_modify_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintmsk, + dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, intr_mask.d32, 0); @@ -2479,5 +3497,5 @@ gintsts.d32 = 0; gintsts.b.ginnakeff = 1; - dwc_write_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintsts, + dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, gintsts.d32); @@ -2489,5 +3507,5 @@ * */ -int32_t dwc_otg_pcd_handle_out_nak_effective( dwc_otg_pcd_t *_pcd ) +int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t *pcd) { gintmsk_data_t intr_mask = { .d32 = 0}; @@ -2498,5 +3516,5 @@ /* Disable the Global IN NAK Effective Interrupt */ intr_mask.b.goutnakeff = 1; - dwc_modify_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintmsk, + dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, intr_mask.d32, 0); @@ -2504,5 +3522,5 @@ gintsts.d32 = 0; gintsts.b.goutnakeff = 1; - dwc_write_reg32 (&GET_CORE_IF(_pcd)->core_global_regs->gintsts, + dwc_write_reg32 (&GET_CORE_IF(pcd)->core_global_regs->gintsts, gintsts.d32); @@ -2523,7 +3541,7 @@ * */ -int32_t dwc_otg_pcd_handle_intr( dwc_otg_pcd_t *_pcd ) -{ - dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd); +int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t *pcd) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); #ifdef VERBOSE dwc_otg_core_global_regs_t *global_regs = @@ -2537,96 +3555,98 @@ DWC_DEBUGPL(DBG_ANY, "%s() gintsts=%08x gintmsk=%08x\n", __func__, - dwc_read_reg32( &global_regs->gintsts), - dwc_read_reg32( &global_regs->gintmsk)); + dwc_read_reg32(&global_regs->gintsts), + dwc_read_reg32(&global_regs->gintmsk)); #endif - if (dwc_otg_is_device_mode(core_if)) - { - SPIN_LOCK(&_pcd->lock); + if (dwc_otg_is_device_mode(core_if)) { + SPIN_LOCK(&pcd->lock); #ifdef VERBOSE DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%08x gintmsk=%08x\n", __func__, - dwc_read_reg32( &global_regs->gintsts), - dwc_read_reg32( &global_regs->gintmsk)); + dwc_read_reg32(&global_regs->gintsts), + dwc_read_reg32(&global_regs->gintmsk)); #endif - + gintr_status.d32 = dwc_otg_read_core_intr(core_if); - if (!gintr_status.d32) - { + +/* + if (!gintr_status.d32) { + SPIN_UNLOCK(&pcd->lock); return 0; } +*/ DWC_DEBUGPL(DBG_PCDV, "%s: gintsts&gintmsk=%08x\n", - __func__, gintr_status.d32 ); - - if (gintr_status.b.sofintr) - { - retval |= dwc_otg_pcd_handle_sof_intr( _pcd ); - } - if (gintr_status.b.rxstsqlvl) - { - retval |= dwc_otg_pcd_handle_rx_status_q_level_intr( _pcd ); - } - if (gintr_status.b.nptxfempty) - { - retval |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr( _pcd ); - } - if (gintr_status.b.ginnakeff) - { - retval |= dwc_otg_pcd_handle_in_nak_effective( _pcd ); - } - if (gintr_status.b.goutnakeff) - { - retval |= dwc_otg_pcd_handle_out_nak_effective( _pcd ); - } - if (gintr_status.b.i2cintr) - { - retval |= dwc_otg_pcd_handle_i2c_intr( _pcd ); - } - if (gintr_status.b.erlysuspend) - { - retval |= dwc_otg_pcd_handle_early_suspend_intr( _pcd ); - } - if (gintr_status.b.usbreset) - { - retval |= dwc_otg_pcd_handle_usb_reset_intr( _pcd ); - } - if (gintr_status.b.enumdone) - { - retval |= dwc_otg_pcd_handle_enum_done_intr( _pcd ); - } - if (gintr_status.b.isooutdrop) - { - retval |= dwc_otg_pcd_handle_isoc_out_packet_dropped_intr( _pcd ); - } - if (gintr_status.b.eopframe) - { - retval |= dwc_otg_pcd_handle_end_periodic_frame_intr( _pcd ); - } - if (gintr_status.b.epmismatch) - { - retval |= dwc_otg_pcd_handle_ep_mismatch_intr( core_if ); - } - if (gintr_status.b.inepint) - { - retval |= dwc_otg_pcd_handle_in_ep_intr( _pcd ); - } - if (gintr_status.b.outepintr) - { - retval |= dwc_otg_pcd_handle_out_ep_intr( _pcd ); - } - if (gintr_status.b.incomplisoin) - { - retval |= dwc_otg_pcd_handle_incomplete_isoc_in_intr( _pcd ); - } - if (gintr_status.b.incomplisoout) - { - retval |= dwc_otg_pcd_handle_incomplete_isoc_out_intr( _pcd ); + __func__, gintr_status.d32); + + if (gintr_status.b.sofintr) { + retval |= dwc_otg_pcd_handle_sof_intr(pcd); + } + if (gintr_status.b.rxstsqlvl) { + retval |= dwc_otg_pcd_handle_rx_status_q_level_intr(pcd); + } + if (gintr_status.b.nptxfempty) { + retval |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr(pcd); + } + if (gintr_status.b.ginnakeff) { + retval |= dwc_otg_pcd_handle_in_nak_effective(pcd); + } + if (gintr_status.b.goutnakeff) { + retval |= dwc_otg_pcd_handle_out_nak_effective(pcd); + } + if (gintr_status.b.i2cintr) { + retval |= dwc_otg_pcd_handle_i2c_intr(pcd); + } + if (gintr_status.b.erlysuspend) { + retval |= dwc_otg_pcd_handle_early_suspend_intr(pcd); + } + if (gintr_status.b.usbreset) { + retval |= dwc_otg_pcd_handle_usb_reset_intr(pcd); + } + if (gintr_status.b.enumdone) { + retval |= dwc_otg_pcd_handle_enum_done_intr(pcd); + } + if (gintr_status.b.isooutdrop) { + retval |= dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(pcd); + } + if (gintr_status.b.eopframe) { + retval |= dwc_otg_pcd_handle_end_periodic_frame_intr(pcd); + } + if (gintr_status.b.epmismatch) { + retval |= dwc_otg_pcd_handle_ep_mismatch_intr(core_if); + } + if (gintr_status.b.inepint) { + if(!core_if->multiproc_int_enable) { + retval |= dwc_otg_pcd_handle_in_ep_intr(pcd); + } + } + if (gintr_status.b.outepintr) { + if(!core_if->multiproc_int_enable) { + retval |= dwc_otg_pcd_handle_out_ep_intr(pcd); + } + } + if (gintr_status.b.incomplisoin) { + retval |= dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd); + } + if (gintr_status.b.incomplisoout) { + retval |= dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd); + } + + /* In MPI mode De vice Endpoints intterrupts are asserted + * without setting outepintr and inepint bits set, so these + * Interrupt handlers are called without checking these bit-fields + */ + if(core_if->multiproc_int_enable) { + retval |= dwc_otg_pcd_handle_in_ep_intr(pcd); + retval |= dwc_otg_pcd_handle_out_ep_intr(pcd); } #ifdef VERBOSE DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__, - dwc_read_reg32( &global_regs->gintsts)); + dwc_read_reg32(&global_regs->gintsts)); #endif - SPIN_UNLOCK(&_pcd->lock); - } + SPIN_UNLOCK(&pcd->lock); + } + + S3C2410X_CLEAR_EINTPEND(); + return retval; } Index: /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_hcd_queue.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_hcd_queue.c (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_hcd_queue.c (revision 12433) @@ -1,6 +1,6 @@ /* ========================================================================== * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_hcd_queue.c $ - * $Revision: 1.1 $ - * $Date: 2007-11-19 05:39:07 $ + * $Revision: 1.5 $ + * $Date: 2008-12-15 06:51:32 $ * $Change: 537387 $ * @@ -51,4 +51,5 @@ #include //#include +#include #include "dwc_otg_driver.h" @@ -59,10 +60,10 @@ * This function allocates and initializes a QH. * - * @param _hcd The HCD state structure for the DWC OTG controller. - * @param[in] _urb Holds the information about the device/endpoint that we need + * @param hcd The HCD state structure for the DWC OTG controller. + * @param[in] urb Holds the information about the device/endpoint that we need * to initialize the QH. * * @return Returns pointer to the newly allocated QH, or NULL on error. */ -dwc_otg_qh_t *dwc_otg_hcd_qh_create (dwc_otg_hcd_t *_hcd, struct urb *_urb) +dwc_otg_qh_t *dwc_otg_hcd_qh_create (dwc_otg_hcd_t *hcd, struct urb *urb) { dwc_otg_qh_t *qh; @@ -75,5 +76,5 @@ } - dwc_otg_hcd_qh_init (_hcd, qh, _urb); + dwc_otg_hcd_qh_init (hcd, qh, urb); return qh; } @@ -83,7 +84,8 @@ * Dequeue. * - * @param[in] _qh The QH to free. - */ -void dwc_otg_hcd_qh_free (dwc_otg_qh_t *_qh) + * @param[in] hcd HCD instance. + * @param[in] qh The QH to free. + */ +void dwc_otg_hcd_qh_free (dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) { dwc_otg_qtd_t *qtd; @@ -92,8 +94,8 @@ /* Free each QTD in the QTD list */ - local_irq_save (flags); - for (pos = _qh->qtd_list.next; - pos != &_qh->qtd_list; - pos = _qh->qtd_list.next) + SPIN_LOCK_IRQSAVE(&hcd->lock, flags) + for (pos = qh->qtd_list.next; + pos != &qh->qtd_list; + pos = qh->qtd_list.next) { list_del (pos); @@ -101,7 +103,14 @@ dwc_otg_hcd_qtd_free (qtd); } - local_irq_restore (flags); - - kfree (_qh); + SPIN_UNLOCK_IRQRESTORE(&hcd->lock, flags) + + if (qh->dw_align_buf) { + dma_free_coherent((dwc_otg_hcd_to_hcd(hcd))->self.controller, + hcd->core_if->core_params->max_transfer_size, + qh->dw_align_buf, + qh->dw_align_buf_dma); + } + + kfree (qh); return; } @@ -109,80 +118,99 @@ /** Initializes a QH structure. * - * @param[in] _hcd The HCD state structure for the DWC OTG controller. - * @param[in] _qh The QH to init. - * @param[in] _urb Holds the information about the device/endpoint that we need + * @param[in] hcd The HCD state structure for the DWC OTG controller. + * @param[in] qh The QH to init. + * @param[in] urb Holds the information about the device/endpoint that we need * to initialize the QH. */ #define SCHEDULE_SLOP 10 -void dwc_otg_hcd_qh_init(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh, struct urb *_urb) -{ - memset (_qh, 0, sizeof (dwc_otg_qh_t)); +void dwc_otg_hcd_qh_init(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh, struct urb *urb) +{ + char *speed, *type; + memset (qh, 0, sizeof (dwc_otg_qh_t)); /* Initialize QH */ - switch (usb_pipetype(_urb->pipe)) { + switch (usb_pipetype(urb->pipe)) { case PIPE_CONTROL: - _qh->ep_type = USB_ENDPOINT_XFER_CONTROL; + qh->ep_type = USB_ENDPOINT_XFER_CONTROL; break; case PIPE_BULK: - _qh->ep_type = USB_ENDPOINT_XFER_BULK; + qh->ep_type = USB_ENDPOINT_XFER_BULK; break; case PIPE_ISOCHRONOUS: - _qh->ep_type = USB_ENDPOINT_XFER_ISOC; + qh->ep_type = USB_ENDPOINT_XFER_ISOC; break; case PIPE_INTERRUPT: - _qh->ep_type = USB_ENDPOINT_XFER_INT; - break; - } - - _qh->ep_is_in = usb_pipein(_urb->pipe) ? 1 : 0; - - _qh->data_toggle = DWC_OTG_HC_PID_DATA0; - _qh->maxp = usb_maxpacket(_urb->dev, _urb->pipe, !(usb_pipein(_urb->pipe))); - INIT_LIST_HEAD(&_qh->qtd_list); - INIT_LIST_HEAD(&_qh->qh_list_entry); - _qh->channel = NULL; + qh->ep_type = USB_ENDPOINT_XFER_INT; + break; + } + + qh->ep_is_in = usb_pipein(urb->pipe) ? 1 : 0; + + qh->data_toggle = DWC_OTG_HC_PID_DATA0; + qh->maxp = usb_maxpacket(urb->dev, urb->pipe, !(usb_pipein(urb->pipe))); +#if 0 /* marklin 20090310 : patch from mobiletechnika */ + /* Special hook for SQN11x0 */ + if( (qh->ep_type == USB_ENDPOINT_XFER_BULK) + && (urb->dev->speed == USB_SPEED_HIGH) ) { + struct usb_device_descriptor *desc = &urb->dev->descriptor; + if (desc->idVendor == 0x148e && + (desc->idProduct == 0x0900 || desc->idProduct == 0x0A00) ) { + if( 256 < dwc_max_packet(qh->maxp) ){ + qh->maxp&= ~0x07FF; + qh->maxp|= 256; + } + printk("SQN pathed qh->maxp= 0x%x,maxp= 0x%x,%s\n",qh->maxp + ,usb_maxpacket(urb->dev, urb->pipe, !(usb_pipein(urb->pipe))) + ,qh->ep_is_in?"in":"out"); + } + } +#endif + INIT_LIST_HEAD(&qh->qtd_list); + INIT_LIST_HEAD(&qh->qh_list_entry); + qh->channel = NULL; /* FS/LS Enpoint on HS Hub * NOT virtual root hub */ - _qh->do_split = 0; - if (((_urb->dev->speed == USB_SPEED_LOW) || - (_urb->dev->speed == USB_SPEED_FULL)) && - (_urb->dev->tt) && (_urb->dev->tt->hub->devnum != 1)) + qh->do_split = 0; + if (((urb->dev->speed == USB_SPEED_LOW) || + (urb->dev->speed == USB_SPEED_FULL)) && + (urb->dev->tt) && (urb->dev->tt->hub->devnum != 1)) { DWC_DEBUGPL(DBG_HCD, "QH init: EP %d: TT found at hub addr %d, for port %d\n", - usb_pipeendpoint(_urb->pipe), _urb->dev->tt->hub->devnum, - _urb->dev->ttport); - _qh->do_split = 1; - } - - if (_qh->ep_type == USB_ENDPOINT_XFER_INT || - _qh->ep_type == USB_ENDPOINT_XFER_ISOC) { + usb_pipeendpoint(urb->pipe), urb->dev->tt->hub->devnum, + urb->dev->ttport); + qh->do_split = 1; + } + + if (qh->ep_type == USB_ENDPOINT_XFER_INT || + qh->ep_type == USB_ENDPOINT_XFER_ISOC) { /* Compute scheduling parameters once and save them. */ hprt0_data_t hprt; /** @todo Account for split transfers in the bus time. */ - int bytecount = dwc_hb_mult(_qh->maxp) * dwc_max_packet(_qh->maxp); - _qh->usecs = usb_calc_bus_time(_urb->dev->speed, - usb_pipein(_urb->pipe), - (_qh->ep_type == USB_ENDPOINT_XFER_ISOC), - bytecount); + int bytecount = dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp); + + /* FIXME: work-around patch by Steven */ + qh->usecs = NS_TO_US(usb_calc_bus_time(urb->dev->speed, + usb_pipein(urb->pipe), + (qh->ep_type == USB_ENDPOINT_XFER_ISOC), + bytecount)); /* Start in a slightly future (micro)frame. */ - _qh->sched_frame = dwc_frame_num_inc(_hcd->frame_number, + qh->sched_frame = dwc_frame_num_inc(hcd->frame_number, SCHEDULE_SLOP); - _qh->interval = _urb->interval; + qh->interval = urb->interval; #if 0 /* Increase interrupt polling rate for debugging. */ - if (_qh->ep_type == USB_ENDPOINT_XFER_INT) { - _qh->interval = 8; + if (qh->ep_type == USB_ENDPOINT_XFER_INT) { + qh->interval = 8; } #endif - hprt.d32 = dwc_read_reg32(_hcd->core_if->host_if->hprt0); + hprt.d32 = dwc_read_reg32(hcd->core_if->host_if->hprt0); if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) && - ((_urb->dev->speed == USB_SPEED_LOW) || - (_urb->dev->speed == USB_SPEED_FULL))) - { - _qh->interval *= 8; - _qh->sched_frame |= 0x7; - _qh->start_split_frame = _qh->sched_frame; + ((urb->dev->speed == USB_SPEED_LOW) || + (urb->dev->speed == USB_SPEED_FULL))) { + qh->interval *= 8; + qh->sched_frame |= 0x7; + qh->start_split_frame = qh->sched_frame; } @@ -190,34 +218,55 @@ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n"); - DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - qh = %p\n", _qh); + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - qh = %p\n", qh); DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Device Address = %d\n", - _urb->dev->devnum); + urb->dev->devnum); DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Endpoint %d, %s\n", - usb_pipeendpoint(_urb->pipe), - usb_pipein(_urb->pipe) == USB_DIR_IN ? "IN" : "OUT"); - DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Speed = %s\n", - ({ char *speed; switch (_urb->dev->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; - }; speed;})); - DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Type = %s\n", - ({ char *type; switch (_qh->ep_type) { - case USB_ENDPOINT_XFER_ISOC: type = "isochronous"; break; - case USB_ENDPOINT_XFER_INT: type = "interrupt"; break; - case USB_ENDPOINT_XFER_CONTROL: type = "control"; break; - case USB_ENDPOINT_XFER_BULK: type = "bulk"; break; - default: type = "?"; break; - }; type;})); + usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe) == USB_DIR_IN ? "IN" : "OUT"); + + switch(urb->dev->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; + } + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Speed = %s\n", speed); + + switch (qh->ep_type) { + case USB_ENDPOINT_XFER_ISOC: + type = "isochronous"; + break; + case USB_ENDPOINT_XFER_INT: + type = "interrupt"; + break; + case USB_ENDPOINT_XFER_CONTROL: + type = "control"; + break; + case USB_ENDPOINT_XFER_BULK: + type = "bulk"; + break; + default: + type = "?"; + break; + } + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Type = %s\n",type); + #ifdef DEBUG - if (_qh->ep_type == USB_ENDPOINT_XFER_INT) { + if (qh->ep_type == USB_ENDPOINT_XFER_INT) { DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - usecs = %d\n", - _qh->usecs); + qh->usecs); DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - interval = %d\n", - _qh->interval); + qh->interval); } #endif - + qh->dw_align_buf = NULL; return; } @@ -228,5 +277,5 @@ * @return 0 if successful, negative error code otherise. */ -static int periodic_channel_available(dwc_otg_hcd_t *_hcd) +static int periodic_channel_available(dwc_otg_hcd_t *hcd) { /* @@ -238,13 +287,13 @@ int num_channels; - num_channels = _hcd->core_if->core_params->host_channels; - if ((_hcd->periodic_channels + _hcd->non_periodic_channels < num_channels) && - (_hcd->periodic_channels < num_channels - 1)) { + num_channels = hcd->core_if->core_params->host_channels; + if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels) && + (hcd->periodic_channels < num_channels - 1)) { status = 0; } else { DWC_NOTICE("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n", - __func__, num_channels, _hcd->periodic_channels, - _hcd->non_periodic_channels); + __func__, num_channels, hcd->periodic_channels, + hcd->non_periodic_channels); status = -ENOSPC; } @@ -258,10 +307,10 @@ * transfers in the periodic schedule may occur in the same (micro)frame. * - * @param _hcd The HCD state structure for the DWC OTG controller. - * @param _qh QH containing periodic bandwidth required. + * @param hcd The HCD state structure for the DWC OTG controller. + * @param qh QH containing periodic bandwidth required. * * @return 0 if successful, negative error code otherwise. */ -static int check_periodic_bandwidth(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh) +static int check_periodic_bandwidth(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) { int status; @@ -270,10 +319,10 @@ status = 0; - if (_hcd->core_if->core_params->speed == DWC_SPEED_PARAM_HIGH) { + if (hcd->core_if->core_params->speed == DWC_SPEED_PARAM_HIGH) { /* * High speed mode. * Max periodic usecs is 80% x 125 usec = 100 usec. */ - max_claimed_usecs = 100 - _qh->usecs; + max_claimed_usecs = 100 - qh->usecs; } else { /* @@ -281,10 +330,10 @@ * Max periodic usecs is 90% x 1000 usec = 900 usec. */ - max_claimed_usecs = 900 - _qh->usecs; - } - - if (_hcd->periodic_usecs > max_claimed_usecs) { + max_claimed_usecs = 900 - qh->usecs; + } + + if (hcd->periodic_usecs > max_claimed_usecs) { DWC_NOTICE("%s: already claimed usecs %d, required usecs %d\n", - __func__, _hcd->periodic_usecs, _qh->usecs); + __func__, hcd->periodic_usecs, qh->usecs); status = -ENOSPC; } @@ -298,10 +347,10 @@ * transfer. * - * @param _hcd The HCD state structure for the DWC OTG controller. - * @param _qh QH for a periodic endpoint. + * @param hcd The HCD state structure for the DWC OTG controller. + * @param qh QH for a periodic endpoint. * * @return 0 if successful, negative error code otherwise. */ -static int check_max_xfer_size(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh) +static int check_max_xfer_size(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) { int status; @@ -311,6 +360,6 @@ status = 0; - max_xfer_size = dwc_max_packet(_qh->maxp) * dwc_hb_mult(_qh->maxp); - max_channel_xfer_size = _hcd->core_if->core_params->max_transfer_size; + max_xfer_size = dwc_max_packet(qh->maxp) * dwc_hb_mult(qh->maxp); + max_channel_xfer_size = hcd->core_if->core_params->max_transfer_size; if (max_xfer_size > max_channel_xfer_size) { @@ -327,15 +376,15 @@ * Schedules an interrupt or isochronous transfer in the periodic schedule. * - * @param _hcd The HCD state structure for the DWC OTG controller. - * @param _qh QH for the periodic transfer. The QH should already contain the + * @param hcd The HCD state structure for the DWC OTG controller. + * @param qh QH for the periodic transfer. The QH should already contain the * scheduling information. * * @return 0 if successful, negative error code otherwise. */ -static int schedule_periodic(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh) +static int schedule_periodic(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) { int status = 0; - status = periodic_channel_available(_hcd); + status = periodic_channel_available(hcd); if (status) { DWC_NOTICE("%s: No host channel available for periodic " @@ -344,5 +393,5 @@ } - status = check_periodic_bandwidth(_hcd, _qh); + status = check_periodic_bandwidth(hcd, qh); if (status) { DWC_NOTICE("%s: Insufficient periodic bandwidth for " @@ -351,5 +400,5 @@ } - status = check_max_xfer_size(_hcd, _qh); + status = check_max_xfer_size(hcd, qh); if (status) { DWC_NOTICE("%s: Channel max transfer size too small " @@ -359,22 +408,22 @@ /* Always start in the inactive schedule. */ - list_add_tail(&_qh->qh_list_entry, &_hcd->periodic_sched_inactive); + list_add_tail(&qh->qh_list_entry, &hcd->periodic_sched_inactive); /* Reserve the periodic channel. */ - _hcd->periodic_channels++; + hcd->periodic_channels++; /* Update claimed usecs per (micro)frame. */ - _hcd->periodic_usecs += _qh->usecs; + hcd->periodic_usecs += qh->usecs; /* Update average periodic bandwidth claimed and # periodic reqs for usbfs. */ - hcd_to_bus(dwc_otg_hcd_to_hcd(_hcd))->bandwidth_allocated += _qh->usecs / _qh->interval; - if (_qh->ep_type == USB_ENDPOINT_XFER_INT) { - hcd_to_bus(dwc_otg_hcd_to_hcd(_hcd))->bandwidth_int_reqs++; + hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_allocated += qh->usecs / qh->interval; + if (qh->ep_type == USB_ENDPOINT_XFER_INT) { + hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_int_reqs++; DWC_DEBUGPL(DBG_HCD, "Scheduled intr: qh %p, usecs %d, period %d\n", - _qh, _qh->usecs, _qh->interval); + qh, qh->usecs, qh->interval); } else { - hcd_to_bus(dwc_otg_hcd_to_hcd(_hcd))->bandwidth_isoc_reqs++; + hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_isoc_reqs++; DWC_DEBUGPL(DBG_HCD, "Scheduled isoc: qh %p, usecs %d, period %d\n", - _qh, _qh->usecs, _qh->interval); + qh, qh->usecs, qh->interval); } @@ -389,12 +438,12 @@ * @return 0 if successful, negative error code otherwise. */ -int dwc_otg_hcd_qh_add (dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh) +int dwc_otg_hcd_qh_add (dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) { unsigned long flags; int status = 0; - local_irq_save(flags); - - if (!list_empty(&_qh->qh_list_entry)) { + SPIN_LOCK_IRQSAVE(&hcd->lock, flags) + + if (!list_empty(&qh->qh_list_entry)) { /* QH already in a schedule. */ goto done; @@ -402,13 +451,13 @@ /* Add the new QH to the appropriate schedule */ - if (dwc_qh_is_non_per(_qh)) { + if (dwc_qh_is_non_per(qh)) { /* Always start in the inactive schedule. */ - list_add_tail(&_qh->qh_list_entry, &_hcd->non_periodic_sched_inactive); + list_add_tail(&qh->qh_list_entry, &hcd->non_periodic_sched_inactive); } else { - status = schedule_periodic(_hcd, _qh); + status = schedule_periodic(hcd, qh); } done: - local_irq_restore(flags); + SPIN_UNLOCK_IRQRESTORE(&hcd->lock, flags) return status; @@ -418,28 +467,28 @@ * Removes an interrupt or isochronous transfer from the periodic schedule. * - * @param _hcd The HCD state structure for the DWC OTG controller. - * @param _qh QH for the periodic transfer. - */ -static void deschedule_periodic(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh) -{ - list_del_init(&_qh->qh_list_entry); + * @param hcd The HCD state structure for the DWC OTG controller. + * @param qh QH for the periodic transfer. + */ +static void deschedule_periodic(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) +{ + list_del_init(&qh->qh_list_entry); /* Release the periodic channel reservation. */ - _hcd->periodic_channels--; + hcd->periodic_channels--; /* Update claimed usecs per (micro)frame. */ - _hcd->periodic_usecs -= _qh->usecs; + hcd->periodic_usecs -= qh->usecs; /* Update average periodic bandwidth claimed and # periodic reqs for usbfs. */ - hcd_to_bus(dwc_otg_hcd_to_hcd(_hcd))->bandwidth_allocated -= _qh->usecs / _qh->interval; - - if (_qh->ep_type == USB_ENDPOINT_XFER_INT) { - hcd_to_bus(dwc_otg_hcd_to_hcd(_hcd))->bandwidth_int_reqs--; + hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_allocated -= qh->usecs / qh->interval; + + if (qh->ep_type == USB_ENDPOINT_XFER_INT) { + hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_int_reqs--; DWC_DEBUGPL(DBG_HCD, "Descheduled intr: qh %p, usecs %d, period %d\n", - _qh, _qh->usecs, _qh->interval); + qh, qh->usecs, qh->interval); } else { - hcd_to_bus(dwc_otg_hcd_to_hcd(_hcd))->bandwidth_isoc_reqs--; + hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_isoc_reqs--; DWC_DEBUGPL(DBG_HCD, "Descheduled isoc: qh %p, usecs %d, period %d\n", - _qh, _qh->usecs, _qh->interval); + qh, qh->usecs, qh->interval); } } @@ -449,28 +498,28 @@ * not freed. * - * @param[in] _hcd The HCD state structure. - * @param[in] _qh QH to remove from schedule. */ -void dwc_otg_hcd_qh_remove (dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh) + * @param[in] hcd The HCD state structure. + * @param[in] qh QH to remove from schedule. */ +void dwc_otg_hcd_qh_remove (dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) { unsigned long flags; - local_irq_save(flags); - - if (list_empty(&_qh->qh_list_entry)) { + SPIN_LOCK_IRQSAVE(&hcd->lock, flags); + + if (list_empty(&qh->qh_list_entry)) { /* QH is not in a schedule. */ goto done; } - if (dwc_qh_is_non_per(_qh)) { - if (_hcd->non_periodic_qh_ptr == &_qh->qh_list_entry) { - _hcd->non_periodic_qh_ptr = _hcd->non_periodic_qh_ptr->next; + if (dwc_qh_is_non_per(qh)) { + if (hcd->non_periodic_qh_ptr == &qh->qh_list_entry) { + hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; } - list_del_init(&_qh->qh_list_entry); + list_del_init(&qh->qh_list_entry); } else { - deschedule_periodic(_hcd, _qh); + deschedule_periodic(hcd, qh); } done: - local_irq_restore(flags); + SPIN_UNLOCK_IRQRESTORE(&hcd->lock, flags) } @@ -488,25 +537,25 @@ * completely removed from the periodic schedule. */ -void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh, int sched_next_periodic_split) +void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh, int sched_next_periodic_split) { unsigned long flags; - local_irq_save(flags); - - if (dwc_qh_is_non_per(_qh)) { - dwc_otg_hcd_qh_remove(_hcd, _qh); - if (!list_empty(&_qh->qtd_list)) { + SPIN_LOCK_IRQSAVE(&hcd->lock, flags); + + if (dwc_qh_is_non_per(qh)) { + dwc_otg_hcd_qh_remove(hcd, qh); + if (!list_empty(&qh->qtd_list)) { /* Add back to inactive non-periodic schedule. */ - dwc_otg_hcd_qh_add(_hcd, _qh); + dwc_otg_hcd_qh_add(hcd, qh); } } else { - uint16_t frame_number = dwc_otg_hcd_get_frame_number(dwc_otg_hcd_to_hcd(_hcd)); - - if (_qh->do_split) { + uint16_t frame_number = dwc_otg_hcd_get_frame_number(dwc_otg_hcd_to_hcd(hcd)); + + if (qh->do_split) { /* Schedule the next continuing periodic split transfer */ if (sched_next_periodic_split) { - _qh->sched_frame = frame_number; + qh->sched_frame = frame_number; if (dwc_frame_num_le(frame_number, - dwc_frame_num_inc(_qh->start_split_frame, 1))) { + dwc_frame_num_inc(qh->start_split_frame, 1))) { /* * Allow one frame to elapse after start @@ -516,26 +565,26 @@ * same frame for an ISOC out. */ - if ((_qh->ep_type != USB_ENDPOINT_XFER_ISOC) || (_qh->ep_is_in != 0)) { - _qh->sched_frame = dwc_frame_num_inc(_qh->sched_frame, 1); + if ((qh->ep_type != USB_ENDPOINT_XFER_ISOC) || (qh->ep_is_in != 0)) { + qh->sched_frame = dwc_frame_num_inc(qh->sched_frame, 1); } } } else { - _qh->sched_frame = dwc_frame_num_inc(_qh->start_split_frame, - _qh->interval); - if (dwc_frame_num_le(_qh->sched_frame, frame_number)) { - _qh->sched_frame = frame_number; + qh->sched_frame = dwc_frame_num_inc(qh->start_split_frame, + qh->interval); + if (dwc_frame_num_le(qh->sched_frame, frame_number)) { + qh->sched_frame = frame_number; } - _qh->sched_frame |= 0x7; - _qh->start_split_frame = _qh->sched_frame; + qh->sched_frame |= 0x7; + qh->start_split_frame = qh->sched_frame; } } else { - _qh->sched_frame = dwc_frame_num_inc(_qh->sched_frame, _qh->interval); - if (dwc_frame_num_le(_qh->sched_frame, frame_number)) { - _qh->sched_frame = frame_number; + qh->sched_frame = dwc_frame_num_inc(qh->sched_frame, qh->interval); + if (dwc_frame_num_le(qh->sched_frame, frame_number)) { + qh->sched_frame = frame_number; } } - if (list_empty(&_qh->qtd_list)) { - dwc_otg_hcd_qh_remove(_hcd, _qh); + if (list_empty(&qh->qtd_list)) { + dwc_otg_hcd_qh_remove(hcd, qh); } else { /* @@ -543,15 +592,15 @@ * appropriate queue. */ - if (_qh->sched_frame == frame_number) { - list_move(&_qh->qh_list_entry, - &_hcd->periodic_sched_ready); + if (qh->sched_frame == frame_number) { + list_move(&qh->qh_list_entry, + &hcd->periodic_sched_ready); } else { - list_move(&_qh->qh_list_entry, - &_hcd->periodic_sched_inactive); + list_move(&qh->qh_list_entry, + &hcd->periodic_sched_inactive); } } } - local_irq_restore(flags); + SPIN_UNLOCK_IRQRESTORE(&hcd->lock, flags); } @@ -559,9 +608,9 @@ * This function allocates and initializes a QTD. * - * @param[in] _urb The URB to create a QTD from. Each URB-QTD pair will end up + * @param[in] urb The URB to create a QTD from. Each URB-QTD pair will end up * pointing to each other so each pair should have a unique correlation. * * @return Returns pointer to the newly allocated QTD, or NULL on error. */ -dwc_otg_qtd_t *dwc_otg_hcd_qtd_create (struct urb *_urb) +dwc_otg_qtd_t *dwc_otg_hcd_qtd_create (struct urb *urb) { dwc_otg_qtd_t *qtd; @@ -572,5 +621,5 @@ } - dwc_otg_hcd_qtd_init (qtd, _urb); + dwc_otg_hcd_qtd_init (qtd, urb); return qtd; } @@ -579,11 +628,11 @@ * Initializes a QTD structure. * - * @param[in] _qtd The QTD to initialize. - * @param[in] _urb The URB to use for initialization. */ -void dwc_otg_hcd_qtd_init (dwc_otg_qtd_t *_qtd, struct urb *_urb) -{ - memset (_qtd, 0, sizeof (dwc_otg_qtd_t)); - _qtd->urb = _urb; - if (usb_pipecontrol(_urb->pipe)) { + * @param[in] qtd The QTD to initialize. + * @param[in] urb The URB to use for initialization. */ +void dwc_otg_hcd_qtd_init (dwc_otg_qtd_t *qtd, struct urb *urb) +{ + memset (qtd, 0, sizeof (dwc_otg_qtd_t)); + qtd->urb = urb; + if (usb_pipecontrol(urb->pipe)) { /* * The only time the QTD data toggle is used is on the data @@ -591,15 +640,15 @@ * DATA1. */ - _qtd->data_toggle = DWC_OTG_HC_PID_DATA1; - _qtd->control_phase = DWC_OTG_CONTROL_SETUP; + qtd->data_toggle = DWC_OTG_HC_PID_DATA1; + qtd->control_phase = DWC_OTG_CONTROL_SETUP; } /* start split */ - _qtd->complete_split = 0; - _qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL; - _qtd->isoc_split_offset = 0; + qtd->complete_split = 0; + qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL; + qtd->isoc_split_offset = 0; /* Store the qtd ptr in the urb to reference what QTD. */ - _urb->hcpriv = _qtd; + urb->hcpriv = qtd; return; } @@ -611,11 +660,11 @@ * is placed into the proper schedule based on its EP type. * - * @param[in] _qtd The QTD to add - * @param[in] _dwc_otg_hcd The DWC HCD structure + * @param[in] qtd The QTD to add + * @param[in] dwc_otg_hcd The DWC HCD structure * * @return 0 if successful, negative error code otherwise. */ -int dwc_otg_hcd_qtd_add (dwc_otg_qtd_t *_qtd, - dwc_otg_hcd_t *_dwc_otg_hcd) +int dwc_otg_hcd_qtd_add (dwc_otg_qtd_t *qtd, + dwc_otg_hcd_t *dwc_otg_hcd) { struct usb_host_endpoint *ep; @@ -624,7 +673,7 @@ int retval = 0; - struct urb *urb = _qtd->urb; - - local_irq_save(flags); + struct urb *urb = qtd->urb; + + SPIN_LOCK_IRQSAVE(&dwc_otg_hcd->lock, flags); /* @@ -635,5 +684,5 @@ qh = (dwc_otg_qh_t *)ep->hcpriv; if (qh == NULL) { - qh = dwc_otg_hcd_qh_create (_dwc_otg_hcd, urb); + qh = dwc_otg_hcd_qh_create (dwc_otg_hcd, urb); if (qh == NULL) { goto done; @@ -642,11 +691,12 @@ } - retval = dwc_otg_hcd_qh_add(_dwc_otg_hcd, qh); + retval = dwc_otg_hcd_qh_add(dwc_otg_hcd, qh); if (retval == 0) { - list_add_tail(&_qtd->qtd_list_entry, &qh->qtd_list); + list_add_tail(&qtd->qtd_list_entry, &qh->qtd_list); } done: - local_irq_restore(flags); + SPIN_UNLOCK_IRQRESTORE(&dwc_otg_hcd->lock, flags); + return retval; } Index: /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_cil_intr.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_cil_intr.c (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_cil_intr.c (revision 12433) @@ -1,7 +1,7 @@ /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_cil_intr.c $ - * $Revision: 1.1 $ - * $Date: 2007-11-19 05:39:07 $ - * $Change: 553126 $ + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $ + * $Revision: 1.2 $ + * $Date: 2008-11-21 05:39:15 $ + * $Change: 1065567 $ * * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, @@ -45,11 +45,11 @@ #ifdef DEBUG -inline const char *op_state_str( dwc_otg_core_if_t *_core_if ) -{ - return (_core_if->op_state==A_HOST?"a_host": - (_core_if->op_state==A_SUSPEND?"a_suspend": - (_core_if->op_state==A_PERIPHERAL?"a_peripheral": - (_core_if->op_state==B_PERIPHERAL?"b_peripheral": - (_core_if->op_state==B_HOST?"b_host": +inline const char *op_state_str(dwc_otg_core_if_t *core_if) +{ + return (core_if->op_state==A_HOST?"a_host": + (core_if->op_state==A_SUSPEND?"a_suspend": + (core_if->op_state==A_PERIPHERAL?"a_peripheral": + (core_if->op_state==B_PERIPHERAL?"b_peripheral": + (core_if->op_state==B_HOST?"b_host": "unknown"))))); } @@ -58,16 +58,16 @@ /** This function will log a debug message * - * @param _core_if Programming view of DWC_otg controller. - */ -int32_t dwc_otg_handle_mode_mismatch_intr (dwc_otg_core_if_t *_core_if) + * @param core_if Programming view of DWC_otg controller. + */ +int32_t dwc_otg_handle_mode_mismatch_intr (dwc_otg_core_if_t *core_if) { gintsts_data_t gintsts; DWC_WARN("Mode Mismatch Interrupt: currently in %s mode\n", - dwc_otg_mode(_core_if) ? "Host" : "Device"); + dwc_otg_mode(core_if) ? "Host" : "Device"); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.modemismatch = 1; - dwc_write_reg32 (&_core_if->core_global_regs->gintsts, gintsts.d32); + dwc_write_reg32 (&core_if->core_global_regs->gintsts, gintsts.d32); return 1; } @@ -75,30 +75,30 @@ /** Start the HCD. Helper function for using the HCD callbacks. * - * @param _core_if Programming view of DWC_otg controller. - */ -static inline void hcd_start( dwc_otg_core_if_t *_core_if ) + * @param core_if Programming view of DWC_otg controller. + */ +static inline void hcd_start(dwc_otg_core_if_t *core_if) { - if (_core_if->hcd_cb && _core_if->hcd_cb->start) { - _core_if->hcd_cb->start( _core_if->hcd_cb->p ); + if (core_if->hcd_cb && core_if->hcd_cb->start) { + core_if->hcd_cb->start(core_if->hcd_cb->p); } } /** Stop the HCD. Helper function for using the HCD callbacks. * - * @param _core_if Programming view of DWC_otg controller. - */ -static inline void hcd_stop( dwc_otg_core_if_t *_core_if ) + * @param core_if Programming view of DWC_otg controller. + */ +static inline void hcd_stop(dwc_otg_core_if_t *core_if) { - if (_core_if->hcd_cb && _core_if->hcd_cb->stop) { - _core_if->hcd_cb->stop( _core_if->hcd_cb->p ); + if (core_if->hcd_cb && core_if->hcd_cb->stop) { + core_if->hcd_cb->stop(core_if->hcd_cb->p); } } /** Disconnect the HCD. Helper function for using the HCD callbacks. * - * @param _core_if Programming view of DWC_otg controller. - */ -static inline void hcd_disconnect( dwc_otg_core_if_t *_core_if ) -{ - if (_core_if->hcd_cb && _core_if->hcd_cb->disconnect) { - _core_if->hcd_cb->disconnect( _core_if->hcd_cb->p ); + * @param core_if Programming view of DWC_otg controller. + */ +static inline void hcd_disconnect(dwc_otg_core_if_t *core_if) +{ + if (core_if->hcd_cb && core_if->hcd_cb->disconnect) { + core_if->hcd_cb->disconnect(core_if->hcd_cb->p); } } @@ -106,10 +106,10 @@ * using the HCD callbacks. * - * @param _core_if Programming view of DWC_otg controller. - */ -static inline void hcd_session_start( dwc_otg_core_if_t *_core_if ) -{ - if (_core_if->hcd_cb && _core_if->hcd_cb->session_start) { - _core_if->hcd_cb->session_start( _core_if->hcd_cb->p ); + * @param core_if Programming view of DWC_otg controller. + */ +static inline void hcd_session_start(dwc_otg_core_if_t *core_if) +{ + if (core_if->hcd_cb && core_if->hcd_cb->session_start) { + core_if->hcd_cb->session_start(core_if->hcd_cb->p); } } @@ -117,40 +117,40 @@ /** Start the PCD. Helper function for using the PCD callbacks. * - * @param _core_if Programming view of DWC_otg controller. - */ -static inline void pcd_start( dwc_otg_core_if_t *_core_if ) -{ - if (_core_if->pcd_cb && _core_if->pcd_cb->start ) { - _core_if->pcd_cb->start( _core_if->pcd_cb->p ); + * @param core_if Programming view of DWC_otg controller. + */ +static inline void pcd_start(dwc_otg_core_if_t *core_if) +{ + if (core_if->pcd_cb && core_if->pcd_cb->start) { + core_if->pcd_cb->start(core_if->pcd_cb->p); } } /** Stop the PCD. Helper function for using the PCD callbacks. * - * @param _core_if Programming view of DWC_otg controller. - */ -static inline void pcd_stop( dwc_otg_core_if_t *_core_if ) -{ - if (_core_if->pcd_cb && _core_if->pcd_cb->stop ) { - _core_if->pcd_cb->stop( _core_if->pcd_cb->p ); + * @param core_if Programming view of DWC_otg controller. + */ +static inline void pcd_stop(dwc_otg_core_if_t *core_if) +{ + if (core_if->pcd_cb && core_if->pcd_cb->stop) { + core_if->pcd_cb->stop(core_if->pcd_cb->p); } } /** Suspend the PCD. Helper function for using the PCD callbacks. * - * @param _core_if Programming view of DWC_otg controller. - */ -static inline void pcd_suspend( dwc_otg_core_if_t *_core_if ) -{ - if (_core_if->pcd_cb && _core_if->pcd_cb->suspend ) { - _core_if->pcd_cb->suspend( _core_if->pcd_cb->p ); + * @param core_if Programming view of DWC_otg controller. + */ +static inline void pcd_suspend(dwc_otg_core_if_t *core_if) +{ + if (core_if->pcd_cb && core_if->pcd_cb->suspend) { + core_if->pcd_cb->suspend(core_if->pcd_cb->p); } } /** Resume the PCD. Helper function for using the PCD callbacks. * - * @param _core_if Programming view of DWC_otg controller. - */ -static inline void pcd_resume( dwc_otg_core_if_t *_core_if ) -{ - if (_core_if->pcd_cb && _core_if->pcd_cb->resume_wakeup ) { - _core_if->pcd_cb->resume_wakeup( _core_if->pcd_cb->p ); + * @param core_if Programming view of DWC_otg controller. + */ +static inline void pcd_resume(dwc_otg_core_if_t *core_if) +{ + if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { + core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); } } @@ -161,29 +161,27 @@ * occurred. * - * @param _core_if Programming view of DWC_otg controller. - */ -int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t *_core_if) + * @param core_if Programming view of DWC_otg controller. + */ +int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t *core_if) { dwc_otg_core_global_regs_t *global_regs = - _core_if->core_global_regs; + core_if->core_global_regs; gotgint_data_t gotgint; gotgctl_data_t gotgctl; gintmsk_data_t gintmsk; - gotgint.d32 = dwc_read_reg32( &global_regs->gotgint); - gotgctl.d32 = dwc_read_reg32( &global_regs->gotgctl); - DWC_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32, - op_state_str(_core_if)); - //DWC_DEBUGPL(DBG_CIL, "gotgctl=%08x\n", gotgctl.d32 ); + gotgint.d32 = dwc_read_reg32(&global_regs->gotgint); + gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); + DWC_DEBUGPL(DBG_CIL, "gotgctl=%08x\n", gotgctl.d32); if (gotgint.b.sesenddet) { - DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " + DWC_DEBUGPL(DBG_ANY, "OTG Interrupt: " "Session End Detected++ (%s)\n", - op_state_str(_core_if)); - gotgctl.d32 = dwc_read_reg32( &global_regs->gotgctl); - - if (_core_if->op_state == B_HOST) { - pcd_start( _core_if ); - _core_if->op_state = B_PERIPHERAL; + op_state_str(core_if)); + gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); + + if (core_if->op_state == B_HOST) { + pcd_start(core_if); + core_if->op_state = B_PERIPHERAL; } else { /* If not B_HOST and Device HNP still set. HNP @@ -191,5 +189,5 @@ if (gotgctl.b.devhnpen) { DWC_DEBUGPL(DBG_ANY, "Session End Detected\n"); - DWC_ERROR( "Device Not Connected/Responding!\n" ); + DWC_ERROR("Device Not Connected/Responding!\n"); } @@ -198,26 +196,26 @@ /* Reset PCD and Gadget driver to a * clean state. */ - pcd_stop(_core_if); + pcd_stop(core_if); } gotgctl.d32 = 0; gotgctl.b.devhnpen = 1; - dwc_modify_reg32( &global_regs->gotgctl, + dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0); } if (gotgint.b.sesreqsucstschng) { - DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " + DWC_DEBUGPL(DBG_ANY, " OTG Interrupt: " "Session Reqeust Success Status Change++\n"); - gotgctl.d32 = dwc_read_reg32( &global_regs->gotgctl); + gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); if (gotgctl.b.sesreqscs) { - if ((_core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) && - (_core_if->core_params->i2c_enable)) { - _core_if->srp_success = 1; + if ((core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) && + (core_if->core_params->i2c_enable)) { + core_if->srp_success = 1; } else { - pcd_resume( _core_if ); + pcd_resume(core_if); /* Clear Session Request */ gotgctl.d32 = 0; gotgctl.b.sesreq = 1; - dwc_modify_reg32( &global_regs->gotgctl, + dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0); } @@ -229,6 +227,6 @@ gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); if (gotgctl.b.hstnegscs) { - if (dwc_otg_is_host_mode(_core_if) ) { - _core_if->op_state = B_HOST; + if (dwc_otg_is_host_mode(core_if)) { + core_if->op_state = B_HOST; /* * Need to disable SOF interrupt immediately. @@ -245,10 +243,10 @@ dwc_modify_reg32(&global_regs->gintmsk, gintmsk.d32, 0); - pcd_stop(_core_if); + pcd_stop(core_if); /* * Initialize the Core for Host mode. */ - hcd_start( _core_if ); - _core_if->op_state = B_HOST; + hcd_start(core_if); + core_if->op_state = B_HOST; } } else { @@ -256,8 +254,8 @@ gotgctl.b.hnpreq = 1; gotgctl.b.devhnpen = 1; - dwc_modify_reg32( &global_regs->gotgctl, + dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0); - DWC_DEBUGPL( DBG_ANY, "HNP Failed\n"); - DWC_ERROR( "Device Not Connected/Responding\n" ); + DWC_DEBUGPL(DBG_ANY, "HNP Failed\n"); + DWC_ERROR("Device Not Connected/Responding\n"); } } @@ -270,10 +268,10 @@ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " "Host Negotiation Detected++ (%s)\n", - (dwc_otg_is_host_mode(_core_if)?"Host":"Device")); - if (dwc_otg_is_device_mode(_core_if)){ - DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n",_core_if->op_state); - hcd_disconnect( _core_if ); - pcd_start( _core_if ); - _core_if->op_state = A_PERIPHERAL; + (dwc_otg_is_host_mode(core_if)?"Host":"Device")); + if (dwc_otg_is_device_mode(core_if)){ + DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n", core_if->op_state); + hcd_disconnect(core_if); + pcd_start(core_if); + core_if->op_state = A_PERIPHERAL; } else { /* @@ -290,7 +288,7 @@ dwc_modify_reg32(&global_regs->gintmsk, gintmsk.d32, 0); - pcd_stop( _core_if ); - hcd_start( _core_if ); - _core_if->op_state = A_HOST; + pcd_stop(core_if); + hcd_start(core_if); + core_if->op_state = A_HOST; } } @@ -305,8 +303,63 @@ /* Clear GOTGINT */ - dwc_write_reg32 (&_core_if->core_global_regs->gotgint, gotgint.d32); + dwc_write_reg32 (&core_if->core_global_regs->gotgint, gotgint.d32); return 1; } + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + +void w_conn_id_status_change(void *p) +{ + dwc_otg_core_if_t *core_if = p; + +#else + +void w_conn_id_status_change(struct work_struct *p) +{ + dwc_otg_core_if_t *core_if = container_of(p, dwc_otg_core_if_t, w_conn_id); + +#endif + + + uint32_t count = 0; + gotgctl_data_t gotgctl = { .d32 = 0 }; + + gotgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl); + DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32); + DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts); + + /* B-Device connector (Device Mode) */ + if (gotgctl.b.conidsts) { + /* Wait for switch to device mode. */ + while (!dwc_otg_is_device_mode(core_if)){ + DWC_PRINT("Waiting for Peripheral Mode, Mode=%s\n", + (dwc_otg_is_host_mode(core_if)?"Host":"Peripheral")); + MDELAY(100); + if (++count > 10000) *(uint32_t*)NULL=0; + } + core_if->op_state = B_PERIPHERAL; + dwc_otg_core_init(core_if); + dwc_otg_enable_global_interrupts(core_if); + pcd_start(core_if); + } else { + /* A-Device connector (Host Mode) */ + while (!dwc_otg_is_host_mode(core_if)) { + DWC_PRINT("Waiting for Host Mode, Mode=%s\n", + (dwc_otg_is_host_mode(core_if)?"Host":"Peripheral")); + MDELAY(100); + if (++count > 10000) *(uint32_t*)NULL=0; + } + core_if->op_state = A_HOST; + /* + * Initialize the Core for Host mode. + */ + dwc_otg_core_init(core_if); + dwc_otg_enable_global_interrupts(core_if); + hcd_start(core_if); + } +} + /** @@ -319,13 +372,8 @@ * connector. * - * @param _core_if Programming view of DWC_otg controller. - */ -int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t *_core_if) -{ - uint32_t count = 0; - - gintsts_data_t gintsts = { .d32 = 0 }; - gintmsk_data_t gintmsk = { .d32 = 0 }; - gotgctl_data_t gotgctl = { .d32 = 0 }; + * @param core_if Programming view of DWC_otg controller. + */ +int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t *core_if) +{ /* @@ -336,46 +384,21 @@ * not get handled and Linux complains loudly. */ + gintmsk_data_t gintmsk = { .d32 = 0 }; + gintsts_data_t gintsts = { .d32 = 0 }; + gintmsk.b.sofintr = 1; - dwc_modify_reg32(&_core_if->core_global_regs->gintmsk, gintmsk.d32, 0); + dwc_modify_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0); DWC_DEBUGPL(DBG_CIL, " ++Connector ID Status Change Interrupt++ (%s)\n", - (dwc_otg_is_host_mode(_core_if)?"Host":"Device")); - gotgctl.d32 = dwc_read_reg32(&_core_if->core_global_regs->gotgctl); - DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32); - DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts); - - /* B-Device connector (Device Mode) */ - if (gotgctl.b.conidsts) { - /* Wait for switch to device mode. */ - while (!dwc_otg_is_device_mode(_core_if) ){ - DWC_PRINT("Waiting for Peripheral Mode, Mode=%s\n", - (dwc_otg_is_host_mode(_core_if)?"Host":"Peripheral")); - MDELAY(100); - if (++count > 10000) *(uint32_t*)NULL=0; - } - _core_if->op_state = B_PERIPHERAL; - dwc_otg_core_init(_core_if); - dwc_otg_enable_global_interrupts(_core_if); - pcd_start( _core_if ); - } else { - /* A-Device connector (Host Mode) */ - while (!dwc_otg_is_host_mode(_core_if) ) { - DWC_PRINT("Waiting for Host Mode, Mode=%s\n", - (dwc_otg_is_host_mode(_core_if)?"Host":"Peripheral")); - MDELAY(100); - if (++count > 10000) *(uint32_t*)NULL=0; - } - _core_if->op_state = A_HOST; - /* - * Initialize the Core for Host mode. - */ - dwc_otg_core_init(_core_if); - dwc_otg_enable_global_interrupts(_core_if); - hcd_start( _core_if ); - } + (dwc_otg_is_host_mode(core_if)?"Host":"Device")); + + /* + * Need to schedule a work, as there are possible DELAY function calls + */ + queue_work(core_if->wq_otg, &core_if->w_conn_id); /* Set flag and clear interrupt */ gintsts.b.conidstschng = 1; - dwc_write_reg32 (&_core_if->core_global_regs->gintsts, gintsts.d32); + dwc_write_reg32 (&core_if->core_global_regs->gintsts, gintsts.d32); return 1; @@ -389,15 +412,15 @@ * controller out of low power mode before turning on bus power. * - * @param _core_if Programming view of DWC_otg controller. - */ -int32_t dwc_otg_handle_session_req_intr( dwc_otg_core_if_t *_core_if ) -{ + * @param core_if Programming view of DWC_otg controller. + */ +int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t *core_if) +{ + gintsts_data_t gintsts; + +#ifndef DWC_HOST_ONLY hprt0_data_t hprt0; - gintsts_data_t gintsts; - -#ifndef DWC_HOST_ONLY DWC_DEBUGPL(DBG_ANY, "++Session Request Interrupt++\n"); - if (dwc_otg_is_device_mode(_core_if) ) { + if (dwc_otg_is_device_mode(core_if)) { DWC_PRINT("SRP: Device mode\n"); } else { @@ -405,11 +428,11 @@ /* Turn on the port power bit. */ - hprt0.d32 = dwc_otg_read_hprt0( _core_if ); + hprt0.d32 = dwc_otg_read_hprt0(core_if); hprt0.b.prtpwr = 1; - dwc_write_reg32(_core_if->host_if->hprt0, hprt0.d32); + dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); /* Start the Connection timer. So a message can be displayed * if connect does not occur within 10 seconds. */ - hcd_session_start( _core_if ); + hcd_session_start(core_if); } #endif @@ -418,9 +441,42 @@ gintsts.d32 = 0; gintsts.b.sessreqintr = 1; - dwc_write_reg32 (&_core_if->core_global_regs->gintsts, gintsts.d32); + dwc_write_reg32 (&core_if->core_global_regs->gintsts, gintsts.d32); return 1; } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +void w_wakeup_detected(void *p) +{ + dwc_otg_core_if_t* core_if = p; + +#else + +void w_wakeup_detected(struct work_struct *p) +{ + struct delayed_work *dw = container_of(p, struct delayed_work, work); + dwc_otg_core_if_t *core_if = container_of(dw, dwc_otg_core_if_t, w_wkp); + +#endif + /* + * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms + * so that OPT tests pass with all PHYs). + */ + hprt0_data_t hprt0 = {.d32=0}; +#if 0 + pcgcctl_data_t pcgcctl = {.d32=0}; + /* Restart the Phy Clock */ + pcgcctl.b.stoppclk = 1; + dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32, 0); + UDELAY(10); +#endif //0 + hprt0.d32 = dwc_otg_read_hprt0(core_if); + DWC_DEBUGPL(DBG_ANY,"Resume: HPRT0=%0x\n", hprt0.d32); +// MDELAY(70); + hprt0.b.prtres = 0; /* Resume */ + dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); + DWC_DEBUGPL(DBG_ANY,"Clear Resume: HPRT0=%0x\n", dwc_read_reg32(core_if->host_if->hprt0)); +} /** * This interrupt indicates that the DWC_otg controller has detected a @@ -430,5 +486,5 @@ * signaling. The handler schedules a time to stop resume signaling. */ -int32_t dwc_otg_handle_wakeup_detected_intr( dwc_otg_core_if_t *_core_if ) +int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t *core_if) { gintsts_data_t gintsts; @@ -436,53 +492,42 @@ DWC_DEBUGPL(DBG_ANY, "++Resume and Remote Wakeup Detected Interrupt++\n"); - if (dwc_otg_is_device_mode(_core_if) ) { + if (dwc_otg_is_device_mode(core_if)) { dctl_data_t dctl = {.d32=0}; DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", - dwc_read_reg32( &_core_if->dev_if->dev_global_regs->dsts)); + dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts)); #ifdef PARTIAL_POWER_DOWN - if (_core_if->hwcfg4.b.power_optimiz) { + if (core_if->hwcfg4.b.power_optimiz) { pcgcctl_data_t power = {.d32=0}; - power.d32 = dwc_read_reg32( _core_if->pcgcctl ); + power.d32 = dwc_read_reg32(core_if->pcgcctl); DWC_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n", power.d32); power.b.stoppclk = 0; - dwc_write_reg32( _core_if->pcgcctl, power.d32); + dwc_write_reg32(core_if->pcgcctl, power.d32); power.b.pwrclmp = 0; - dwc_write_reg32( _core_if->pcgcctl, power.d32); + dwc_write_reg32(core_if->pcgcctl, power.d32); power.b.rstpdwnmodule = 0; - dwc_write_reg32( _core_if->pcgcctl, power.d32); + dwc_write_reg32(core_if->pcgcctl, power.d32); } #endif /* Clear the Remote Wakeup Signalling */ dctl.b.rmtwkupsig = 1; - dwc_modify_reg32( &_core_if->dev_if->dev_global_regs->dctl, - dctl.d32, 0 ); - - if (_core_if->pcd_cb && _core_if->pcd_cb->resume_wakeup) { - _core_if->pcd_cb->resume_wakeup( _core_if->pcd_cb->p ); + dwc_modify_reg32(&core_if->dev_if->dev_global_regs->dctl, + dctl.d32, 0); + + if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { + core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); } } else { - /* - * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms - * so that OPT tests pass with all PHYs). - */ - hprt0_data_t hprt0 = {.d32=0}; - pcgcctl_data_t pcgcctl = {.d32=0}; - /* Restart the Phy Clock */ - pcgcctl.b.stoppclk = 1; - dwc_modify_reg32(_core_if->pcgcctl, pcgcctl.d32, 0); - UDELAY(10); + pcgcctl_data_t pcgcctl = {.d32=0}; + + /* Restart the Phy Clock */ + pcgcctl.b.stoppclk = 1; + dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32, 0); - /* Now wait for 70 ms. */ - hprt0.d32 = dwc_otg_read_hprt0( _core_if ); - DWC_DEBUGPL(DBG_ANY,"Resume: HPRT0=%0x\n", hprt0.d32); - MDELAY(70); - hprt0.b.prtres = 0; /* Resume */ - dwc_write_reg32(_core_if->host_if->hprt0, hprt0.d32); - DWC_DEBUGPL(DBG_ANY,"Clear Resume: HPRT0=%0x\n", dwc_read_reg32(_core_if->host_if->hprt0)); + queue_delayed_work(core_if->wq_otg, &core_if->w_wkp, ((70 * HZ / 1000) + 1)); } @@ -490,5 +535,5 @@ gintsts.d32 = 0; gintsts.b.wkupintr = 1; - dwc_write_reg32 (&_core_if->core_global_regs->gintsts, gintsts.d32); + dwc_write_reg32 (&core_if->core_global_regs->gintsts, gintsts.d32); return 1; @@ -499,23 +544,23 @@ * the root port. */ -int32_t dwc_otg_handle_disconnect_intr( dwc_otg_core_if_t *_core_if) +int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t *core_if) { gintsts_data_t gintsts; DWC_DEBUGPL(DBG_ANY, "++Disconnect Detected Interrupt++ (%s) %s\n", - (dwc_otg_is_host_mode(_core_if)?"Host":"Device"), - op_state_str(_core_if)); + (dwc_otg_is_host_mode(core_if)?"Host":"Device"), + op_state_str(core_if)); /** @todo Consolidate this if statement. */ #ifndef DWC_HOST_ONLY - if (_core_if->op_state == B_HOST) { + if (core_if->op_state == B_HOST) { /* If in device mode Disconnect and stop the HCD, then * start the PCD. */ - hcd_disconnect( _core_if ); - pcd_start( _core_if ); - _core_if->op_state = B_PERIPHERAL; - } else if (dwc_otg_is_device_mode(_core_if)) { + hcd_disconnect(core_if); + pcd_start(core_if); + core_if->op_state = B_PERIPHERAL; + } else if (dwc_otg_is_device_mode(core_if)) { gotgctl_data_t gotgctl = { .d32 = 0 }; - gotgctl.d32 = dwc_read_reg32(&_core_if->core_global_regs->gotgctl); + gotgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl); if (gotgctl.b.hstsethnpen==1) { /* Do nothing, if HNP in process the OTG @@ -526,14 +571,14 @@ /* If in device mode Disconnect and stop the HCD, then * start the PCD. */ - hcd_disconnect( _core_if ); - pcd_start( _core_if ); - _core_if->op_state = B_PERIPHERAL; + hcd_disconnect(core_if); + pcd_start(core_if); + core_if->op_state = B_PERIPHERAL; } else { DWC_DEBUGPL(DBG_ANY,"!a_peripheral && !devhnpen\n"); } } else { - if (_core_if->op_state == A_HOST) { + if (core_if->op_state == A_HOST) { /* A-Cable still connected but device disconnected. */ - hcd_disconnect( _core_if ); + hcd_disconnect(core_if); } } @@ -542,5 +587,5 @@ gintsts.d32 = 0; gintsts.b.disconnect = 1; - dwc_write_reg32 (&_core_if->core_global_regs->gintsts, gintsts.d32); + dwc_write_reg32 (&core_if->core_global_regs->gintsts, gintsts.d32); return 1; } @@ -555,5 +600,5 @@ * mode. */ -int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t *_core_if ) +int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t *core_if) { dsts_data_t dsts; @@ -562,12 +607,12 @@ DWC_DEBUGPL(DBG_ANY,"USB SUSPEND\n"); - if (dwc_otg_is_device_mode( _core_if ) ) { + if (dwc_otg_is_device_mode(core_if)) { /* Check the Device status register to determine if the Suspend * state is active. */ - dsts.d32 = dwc_read_reg32( &_core_if->dev_if->dev_global_regs->dsts); + dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32); DWC_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d " "HWCFG4.power Optimize=%d\n", - dsts.b.suspsts, _core_if->hwcfg4.b.power_optimiz); + dsts.b.suspsts, core_if->hwcfg4.b.power_optimiz); @@ -575,16 +620,16 @@ /** @todo Add a module parameter for power management. */ - if (dsts.b.suspsts && _core_if->hwcfg4.b.power_optimiz) { + if (dsts.b.suspsts && core_if->hwcfg4.b.power_optimiz) { pcgcctl_data_t power = {.d32=0}; DWC_DEBUGPL(DBG_CIL, "suspend\n"); power.b.pwrclmp = 1; - dwc_write_reg32( _core_if->pcgcctl, power.d32); + dwc_write_reg32(core_if->pcgcctl, power.d32); power.b.rstpdwnmodule = 1; - dwc_modify_reg32( _core_if->pcgcctl, 0, power.d32); + dwc_modify_reg32(core_if->pcgcctl, 0, power.d32); power.b.stoppclk = 1; - dwc_modify_reg32( _core_if->pcgcctl, 0, power.d32); + dwc_modify_reg32(core_if->pcgcctl, 0, power.d32); } else { @@ -593,12 +638,12 @@ #endif /* PCD callback for suspend. */ - pcd_suspend(_core_if); + pcd_suspend(core_if); } else { - if (_core_if->op_state == A_PERIPHERAL) { + if (core_if->op_state == A_PERIPHERAL) { DWC_DEBUGPL(DBG_ANY,"a_peripheral->a_host\n"); /* Clear the a_peripheral flag, back to a_host. */ - pcd_stop( _core_if ); - hcd_start( _core_if ); - _core_if->op_state = A_HOST; + pcd_stop(core_if); + hcd_start(core_if); + core_if->op_state = A_HOST; } } @@ -607,5 +652,5 @@ gintsts.d32 = 0; gintsts.b.usbsuspend = 1; - dwc_write_reg32( &_core_if->core_global_regs->gintsts, gintsts.d32); + dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); return 1; @@ -616,5 +661,5 @@ * This function returns the Core Interrupt register. */ -static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t *_core_if) +static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t *core_if) { gintsts_data_t gintsts; @@ -633,6 +678,6 @@ gintmsk_common.b.portintr = 1; - gintsts.d32 = dwc_read_reg32(&_core_if->core_global_regs->gintsts); - gintmsk.d32 = dwc_read_reg32(&_core_if->core_global_regs->gintmsk); + gintsts.d32 = dwc_read_reg32(&core_if->core_global_regs->gintsts); + gintmsk.d32 = dwc_read_reg32(&core_if->core_global_regs->gintmsk); #ifdef DEBUG /* if any common interrupts set */ @@ -643,5 +688,5 @@ #endif - return ((gintsts.d32 & gintmsk.d32 ) & gintmsk_common.d32); + return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32); } @@ -660,33 +705,33 @@ * */ -extern int32_t dwc_otg_handle_common_intr( dwc_otg_core_if_t *_core_if ) +int32_t dwc_otg_handle_common_intr(dwc_otg_core_if_t *core_if) { int retval = 0; gintsts_data_t gintsts; - gintsts.d32 = dwc_otg_read_common_intr(_core_if); + gintsts.d32 = dwc_otg_read_common_intr(core_if); if (gintsts.b.modemismatch) { - retval |= dwc_otg_handle_mode_mismatch_intr( _core_if ); + retval |= dwc_otg_handle_mode_mismatch_intr(core_if); } if (gintsts.b.otgintr) { - retval |= dwc_otg_handle_otg_intr( _core_if ); + retval |= dwc_otg_handle_otg_intr(core_if); } if (gintsts.b.conidstschng) { - retval |= dwc_otg_handle_conn_id_status_change_intr( _core_if ); + retval |= dwc_otg_handle_conn_id_status_change_intr(core_if); } if (gintsts.b.disconnect) { - retval |= dwc_otg_handle_disconnect_intr( _core_if ); + retval |= dwc_otg_handle_disconnect_intr(core_if); } if (gintsts.b.sessreqintr) { - retval |= dwc_otg_handle_session_req_intr( _core_if ); + retval |= dwc_otg_handle_session_req_intr(core_if); } if (gintsts.b.wkupintr) { - retval |= dwc_otg_handle_wakeup_detected_intr( _core_if ); + retval |= dwc_otg_handle_wakeup_detected_intr(core_if); } if (gintsts.b.usbsuspend) { - retval |= dwc_otg_handle_usb_suspend_intr( _core_if ); - } - if (gintsts.b.portintr && dwc_otg_is_device_mode(_core_if)) { + retval |= dwc_otg_handle_usb_suspend_intr(core_if); + } + if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) { /* The port interrupt occurs while in device mode with HPRT0 * Port Enable/Disable. @@ -694,9 +739,12 @@ gintsts.d32 = 0; gintsts.b.portintr = 1; - dwc_write_reg32(&_core_if->core_global_regs->gintsts, + dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); retval |= 1; } + + S3C2410X_CLEAR_EINTPEND(); + return retval; } Index: /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_hcd.h =================================================================== --- /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_hcd.h (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_hcd.h (revision 12433) @@ -1,12 +1,12 @@ /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_hcd.h $ - * $Revision: 1.1 $ - * $Date: 2007-11-19 05:39:07 $ - * $Change: 762293 $ + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $ + * $Revision: 1.3 $ + * $Date: 2008-12-15 06:51:32 $ + * $Change: 1064918 $ * * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless * otherwise expressly agreed to in writing between Synopsys and you. - * + * * The Software IS NOT an item of Licensed Software or Licensed Product under * any End User Software License Agreement or Agreement for Licensed Product @@ -18,5 +18,5 @@ * Synopsys. If you do not agree with this notice, including the disclaimer * below, then you are not authorized to use the Software. - * + * * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -32,5 +32,5 @@ * ========================================================================== */ #ifndef DWC_DEVICE_ONLY -#if !defined(__DWC_HCD_H__) +#ifndef __DWC_HCD_H__ #define __DWC_HCD_H__ @@ -101,8 +101,8 @@ /** Keep track of the current split type * for FS/LS endpoints on a HS Hub */ - uint8_t complete_split; + uint8_t complete_split; /** How many bytes transferred during SSPLIT OUT */ - uint32_t ssplit_out_xfer_count; + uint32_t ssplit_out_xfer_count; /** @@ -110,5 +110,5 @@ * within this transfer. */ - uint8_t error_count; + uint8_t error_count; /** @@ -122,14 +122,14 @@ /** Position of the ISOC split on full/low speed */ - uint8_t isoc_split_pos; + uint8_t isoc_split_pos; /** Position of the ISOC split in the buffer for the current frame */ - uint16_t isoc_split_offset; + uint16_t isoc_split_offset; /** URB for this transfer */ - struct urb *urb; + struct urb *urb; /** This list of QTDs */ - struct list_head qtd_list_entry; + struct list_head qtd_list_entry; } dwc_otg_qtd_t; @@ -144,11 +144,11 @@ * Endpoint type. * One of the following values: - * - USB_ENDPOINT_XFER_CONTROL + * - USB_ENDPOINT_XFER_CONTROL * - USB_ENDPOINT_XFER_ISOC * - USB_ENDPOINT_XFER_BULK * - USB_ENDPOINT_XFER_INT */ - uint8_t ep_type; - uint8_t ep_is_in; + uint8_t ep_type; + uint8_t ep_is_in; /** wMaxPacketSize Field of Endpoint Descriptor. */ @@ -160,15 +160,15 @@ * One of the following values: * - DWC_OTG_HC_PID_DATA0 - * - DWC_OTG_HC_PID_DATA1 + * - DWC_OTG_HC_PID_DATA1 */ uint8_t data_toggle; /** Ping state if 1. */ - uint8_t ping_state; + uint8_t ping_state; /** * List of QTDs for this QH. */ - struct list_head qtd_list; + struct list_head qtd_list; /** Host channel currently processing transfers for this QH. */ @@ -179,5 +179,5 @@ /** Full/low speed endpoint on high-speed hub requires split. */ - uint8_t do_split; + uint8_t do_split; /** @name Periodic schedule information */ @@ -202,5 +202,9 @@ /** Entry for QH in either the periodic or non-periodic schedule. */ - struct list_head qh_list_entry; + struct list_head qh_list_entry; + + /* For non-dword aligned buffer support */ + uint8_t *dw_align_buf; + dma_addr_t dw_align_buf_dma; } dwc_otg_qh_t; @@ -210,9 +214,11 @@ */ typedef struct dwc_otg_hcd { + /** The DWC otg device pointer */ + struct dwc_otg_device *otg_dev; /** DWC OTG Core Interface Layer */ - dwc_otg_core_if_t *core_if; - - /** Internal DWC HCD Flags */ + dwc_otg_core_if_t *core_if; + + /** Internal DWC HCD Flags */ volatile union dwc_otg_hcd_internal_flags { uint32_t d32; @@ -233,5 +239,5 @@ * currently assigned to a host channel. */ - struct list_head non_periodic_sched_inactive; + struct list_head non_periodic_sched_inactive; /** @@ -240,5 +246,5 @@ * currently assigned to a host channel. */ - struct list_head non_periodic_sched_active; + struct list_head non_periodic_sched_active; /** @@ -246,5 +252,5 @@ * non-periodic schedule. */ - struct list_head *non_periodic_qh_ptr; + struct list_head *non_periodic_qh_ptr; /** @@ -310,5 +316,5 @@ * dwc_hc_t items. */ - struct list_head free_hc_list; + struct list_head free_hc_list; /** @@ -335,5 +341,5 @@ * Buffer to use for any data received during the status phase of a * control transfer. Normally no data is transferred during the status - * phase. This buffer is used as a bit bucket. + * phase. This buffer is used as a bit bucket. */ uint8_t *status_buf; @@ -343,5 +349,5 @@ */ dma_addr_t status_buf_dma; -#define DWC_OTG_HCD_STATUS_BUF_SIZE 64 +#define DWC_OTG_HCD_STATUS_BUF_SIZE 64 /** @@ -349,5 +355,9 @@ * during an OTG role change. */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) struct work_struct start_work; +#else + struct delayed_work start_work; +#endif /** @@ -356,12 +366,15 @@ * sysfs attribute "buspower". */ - struct timer_list conn_timer; + struct timer_list conn_timer; /* Tasket to do a reset */ - struct tasklet_struct *reset_tasklet; + struct tasklet_struct *reset_tasklet; + + /* */ + spinlock_t lock; #ifdef DEBUG - uint32_t frrem_samples; - uint64_t frrem_accum; + uint32_t frrem_samples; + uint64_t frrem_accum; uint32_t hfnum_7_samples_a; @@ -378,6 +391,5 @@ uint32_t hfnum_other_samples_b; uint64_t hfnum_other_frrem_accum_b; -#endif - +#endif } dwc_otg_hcd_t; @@ -396,6 +408,6 @@ /** @name HCD Create/Destroy Functions */ /** @{ */ -extern int dwc_otg_hcd_init(struct lm_device *_lmdev); -extern void dwc_otg_hcd_remove(struct lm_device *_lmdev); +extern int dwc_otg_hcd_init(struct lm_device *lmdev); +extern void dwc_otg_hcd_remove(struct lm_device *lmdev); /** @} */ @@ -407,21 +419,32 @@ extern int dwc_otg_hcd_get_frame_number(struct usb_hcd *hcd); extern void dwc_otg_hcd_free(struct usb_hcd *hcd); -extern int dwc_otg_hcd_urb_enqueue(struct usb_hcd *hcd, +extern int dwc_otg_hcd_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *ep, - struct urb *urb, - gfp_t mem_flags); -extern int dwc_otg_hcd_urb_dequeue(struct usb_hcd *hcd, -/* struct usb_host_endpoint *ep,*/ + struct urb *urb, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + int mem_flags +#else + gfp_t mem_flags +#endif + ); +extern int dwc_otg_hcd_urb_dequeue(struct usb_hcd *hcd, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + struct usb_host_endpoint *ep, +#endif struct urb *urb); extern void dwc_otg_hcd_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep); -extern irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd); -extern int dwc_otg_hcd_hub_status_data(struct usb_hcd *hcd, +extern irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + , struct pt_regs *regs +#endif + ); +extern int dwc_otg_hcd_hub_status_data(struct usb_hcd *hcd, char *buf); -extern int dwc_otg_hcd_hub_control(struct usb_hcd *hcd, - u16 typeReq, - u16 wValue, - u16 wIndex, - char *buf, +extern int dwc_otg_hcd_hub_control(struct usb_hcd *hcd, + u16 typeReq, + u16 wValue, + u16 wIndex, + char *buf, u16 wLength); @@ -430,26 +453,26 @@ /** @name Transaction Execution Functions */ /** @{ */ -extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t *_hcd); -extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t *_hcd, - dwc_otg_transaction_type_e _tr_type); -extern void dwc_otg_hcd_complete_urb(dwc_otg_hcd_t *_hcd, struct urb *_urb, - int _status); +extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t *hcd); +extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t *hcd, + dwc_otg_transaction_type_e tr_type); +extern void dwc_otg_hcd_complete_urb(dwc_otg_hcd_t *_hcd, struct urb *urb, + int status); /** @} */ /** @name Interrupt Handler Functions */ /** @{ */ -extern int32_t dwc_otg_hcd_handle_intr (dwc_otg_hcd_t *_dwc_otg_hcd); -extern int32_t dwc_otg_hcd_handle_sof_intr (dwc_otg_hcd_t *_dwc_otg_hcd); -extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr (dwc_otg_hcd_t *_dwc_otg_hcd); -extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr (dwc_otg_hcd_t *_dwc_otg_hcd); -extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr (dwc_otg_hcd_t *_dwc_otg_hcd); -extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t *_dwc_otg_hcd); -extern int32_t dwc_otg_hcd_handle_port_intr (dwc_otg_hcd_t *_dwc_otg_hcd); -extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr (dwc_otg_hcd_t *_dwc_otg_hcd); -extern int32_t dwc_otg_hcd_handle_disconnect_intr (dwc_otg_hcd_t *_dwc_otg_hcd); -extern int32_t dwc_otg_hcd_handle_hc_intr (dwc_otg_hcd_t *_dwc_otg_hcd); -extern int32_t dwc_otg_hcd_handle_hc_n_intr (dwc_otg_hcd_t *_dwc_otg_hcd, uint32_t _num); -extern int32_t dwc_otg_hcd_handle_session_req_intr (dwc_otg_hcd_t *_dwc_otg_hcd); -extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr (dwc_otg_hcd_t *_dwc_otg_hcd); +extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t *dwc_otg_hcd); +extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t *dwc_otg_hcd); +extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *dwc_otg_hcd); +extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *dwc_otg_hcd); +extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t *dwc_otg_hcd); +extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t *dwc_otg_hcd); +extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t *dwc_otg_hcd); +extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t *dwc_otg_hcd); +extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t *dwc_otg_hcd); +extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t *dwc_otg_hcd); +extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t *dwc_otg_hcd, uint32_t num); +extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t *dwc_otg_hcd); +extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t *dwc_otg_hcd); /** @} */ @@ -459,60 +482,61 @@ /* Implemented in dwc_otg_hcd_queue.c */ -extern dwc_otg_qh_t *dwc_otg_hcd_qh_create (dwc_otg_hcd_t *_hcd, struct urb *_urb); -extern void dwc_otg_hcd_qh_init (dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh, struct urb *_urb); -extern void dwc_otg_hcd_qh_free (dwc_otg_qh_t *_qh); -extern int dwc_otg_hcd_qh_add (dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh); -extern void dwc_otg_hcd_qh_remove (dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh); -extern void dwc_otg_hcd_qh_deactivate (dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh, int sched_csplit); +extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t *hcd, struct urb *urb); +extern void dwc_otg_hcd_qh_init(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh, struct urb *urb); +extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh); +extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh); +extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh); +extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh, int sched_csplit); /** Remove and free a QH */ -static inline void dwc_otg_hcd_qh_remove_and_free (dwc_otg_hcd_t *_hcd, - dwc_otg_qh_t *_qh) -{ - dwc_otg_hcd_qh_remove (_hcd, _qh); - dwc_otg_hcd_qh_free (_qh); +static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t *hcd, + dwc_otg_qh_t *qh) +{ + dwc_otg_hcd_qh_remove(hcd, qh); + dwc_otg_hcd_qh_free(hcd, qh); } /** Allocates memory for a QH structure. * @return Returns the memory allocate or NULL on error. */ -static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc (void) -{ - return (dwc_otg_qh_t *) kmalloc (sizeof(dwc_otg_qh_t), GFP_KERNEL); -} - -extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create (struct urb *urb); -extern void dwc_otg_hcd_qtd_init (dwc_otg_qtd_t *qtd, struct urb *urb); -extern int dwc_otg_hcd_qtd_add (dwc_otg_qtd_t *qtd, dwc_otg_hcd_t *dwc_otg_hcd); +static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(void) +{ + return (dwc_otg_qh_t *) kmalloc(sizeof(dwc_otg_qh_t), GFP_KERNEL); +} + +extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(struct urb *urb); +extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t *qtd, struct urb *urb); +extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t *qtd, dwc_otg_hcd_t *dwc_otg_hcd); /** Allocates memory for a QTD structure. * @return Returns the memory allocate or NULL on error. */ -static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc (void) -{ - return (dwc_otg_qtd_t *) kmalloc (sizeof(dwc_otg_qtd_t), GFP_KERNEL); +static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(void) +{ + return (dwc_otg_qtd_t *) kmalloc(sizeof(dwc_otg_qtd_t), GFP_KERNEL); } /** Frees the memory for a QTD structure. QTD should already be removed from * list. - * @param[in] _qtd QTD to free.*/ -static inline void dwc_otg_hcd_qtd_free (dwc_otg_qtd_t *_qtd) -{ - kfree (_qtd); + * @param[in] qtd QTD to free.*/ +static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t *qtd) +{ + kfree(qtd); } /** Removes a QTD from list. - * @param[in] _qtd QTD to remove from list. */ -static inline void dwc_otg_hcd_qtd_remove (dwc_otg_qtd_t *_qtd) + * @param[in] hcd HCD instance. + * @param[in] qtd QTD to remove from list. */ +static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t *hcd, dwc_otg_qtd_t *qtd) { unsigned long flags; - local_irq_save (flags); - list_del (&_qtd->qtd_list_entry); - local_irq_restore (flags); + SPIN_LOCK_IRQSAVE(&hcd->lock, flags); + list_del(&qtd->qtd_list_entry); + SPIN_UNLOCK_IRQRESTORE(&hcd->lock, flags); } /** Remove and free a QTD */ -static inline void dwc_otg_hcd_qtd_remove_and_free (dwc_otg_qtd_t *_qtd) -{ - dwc_otg_hcd_qtd_remove (_qtd); - dwc_otg_hcd_qtd_free (_qtd); +static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t *hcd, dwc_otg_qtd_t *qtd) +{ + dwc_otg_hcd_qtd_remove(hcd, qtd); + dwc_otg_hcd_qtd_free(qtd); } @@ -522,16 +546,16 @@ /** @name Internal Functions */ /** @{ */ -dwc_otg_qh_t *dwc_urb_to_qh(struct urb *_urb); -void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t *_hcd); -void dwc_otg_hcd_dump_state(dwc_otg_hcd_t *_hcd); +dwc_otg_qh_t *dwc_urb_to_qh(struct urb *urb); +void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t *hcd); +void dwc_otg_hcd_dump_state(dwc_otg_hcd_t *hcd); /** @} */ /** Gets the usb_host_endpoint associated with an URB. */ -static inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *_urb) -{ - struct usb_device *dev = _urb->dev; - int ep_num = usb_pipeendpoint(_urb->pipe); - - if (usb_pipein(_urb->pipe)) +static inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb) +{ + struct usb_device *dev = urb->dev; + int ep_num = usb_pipeendpoint(urb->pipe); + + if (usb_pipein(urb->pipe)) return dev->ep_in[ep_num]; else @@ -544,15 +568,15 @@ */ #define dwc_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \ - ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4) + ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4) /** Gets the QH that contains the list_head */ -#define dwc_list_to_qh(_list_head_ptr_) (container_of(_list_head_ptr_,dwc_otg_qh_t,qh_list_entry)) +#define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry) /** Gets the QTD that contains the list_head */ -#define dwc_list_to_qtd(_list_head_ptr_) (container_of(_list_head_ptr_,dwc_otg_qtd_t,qtd_list_entry)) +#define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry) /** Check if QH is non-periodic */ #define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == USB_ENDPOINT_XFER_BULK) || \ - (_qh_ptr_->ep_type == USB_ENDPOINT_XFER_CONTROL)) + (_qh_ptr_->ep_type == USB_ENDPOINT_XFER_CONTROL)) /** High bandwidth multiplier as encoded in highspeed endpoint descriptors */ @@ -567,7 +591,7 @@ * frame number when the max frame number is reached. */ -static inline int dwc_frame_num_le(uint16_t _frame1, uint16_t _frame2) -{ - return ((_frame2 - _frame1) & DWC_HFNUM_MAX_FRNUM) <= +static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2) +{ + return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <= (DWC_HFNUM_MAX_FRNUM >> 1); } @@ -578,8 +602,8 @@ * number when the max frame number is reached. */ -static inline int dwc_frame_num_gt(uint16_t _frame1, uint16_t _frame2) -{ - return (_frame1 != _frame2) && - (((_frame1 - _frame2) & DWC_HFNUM_MAX_FRNUM) < +static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2) +{ + return (frame1 != frame2) && + (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) < (DWC_HFNUM_MAX_FRNUM >> 1)); } @@ -589,17 +613,17 @@ * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value. */ -static inline uint16_t dwc_frame_num_inc(uint16_t _frame, uint16_t _inc) -{ - return (_frame + _inc) & DWC_HFNUM_MAX_FRNUM; -} - -static inline uint16_t dwc_full_frame_num (uint16_t _frame) -{ - return ((_frame) & DWC_HFNUM_MAX_FRNUM) >> 3; -} - -static inline uint16_t dwc_micro_frame_num (uint16_t _frame) -{ - return (_frame) & 0x7; +static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc) +{ + return (frame + inc) & DWC_HFNUM_MAX_FRNUM; +} + +static inline uint16_t dwc_full_frame_num(uint16_t frame) +{ + return (frame & DWC_HFNUM_MAX_FRNUM) >> 3; +} + +static inline uint16_t dwc_micro_frame_num(uint16_t frame) +{ + return frame & 0x7; } @@ -638,6 +662,6 @@ } #else -#define dwc_sample_frrem(_hcd, _qh, _letter) -#endif +#define dwc_sample_frrem(_hcd, _qh, _letter) +#endif #endif #endif /* DWC_DEVICE_ONLY */ Index: /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_regs.h =================================================================== --- /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_regs.h (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_regs.h (revision 12433) @@ -1,7 +1,7 @@ /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_regs.h $ - * $Revision: 1.1 $ - * $Date: 2007-11-19 05:39:07 $ - * $Change: 791271 $ + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $ + * $Revision: 1.2 $ + * $Date: 2008-11-21 05:39:15 $ + * $Change: 1099526 $ * * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, @@ -61,4 +61,12 @@ * would be after a power-on reset. */ + +/** Maximum number of Periodic FIFOs */ +#define MAX_PERIO_FIFOS 15 +/** Maximum number of Transmit FIFOs */ +#define MAX_TX_FIFOS 15 + +/** Maximum number of Endpoints/HostChannels */ +#define MAX_EPS_CHANNELS 16 /****************************************************************************/ @@ -133,5 +141,5 @@ volatile uint32_t ghwcfg4; /** Reserved Offset: 054h-0FFh */ - uint32_t reserved[43]; + volatile uint32_t reserved[43]; /** Host Periodic Transmit FIFO Size Register. Offset: 100h */ volatile uint32_t hptxfsiz; @@ -274,5 +282,7 @@ unsigned ulpi_int_vbus_indicator : 1; unsigned term_sel_dl_pulse : 1; - unsigned reserved : 9; + unsigned reserved23_27 : 5; + unsigned tx_end_delay : 1; + unsigned reserved29_31 : 3; } b; } gusbcfg_data_t; @@ -711,5 +721,6 @@ unsigned perio_ep_supported : 1; unsigned dynamic_fifo : 1; - unsigned rx_status_q_depth : 2; + unsigned multi_proc_int : 1; + unsigned reserved21 : 1; unsigned nonperio_tx_q_depth : 2; unsigned host_perio_tx_q_depth : 2; @@ -769,5 +780,6 @@ unsigned ded_fifo_en : 1; unsigned num_in_eps : 4; - unsigned reserved31_30 : 2; + unsigned desc_dma : 1; + unsigned desc_dma_dyn : 1; } b; } hwcfg4_data_t; @@ -823,4 +835,16 @@ * Offset: 834h */ volatile uint32_t dtknqr4_fifoemptymsk; + /** Device Each Endpoint Interrupt Register (Read Only). / + * Offset: 838h */ + volatile uint32_t deachint; + /** Device Each Endpoint Interrupt mask Register (Read/Write). / + * Offset: 83Ch */ + volatile uint32_t deachintmsk; + /** Device Each In Endpoint Interrupt mask Register (Read/Write). / + * Offset: 840h */ + volatile uint32_t diepeachintmsk[MAX_EPS_CHANNELS]; + /** Device Each Out Endpoint Interrupt mask Register (Read/Write). / + * Offset: 880h */ + volatile uint32_t doepeachintmsk[MAX_EPS_CHANNELS]; } dwc_otg_device_global_regs_t; @@ -856,5 +880,7 @@ unsigned reserved13_17 : 5; /** In Endpoint Mis-match count */ - unsigned epmscnt : 4; + unsigned epmscnt : 5; + /** Enable Descriptor DMA in Device mode */ + unsigned descdma : 1; } b; } dcfg_data_t; @@ -891,5 +917,16 @@ unsigned cgoutnak : 1; - unsigned reserved : 21; + /** Power-On Programming Done */ + unsigned pwronprgdone : 1; + /** Global Continue on BNA */ + unsigned gcontbna : 1; + /** Global Multi Count */ + unsigned gmc : 2; + /** Ignore Frame Number for ISOC EPs */ + unsigned ifrmnum : 1; + /** NAK on Babble */ + unsigned nakonbble : 1; + + unsigned reserved16_31 : 16; } b; } dctl_data_t; @@ -958,10 +995,18 @@ unsigned txfifoundrn : 1; - unsigned reserved08_31 : 23; + /** BNA Interrupt mask */ + unsigned bna : 1; + + unsigned reserved10_12 : 3; + /** BNA Interrupt mask */ + unsigned nak : 1; + + unsigned reserved14_31 : 18; } b; } diepint_data_t; -/** - * This union represents the bit fields in the Device IN EP Common - * Interrupt Mask Register. + +/** + * This union represents the bit fields in the Device IN EP + * Common/Dedicated Interrupt Mask Register. */ typedef union diepint_data diepmsk_data_t; @@ -989,13 +1034,36 @@ /** Setup Phase Done (contorl EPs) */ unsigned setup : 1; - unsigned reserved04_31 : 28; + /** OUT Token Received when Endpoint Disabled */ + unsigned outtknepdis : 1; + + unsigned stsphsercvd : 1; + /** Back-to-Back SETUP Packets Received */ + unsigned back2backsetup : 1; + + unsigned reserved7 : 1; + /** OUT packet Error */ + unsigned outpkterr : 1; + /** BNA Interrupt */ + unsigned bna : 1; + + unsigned reserved10 : 1; + /** Packet Drop Status */ + unsigned pktdrpsts : 1; + /** Babble Interrupt */ + unsigned babble : 1; + /** NAK Interrupt */ + unsigned nak : 1; + /** NYET Interrupt */ + unsigned nyet : 1; + + unsigned reserved15_31 : 17; } b; } doepint_data_t; -/** - * This union represents the bit fields in the Device OUT EP Common - * Interrupt Mask Register. + +/** + * This union represents the bit fields in the Device OUT EP + * Common/Dedicated Interrupt Mask Register. */ typedef union doepint_data doepmsk_data_t; - /** @@ -1141,7 +1209,7 @@ * (ep_num * 20h) + 18h */ volatile uint32_t dtxfsts; - /** Reserved. Offset:900h + (ep_num * 20h) + 1Ch - 900h + - * (ep_num * 20h) + 1Ch*/ - uint32_t reserved18; + /** Device IN Endpoint DMA Buffer Register. Offset:900h + + * (ep_num * 20h) + 1Ch */ + volatile uint32_t diepdmab; } dwc_otg_dev_in_ep_regs_t; @@ -1175,7 +1243,9 @@ * + (ep_num * 20h) + 14h */ volatile uint32_t doepdma; - /** Reserved. Offset:B00h + (ep_num * 20h) + 18h - B00h + - * (ep_num * 20h) + 1Ch */ - uint32_t unused[2]; + /** Reserved. Offset:B00h + * (ep_num * 20h) + 1Ch */ + uint32_t unused; + /** Device OUT Endpoint DMA Buffer Register. Offset:B00h + * + (ep_num * 20h) + 1Ch */ + uint32_t doepdmab; } dwc_otg_dev_out_ep_regs_t; @@ -1328,11 +1398,113 @@ -/** Maximum number of Periodic FIFOs */ -#define MAX_PERIO_FIFOS 15 -/** Maximum number of Periodic FIFOs */ -#define MAX_TX_FIFOS 15 - -/** Maximum number of Endpoints/HostChannels */ -#define MAX_EPS_CHANNELS 16 +///////////////////////////////////////////////// +// DMA Descriptor Specific Structures +// + +/** Buffer status definitions */ + +#define BS_HOST_READY 0x0 +#define BS_DMA_BUSY 0x1 +#define BS_DMA_DONE 0x2 +#define BS_HOST_BUSY 0x3 + +/** Receive/Transmit status definitions */ + +#define RTS_SUCCESS 0x0 +#define RTS_BUFFLUSH 0x1 +#define RTS_RESERVED 0x2 +#define RTS_BUFERR 0x3 + + +/** + * This union represents the bit fields in the DMA Descriptor + * status quadlet. Read the quadlet into the d32 member then + * set/clear the bits using the bit, b_iso_out and + * b_iso_in elements. + */ +typedef union desc_sts_data +{ + /** raw register data */ + uint32_t d32; + /** quadlet bits */ + struct { + /** Received number of bytes */ + unsigned bytes : 16; + + unsigned reserved16_22 : 7; + /** Multiple Transfer - only for OUT EPs */ + unsigned mtrf : 1; + /** Setup Packet received - only for OUT EPs */ + unsigned sr : 1; + /** Interrupt On Complete */ + unsigned ioc : 1; + /** Short Packet */ + unsigned sp : 1; + /** Last */ + unsigned l : 1; + /** Receive Status */ + unsigned sts : 2; + /** Buffer Status */ + unsigned bs : 2; + } b; + +#ifdef DWC_EN_ISOC + /** iso out quadlet bits */ + struct { + /** Received number of bytes */ + unsigned rxbytes : 11; + + unsigned reserved11 : 1; + /** Frame Number */ + unsigned framenum : 11; + /** Received ISO Data PID */ + unsigned pid : 2; + /** Interrupt On Complete */ + unsigned ioc : 1; + /** Short Packet */ + unsigned sp : 1; + /** Last */ + unsigned l : 1; + /** Receive Status */ + unsigned rxsts : 2; + /** Buffer Status */ + unsigned bs : 2; + } b_iso_out; + + /** iso in quadlet bits */ + struct { + /** Transmited number of bytes */ + unsigned txbytes : 12; + /** Frame Number */ + unsigned framenum : 11; + /** Transmited ISO Data PID */ + unsigned pid : 2; + /** Interrupt On Complete */ + unsigned ioc : 1; + /** Short Packet */ + unsigned sp : 1; + /** Last */ + unsigned l : 1; + /** Transmit Status */ + unsigned txsts : 2; + /** Buffer Status */ + unsigned bs : 2; + } b_iso_in; +#endif //DWC_EN_ISOC +} desc_sts_data_t; + +/** + * DMA Descriptor structure + * + * DMA Descriptor structure contains two quadlets: + * Status quadlet and Data buffer pointer. + */ +typedef struct dwc_otg_dma_desc +{ + /** DMA Descriptor status quadlet */ + desc_sts_data_t status; + /** DMA Descriptor data buffer pointer */ + dma_addr_t buf; +} dwc_otg_dma_desc_t; /** @@ -1378,4 +1550,27 @@ uint16_t rx_thr_length; uint16_t tx_thr_length; + + /** + * Pointers to the DMA Descriptors for EP0 Control + * transfers (virtual and physical) + */ + + /** 2 descriptors for SETUP packets */ + uint32_t dma_setup_desc_addr[2]; + dwc_otg_dma_desc_t* setup_desc_addr[2]; + + /** Pointer to Descriptor with latest SETUP packet */ + dwc_otg_dma_desc_t* psetup; + + /** Index of current SETUP handler descriptor */ + uint32_t setup_desc_index; + + /** Descriptor for Data In or Status In phases */ + uint32_t dma_in_desc_addr; + dwc_otg_dma_desc_t* in_desc_addr;; + + /** Descriptor for Data Out or Status Out phases */ + uint32_t dma_out_desc_addr; + dwc_otg_dma_desc_t* out_desc_addr; } dwc_otg_dev_if_t; Index: /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dummy_audio.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dummy_audio.c (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dummy_audio.c (revision 12433) @@ -85,5 +85,10 @@ #include -#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) +# include +#else +# include +#endif + #include Index: /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_pcd.c =================================================================== --- /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_pcd.c (revision 10741) +++ /src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_pcd.c (revision 12433) @@ -1,7 +1,7 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_pcd.c $ - * $Revision: 1.3 $ - * $Date: 2008-03-08 08:43:10 $ - * $Change: 791271 $ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $ + * $Revision: 1.5 $ + * $Date: 2008-11-27 09:21:25 $ + * $Change: 1115682 $ * * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, @@ -73,11 +73,20 @@ #include #include +#include + //#include +//#include #include -//#include - -#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) +# include +#else +# include +#endif + #include + + #include "dwc_otg_driver.h" #include "dwc_otg_pcd.h" @@ -99,33 +108,29 @@ * This function completes a request. It call's the request call back. */ -void request_done(dwc_otg_pcd_ep_t *_ep, dwc_otg_pcd_request_t *_req, - int _status) -{ - unsigned stopped = _ep->stopped; - - DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _ep); - list_del_init(&_req->queue); - - if (_req->req.status == -EINPROGRESS) - { - _req->req.status = _status; - } - else - { - _status = _req->req.status; +void dwc_otg_request_done(dwc_otg_pcd_ep_t *ep, dwc_otg_pcd_request_t *req, + int status) +{ + unsigned stopped = ep->stopped; + + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, ep); + list_del_init(&req->queue); + + if (req->req.status == -EINPROGRESS) { + req->req.status = status; + } else { + status = req->req.status; } /* don't modify queue heads during completion callback */ - _ep->stopped = 1; - SPIN_UNLOCK(&_ep->pcd->lock); - _req->req.complete(&_ep->ep, &_req->req); - SPIN_LOCK(&_ep->pcd->lock); - - if (_ep->pcd->request_pending > 0) - { - --_ep->pcd->request_pending; - } - - _ep->stopped = stopped; + ep->stopped = 1; + SPIN_UNLOCK(&ep->pcd->lock); + req->req.complete(&ep->ep, &req->req); + SPIN_LOCK(&ep->pcd->lock); + + if (ep->pcd->request_pending > 0) { + --ep->pcd->request_pending; + } + + ep->stopped = stopped; } @@ -133,16 +138,15 @@ * This function terminates all the requsts in the EP request queue. */ -void request_nuke( dwc_otg_pcd_ep_t *_ep ) +void dwc_otg_request_nuke(dwc_otg_pcd_ep_t *ep) { dwc_otg_pcd_request_t *req; - _ep->stopped = 1; + ep->stopped = 1; /* called with irqs blocked?? */ - while (!list_empty(&_ep->queue)) - { - req = list_entry(_ep->queue.next, dwc_otg_pcd_request_t, + while (!list_empty(&ep->queue)) { + req = list_entry(ep->queue.next, dwc_otg_pcd_request_t, queue); - request_done(_ep, req, -ESHUTDOWN ); + dwc_otg_request_done(ep, req, -ESHUTDOWN); } } @@ -175,6 +179,5 @@ for(i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; ++i) { - if((PerTxMsk & core_if->p_tx_msk) == 0) - { + if((PerTxMsk & core_if->p_tx_msk) == 0) { core_if->p_tx_msk |= PerTxMsk; return i + 1; @@ -192,38 +195,4 @@ core_if->p_tx_msk = (core_if->p_tx_msk & (1 << (fifo_num - 1))) ^ core_if->p_tx_msk; } - -// Modify by kaiker ,for RT3052 device mode config -/** - * This function assigns a Tx FIFO to an for IN Endpoint(Must Non-periodic ep or interrupt ep) - * in Dedicated Tx FIFO mode - */ -static uint32_t assign_tx_fifo_with_ralink_fifo_config(unsigned int type) -{ - static int fifo_num = 2; - - - switch (type) - { - - case 1: - DWC_DEBUGPL(DBG_CIL," [Isochronous] \n"); - return fifo_num++; - - case 2: - DWC_DEBUGPL(DBG_CIL," [Bulk] \n"); - return 1; - case 3: - DWC_DEBUGPL(DBG_CIL," [Interrupt] \n"); - return fifo_num++; - default: - - return 9; - - - - } -} - - /** * This function assigns periodic Tx FIFO to an periodic EP @@ -237,6 +206,5 @@ for(i = 0; i < core_if->hwcfg4.b.num_in_eps; ++i) { - if((TxMsk & core_if->tx_msk) == 0) - { + if((TxMsk & core_if->tx_msk) == 0) { core_if->tx_msk |= TxMsk; return i + 1; @@ -254,4 +222,5 @@ core_if->tx_msk = (core_if->tx_msk & (1 << (fifo_num - 1))) ^ core_if->tx_msk; } + /** * This function is called by the Gadget Driver for each EP to be @@ -261,6 +230,6 @@ * calls dwc_otg_ep_activate. */ -static int dwc_otg_pcd_ep_enable(struct usb_ep *_ep, - const struct usb_endpoint_descriptor *_desc) +static int dwc_otg_pcd_ep_enable(struct usb_ep *usb_ep, + const struct usb_endpoint_descriptor *ep_desc) { dwc_otg_pcd_ep_t *ep = 0; @@ -268,15 +237,13 @@ unsigned long flags; - DWC_DEBUGPL(DBG_PCDV,"%s(%p,%p)\n", __func__, _ep, _desc ); - - ep = container_of(_ep, dwc_otg_pcd_ep_t, ep); - if (!_ep || !_desc || ep->desc || - _desc->bDescriptorType != USB_DT_ENDPOINT) - { - DWC_WARN( "%s, bad ep or descriptor\n", __func__); + DWC_DEBUGPL(DBG_PCDV,"%s(%p,%p)\n", __func__, usb_ep, ep_desc); + + ep = container_of(usb_ep, dwc_otg_pcd_ep_t, ep); + if (!usb_ep || !ep_desc || ep->desc || + ep_desc->bDescriptorType != USB_DT_ENDPOINT) { + DWC_WARN("%s, bad ep or descriptor\n", __func__); return -EINVAL; } - if (ep == &ep->pcd->ep0) - { + if (ep == &ep->pcd->ep0) { DWC_WARN("%s, bad ep(0)\n", __func__); return -EINVAL; @@ -284,13 +251,11 @@ /* Check FIFO size? */ - if (!_desc->wMaxPacketSize) - { - DWC_WARN("%s, bad %s maxpacket\n", __func__, _ep->name); + if (!ep_desc->wMaxPacketSize) { + DWC_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name); return -ERANGE; } pcd = ep->pcd; - if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN) - { + if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN) { DWC_WARN("%s, bogus device state\n", __func__); return -ESHUTDOWN; @@ -299,6 +264,6 @@ SPIN_LOCK_IRQSAVE(&pcd->lock, flags); - ep->desc = _desc; - ep->ep.maxpacket = le16_to_cpu (_desc->wMaxPacketSize); + ep->desc = ep_desc; + ep->ep.maxpacket = le16_to_cpu (ep_desc->wMaxPacketSize); /* @@ -307,18 +272,14 @@ ep->stopped = 0; - ep->dwc_ep.is_in = (USB_DIR_IN & _desc->bEndpointAddress) != 0; + ep->dwc_ep.is_in = (USB_DIR_IN & ep_desc->bEndpointAddress) != 0; ep->dwc_ep.maxpacket = ep->ep.maxpacket; - ep->dwc_ep.type = _desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - - if(ep->dwc_ep.is_in) - { - if(!pcd->otg_dev->core_if->en_multiple_tx_fifo) - { + ep->dwc_ep.type = ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + + if(ep->dwc_ep.is_in) { + if(!pcd->otg_dev->core_if->en_multiple_tx_fifo) { ep->dwc_ep.tx_fifo_num = 0; - if ((_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_ISOC ) - { + if (ep->dwc_ep.type == USB_ENDPOINT_XFER_ISOC) { /* * if ISOC EP then assign a Periodic Tx FIFO. @@ -326,51 +287,28 @@ ep->dwc_ep.tx_fifo_num = assign_perio_tx_fifo(pcd->otg_dev->core_if); } - } - else - { - + } else { /* * if Dedicated FIFOs mode is on then assign a Tx FIFO. */ -#if 1 - /* - Modify by kaiker ,for RT3052 device mode config - - Bulk EP must set to FIFOnum 1 - Interrupt/ISO EP must set to FIFOnum 2 ~ 3 - - */ - - - ep->dwc_ep.tx_fifo_num = assign_tx_fifo_with_ralink_fifo_config((unsigned int)ep->dwc_ep.type); - if(ep->dwc_ep.tx_fifo_num > 3) - { - printk("\n FAIL !! The FIFO num is illegal \n"); - - return -ESHUTDOWN; - } - else - { - printk("\n By Assign TX FIFO num = [ %d ]\n",ep->dwc_ep.tx_fifo_num); - } -#else ep->dwc_ep.tx_fifo_num = assign_tx_fifo(pcd->otg_dev->core_if); -#endif - + } } /* Set initial data PID. */ - if ((_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_BULK ) - { + if (ep->dwc_ep.type == USB_ENDPOINT_XFER_BULK) { ep->dwc_ep.data_pid_start = 0; } - + DWC_DEBUGPL(DBG_PCD, "Activate %s-%s: type=%d, mps=%d desc=%p\n", ep->ep.name, (ep->dwc_ep.is_in ?"IN":"OUT"), - ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc ); - - dwc_otg_ep_activate( GET_CORE_IF(pcd), &ep->dwc_ep ); + ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc); + + if(ep->dwc_ep.type != USB_ENDPOINT_XFER_ISOC) { + ep->dwc_ep.desc_addr = dwc_otg_ep_alloc_desc_chain(&ep->dwc_ep.dma_desc_addr, MAX_DMA_DESC_CNT); + } + + dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep); SPIN_UNLOCK_IRQRESTORE(&pcd->lock, flags); + return 0; } @@ -384,15 +322,15 @@ * and then calls dwc_otg_ep_deactivate. */ -static int dwc_otg_pcd_ep_disable(struct usb_ep *_ep) +static int dwc_otg_pcd_ep_disable(struct usb_ep *usb_ep) { dwc_otg_pcd_ep_t *ep; + dwc_otg_pcd_t *pcd = 0; unsigned long flags; - DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _ep); - ep = container_of(_ep, dwc_otg_pcd_ep_t, ep); - if (!_ep || !ep->desc) - { + DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, usb_ep); + ep = container_of(usb_ep, dwc_otg_pcd_ep_t, ep); + if (!usb_ep || !ep->desc) { DWC_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__, - _ep ? ep->ep.name : NULL); + usb_ep ? ep->ep.name : NULL); return -EINVAL; } @@ -400,19 +338,26 @@ SPIN_LOCK_IRQSAVE(&ep->pcd->lock, flags); - request_nuke( ep ); - - dwc_otg_ep_deactivate( GET_CORE_IF(ep->pcd), &ep->dwc_ep ); + dwc_otg_request_nuke(ep); + + dwc_otg_ep_deactivate(GET_CORE_IF(ep->pcd), &ep->dwc_ep); ep->desc = 0; ep->stopped = 1; - if(ep->dwc_ep.is_in) - { + if(ep->dwc_ep.is_in) { + dwc_otg_flush_tx_fifo(GET_CORE_IF(ep->pcd), ep->dwc_ep.tx_fifo_num); release_perio_tx_fifo(GET_CORE_IF(ep->pcd), ep->dwc_ep.tx_fifo_num); release_tx_fifo(GET_CORE_IF(ep->pcd), ep->dwc_ep.tx_fifo_num); } + /* Free DMA Descriptors */ + pcd = ep->pcd; + SPIN_UNLOCK_IRQRESTORE(&ep->pcd->lock, flags); - DWC_DEBUGPL(DBG_PCD, "%s disabled\n", _ep->name); + if(ep->dwc_ep.type != USB_ENDPOINT_XFER_ISOC && ep->dwc_ep.desc_addr) { + dwc_otg_ep_free_desc_chain(ep->dwc_ep.desc_addr, ep->dwc_ep.dma_desc_addr, MAX_DMA_DESC_CNT); + } + + DWC_DEBUGPL(DBG_PCD, "%s disabled\n", usb_ep->name); return 0; } @@ -423,21 +368,24 @@ * endpoint. * - * @param _ep The endpoint to be used with with the request - * @param _gfp_flags the GFP_* flags to use. - */ -static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *_ep, - int _gfp_flags) + * @param ep The endpoint to be used with with the request + * @param gfp_flags the GFP_* flags to use. + */ +static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *ep, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + int gfp_flags +#else + gfp_t gfp_flags +#endif + ) { dwc_otg_pcd_request_t *req; - DWC_DEBUGPL(DBG_PCDV,"%s(%p,%d)\n", __func__, _ep, _gfp_flags); - if (0 == _ep ) - { + DWC_DEBUGPL(DBG_PCDV,"%s(%p,%d)\n", __func__, ep, gfp_flags); + if (0 == ep) { DWC_WARN("%s() %s\n", __func__, "Invalid EP!\n"); return 0; } - req = kmalloc( sizeof(dwc_otg_pcd_request_t), _gfp_flags); - if (0 == req) - { + req = kmalloc(sizeof(dwc_otg_pcd_request_t), gfp_flags); + if (0 == req) { DWC_WARN("%s() %s\n", __func__, "request allocation failed!\n"); @@ -453,15 +401,14 @@ * This function frees a request object. * - * @param _ep The endpoint associated with the request - * @param _req The request being freed - */ -static void dwc_otg_pcd_free_request(struct usb_ep *_ep, - struct usb_request *_req) -{ - dwc_otg_pcd_request_t *req; - DWC_DEBUGPL(DBG_PCDV,"%s(%p,%p)\n", __func__, _ep, _req); - - if (0 == _ep || 0 == _req) - { + * @param ep The endpoint associated with the request + * @param req The request being freed + */ +static void dwc_otg_pcd_free_request(struct usb_ep *ep, + struct usb_request *req) +{ + dwc_otg_pcd_request_t *request; + DWC_DEBUGPL(DBG_PCDV,"%s(%p,%p)\n", __func__, ep, req); + + if (0 == ep || 0 == req) { DWC_WARN("%s() %s\n", __func__, "Invalid ep or req argument!\n"); @@ -469,6 +416,6 @@ } - req = container_of(_req, dwc_otg_pcd_request_t, req); - kfree(req); + request = container_of(req, dwc_otg_pcd_request_t, req); + kfree(request); } @@ -477,12 +424,18 @@ * to/from the specified endpoint. * - * @param _ep The endpoint to be used with with the request - * @param _bytes The desired number of bytes for the buffer - * @param _dma Pointer to the buffer's DMA address; must be valid - * @param _gfp_flags the GFP_* flags to use. + * @param usb_ep The endpoint to be used with with the request + * @param bytes The desired number of bytes for the buffer + * @param dma Pointer to the buffer's DMA address; must be valid + * @param gfp_flags the GFP_* flags to use. * @return address of a new buffer or null is buffer could not be allocated. */ -static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *_ep, unsigned _bytes, - dma_addr_t *_dma, int _gfp_flags) +static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes, + dma_addr_t *dma, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + int gfp_flags +#else + gfp_t gfp_flags +#endif + ) { void *buf; @@ -490,29 +443,25 @@ dwc_otg_pcd_t *pcd = 0; - ep = container_of(_ep, dwc_otg_pcd_ep_t, ep); + ep = container_of(usb_ep, dwc_otg_pcd_ep_t, ep); pcd = ep->pcd; - DWC_DEBUGPL(DBG_PCDV,"%s(%p,%d,%p,%0x)\n", __func__, _ep, _bytes, - _dma, _gfp_flags); + DWC_DEBUGPL(DBG_PCDV,"%s(%p,%d,%p,%0x)\n", __func__, usb_ep, bytes, + dma, gfp_flags); /* Check dword alignment */ - if ((_bytes & 0x3UL) != 0) - { + if ((bytes & 0x3UL) != 0) { DWC_WARN("%s() Buffer size is not a multiple of" - "DWORD size (%d)",__func__, _bytes); - } - - if (GET_CORE_IF(pcd)->dma_enable) - { - buf = dma_alloc_coherent (NULL, _bytes, _dma, _gfp_flags); - } - else - { - buf = kmalloc( _bytes, _gfp_flags); + "DWORD size (%d)",__func__, bytes); + } + + if (GET_CORE_IF(pcd)->dma_enable) { + buf = dma_alloc_coherent (NULL, bytes, dma, gfp_flags); + } + else { + buf = kmalloc(bytes, gfp_flags); } /* Check dword alignment */ - if (((int)buf & 0x3UL) != 0) - { + if (((int)buf & 0x3UL) != 0) { DWC_WARN("%s() Buffer is not DWORD aligned (%p)", __func__, buf); @@ -525,29 +474,28 @@ * This function frees an I/O buffer that was allocated by alloc_buffer. * - * @param _ep the endpoint associated with the buffer - * @param _buf address of the buffer - * @param _dma The buffer's DMA address - * @param _bytes The number of bytes of the buffer - */ -static void dwc_otg_pcd_free_buffer(struct usb_ep *_ep, void *_buf, - dma_addr_t _dma, unsigned _bytes) + * @param usb_ep the endpoint associated with the buffer + * @param buf address of the buffer + * @param dma The buffer's DMA address + * @param bytes The number of bytes of the buffer + */ +static void dwc_otg_pcd_free_buffer(struct usb_ep *usb_ep, void *buf, + dma_addr_t dma, unsigned bytes) { dwc_otg_pcd_ep_t *ep; dwc_otg_pcd_t *pcd = 0; - ep = container_of(_ep, dwc_otg_pcd_ep_t, ep); + ep = container_of(usb_ep, dwc_otg_pcd_ep_t, ep); pcd = ep->pcd; - DWC_DEBUGPL(DBG_PCDV,"%s(%p,%p,%0x,%d)\n", __func__, _ep, _buf, _dma, _bytes); - - if (GET_CORE_IF(pcd)->dma_enable) - { - dma_free_coherent (NULL, _bytes, _buf, _dma); - } - else - { - kfree( _buf ); - } -} + DWC_DEBUGPL(DBG_PCDV,"%s(%p,%p,%0x,%d)\n", __func__, ep, buf, dma, bytes); + + if (GET_CORE_IF(pcd)->dma_enable) { + dma_free_coherent (NULL, bytes, buf, dma); + } + else { + kfree(buf); + } +} + /** @@ -565,6 +513,12 @@ * flag. */ -static int dwc_otg_pcd_ep_queue(struct usb_ep *_ep, - struct usb_request *_req, int _gfp_flags) +static int dwc_otg_pcd_ep_queue(struct usb_ep *usb_ep, + struct usb_request *usb_req, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + int gfp_flags +#else + gfp_t gfp_flags +#endif + ) { int prevented = 0; @@ -573,28 +527,24 @@ dwc_otg_pcd_t *pcd; unsigned long flags = 0; - dwc_otg_core_if_t *_core_if; - DWC_DEBUGPL(DBG_PCDV,"%s(%p,%p,%d)\n", - __func__, _ep, _req, _gfp_flags); - - req = container_of(_req, dwc_otg_pcd_request_t, req); - if (!_req || !_req->complete || !_req->buf || - !list_empty(&req->queue)) - { + __func__, usb_ep, usb_req, gfp_flags); + + req = container_of(usb_req, dwc_otg_pcd_request_t, req); + if (!usb_req || !usb_req->complete || !usb_req->buf || + !list_empty(&req->queue)) { DWC_WARN("%s, bad params\n", __func__); return -EINVAL; } - ep = container_of(_ep, dwc_otg_pcd_ep_t, ep); - if (!_ep || (!ep->desc && ep->dwc_ep.num != 0)) - { + ep = container_of(usb_ep, dwc_otg_pcd_ep_t, ep); + if (!usb_ep || (!ep->desc && ep->dwc_ep.num != 0)/* || ep->stopped != 0*/) { DWC_WARN("%s, bad ep\n", __func__); return -EINVAL; } + pcd = ep->pcd; - if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN) - { + if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN) { DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n", pcd->gadget.speed); DWC_WARN("%s, bogus device state\n", __func__); @@ -604,12 +554,10 @@ DWC_DEBUGPL(DBG_PCD, "%s queue req %p, len %d buf %p\n", - _ep->name, _req, _req->length, _req->buf); - - if (!GET_CORE_IF(pcd)->core_params->opt) - { - if (ep->dwc_ep.num != 0) - { + usb_ep->name, usb_req, usb_req->length, usb_req->buf); + + if (!GET_CORE_IF(pcd)->core_params->opt) { + if (ep->dwc_ep.num != 0) { DWC_ERROR("%s queue req %p, len %d buf %p\n", - _ep->name, _req, _req->length, _req->buf); + usb_ep->name, usb_req, usb_req->length, usb_req->buf); } } @@ -627,10 +575,10 @@ if (_core_if->dma_enable) { - _req->dma = virt_to_phys((u32) _req->buf); + usb_req->dma = virt_to_phys((void *)usb_req->buf); if(ep->dwc_ep.is_in) { - if(_req->length) - dma_cache_wback_inv((unsigned long)_req->buf, _req->length + 2); + if(usb_req->length) + dma_cache_wback_inv((unsigned long)usb_req->buf, usb_req->length + 2); } } @@ -639,87 +587,113 @@ #if defined(DEBUG) & defined(VERBOSE) - dump_msg(_req->buf, _req->length); + dump_msg(usb_req->buf, usb_req->length); #endif - _req->status = -EINPROGRESS; - _req->actual = 0; + usb_req->status = -EINPROGRESS; + usb_req->actual = 0; /* * For EP0 IN without premature status, zlp is required? */ - if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) - { - DWC_DEBUGPL(DBG_PCDV, "%s-OUT ZLP\n", _ep->name); + if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) { + DWC_DEBUGPL(DBG_PCDV, "%s-OUT ZLP\n", usb_ep->name); //_req->zero = 1; } /* Start the transfer */ - if (list_empty(&ep->queue) && !ep->stopped) - { + if (list_empty(&ep->queue) && !ep->stopped) { /* EP0 Transfer? */ - if (ep->dwc_ep.num == 0) - { - switch (pcd->ep0state) - { + if (ep->dwc_ep.num == 0) { + switch (pcd->ep0state) { case EP0_IN_DATA_PHASE: DWC_DEBUGPL(DBG_PCD, - "%s ep0: EP0_IN_DATA_PHASE\n", - __func__); + "%s ep0: EP0_IN_DATA_PHASE\n", + __func__); break; case EP0_OUT_DATA_PHASE: DWC_DEBUGPL(DBG_PCD, - "%s ep0: EP0_OUT_DATA_PHASE\n", - __func__); - if (pcd->request_config) - { + "%s ep0: EP0_OUT_DATA_PHASE\n", + __func__); + if (pcd->request_config) { /* Complete STATUS PHASE */ ep->dwc_ep.is_in = 1; - pcd->ep0state = EP0_STATUS; + pcd->ep0state = EP0_IN_STATUS_PHASE; } break; + case EP0_IN_STATUS_PHASE: + DWC_DEBUGPL(DBG_PCD, + "%s ep0: EP0_IN_STATUS_PHASE\n", + __func__); + break; + default: DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n", - pcd->ep0state); + pcd->ep0state); SPIN_UNLOCK_IRQRESTORE(&pcd->lock, flags); return -EL2HLT; } - - ep->dwc_ep.dma_addr = _req->dma; - ep->dwc_ep.start_xfer_buff = _req->buf; - ep->dwc_ep.xfer_buff = _req->buf; - ep->dwc_ep.xfer_len = _req->length; + ep->dwc_ep.dma_addr = usb_req->dma; + ep->dwc_ep.start_xfer_buff = usb_req->buf; + ep->dwc_ep.xfer_buff = usb_req->buf; + ep->dwc_ep.xfer_len = usb_req->length; ep->dwc_ep.xfer_count = 0; ep->dwc_ep.sent_zlp = 0; ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; - dwc_otg_ep0_start_transfer( GET_CORE_IF(pcd), - &ep->dwc_ep ); + + if(usb_req->zero) { + if((ep->dwc_ep.xfer_len % ep->dwc_ep.maxpacket == 0) + && (ep->dwc_ep.xfer_len != 0)) { + ep->dwc_ep.sent_zlp = 1; + } + + } + + dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep->dwc_ep); } - else - { + else { + + uint32_t max_transfer = GET_CORE_IF(ep->pcd)->core_params->max_transfer_size; + /* Setup and start the Transfer */ - ep->dwc_ep.dma_addr = _req->dma; - ep->dwc_ep.start_xfer_buff = _req->buf; - ep->dwc_ep.xfer_buff = _req->buf; - ep->dwc_ep.xfer_len = _req->length; + ep->dwc_ep.dma_addr = usb_req->dma; + ep->dwc_ep.start_xfer_buff = usb_req->buf; + ep->dwc_ep.xfer_buff = usb_req->buf; + ep->dwc_ep.sent_zlp = 0; + ep->dwc_ep.total_len = usb_req->length; + ep->dwc_ep.xfer_len = 0; ep->dwc_ep.xfer_count = 0; - ep->dwc_ep.sent_zlp = 0; - ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; - dwc_otg_ep_start_transfer( GET_CORE_IF(pcd), - &ep->dwc_ep ); - } - } - - if ((req != 0) || prevented) - { + + if(max_transfer > MAX_TRANSFER_SIZE) { + ep->dwc_ep.maxxfer = max_transfer - (max_transfer % ep->dwc_ep.maxpacket); + } else { + ep->dwc_ep.maxxfer = max_transfer; + } + + if(usb_req->zero) { + if((ep->dwc_ep.total_len % ep->dwc_ep.maxpacket == 0) + && (ep->dwc_ep.total_len != 0)) { + ep->dwc_ep.sent_zlp = 1; + } + + } + dwc_otg_ep_start_transfer(GET_CORE_IF(pcd), &ep->dwc_ep); + } + } + + if ((req != 0) || prevented) { ++pcd->request_pending; list_add_tail(&req->queue, &ep->queue); - if (ep->dwc_ep.is_in && ep->stopped && !(GET_CORE_IF(pcd)->dma_enable)) - { + if (ep->dwc_ep.is_in && ep->stopped && !(GET_CORE_IF(pcd)->dma_enable)) { /** @todo NGS Create a function for this. */ diepmsk_data_t diepmsk = { .d32 = 0}; diepmsk.b.intktxfemp = 1; - dwc_modify_reg32( &GET_CORE_IF(pcd)->dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32 ); + if(&GET_CORE_IF(pcd)->multiproc_int_enable) { + dwc_modify_reg32(&GET_CORE_IF(pcd)->dev_if->dev_global_regs->diepeachintmsk[ep->dwc_ep.num], + 0, diepmsk.d32); + } else { + dwc_modify_reg32(&GET_CORE_IF(pcd)->dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32); + } } } @@ -732,6 +706,6 @@ * This function cancels an I/O request from an EP. */ -static int dwc_otg_pcd_ep_dequeue(struct usb_ep *_ep, - struct usb_request *_req) +static int dwc_otg_pcd_ep_dequeue(struct usb_ep *usb_ep, + struct usb_request *usb_req) { dwc_otg_pcd_request_t *req; @@ -740,15 +714,13 @@ unsigned long flags; - DWC_DEBUGPL(DBG_PCDV,"%s(%p,%p)\n", __func__, _ep, _req); - - ep = container_of(_ep, dwc_otg_pcd_ep_t, ep); - if (!_ep || !_req || (!ep->desc && ep->dwc_ep.num != 0)) - { + DWC_DEBUGPL(DBG_PCDV,"%s(%p,%p)\n", __func__, usb_ep, usb_req); + + ep = container_of(usb_ep, dwc_otg_pcd_ep_t, ep); + if (!usb_ep || !usb_req || (!ep->desc && ep->dwc_ep.num != 0)) { DWC_WARN("%s, bad argument\n", __func__); return -EINVAL; } pcd = ep->pcd; - if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN) - { + if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN) { DWC_WARN("%s, bogus device state\n", __func__); return -ESHUTDOWN; @@ -756,29 +728,25 @@ SPIN_LOCK_IRQSAVE(&pcd->lock, flags); - DWC_DEBUGPL(DBG_PCDV, "%s %s %s %p\n", __func__, _ep->name, + DWC_DEBUGPL(DBG_PCDV, "%s %s %s %p\n", __func__, usb_ep->name, ep->dwc_ep.is_in ? "IN" : "OUT", - _req); + usb_req); /* make sure it's actually queued on this endpoint */ - list_for_each_entry( req, &ep->queue, queue) + list_for_each_entry(req, &ep->queue, queue) { - if (&req->req == _req) - { + if (&req->req == usb_req) { break; } } - if (&req->req != _req) - { + if (&req->req != usb_req) { SPIN_UNLOCK_IRQRESTORE(&pcd->lock, flags); return -EINVAL; } - if (!list_empty(&req->queue)) - { - request_done(ep, req, -ECONNRESET); + if (!list_empty(&req->queue)) { + dwc_otg_request_done(ep, req, -ECONNRESET); } - else - { + else { req = 0; } @@ -798,6 +766,6 @@ * function. The behavior depends on the value argument. * - * @param[in] _ep the Endpoint to halt or clear halt. - * @param[in] _value + * @param[in] usb_ep the Endpoint to halt or clear halt. + * @param[in] value * - 0 means clear_halt. * - 1 means set_halt, @@ -805,5 +773,5 @@ * - 3 means set stall lock flag. */ -static int dwc_otg_pcd_ep_set_halt(struct usb_ep *_ep, int _value) +static int dwc_otg_pcd_ep_set_halt(struct usb_ep *usb_ep, int value) { int retval = 0; @@ -812,11 +780,10 @@ - DWC_DEBUGPL(DBG_PCD,"HALT %s %d\n", _ep->name, _value); - - ep = container_of(_ep, dwc_otg_pcd_ep_t, ep); - - if (!_ep || (!ep->desc && ep != &ep->pcd->ep0) || - ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) - { + DWC_DEBUGPL(DBG_PCD,"HALT %s %d\n", usb_ep->name, value); + + ep = container_of(usb_ep, dwc_otg_pcd_ep_t, ep); + + if (!usb_ep || (!ep->desc && ep != &ep->pcd->ep0) || + ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { DWC_WARN("%s, bad ep\n", __func__); return -EINVAL; @@ -824,31 +791,48 @@ SPIN_LOCK_IRQSAVE(&ep->pcd->lock, flags); - if (!list_empty(&ep->queue)) - { - DWC_WARN("%s() %s XFer In process\n", __func__, _ep->name); + if (!list_empty(&ep->queue)) { + DWC_WARN("%s() %s XFer In process\n", __func__, usb_ep->name); retval = -EAGAIN; } - else if (_value == 0) - { - dwc_otg_ep_clear_stall( ep->pcd->otg_dev->core_if, - &ep->dwc_ep ); - } - else if(_value == 1) - { - if (ep->dwc_ep.num == 0) - { - ep->pcd->ep0state = EP0_STALL; - } - - ep->stopped = 1; - dwc_otg_ep_set_stall( ep->pcd->otg_dev->core_if, - &ep->dwc_ep ); - } - else if (_value == 2) - { + else if (value == 0) { + dwc_otg_ep_clear_stall(ep->pcd->otg_dev->core_if, + &ep->dwc_ep); + } + else if(value == 1) { + if (ep->dwc_ep.is_in == 1 && ep->pcd->otg_dev->core_if->dma_desc_enable) { + dtxfsts_data_t txstatus; + fifosize_data_t txfifosize; + + txfifosize.d32 = dwc_read_reg32(&ep->pcd->otg_dev->core_if->core_global_regs->dptxfsiz_dieptxf[ep->dwc_ep.tx_fifo_num]); + txstatus.d32 = dwc_read_reg32(&ep->pcd->otg_dev->core_if->dev_if->in_ep_regs[ep->dwc_ep.num]->dtxfsts); + + if(txstatus.b.txfspcavail < txfifosize.b.depth) { + DWC_WARN("%s() %s Data In Tx Fifo\n", __func__, usb_ep->name); + retval = -EAGAIN; + } + else { + if (ep->dwc_ep.num == 0) { + ep->pcd->ep0state = EP0_STALL; + } + + ep->stopped = 1; + dwc_otg_ep_set_stall(ep->pcd->otg_dev->core_if, + &ep->dwc_ep); + } + } + else { + if (ep->dwc_ep.num == 0) { + ep->pcd->ep0state = EP0_STALL; + } + + ep->stopped = 1; + dwc_otg_ep_set_stall(ep->pcd->otg_dev->core_if, + &ep->dwc_ep); + } + } + else if (value == 2) { ep->dwc_ep.stall_clear_flag = 0; } - else if (_value == 3) - { + else if (value == 3) { ep->dwc_ep.stall_clear_flag = 1; } @@ -858,5 +842,707 @@ } - +/** + * This function allocates a DMA Descriptor chain for the Endpoint + * buffer to be used for a transfer to/from the specified endpoint. + */ +dwc_otg_dma_desc_t* dwc_otg_ep_alloc_desc_chain(uint32_t * dma_desc_addr, uint32_t count) +{ + + return dma_alloc_coherent(NULL, count * sizeof(dwc_otg_dma_desc_t), dma_desc_addr, GFP_KERNEL); +} + +/** + * This function frees a DMA Descriptor chain that was allocated by ep_alloc_desc. + */ +void dwc_otg_ep_free_desc_chain(dwc_otg_dma_desc_t* desc_addr, uint32_t dma_desc_addr, uint32_t count) +{ + dma_free_coherent(NULL, count * sizeof(dwc_otg_dma_desc_t), desc_addr, dma_desc_addr); +} + +#ifdef DWC_EN_ISOC + +/** + * This function initializes a descriptor chain for Isochronous transfer + * + * @param core_if Programming view of DWC_otg controller. + * @param dwc_ep The EP to start the transfer on. + * + */ +void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t *core_if, dwc_ep_t *dwc_ep) +{ + + dsts_data_t dsts = { .d32 = 0}; + depctl_data_t depctl = { .d32 = 0 }; + volatile uint32_t *addr; + int i, j; + + if(dwc_ep->is_in) + dwc_ep->desc_cnt = dwc_ep->buf_proc_intrvl / dwc_ep->bInterval; + else + dwc_ep->desc_cnt = dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm / dwc_ep->bInterval; + + + /** Allocate descriptors for double buffering */ + dwc_ep->iso_desc_addr = dwc_otg_ep_alloc_desc_chain(&dwc_ep->iso_dma_desc_addr,dwc_ep->desc_cnt*2); + if(dwc_ep->desc_addr) { + DWC_WARN("%s, can't allocate DMA descriptor chain\n", __func__); + return; + } + + dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); + + /** ISO OUT EP */ + if(dwc_ep->is_in == 0) { + desc_sts_data_t sts = { .d32 =0 }; + dwc_otg_dma_desc_t* dma_desc = dwc_ep->iso_desc_addr; + dma_addr_t dma_ad; + uint32_t data_per_desc; + dwc_otg_dev_out_ep_regs_t *out_regs = + core_if->dev_if->out_ep_regs[dwc_ep->num]; + int offset; + + addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl; + dma_ad = (dma_addr_t)dwc_read_reg32(&(out_regs->doepdma)); + + /** Buffer 0 descriptors setup */ + dma_ad = dwc_ep->dma_addr0; + + sts.b_iso_out.bs = BS_HOST_READY; + sts.b_iso_out.rxsts = 0; + sts.b_iso_out.l = 0; + sts.b_iso_out.sp = 0; + sts.b_iso_out.ioc = 0; + sts.b_iso_out.pid = 0; + sts.b_iso_out.framenum = 0; + + offset = 0; + for(i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; i+= dwc_ep->pkt_per_frm) + { + + for(j = 0; j < dwc_ep->pkt_per_frm; ++j) + { + data_per_desc = ((j + 1) * dwc_ep->maxpacket > dwc_ep->data_per_frame) ? + dwc_ep->data_per_frame - j * dwc_ep->maxpacket : dwc_ep->maxpacket; + + data_per_desc += (data_per_desc % 4) ? (4 - data_per_desc % 4):0; + sts.b_iso_out.rxbytes = data_per_desc; + writel((uint32_t)dma_ad, &dma_desc->buf); + writel(sts.d32, &dma_desc->status); + + offset += data_per_desc; + dma_desc ++; + (uint32_t)dma_ad += data_per_desc; + } + } + + for(j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) + { + data_per_desc = ((j + 1) * dwc_ep->maxpacket > dwc_ep->data_per_frame) ? + dwc_ep->data_per_frame - j * dwc_ep->maxpacket : dwc_ep->maxpacket; + data_per_desc += (data_per_desc % 4) ? (4 - data_per_desc % 4):0; + sts.b_iso_out.rxbytes = data_per_desc; + writel((uint32_t)dma_ad, &dma_desc->buf); + writel(sts.d32, &dma_desc->status); + + offset += data_per_desc; + dma_desc ++; + (uint32_t)dma_ad += data_per_desc; + } + + sts.b_iso_out.ioc = 1; + data_per_desc = ((j + 1) * dwc_ep->maxpacket > dwc_ep->data_per_frame) ? + dwc_ep->data_per_frame - j * dwc_ep->maxpacket : dwc_ep->maxpacket; + data_per_desc += (data_per_desc % 4) ? (4 - data_per_desc % 4):0; + sts.b_iso_out.rxbytes = data_per_desc; + + writel((uint32_t)dma_ad, &dma_desc->buf); + writel(sts.d32, &dma_desc->status); + dma_desc ++; + + /** Buffer 1 descriptors setup */ + sts.b_iso_out.ioc = 0; + dma_ad = dwc_ep->dma_addr1; + + offset = 0; + for(i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; i+= dwc_ep->pkt_per_frm) + { + for(j = 0; j < dwc_ep->pkt_per_frm; ++j) + { + data_per_desc = ((j + 1) * dwc_ep->maxpacket > dwc_ep->data_per_frame) ? + dwc_ep->data_per_frame - j * dwc_ep->maxpacket : dwc_ep->maxpacket; + data_per_desc += (data_per_desc % 4) ? (4 - data_per_desc % 4):0; + sts.b_iso_out.rxbytes = data_per_desc; + writel((uint32_t)dma_ad, &dma_desc->buf); + writel(sts.d32, &dma_desc->status); + + offset += data_per_desc; + dma_desc ++; + (uint32_t)dma_ad += data_per_desc; + } + } + for(j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) + { + data_per_desc = ((j + 1) * dwc_ep->maxpacket > dwc_ep->data_per_frame) ? + dwc_ep->data_per_frame - j * dwc_ep->maxpacket : dwc_ep->maxpacket; + data_per_desc += (data_per_desc % 4) ? (4 - data_per_desc % 4):0; + sts.b_iso_out.rxbytes = data_per_desc; + writel((uint32_t)dma_ad, &dma_desc->buf); + writel(sts.d32, &dma_desc->status); + + offset += data_per_desc; + dma_desc ++; + (uint32_t)dma_ad += data_per_desc; + } + + sts.b_iso_out.ioc = 1; + sts.b_iso_out.l = 1; + data_per_desc = ((j + 1) * dwc_ep->maxpacket > dwc_ep->data_per_frame) ? + dwc_ep->data_per_frame - j * dwc_ep->maxpacket : dwc_ep->maxpacket; + data_per_desc += (data_per_desc % 4) ? (4 - data_per_desc % 4):0; + sts.b_iso_out.rxbytes = data_per_desc; + + writel((uint32_t)dma_ad, &dma_desc->buf); + writel(sts.d32, &dma_desc->status); + + dwc_ep->next_frame = 0; + + /** Write dma_ad into DOEPDMA register */ + dwc_write_reg32(&(out_regs->doepdma),(uint32_t)dwc_ep->iso_dma_desc_addr); + + } + /** ISO IN EP */ + else { + desc_sts_data_t sts = { .d32 =0 }; + dwc_otg_dma_desc_t* dma_desc = dwc_ep->iso_desc_addr; + dma_addr_t dma_ad; + dwc_otg_dev_in_ep_regs_t *in_regs = + core_if->dev_if->in_ep_regs[dwc_ep->num]; + unsigned int frmnumber; + fifosize_data_t txfifosize,rxfifosize; + + txfifosize.d32 = dwc_read_reg32(&core_if->dev_if->in_ep_regs[dwc_ep->num]->dtxfsts); + rxfifosize.d32 = dwc_read_reg32(&core_if->core_global_regs->grxfsiz); + + + addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl; + + dma_ad = dwc_ep->dma_addr0; + + dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); + + sts.b_iso_in.bs = BS_HOST_READY; + sts.b_iso_in.txsts = 0; + sts.b_iso_in.sp = (dwc_ep->data_per_frame % dwc_ep->maxpacket)? 1 : 0; + sts.b_iso_in.ioc = 0; + sts.b_iso_in.pid = dwc_ep->pkt_per_frm; + + + frmnumber = dwc_ep->next_frame; + + sts.b_iso_in.framenum = frmnumber; + sts.b_iso_in.txbytes = dwc_ep->data_per_frame; + sts.b_iso_in.l = 0; + + /** Buffer 0 descriptors setup */ + for(i = 0; i < dwc_ep->desc_cnt - 1; i++) + { + writel((uint32_t)dma_ad, &dma_desc->buf); + writel(sts.d32, &dma_desc->status); + dma_desc ++; + + (uint32_t)dma_ad += dwc_ep->data_per_frame; + sts.b_iso_in.framenum += dwc_ep->bInterval; + } + + sts.b_iso_in.ioc = 1; + writel((uint32_t)dma_ad, &dma_desc->buf); + writel(sts.d32, &dma_desc->status); + ++dma_desc; + + /** Buffer 1 descriptors setup */ + sts.b_iso_in.ioc = 0; + dma_ad = dwc_ep->dma_addr1; + + for(i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; i+= dwc_ep->pkt_per_frm) + { + writel((uint32_t)dma_ad, &dma_desc->buf); + writel(sts.d32, &dma_desc->status); + dma_desc ++; + + (uint32_t)dma_ad += dwc_ep->data_per_frame; + sts.b_iso_in.framenum += dwc_ep->bInterval; + + sts.b_iso_in.ioc = 0; + } + sts.b_iso_in.ioc = 1; + sts.b_iso_in.l = 1; + + writel((uint32_t)dma_ad, &dma_desc->buf); + writel(sts.d32, &dma_desc->status); + + dwc_ep->next_frame = sts.b_iso_in.framenum + dwc_ep->bInterval; + + /** Write dma_ad into diepdma register */ + dwc_write_reg32(&(in_regs->diepdma),(uint32_t)dwc_ep->iso_dma_desc_addr); + } + /** Enable endpoint, clear nak */ + depctl.d32 = 0; + depctl.b.epena = 1; + depctl.b.usbactep = 1; + depctl.b.cnak = 1; + + dwc_modify_reg32(addr, depctl.d32,depctl.d32); + depctl.d32 = dwc_read_reg32(addr); +} + +/** + * This function initializes a descriptor chain for Isochronous transfer + * + * @param core_if Programming view of DWC_otg controller. + * @param ep The EP to start the transfer on. + * + */ + +void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t *core_if, dwc_ep_t *ep) +{ + depctl_data_t depctl = { .d32 = 0 }; + volatile uint32_t *addr; + + + if(ep->is_in) { + addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; + } else { + addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; + } + + + if(core_if->dma_enable == 0 || core_if->dma_desc_enable!= 0) { + return; + } else { + deptsiz_data_t deptsiz = { .d32 = 0 }; + + ep->xfer_len = ep->data_per_frame * ep->buf_proc_intrvl / ep->bInterval; + ep->pkt_cnt = (ep->xfer_len - 1 + ep->maxpacket) / + ep->maxpacket; + ep->xfer_count = 0; + ep->xfer_buff = (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0; + ep->dma_addr = (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0; + + if(ep->is_in) { + /* Program the transfer size and packet count + * as follows: xfersize = N * maxpacket + + * short_packet pktcnt = N + (short_packet + * exist ? 1 : 0) + */ + deptsiz.b.mc = ep->pkt_per_frm; + deptsiz.b.xfersize = ep->xfer_len; + deptsiz.b.pktcnt = + (ep->xfer_len - 1 + ep->maxpacket) / + ep->maxpacket; + dwc_write_reg32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz, deptsiz.d32); + + /* Write the DMA register */ + dwc_write_reg32 (&(core_if->dev_if->in_ep_regs[ep->num]->diepdma), (uint32_t)ep->dma_addr); + + } else { + deptsiz.b.pktcnt = + (ep->xfer_len + (ep->maxpacket - 1)) / + ep->maxpacket; + deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; + + dwc_write_reg32(&core_if->dev_if->out_ep_regs[ep->num]->doeptsiz, deptsiz.d32); + + /* Write the DMA register */ + dwc_write_reg32 (&(core_if->dev_if->out_ep_regs[ep->num]->doepdma), (uint32_t)ep->dma_addr); + + } + /** Enable endpoint, clear nak */ + depctl.d32 = 0; + dwc_modify_reg32(addr, depctl.d32,depctl.d32); + + depctl.b.epena = 1; + depctl.b.cnak = 1; + + dwc_modify_reg32(addr, depctl.d32,depctl.d32); + } +} + + +/** + * This function does the setup for a data transfer for an EP and + * starts the transfer. For an IN transfer, the packets will be + * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers, + * the packets are unloaded from the Rx FIFO in the ISR. the ISR. + * + * @param core_if Programming view of DWC_otg controller. + * @param ep The EP to start the transfer on. + */ + +void dwc_otg_iso_ep_start_transfer(dwc_otg_core_if_t *core_if, dwc_ep_t *ep) +{ + if(core_if->dma_enable) { + if(core_if->dma_desc_enable) { + if(ep->is_in) { + ep->desc_cnt = ep->pkt_cnt / ep->pkt_per_frm; + } else { + ep->desc_cnt = ep->pkt_cnt; + } + dwc_otg_iso_ep_start_ddma_transfer(core_if, ep); + } else { + if(core_if->pti_enh_enable) { + dwc_otg_iso_ep_start_buf_transfer(core_if, ep); + } else { + ep->cur_pkt_addr = (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0; + ep->cur_pkt_dma_addr = (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0; + dwc_otg_iso_ep_start_frm_transfer(core_if, ep); + } + } + } else { + ep->cur_pkt_addr = (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0; + ep->cur_pkt_dma_addr = (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0; + dwc_otg_iso_ep_start_frm_transfer(core_if, ep); + } +} + +/** + * This function does the setup for a data transfer for an EP and + * starts the transfer. For an IN transfer, the packets will be + * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers, + * the packets are unloaded from the Rx FIFO in the ISR. the ISR. + * + * @param core_if Programming view of DWC_otg controller. + * @param ep The EP to start the transfer on. + */ + +void dwc_otg_iso_ep_stop_transfer(dwc_otg_core_if_t *core_if, dwc_ep_t *ep) +{ + depctl_data_t depctl = { .d32 = 0 }; + volatile uint32_t *addr; + + if(ep->is_in == 1) { + addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; + } + else { + addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; + } + + /* disable the ep */ + depctl.d32 = dwc_read_reg32(addr); + + depctl.b.epdis = 1; + depctl.b.snak = 1; + + dwc_write_reg32(addr, depctl.d32); + + if(core_if->dma_desc_enable && + ep->iso_desc_addr && ep->iso_dma_desc_addr) { + dwc_otg_ep_free_desc_chain(ep->iso_desc_addr,ep->iso_dma_desc_addr,ep->desc_cnt * 2); + } + + /* reset varibales */ + ep->dma_addr0 = 0; + ep->dma_addr1 = 0; + ep->xfer_buff0 = 0; + ep->xfer_buff1 = 0; + ep->data_per_frame = 0; + ep->data_pattern_frame = 0; + ep->sync_frame = 0; + ep->buf_proc_intrvl = 0; + ep->bInterval = 0; + ep->proc_buf_num = 0; + ep->pkt_per_frm = 0; + ep->pkt_per_frm = 0; + ep->desc_cnt = 0; + ep->iso_desc_addr = 0; + ep->iso_dma_desc_addr = 0; +} + + +/** + * This function is used to submit an ISOC Transfer Request to an EP. + * + * - Every time a sync period completes the request's completion callback + * is called to provide data to the gadget driver. + * - Once submitted the request cannot be modified. + * - Each request is turned into periodic data packets untill ISO + * Transfer is stopped.. + */ +static int dwc_otg_pcd_iso_ep_start(struct usb_ep *usb_ep, struct usb_iso_request *req, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + int gfp_flags +#else + gfp_t gfp_flags +#endif +) +{ + dwc_otg_pcd_ep_t *ep; + dwc_otg_pcd_t *pcd; + dwc_ep_t *dwc_ep; + unsigned long flags = 0; + int32_t frm_data; + dwc_otg_core_if_t *core_if; + dcfg_data_t dcfg; + dsts_data_t dsts; + + + if (!req || !req->process_buffer || !req->buf0 || !req->buf1) { + DWC_WARN("%s, bad params\n", __func__); + return -EINVAL; + } + + ep = container_of(usb_ep, dwc_otg_pcd_ep_t, ep); + + if (!usb_ep || !ep->desc || ep->dwc_ep.num == 0) { + DWC_WARN("%s, bad ep\n", __func__); + return -EINVAL; + } + + pcd = ep->pcd; + core_if = GET_CORE_IF(pcd); + + dcfg.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg); + + if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN) { + DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n", pcd->gadget.speed); + DWC_WARN("%s, bogus device state\n", __func__); + return -ESHUTDOWN; + } + + SPIN_LOCK_IRQSAVE(&ep->pcd->lock, flags); + + dwc_ep = &ep->dwc_ep; + + if(ep->iso_req) { + DWC_WARN("%s, iso request in progress\n", __func__); + } + req->status = -EINPROGRESS; + + dwc_ep->dma_addr0 = req->dma0; + dwc_ep->dma_addr1 = req->dma1; + + dwc_ep->xfer_buff0 = req->buf0; + dwc_ep->xfer_buff1 = req->buf1; + + ep->iso_req = req; + + dwc_ep->data_per_frame = req->data_per_frame; + + /** @todo - pattern data support is to be implemented in the future */ + dwc_ep->data_pattern_frame = req->data_pattern_frame; + dwc_ep->sync_frame = req->sync_frame; + + dwc_ep->buf_proc_intrvl = req->buf_proc_intrvl; + + dwc_ep->bInterval = 1 << (ep->desc->bInterval - 1); + + dwc_ep->proc_buf_num = 0; + + dwc_ep->pkt_per_frm = 0; + frm_data = ep->dwc_ep.data_per_frame; + while(frm_data > 0) { + dwc_ep->pkt_per_frm++; + frm_data -= ep->dwc_ep.maxpacket; + } + + dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); + + if(req->flags & USB_REQ_ISO_ASAP) { + dwc_ep->next_frame = dsts.b.soffn + 1; + if(dwc_ep->bInterval != 1){ + dwc_ep->next_frame = dwc_ep->next_frame + (dwc_ep->bInterval - 1 - dwc_ep->next_frame % dwc_ep->bInterval); + } + } else { + dwc_ep->next_frame = req->start_frame; + } + + + if(!core_if->pti_enh_enable) { + dwc_ep->pkt_cnt = dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm / dwc_ep->bInterval; + } else { + dwc_ep->pkt_cnt = + (dwc_ep->data_per_frame * (dwc_ep->buf_proc_intrvl / dwc_ep->bInterval) + - 1 + dwc_ep->maxpacket) / dwc_ep->maxpacket; + } + + if(core_if->dma_desc_enable) { + dwc_ep->desc_cnt = + dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm / dwc_ep->bInterval; + } + + dwc_ep->pkt_info = kmalloc(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt, GFP_KERNEL); + if(!dwc_ep->pkt_info) { + return -ENOMEM; + } + if(core_if->pti_enh_enable) { + memset(dwc_ep->pkt_info, 0, sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); + } + + dwc_ep->cur_pkt = 0; + + SPIN_UNLOCK_IRQRESTORE(&pcd->lock, flags); + + dwc_otg_iso_ep_start_transfer(core_if, dwc_ep); + + return 0; +} + +/** + * This function stops ISO EP Periodic Data Transfer. + */ +static int dwc_otg_pcd_iso_ep_stop(struct usb_ep *usb_ep, struct usb_iso_request *req) +{ + dwc_otg_pcd_ep_t *ep; + dwc_otg_pcd_t *pcd; + dwc_ep_t *dwc_ep; + unsigned long flags; + + ep = container_of(usb_ep, dwc_otg_pcd_ep_t, ep); + + if (!usb_ep || !ep->desc || ep->dwc_ep.num == 0) { + DWC_WARN("%s, bad ep\n", __func__); + return -EINVAL; + } + + pcd = ep->pcd; + + if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN) { + DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n", pcd->gadget.speed); + DWC_WARN("%s, bogus device state\n", __func__); + return -ESHUTDOWN; + } + + dwc_ep = &ep->dwc_ep; + + dwc_otg_iso_ep_stop_transfer(GET_CORE_IF(pcd), dwc_ep); + + kfree(dwc_ep->pkt_info); + + SPIN_LOCK_IRQSAVE(&pcd->lock, flags); + + if(ep->iso_req != req) { + return -EINVAL; + } + + req->status = -ECONNRESET; + + SPIN_UNLOCK_IRQRESTORE(&pcd->lock, flags); + + + ep->iso_req = 0; + + return 0; +} + +/** + * This function is used for perodical data exchnage between PCD and gadget drivers. + * for Isochronous EPs + * + * - Every time a sync period completes this function is called to + * perform data exchange between PCD and gadget + */ +void dwc_otg_iso_buffer_done(dwc_otg_pcd_ep_t *ep, dwc_otg_pcd_iso_request_t *req) +{ + int i; + struct usb_gadget_iso_packet_descriptor *iso_packet; + dwc_ep_t *dwc_ep; + + dwc_ep = &ep->dwc_ep; + + if(ep->iso_req->status == -ECONNRESET) { + DWC_PRINT("Device has already disconnected\n"); + /*Device has been disconnected*/ + return; + } + + if(dwc_ep->proc_buf_num != 0) { + iso_packet = ep->iso_req->iso_packet_desc0; + } + + else { + iso_packet = ep->iso_req->iso_packet_desc1; + } + + /* Fill in ISOC packets descriptors & pass to gadget driver*/ + + for(i = 0; i < dwc_ep->pkt_cnt; ++i) { + iso_packet[i].status = dwc_ep->pkt_info[i].status; + iso_packet[i].offset = dwc_ep->pkt_info[i].offset; + iso_packet[i].actual_length = dwc_ep->pkt_info[i].length; + dwc_ep->pkt_info[i].status = 0; + dwc_ep->pkt_info[i].offset = 0; + dwc_ep->pkt_info[i].length = 0; + } + + /* Call callback function to process data buffer */ + ep->iso_req->status = 0;/* success */ + + SPIN_UNLOCK(&ep->pcd->lock); + ep->iso_req->process_buffer(&ep->ep, ep->iso_req); + SPIN_LOCK(&ep->pcd->lock); +} + + +static struct usb_iso_request *dwc_otg_pcd_alloc_iso_request(struct usb_ep *ep,int packets, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + int gfp_flags +#else + gfp_t gfp_flags +#endif +) +{ + struct usb_iso_request *pReq = NULL; + uint32_t req_size; + + + req_size = sizeof(struct usb_iso_request); + req_size += (2 * packets * (sizeof(struct usb_gadget_iso_packet_descriptor))); + + + pReq = kmalloc(req_size, gfp_flags); + if (!pReq) { + DWC_WARN("%s, can't allocate Iso Request\n", __func__); + return 0; + } + pReq->iso_packet_desc0 = (void*) (pReq + 1); + + pReq->iso_packet_desc1 = pReq->iso_packet_desc0 + packets; + + return pReq; +} + +static void dwc_otg_pcd_free_iso_request(struct usb_ep *ep, struct usb_iso_request *req) +{ + kfree(req); +} + +static struct usb_isoc_ep_ops dwc_otg_pcd_ep_ops = +{ + .ep_ops = + { + .enable = dwc_otg_pcd_ep_enable, + .disable = dwc_otg_pcd_ep_disable, + + .alloc_request = dwc_otg_pcd_alloc_request, + .free_request = dwc_otg_pcd_free_request, + + .alloc_buffer = dwc_otg_pcd_alloc_buffer, + .free_buffer = dwc_otg_pcd_free_buffer, + + .queue = dwc_otg_pcd_ep_queue, + .dequeue = dwc_otg_pcd_ep_dequeue, + + .set_halt = dwc_otg_pcd_ep_set_halt, + .fifo_status = 0, + .fifo_flush = 0, + }, + .iso_ep_start = dwc_otg_pcd_iso_ep_start, + .iso_ep_stop = dwc_otg_pcd_iso_ep_stop, + .alloc_iso_request = dwc_otg_pcd_alloc_iso_request, + .free_iso_request = dwc_otg_pcd_free_iso_request, +}; + +#else + + static struct usb_ep_ops dwc_otg_pcd_ep_ops = { @@ -876,6 +1562,9 @@ .fifo_status = 0, .fifo_flush = 0, + + }; +#endif /* DWC_EN_ISOC */ /* Gadget Operations */ /** @@ -897,18 +1586,16 @@ *Gets the USB Frame number of the last SOF. */ -static int dwc_otg_pcd_get_frame(struct usb_gadget *_gadget) +static int dwc_otg_pcd_get_frame(struct usb_gadget *gadget) { dwc_otg_pcd_t *pcd; - DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _gadget); - - if (_gadget == 0) - { + DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, gadget); + + if (gadget == 0) { return -ENODEV; } - else - { - pcd = container_of(_gadget, dwc_otg_pcd_t, gadget); - dwc_otg_get_frame_number( GET_CORE_IF(pcd) ); + else { + pcd = container_of(gadget, dwc_otg_pcd_t, gadget); + dwc_otg_get_frame_number(GET_CORE_IF(pcd)); } @@ -916,13 +1603,12 @@ } -void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t *_pcd) -{ - uint32_t *addr = (uint32_t *)&(GET_CORE_IF(_pcd)->core_global_regs->gotgctl); +void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t *pcd) +{ + uint32_t *addr = (uint32_t *)&(GET_CORE_IF(pcd)->core_global_regs->gotgctl); gotgctl_data_t mem; gotgctl_data_t val; - val.d32 = dwc_read_reg32( addr ); - if (val.b.sesreq) - { + val.d32 = dwc_read_reg32(addr); + if (val.b.sesreq) { DWC_ERROR("Session Request Already active!\n"); return; @@ -935,37 +1621,30 @@ /* Start the SRP timer */ - dwc_otg_pcd_start_srp_timer( _pcd ); + dwc_otg_pcd_start_srp_timer(pcd); return; } -void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t *_pcd, int set) +void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t *pcd, int set) { dctl_data_t dctl = {.d32=0}; - volatile uint32_t *addr = - &(GET_CORE_IF(_pcd)->dev_if->dev_global_regs->dctl); - - if (dwc_otg_is_device_mode(GET_CORE_IF(_pcd))) - { - if (_pcd->remote_wakeup_enable) - { - if (set) - { + volatile uint32_t *addr = &(GET_CORE_IF(pcd)->dev_if->dev_global_regs->dctl); + + if (dwc_otg_is_device_mode(GET_CORE_IF(pcd))) { + if (pcd->remote_wakeup_enable) { + if (set) { dctl.b.rmtwkupsig = 1; - dwc_modify_reg32( addr, 0, dctl.d32 ); + dwc_modify_reg32(addr, 0, dctl.d32); DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n"); mdelay(1); - dwc_modify_reg32( addr, dctl.d32, 0 ); + dwc_modify_reg32(addr, dctl.d32, 0); DWC_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n"); } - else - { + else { } } - else - { + else { DWC_DEBUGPL(DBG_PCD, "Remote Wakeup is disabled\n"); } } - return; } @@ -977,5 +1656,5 @@ * */ -static int dwc_otg_pcd_wakeup(struct usb_gadget *_gadget) +static int dwc_otg_pcd_wakeup(struct usb_gadget *gadget) { unsigned long flags; @@ -984,13 +1663,11 @@ gotgctl_data_t gotgctl; - DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _gadget); - - if (_gadget == 0) - { + DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, gadget); + + if (gadget == 0) { return -ENODEV; } - else - { - pcd = container_of(_gadget, dwc_otg_pcd_t, gadget); + else { + pcd = container_of(gadget, dwc_otg_pcd_t, gadget); } SPIN_LOCK_IRQSAVE(&pcd->lock, flags); @@ -1004,15 +1681,12 @@ /* Check if valid session */ gotgctl.d32 = dwc_read_reg32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl)); - if (gotgctl.b.bsesvld) - { + if (gotgctl.b.bsesvld) { /* Check if suspend state */ dsts.d32 = dwc_read_reg32(&(GET_CORE_IF(pcd)->dev_if->dev_global_regs->dsts)); - if (dsts.b.suspsts) - { + if (dsts.b.suspsts) { dwc_otg_pcd_remote_wakeup(pcd, 1); } } - else - { + else { dwc_otg_pcd_initiate_srp(pcd); } @@ -1032,20 +1706,19 @@ * This function updates the otg values in the gadget structure. */ -void dwc_otg_pcd_update_otg( dwc_otg_pcd_t *_pcd, const unsigned _reset ) -{ - - if (!_pcd->gadget.is_otg) +void dwc_otg_pcd_update_otg(dwc_otg_pcd_t *pcd, const unsigned reset) +{ + + if (!pcd->gadget.is_otg) return; - if (_reset) - { - _pcd->b_hnp_enable = 0; - _pcd->a_hnp_support = 0; - _pcd->a_alt_hnp_support = 0; - } - - _pcd->gadget.b_hnp_enable = _pcd->b_hnp_enable; - _pcd->gadget.a_hnp_support = _pcd->a_hnp_support; - _pcd->gadget.a_alt_hnp_support = _pcd->a_alt_hnp_support; + if (reset) { + pcd->b_hnp_enable = 0; + pcd->a_hnp_support = 0; + pcd->a_alt_hnp_support = 0; + } + + pcd->gadget.b_hnp_enable = pcd->b_hnp_enable; + pcd->gadget.a_hnp_support = pcd->a_hnp_support; + pcd->gadget.a_alt_hnp_support = pcd->a_alt_hnp_support; } @@ -1053,11 +1726,14 @@ * This function is the top level PCD interrupt handler. */ -static irqreturn_t -dwc_otg_pcd_irq(int _irq, void *_dev, struct pt_regs *_r) -{ - dwc_otg_pcd_t *pcd = _dev; +static irqreturn_t dwc_otg_pcd_irq(int irq, void *dev +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) + , struct pt_regs *r +#endif + ) +{ + dwc_otg_pcd_t *pcd = dev; int32_t retval = IRQ_NONE; - retval = dwc_otg_pcd_handle_intr( pcd ); + retval = dwc_otg_pcd_handle_intr(pcd); return IRQ_RETVAL(retval); } @@ -1067,18 +1743,16 @@ * device mode. * - * @param _p void pointer to the dwc_otg_pcd_t - */ -static int32_t dwc_otg_pcd_start_cb( void *_p ) -{ - dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *)_p; + * @param p void pointer to the dwc_otg_pcd_t + */ +static int32_t dwc_otg_pcd_start_cb(void *p) +{ + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *)p; /* * Initialized the Core for Device mode. */ - if (dwc_otg_is_device_mode( GET_CORE_IF(pcd) )) - { - dwc_otg_core_dev_init(GET_CORE_IF(pcd)); - } - + if (dwc_otg_is_device_mode(GET_CORE_IF(pcd))) { + dwc_otg_core_dev_init(GET_CORE_IF(pcd)); + } return 1; } @@ -1088,12 +1762,12 @@ * mode. * - * @param _p void pointer to the dwc_otg_pcd_t - */ -static int32_t dwc_otg_pcd_stop_cb( void *_p ) -{ - dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *)_p; + * @param p void pointer to the dwc_otg_pcd_t + */ +static int32_t dwc_otg_pcd_stop_cb(void *p) +{ + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *)p; extern void dwc_otg_pcd_stop(dwc_otg_pcd_t *_pcd); - dwc_otg_pcd_stop( pcd ); + dwc_otg_pcd_stop(pcd); return 1; } @@ -1104,12 +1778,11 @@ * suspend. * - * @param _p void pointer to the dwc_otg_pcd_t - */ -static int32_t dwc_otg_pcd_suspend_cb( void *_p ) -{ - dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *)_p; - - if (pcd->driver && pcd->driver->resume) - { + * @param p void pointer to the dwc_otg_pcd_t + */ +static int32_t dwc_otg_pcd_suspend_cb(void *p) +{ + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *)p; + + if (pcd->driver && pcd->driver->resume) { SPIN_UNLOCK(&pcd->lock); pcd->driver->suspend(&pcd->gadget); @@ -1125,12 +1798,11 @@ * suspend. * - * @param _p void pointer to the dwc_otg_pcd_t - */ -static int32_t dwc_otg_pcd_resume_cb( void *_p ) -{ - dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *)_p; - - if (pcd->driver && pcd->driver->resume) - { + * @param p void pointer to the dwc_otg_pcd_t + */ +static int32_t dwc_otg_pcd_resume_cb(void *p) +{ + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *)p; + + if (pcd->driver && pcd->driver->resume) { SPIN_UNLOCK(&pcd->lock); pcd->driver->resume(&pcd->gadget); @@ -1140,10 +1812,8 @@ /* Stop the SRP timeout timer. */ if ((GET_CORE_IF(pcd)->core_params->phy_type != DWC_PHY_TYPE_PARAM_FS) || - (!GET_CORE_IF(pcd)->core_params->i2c_enable)) - { - if (GET_CORE_IF(pcd)->srp_timer_started) - { + (!GET_CORE_IF(pcd)->core_params->i2c_enable)) { + if (GET_CORE_IF(pcd)->srp_timer_started) { GET_CORE_IF(pcd)->srp_timer_started = 0; - del_timer( &pcd->srp_timer ); + del_timer(&pcd->srp_timer); } } @@ -1168,8 +1838,8 @@ * complete within 6 seconds. */ -static void srp_timeout( unsigned long _ptr ) +static void srp_timeout(unsigned long ptr) { gotgctl_data_t gotgctl; - dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *)_ptr; + dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *)ptr; volatile uint32_t *addr = &core_if->core_global_regs->gotgctl; @@ -1179,13 +1849,10 @@ if ((core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) && - (core_if->core_params->i2c_enable)) - { - DWC_PRINT( "SRP Timeout\n"); + (core_if->core_params->i2c_enable)) { + DWC_PRINT("SRP Timeout\n"); if ((core_if->srp_success) && - (gotgctl.b.bsesvld)) - { - if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup ) - { + (gotgctl.b.bsesvld)) { + if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); } @@ -1194,27 +1861,24 @@ gotgctl.d32 = 0; gotgctl.b.sesreq = 1; - dwc_modify_reg32( &core_if->core_global_regs->gotgctl, + dwc_modify_reg32(&core_if->core_global_regs->gotgctl, gotgctl.d32, 0); core_if->srp_success = 0; } - else - { - DWC_ERROR( "Device not connected/responding\n"); + else { + DWC_ERROR("Device not connected/responding\n"); gotgctl.b.sesreq = 0; dwc_write_reg32(addr, gotgctl.d32); } } - else if (gotgctl.b.sesreq) - { - DWC_PRINT( "SRP Timeout\n"); - - DWC_ERROR( "Device not connected/responding\n"); + else if (gotgctl.b.sesreq) { + DWC_PRINT("SRP Timeout\n"); + + DWC_ERROR("Device not connected/responding\n"); gotgctl.b.sesreq = 0; dwc_write_reg32(addr, gotgctl.d32); } - else - { - DWC_PRINT( " SRP GOTGCTL=%0x\n", gotgctl.d32); + else { + DWC_PRINT(" SRP GOTGCTL=%0x\n", gotgctl.d32); } } @@ -1224,15 +1888,15 @@ * 6 seconds. * - * @param _pcd the pcd structure. - */ -void dwc_otg_pcd_start_srp_timer(dwc_otg_pcd_t *_pcd ) -{ - struct timer_list *srp_timer = &_pcd->srp_timer; - GET_CORE_IF(_pcd)->srp_timer_started = 1; - init_timer( srp_timer ); + * @param pcd the pcd structure. + */ +void dwc_otg_pcd_start_srp_timer(dwc_otg_pcd_t *pcd) +{ + struct timer_list *srp_timer = &pcd->srp_timer; + GET_CORE_IF(pcd)->srp_timer_started = 1; + init_timer(srp_timer); srp_timer->function = srp_timeout; - srp_timer->data = (unsigned long)GET_CORE_IF(_pcd); + srp_timer->data = (unsigned long)GET_CORE_IF(pcd); srp_timer->expires = jiffies + (HZ*6); - add_timer( srp_timer ); + add_timer(srp_timer); } @@ -1241,5 +1905,5 @@ * */ -extern void start_next_request( dwc_otg_pcd_ep_t *_ep ); +extern void start_next_request(dwc_otg_pcd_ep_t *ep); static void start_xfer_tasklet_func (unsigned long data) @@ -1253,8 +1917,7 @@ DWC_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n"); - diepctl.d32 = dwc_read_reg32( &core_if->dev_if->in_ep_regs[0]->diepctl); - - if (pcd->ep0.queue_sof) - { + diepctl.d32 = dwc_read_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl); + + if (pcd->ep0.queue_sof) { pcd->ep0.queue_sof = 0; start_next_request (&pcd->ep0); @@ -1265,8 +1928,7 @@ { depctl_data_t diepctl; - diepctl.d32 = dwc_read_reg32( &core_if->dev_if->in_ep_regs[i]->diepctl); - - if (pcd->in_ep[i].queue_sof) - { + diepctl.d32 = dwc_read_reg32(&core_if->dev_if->in_ep_regs[i]->diepctl); + + if (pcd->in_ep[i].queue_sof) { pcd->in_ep[i].queue_sof = 0; start_next_request (&pcd->in_ep[i]); @@ -1295,7 +1957,7 @@ * state. * - * @param _pcd the pcd structure. - */ -void dwc_otg_pcd_reinit(dwc_otg_pcd_t *_pcd) + * @param pcd the pcd structure. + */ +void dwc_otg_pcd_reinit(dwc_otg_pcd_t *pcd) { static const char * names[] = @@ -1339,24 +2001,24 @@ int in_ep_cntr, out_ep_cntr; uint32_t hwcfg1; - uint32_t num_in_eps = (GET_CORE_IF(_pcd))->dev_if->num_in_eps; - uint32_t num_out_eps = (GET_CORE_IF(_pcd))->dev_if->num_out_eps; + uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps; + uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps; dwc_otg_pcd_ep_t *ep; - DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd); - - INIT_LIST_HEAD (&_pcd->gadget.ep_list); - _pcd->gadget.ep0 = &_pcd->ep0.ep; - _pcd->gadget.speed = USB_SPEED_UNKNOWN; - - INIT_LIST_HEAD (&_pcd->gadget.ep0->ep_list); + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, pcd); + + INIT_LIST_HEAD (&pcd->gadget.ep_list); + pcd->gadget.ep0 = &pcd->ep0.ep; + pcd->gadget.speed = USB_SPEED_UNKNOWN; + + INIT_LIST_HEAD (&pcd->gadget.ep0->ep_list); /** * Initialize the EP0 structure. */ - ep = &_pcd->ep0; + ep = &pcd->ep0; /* Init EP structure */ ep->desc = 0; - ep->pcd = _pcd; + ep->pcd = pcd; ep->stopped = 1; @@ -1366,5 +2028,5 @@ ep->dwc_ep.tx_fifo_num = 0; /* Control until ep is actvated */ - ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL; + ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL; ep->dwc_ep.maxpacket = MAX_PACKET_SIZE; ep->dwc_ep.dma_addr = 0; @@ -1376,8 +2038,11 @@ ep->dwc_ep.total_len = 0; ep->queue_sof = 0; + ep->dwc_ep.desc_addr = 0; + ep->dwc_ep.dma_desc_addr = 0; + /* Init the usb_ep structure. */ ep->ep.name = names[0]; - ep->ep.ops = &dwc_otg_pcd_ep_ops; + ep->ep.ops = (struct usb_ep_ops*)&dwc_otg_pcd_ep_ops; /** @@ -1387,5 +2052,5 @@ ep->ep.maxpacket = MAX_PACKET_SIZE; - list_add_tail (&ep->ep.ep_list, &_pcd->gadget.ep_list); + list_add_tail (&ep->ep.ep_list, &pcd->gadget.ep_list); INIT_LIST_HEAD (&ep->queue); @@ -1394,16 +2059,15 @@ */ in_ep_cntr = 0; - hwcfg1 = (GET_CORE_IF(_pcd))->hwcfg1.d32 >> 3; + hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3; for (i = 1; in_ep_cntr < num_in_eps; i++) { - if((hwcfg1 & 0x1) == 0) - { - dwc_otg_pcd_ep_t *ep = &_pcd->in_ep[in_ep_cntr]; + if((hwcfg1 & 0x1) == 0) { + dwc_otg_pcd_ep_t *ep = &pcd->in_ep[in_ep_cntr]; in_ep_cntr ++; /* Init EP structure */ ep->desc = 0; - ep->pcd = _pcd; + ep->pcd = pcd; ep->stopped = 1; @@ -1425,13 +2089,10 @@ ep->dwc_ep.total_len = 0; ep->queue_sof = 0; + ep->dwc_ep.desc_addr = 0; + ep->dwc_ep.dma_desc_addr = 0; /* Init the usb_ep structure. */ - /** - * @todo NGS: Add direction to EP, based on contents - * of HWCFG1. Need a copy of HWCFG1 in pcd structure? - * sprintf( ";r - */ ep->ep.name = names[i]; - ep->ep.ops = &dwc_otg_pcd_ep_ops; + ep->ep.ops = (struct usb_ep_ops*)&dwc_otg_pcd_ep_ops; /** @@ -1441,5 +2102,5 @@ ep->ep.maxpacket = MAX_PACKET_SIZE; - list_add_tail (&ep->ep.ep_list, &_pcd->gadget.ep_list); + list_add_tail (&ep->ep.ep_list, &pcd->gadget.ep_list); INIT_LIST_HEAD (&ep->queue); @@ -1449,18 +2110,17 @@ out_ep_cntr = 0; - hwcfg1 = (GET_CORE_IF(_pcd))->hwcfg1.d32 >> 2; + hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2; for (i = 1; out_ep_cntr < num_out_eps; i++) { - if((hwcfg1 & 0x1) == 0) - { - dwc_otg_pcd_ep_t *ep = &_pcd->out_ep[out_ep_cntr]; + if((hwcfg1 & 0x1) == 0) { + dwc_otg_pcd_ep_t *ep = &pcd->out_ep[out_ep_cntr]; out_ep_cntr++; /* Init EP structure */ ep->desc = 0; - ep->pcd = _pcd; + ep->pcd = pcd; ep->stopped = 1; - + /* Init DWC ep structure */ ep->dwc_ep.is_in = 0; @@ -1481,11 +2141,6 @@ /* Init the usb_ep structure. */ - /** - * @todo NGS: Add direction to EP, based on contents - * of HWCFG1. Need a copy of HWCFG1 in pcd structure? - * sprintf( ";r - */ ep->ep.name = names[15 + i]; - ep->ep.ops = &dwc_otg_pcd_ep_ops; + ep->ep.ops = (struct usb_ep_ops*)&dwc_otg_pcd_ep_ops; /** * @todo NGS: What should the max packet size be set to @@ -1494,5 +2149,5 @@ ep->ep.maxpacket = MAX_PACKET_SIZE; - list_add_tail (&ep->ep.ep_list, &_pcd->gadget.ep_list); + list_add_tail (&ep->ep.ep_list, &pcd->gadget.ep_list); INIT_LIST_HEAD (&ep->queue); @@ -1502,10 +2157,10 @@ /* remove ep0 from the list. There is a ep0 pointer.*/ - list_del_init (&_pcd->ep0.ep.ep_list); + list_del_init (&pcd->ep0.ep.ep_list); - _pcd->ep0state = EP0_DISCONNECT; - _pcd->ep0.ep.maxpacket = MAX_EP0_SIZE; - _pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE; - _pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL; + pcd->ep0state = EP0_DISCONNECT; + pcd->ep0.ep.maxpacket = MAX_EP0_SIZE; + pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE; + pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL; } @@ -1516,8 +2171,9 @@ * @todo Should this do something? Should it free the PCD? */ -static void dwc_otg_pcd_gadget_release(struct device *_dev) -{ - DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _dev); -} +static void dwc_otg_pcd_gadget_release(struct device *dev) +{ + DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, dev); +} + @@ -1527,25 +2183,26 @@ */ -int dwc_otg_pcd_init(struct lm_device *_lmdev) +int dwc_otg_pcd_init(struct lm_device *lmdev) { static char pcd_name[] = "dwc_otg_pcd"; dwc_otg_pcd_t *pcd; - dwc_otg_device_t *otg_dev = lm_get_drvdata(_lmdev); + dwc_otg_core_if_t* core_if; + dwc_otg_dev_if_t* dev_if; + dwc_otg_device_t *otg_dev = lm_get_drvdata(lmdev); int retval = 0; - DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n",__func__, _lmdev ); + DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n",__func__, lmdev); /* * Allocate PCD structure */ - pcd = kmalloc( sizeof(dwc_otg_pcd_t), GFP_KERNEL); - - if (pcd == 0) - { - return -ENOMEM; - } -
Parameter NameMeaning
Parameter NameMeaning
otg_cap
dma_enable
dma_burst_size
speed
host_support_fs_ls_low_power
host_ls_low_power_phy_clk
enable_dynamic_fifo
data_fifo_size
dev_rx_fifo_size
dev_nperio_tx_fifo_size
dev_perio_tx_fifo_size_n (n = 1 to 15)
host_rx_fifo_size
host_nperio_tx_fifo_size
host_perio_tx_fifo_size
max_transfer_size
max_packet_count
host_channels
dev_endpoints
phy_type
phy_utmi_width
phy_ulpi_ddr